简体   繁体   中英

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.

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. Similarly, do...end block will result in other compilation errors.

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.

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 . You can still call them using 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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