Ruby 是否可以声明块为默认值的方法?

Ruby 是否可以声明块为默认值的方法?,ruby,lambda,block,Ruby,Lambda,Block,我想写一个方法,它接受一个块,如果没有给定的块,它应该使用一个默认块。所以我想要这样的东西: def say_hello(name, &block = ->(name) { puts "Hi, #{name}" }) # do something end 但是当我尝试这样做时,我得到了语法错误 我知道我可以用电脑解决我的问题。但我对第一种方法感兴趣。 我遗漏了什么或者这是不可能的吗?你可以用普通的lambda来做 def say_hello(name, block = -&

我想写一个方法,它接受一个块,如果没有给定的块,它应该使用一个默认块。所以我想要这样的东西:

def say_hello(name, &block = ->(name) { puts "Hi, #{name}" })
  # do something
end 
但是当我尝试这样做时,我得到了语法错误

我知道我可以用电脑解决我的问题。但我对第一种方法感兴趣。
我遗漏了什么或者这是不可能的吗?

你可以用普通的lambda来做

def say_hello(name, block = ->(name) { puts "Hi, #{name}" })
  block.call(name)
end 

say_hello("Sergio")
say_hello("Ivan", ->(name) { puts "Where are you from, #{name}?"})
# >> Hi, Sergio
# >> Where are you from, Ivan?

但是,不确定是否可以使用块来执行此操作。块不是普通参数。

您不能在方法定义中声明默认块,但是如果没有指定自定义块,您可以使用一些小技巧来使用自定义块

def say_hello(name)
  block = block_given? ? Proc.new : ->(name) { puts "Hi, #{name}" }
  block.call(name)
end

# This example uses a custom block
say_hello('weppos') { |name| puts "Hello, #{name}!" }
# => Hello, weppos!

# This example fallbacks to the default
say_hello('weppos')
# => Hi, weppos!
让我解释一下。让我们从一个更可读的版本开始

def say_hello(name, &block)
  block = block ? block : ->(name) { puts "Hi, #{name}" }
  block.call(name)
end
定义接受块的方法,然后检查是否定义了块。如果不是,则指定一个自定义块。最后,执行块

让我们把它增强一点。你可以使用block_吗?检查是否通过了块

def say_hello(name, &block)
  block = block_given? ? block : ->(name) { puts "Hi, #{name}" }
  block.call(name)
end
这还允许您跳过方法定义中的块声明(
&block

def say_hello(name)
  if block_given?
    yield name
  else
    # This is rendundant, but it's for clarity
    block = ->(name) { puts "Hi, #{name}" }
    block.call(name)
  end
end
但是,此时,您还可以使用
Proc.new
将块分配给变量

def say_hello(name)
  block = block_given? ? Proc.new : ->(name) { puts "Hi, #{name}" }
  block.call(name)
end

最后一句话,我试图理解这种方法何时才有意义。在大多数情况下,您可能可以将代码包装在类或模块中,并将其作为参数传递。可能更好。

不,不能在方法定义中提供默认块值。但是,您可以通过在方法主体内使用
block\u given?
实现等效行为,如下所示:

def say_hello(name, &block)
  block = ->(name) { puts "Hi, #{name}" } unless block_given?
  # do something
end

但是,在这种情况下,您不能利用
yield
调用传入的任何块,因为在默认情况下它不在那里。您必须调用
Proc
对象,如
块。(名称)

一些答案建议使用
块(给定)
,但由于在给定块时,块不可能是
nil
false
,因此您可以简单地使用
| |=

def say_hello(name, &block)
  block ||= ->(name){puts "Hi, #{name}"}
  # do something
end

当我发布我的答案时,没有看到你的答案。如果使用
&block
作为参数,则如果未传递块,则不必将
block
定义为
Proc.new
,因为Ruby会为您处理。对吗?我必须写下我知道什么是
block\u给定的?
do.)虽然答案很棒。我目前正在玩的东西需要在
method\u missing
上声明一个方法。例如
foobar{| x | puts x}
将向当前对象类添加一个方法
foobar(x)
。您是否也必须切换访问块的方法以避免
yield
?@PeterAlfvin我不明白您的意思。如果调用中没有提供块,那么
yield
语句将无法工作。您必须使用
block.call(…)
或类似的方法调用它。@PeterAlfvin没错。那么,
收益率如何相关?你想告诉我什么?我想告诉你,如果调用方不提供值,这种为
赋值的技术与为
&block
提供默认值相比,不是一种透明的替代方法(即提供一个“默认块”,以便在调用方不提供时使用)。OP需要知道,如果他以前使用了
yield
,他需要更改他的代码(即
#do something
)以使用这种替代方法。