为什么 Ruby setter 方法返回的是字符串而不是符号作为最后计算的表达式?
Why is a Ruby setter method returning a String rather than a Symbol as the last expression evaluated?
意外的Return方法的值:期望符号
我有以下票证class:
class Ticket
VALID_STATES = %i[open closed invalid wontfix]
attr_reader :status
def status= new_state
new_state = new_state.to_sym
@status = new_state
end
end
当传递字符串而不是符号时,setter 方法意外地 return 是一个字符串,即使 return 方法getter 编辑了正确的值方法。例如:
t = Ticket.new
t.status = 'closed'
#=> "closed"
t.status
#=> :closed
看起来正确的值正在 存储 作为符号,但我不知道为什么该方法是 returning "closed"
在 REPL 中最后一个表达式求值应该 return :closed
。我的期望是所讨论的表达式应该解析为 @status = :closed
,因此应该 return 一个符号。
谁能解释为什么我从 setter 方法中得到一个字符串而不是符号作为 return 值?
警告和自行车脱落预防
- 我知道这个例子可以只使用
@status = new_state.to_sym
而不是分配回 new_state,但是删除了中间代码来创建这个最小的例子.我不想过多地更改代码,因为这违背了显示我的真实代码在做什么的意义。无论如何,它似乎对这个特定问题没有影响;两种方法我都试过了。
- 我用 Ruby 2.3.1、2.4.0-preview2 和 JRuby 9.1.4.0 试过了,所以它不是特定于版本的。
- 各种调试尝试 运行 与 Pry 和 IRB 中 REPL 顶层的其他特定问题发生冲突,我将作为一个单独的问题打开。这里的要点是,尝试使用
def foo=(str); @foo = str.to_sym; end
等替代抽象进行调试会导致进一步陷入困境。
- 极有可能键盘和椅子之间存在问题,但问题的重点实际上是关于为什么return值不是预计 class.
这是意料之中的。来自 documentation:
Note that for assignment methods the return value will always be
ignored. Instead, the argument will be returned:
def a=(value)
return 1 + value
end
p(a = 5) # prints 5
Ruby 允许您链式赋值:
foo = bar = 'closed'
以上将 "closed"
分配给 foo
和 bar
。
返回参数并忽略方法的 return 值让您可以用方法调用替换 bar
:
foo = t.status = 'closed'
IMO 如果上面将 :closed
赋值给 foo
.
,那将是非常令人惊讶的
如果您真的想要 return 值,请使用 send
或 public_send
:
def a=(value)
return 1 + value
end
p(a = 5) # prints 5
p(send(:a=, 5)) # prints 6
答案很简单:在 Ruby 中,赋值求值为被赋值。方法赋值没什么特别的。
意外的Return方法的值:期望符号
我有以下票证class:
class Ticket
VALID_STATES = %i[open closed invalid wontfix]
attr_reader :status
def status= new_state
new_state = new_state.to_sym
@status = new_state
end
end
当传递字符串而不是符号时,setter 方法意外地 return 是一个字符串,即使 return 方法getter 编辑了正确的值方法。例如:
t = Ticket.new
t.status = 'closed'
#=> "closed"
t.status
#=> :closed
看起来正确的值正在 存储 作为符号,但我不知道为什么该方法是 returning "closed"
在 REPL 中最后一个表达式求值应该 return :closed
。我的期望是所讨论的表达式应该解析为 @status = :closed
,因此应该 return 一个符号。
谁能解释为什么我从 setter 方法中得到一个字符串而不是符号作为 return 值?
警告和自行车脱落预防
- 我知道这个例子可以只使用
@status = new_state.to_sym
而不是分配回 new_state,但是删除了中间代码来创建这个最小的例子.我不想过多地更改代码,因为这违背了显示我的真实代码在做什么的意义。无论如何,它似乎对这个特定问题没有影响;两种方法我都试过了。 - 我用 Ruby 2.3.1、2.4.0-preview2 和 JRuby 9.1.4.0 试过了,所以它不是特定于版本的。
- 各种调试尝试 运行 与 Pry 和 IRB 中 REPL 顶层的其他特定问题发生冲突,我将作为一个单独的问题打开。这里的要点是,尝试使用
def foo=(str); @foo = str.to_sym; end
等替代抽象进行调试会导致进一步陷入困境。 - 极有可能键盘和椅子之间存在问题,但问题的重点实际上是关于为什么return值不是预计 class.
这是意料之中的。来自 documentation:
Note that for assignment methods the return value will always be ignored. Instead, the argument will be returned:
def a=(value) return 1 + value end p(a = 5) # prints 5
Ruby 允许您链式赋值:
foo = bar = 'closed'
以上将 "closed"
分配给 foo
和 bar
。
返回参数并忽略方法的 return 值让您可以用方法调用替换 bar
:
foo = t.status = 'closed'
IMO 如果上面将 :closed
赋值给 foo
.
如果您真的想要 return 值,请使用 send
或 public_send
:
def a=(value)
return 1 + value
end
p(a = 5) # prints 5
p(send(:a=, 5)) # prints 6
答案很简单:在 Ruby 中,赋值求值为被赋值。方法赋值没什么特别的。