简体   繁体   English

以`=`结尾的方法可以接受块吗?

[英]Can methods that end with `=` accept blocks?

This seems to work when the method name doesn't end in = . 当方法名称不以=结尾时,这似乎有效。

class C
  def x= value = nil, &block
  end  
end

c = C.new

c.x = 1                  # => fine
c.x=(2)                  # => fine
c.method(:x=).call { 3 } # => fine
c.x= { 4 }               # => syntax error
c.x= do
  5
end                      # => syntax error

Does anyone have any idea why this is, or whether there is a similar syntax to the two that don't work? 有没有人知道为什么会这样,或者是否有两种类似的语法不起作用?

sample usage: 样品用量:

logger.level=(:debug) do
  # log at debug level inside this block
end

there are of course many alternatives, such as: 当然有很多替代品,例如:

logger.with_level(:debug) do
  # log at debug level inside this block
end

i am just interested if i was missing something syntax-wise or if anyone had any explanation for this behavior. 我只是感兴趣,如果我错过了语法方面的东西,或者如果有人对此行为有任何解释。

Methods ending with = are called Assignment methods , and as such all rules of assignment applies. =结尾的方法称为赋值方法 ,因此所有赋值规则都适用。

Any assignment statement can be depicted as 任何赋值语句都可以描述为

LHS = RHS

where LHS is Left Hand Side, RHS is Right Hand Side. LHS是左手侧, RHS是右手侧。

The RHS is evaluated to be a new value for LHS , and if use attempt to specify block as RHS using {...} , it will get interpreted as definition of Hash literal and result in compilation error for being invalid hash. RHS被评估为LHS的新值,并且如果使用尝试使用{...}将块指定为RHS ,则它将被解释为Hash文字的定义,并导致编译错误为无效散列。 Similarly, do...end block will result in other compilation errors. 同样, do...end block会导致其他编译错误。

Assignment methods should always have single parameter whose value can be assigned to an instance variable, or whose value can be used to derive new value for the instance variable. 赋值方法应始终具有单个参数,其值可以分配给实例变量,或者其值可用于派生实例变量的新值。

If you wish you can use Proc or lambda as parameter, as they are Objects. 如果您希望可以使用Proclambda作为参数,因为它们是对象。

class C
  def x= value
    @x = (value.class == Proc ? value.call : value)
    p @x
  end  
end

c = C.new

# fine
c.x = -> {10}
c.x = lambda {20}
c.x = Proc.new {30}

They can, but calling them the regular way would cause the block to be evaluated as hash thus giving you SyntaxError . 他们可以,但以常规方式调用它们会导致块被评估为哈希,从而为您提供SyntaxError You can still call them using Object#public_send / Object#send : 您仍然可以使用Object#public_send / Object#send调用它们:

def foo=
  puts 'bar'
  yield
  puts 'baz'
end

public_send(:foo=) { puts 'quiz' } # bar quiz baz
foo= { puts 'fail' } # SyntaxError

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM