Ruby 语法上的甜言蜜语迫使我使用难看的语句 def foo(bar) “返回值” 结束 foo'bar'#=>“返回值” def foo=(巴) “返回值” 结束 foo='bar'#=>“bar” 发送:foo=,'bar'#=>“返回值”

Ruby 语法上的甜言蜜语迫使我使用难看的语句 def foo(bar) “返回值” 结束 foo'bar'#=>“返回值” def foo=(巴) “返回值” 结束 foo='bar'#=>“bar” 发送:foo=,'bar'#=>“返回值”,ruby,Ruby,我希望foo='bar'返回“返回值”,但不要为此使用send。我该怎么做 更新 我需要在我的宝石中有一个理想的行为。以下是一个例子: car=car.new car.gear#=>:第一 car.next#u gear#=>:秒 car.gear#=>:秒 car.gear=:第四个#=>错误 car.gear#=>:秒 car.gear=:第三#=>:第三 car.gear#=>:第三 您需要执行以下操作: self.foo = 'bar' 我认为它失败的原因是局部变量名在定义时优先于方

我希望
foo='bar'
返回
“返回值”
,但不要为此使用
send
。我该怎么做

更新 我需要在我的宝石中有一个理想的行为。以下是一个例子:

car=car.new
car.gear#=>:第一
car.next#u gear#=>:秒
car.gear#=>:秒
car.gear=:第四个#=>错误
car.gear#=>:秒
car.gear=:第三#=>:第三
car.gear#=>:第三
您需要执行以下操作:

 self.foo = 'bar'

我认为它失败的原因是局部变量名在定义时优先于方法名


因此,您需要使用
send
,以便
self
知道它正在寻找一个方法而不是一个变量。

Assignments始终返回赋值的右侧

有关详细信息,请查看:

以等号结尾的方法表示赋值方法。 对于赋值方法,返回值被忽略,参数为 他回来了

话虽如此,
foo=bar
也将赋值给局部变量
foo
,而不是使用
foo=
方法。同样,这在以下章节中定义:

当使用方法分配时,您必须始终具有接收器。如果你 没有接收器Ruby假定您正在分配给本地 变数

您可以通过运行

local_variables #=> []
def foo=(bar);end
foo = 42
local_variables #=> [:foo]
您可以看到局部变量
foo
已创建。最好使用self.foo='bar'


为了解决您的gem的具体问题:遵循尼尔的建议,使用额外的方法,如
change\u gear
,来完成您想要做的事情。他在评论中给了你很好的评价。

这是一个Ruby问题:访问器方法的返回值被忽略

此代码将更清楚地说明实际发生的情况:

#!/usr/bin/env ruby

def foo(bar)
  p "called :foo w/ #{bar.inspect}"
end

def foo=(bar)
  p "called :foo= with #{bar.inspect}"
end

ret = (foo :bar1)            # calls foo(bar)
p "ret: #{ret}"              # "ret: called :foo w/ :bar1"
ret = (foo = :bar2)          # assigns a local variable foo = 'bar2'
p "ret: #{ret}"              # "ret: bar2"
ret = (send :foo=, :bar3)    # calls foo=(bar), returns what p returns
p "ret: #{ret}"              # "ret: called :foo= with :bar3"
ret = (self.foo = :bar4)     # calls foo=(bar), returns ???
p "ret: #{ret}"              # "ret: bar4"
基本上,Ruby解析器(至少在2.1中)的行为就像
self.foo=
在调用访问器方法一样(即使它实际上没有赋值),并且总是返回传递给它的值,而不管你发送了什么,而不是访问器的返回值

演示:

#!/usr/bin/env ruby

class << self
  attr_accessor :foo

  def foo=(bar)
    p "called :foo= with #{bar.inspect}"
    @foo = :baz
  end
end

ret = (self.foo = :bar)
p "ret: #{ret} vs @foo: #{@foo.inspect}"
编辑:hat@tessi,用于:

以等号结尾的方法表示赋值方法。对于赋值方法,将忽略返回值,而返回参数


self.foo='bar'
在ruby 2上为我返回
'bar'
。0@tessi:确实如此,但我认为OP遇到了Ruby bug或是被抓住了
self.foo
应该调用
foo=
。如果您定义一个
attr\u访问器
,它确实可以做到这一点。实际上,它有更多的功能。(见我的答案。)@Denis看看我的更新。“局部变量”也是一种预期行为。是的,我认为每个人都很清楚为什么foo=42会分配局部变量,包括OP。我要强调的是,你没有解释为什么OP需要使用
send foo=,…
而不是
self.foo=
。(根据我的回答)这与Ruby所走的捷径有关。事实上,这不是全部答案,但也没有错。你必须有一个接收者才能让ruby调用
foo=
方法。你有什么理由不能绕过赋值运算符而使用常规方法,例如
def set\u foo(bar)
?我建议这样做的原因是,大多数库/作业的使用预期返回RHS的当前行为(并且改变作业应该如何工作的契约),所以只有您的代码需要其他行为。@NeilSlater,看看我的问题的更新对我来说似乎是不可取的设计。你将打破Ruby惯例,选择个人风格。用
car.change\u gear:fourth
代替
car.gear=:fourth
,会有什么问题?您的另一个选择是,如果有人试图设置不正确的档位,则会引发错误(可以说,这比期望用户处理assignemnt的返回值要好)
"called :foo= with :bar"
"ret: bar vs @foo: :baz"