为什么Ruby setter方法返回字符串而不是符号作为最后一个计算表达式? 方法的意外返回值:应为符号

为什么Ruby setter方法返回字符串而不是符号作为最后一个计算表达式? 方法的意外返回值:应为符号,ruby,string,casting,symbols,setter,Ruby,String,Casting,Symbols,Setter,我有以下的机票等级: 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方法意外地返回字符串,即使getter方法返回的是正确的值。例如: t = 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
当传递字符串而不是符号时,setter方法意外地返回字符串,即使getter方法返回的是正确的值。例如:

t = Ticket.new
t.status = 'closed'
#=> "closed"

t.status
#=> :closed
看起来正确的值被存储为一个符号,但我不知道为什么当最后一个计算的表达式应该返回
:closed
时,该方法在REPL返回
“closed”
。我的期望是,所讨论的表达式应该解析为
@status=:closed
,因此应该返回一个符号

有人能解释为什么我从setter方法得到一个字符串而不是一个符号作为返回值吗

注意事项和防止自行车脱落
  • 我知道这个示例可以只使用
    @status=new\u state.to\u sym
    而不是分配回new\u state,但是有一个中间代码被删除以创建这个最小的示例。我不想对代码做太多的修改,因为这样就无法显示我真正的代码在做什么。不管怎么说,这似乎对这个具体问题没有什么影响;我试过两种方法
  • 我在Ruby 2.3.1、2.4.0-preview2和JRuby 9.1.4.0中尝试了这一点,因此它不是特定于版本的
  • 在Pry和IRB中,各种调试尝试都与REPL顶级的其他问题相冲突,我将作为单独的问题进行讨论。这里的要点是,尝试使用类似
    deffoo=(str)的替代抽象进行调试@foo=str.to_sym;end
    进一步引导兔子洞
  • 键盘和椅子之间极有可能存在问题,但问题的焦点实际上是为什么返回值不属于预期类别
  • 这是意料之中的。从:

    注意,对于赋值方法,返回值总是 忽略。相反,将返回参数:

    def a=(value)
      return 1 + value
    end
    
    p(a = 5) # prints 5
    
    Ruby允许您链接分配:

    foo = bar = 'closed'
    
    上面将
    指定为“关闭”
    foo
    bar

    通过返回参数并忽略方法的返回值,可以使用方法调用替换
    bar

    foo = t.status = 'closed'
    
    在我看来,如果上面将
    :closed
    分配给
    foo
    ,那将非常令人惊讶

    如果确实需要返回值,请使用
    send
    public\u send

    def a=(value)
      return 1 + value
    end
    
    p(a = 5)        # prints 5
    p(send(:a=, 5)) # prints 6
    

    答案很简单:在Ruby中,赋值根据被赋值来计算。方法分配没有什么特别之处。

    我真的很喜欢这些准备充分的问题感谢文档的链接。你是对的,这似乎是一个仅适用于赋值方法(而不是赋值表达式)的文档化的小案例,但这仍然让我感到惊讶,因为我期望的行为与
    foo='a'。to_sym#=>:a
    相同。但显然情况并非如此/我经常同意你的答案,但在这种情况下我不能。在方法内部,指定的值是一个符号。因此,当文档为不同的行为调用方法赋值时,“赋值”是一个符号,而不是字符串。@CodeGnome是两个不同的赋值。您的方法中有
    @status=new\u state
    ,其计算结果为
    new\u state
    (即
    :closed
    )。您的方法之外有
    t.status='closed'
    ,该方法的计算结果为
    “closed”
    。内部赋值不会以任何方式影响外部赋值。返回值始终是右侧的值。