Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby中的条件块_Ruby - Fatal编程技术网

Ruby中的条件块

Ruby中的条件块,ruby,Ruby,假设我有一个带有_foo的函数,它需要一个块,并将它包装在一段代码周围,如 with_foo do puts "hello!" end 现在我想让包装有条件,比如 if do_with_foo? with_foo do puts "hello!" end else puts "hello!" # without foo end 有没有办法写得更短/更优雅,这意味着不必重复代码放入“hello!”?您可以将重复代码放入Proc对象中,并将其作为块传递给方法或直接调用它

假设我有一个带有_foo的函数
,它需要一个块,并将它包装在一段代码周围,如

with_foo do
  puts "hello!"
end
现在我想让包装有条件,比如

if do_with_foo?
  with_foo do
    puts "hello!"
  end
else
  puts "hello!" # without foo
end

有没有办法写得更短/更优雅,这意味着不必重复代码
放入“hello!”

您可以将重复代码放入
Proc
对象中,并将其作为块传递给方法或直接调用它

hello = proc { puts 'hello' }

with_foo(&hello)
# OR
hello.call

如果您愿意用一个块指定参数,这是可能的

给定上面的
和foo
,您可以编写这样的代码片段:

whatever = proc {puts "hello"}
#build a proc object with a block
if do_with_foo?
  with_foo &whatever
#pass it to with_foo
else
  whatever.call
#normally call it
end

使用代理模式的概念证明:

class BlockWrapper
  def initialize(obj, use_wrapper)
    @obj = obj
    @use_wrapper = use_wrapper
  end

  def method_missing(*args, &block)
    @use_wrapper ? @obj.send(*args, &block) : block.call
  end
end

module Kernel
  def wrap_if(use_wrapper)
    BlockWrapper.new(self, use_wrapper)        
  end
end

def with_foo
  puts "with_foo: start"
  yield
  puts "with_foo: end"
end

wrap_if(true).with_foo do 
  puts "hello!"
end

wrap_if(false).with_foo do 
  puts "hello, no with_foo here!"
end
输出:

with_foo: start
hello!
with_foo: end
hello, no with_foo here!

我认为你可以做到这一点:

def without_foo &pr
  pr.call
end

send(do_with_foo?? "with_foo" : "without_foo") do
  puts "hello!"
end

看起来比我的解决方案更好,但我正在寻找一种甚至不需要我写两次
任何东西的方法。有什么想法吗?@zero除数:我用一点元编程添加了一个答案。我不认为你可以直接用现有的基础设施来做。哪一部分是不可读的?你不喜欢三元运算符吗?不仅仅是三元运算符(我喜欢,尽管我在做条件赋值时更喜欢它),还有一个事实,我们必须在这里定义一个不起任何作用的包装函数。特别是在Ruby中,通常可以编写代码,在看了一秒钟之后,你已经知道它在做什么了,我一直在寻找这样一种解决方案。我下了一点赌注来支持这个概念,但我想我现在明白了,看起来不错!为什么我们真的需要在这里打开对象类?@zero divisor:是的,一开始很难理解,Ruby中的元编程实现起来可能很难看,但使用起来很有趣。如果
在任何地方都可用(这是一个通用特性),我们需要将它添加到类
对象
或模块
内核
(包含在
对象
中)。
def simple_yielder
  yield
end
def maybe_with condition, with_method
  send( condition ? with_method : :simple_yielder ) { yield }
end

#...

maybe_with( do_with_foo?, :with_foo ) do
  puts "Hello?"
end