为什么一个Ruby setter方法返回一个String而不是一个Symbol作为最后一个表达式求值? [英] Why is a Ruby setter method returning a String rather than a Symbol as the last expression evaluated?
问题描述
来自方法的意外返回值:期望符号
我有以下Ticket类:
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
传递String时, a Symbol,setter方法意外地返回一个String,即使正确的值由getter方法返回。例如:
t = Ticket.new
t.status ='closed'
#=> ; closed
t.status
#=> :closed
看起来正确的值正以 ,但是我不知道为什么该方法在REPL返回closed
,最后一个表达式应该返回:closed
。我的期望是,所讨论的表达式应该解析为 @status =:closed
,因此应该返回一个符号。
任何人都可以解释为什么我得到一个字符串而不是一个符号作为setter方法的返回值?
注意和自行车脱落预防
- 我知道这个例子可以使用
@status = new_state.to_sym
new_state ,但中间代码已删除,以创建此最小示例。我不想更改代码太多,因为它打败了显示我的真正的代码是做什么的点。它似乎没有使这个具体问题有所区别; - 我尝试使用Ruby 2.3.1,2.4.0-preview2和JRuby 9.1.4.0,因此它不是特定于版本的。
- 在Pry和IRB中,各种调试尝试都与REPL的toplevel特有的其他问题有关,我将作为一个单独的问题打开。这里的点是,试图调试与替代抽象如
def foo =(str); @foo = str.to_sym;
- 很可能这个问题存在于键盘和椅子之间,但问题的焦点真的是为什么 这是预期。从文档:
- I know this example could just use
@status = new_state.to_sym
rather than assigning back to new_state, but there's intermediate code that was removed to create this minimal example. I didn't want to change the code too much, as that defeats the point of showing what my real code is doing. It doesn't seem to make a difference for this specific problem anyway; I've tried it both ways. - I tried this with Ruby 2.3.1, 2.4.0-preview2, and JRuby 9.1.4.0, so it's not version-specific.
- Various debugging attempts ran afoul of other issues specific to the REPL's toplevel in both Pry and IRB, which I will open as a separate question. The point here is that trying to debug with alternative abstractions like
def foo=(str); @foo = str.to_sym; end
leads further down the rabbit hole. - It's extremely possible that the problem exists between the keyboard and the chair, but the focus of the question is really about why the return value is not of the expected class.
请注意,对于赋值方法,返回值总是
。相反,将返回参数:def a =(value)
return 1 + value
end
p(a = 5)#prints 5
$ b b
Ruby允许您链接作业:
foo = bar ='closed'
上面的两个都分配了
和closed
bar
。
返回参数并忽略方法的返回值, bar
使用方法调用:
foo = t.status =关闭'
IMO如果上面分配 $
到
foo
。
如果真的想要返回值, $ c> send 或 public_send
:
def a =(value)
return 1 + value
end
p(a = 5)#prints 5
p(send(:a =,5)) #prints 6
Unexpected Return Value from Method: Expecting Symbol
I have the following Ticket 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
When passed a String rather than a Symbol, the setter method unexpectedly returns a String, even though the correct value is being returned by the getter method. For example:
t = Ticket.new
t.status = 'closed'
#=> "closed"
t.status
#=> :closed
It looks like the correct value is being stored as a Symbol, but I'm at a loss as to why the method is returning "closed"
at the REPL when the last expression evaluated should return :closed
. My expectation is that the expression in question ought to resolve as @status = :closed
, and therefore should return a Symbol.
Can anyone explain why I'm getting a String rather than a Symbol as the return value from the setter method?
Caveats and Bike-Shedding Prevention
It's expected. From the 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 allows you to chain assignments:
foo = bar = 'closed'
The above assigns "closed"
to both, foo
and bar
.
Returning the argument and ignoring the method's return value lets you replace bar
with a method call:
foo = t.status = 'closed'
IMO it would be quite surprising if the above would assign :closed
to foo
.
If you really want the return value, use send
or public_send
:
def a=(value)
return 1 + value
end
p(a = 5) # prints 5
p(send(:a=, 5)) # prints 6
这篇关于为什么一个Ruby setter方法返回一个String而不是一个Symbol作为最后一个表达式求值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!