为什么一个Ruby setter方法返回一个String而不是一个Symbol作为最后一个表达式求值? [英] Why is a Ruby setter method returning a String rather than a Symbol as the last expression evaluated?

查看:120
本文介绍了为什么一个Ruby setter方法返回一个String而不是一个Symbol作为最后一个表达式求值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来自方法的意外返回值:期望符号



我有以下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方法的返回值?



注意和自行车脱落预防




  1. 我知道这个例子可以使用 @status = new_state.to_sym new_state ,但中间代码已删除,以创建此最小示例。我不想更改代码太多,因为它打败了显示我的真正的代码是做什么的点。它似乎没有使这个具体问题有所区别;

  2. 我尝试使用Ruby 2.3.1,2.4.0-preview2和JRuby 9.1.4.0,因此它不是特定于版本的。

  3. 在Pry和IRB中,各种调试尝试都与REPL的toplevel特有的其他问题有关,我将作为一个单独的问题打开。这里的点是,试图调试与替代抽象如 def foo =(str); @foo = str.to_sym;

  4. 很可能这个问题存在于键盘和椅子之间,但问题的焦点真的是为什么
  5. 这是预期。从文档


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

      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

    1. 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.
    2. I tried this with Ruby 2.3.1, 2.4.0-preview2, and JRuby 9.1.4.0, so it's not version-specific.
    3. 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.
    4. 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.

    解决方案

    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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆