Ruby 在条件语句中声明变量
我知道整行都被解析,变量的值在Ruby 在条件语句中声明变量,ruby,syntax,Ruby,Syntax,我知道整行都被解析,变量的值在put解析它之前被设置,如下所示: def get_value 42 end if value = get_value puts value end # => 42 p = 1 puts "Am i a string? #{p}" if p = "Im a confused string" # => "Am i a string? Im a confused string" 我得到以下结果,我期望: #p = "Im totally a s
put
解析它之前被设置,如下所示:
def get_value
42
end
if value = get_value
puts value
end
# => 42
p = 1
puts "Am i a string? #{p}" if p = "Im a confused string"
# => "Am i a string? Im a confused string"
我得到以下结果,我期望:
#p = "Im totally a string" # <--Commented.
puts "Am i a string? #{p}" if p = "Im a confused string"
# => "Am i a string? "
p
是一个FixNum
,而不是字符串
:
def get_value
42
end
if value = get_value
puts value
end
# => 42
p = 1
puts "Am i a string? #{p}" if p = "Im a confused string"
# => "Am i a string? Im a confused string"
发生了什么事?如果一开始不明显,那么第二段代码说明了如何插入“我是一个混乱的字符串”
。然而,在第三个示例中,仅仅声明p
(类型不可知)就会导致插入“我是一个混乱的字符串”
我认为这个问题不同于但类似于这些问题:
变量_
。。。到目前为止还没有遇到。。。是一个方法调用
推导的经验法则是
条件中的赋值总是在执行条件代码之前执行(当然,对于前导条件和尾随条件为true)
然而。。。在尾部条件中引用未定义的变量是有问题的,即使在条件中建立赋值变量也是如此
“预期”的代码是异常的:在正常行为中,尾随条件中的赋值和/或方法在条件代码之前执行,因此如果条件代码引用的变量的内容由条件代码修改,条件代码将使用修改后的变量。TLDR:不幸的是,您的示例有缺陷,因为您为变量选择的名称与core ruby中的现有方法冲突
正如@SteveTurczyn几分钟前提到的,如果变量在带有条件的行之前未知,则将其解释为方法调用 让我们探索一些机器代码,好吗?重要的行被注释
puts "Am i a string? #{myvar}" if myvar = "Im a confused string"
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, keyword: 0@3] s1)
[ 2] myvar
0000 trace 1 ( 2)
0002 putstring "Im a confused string"
0004 dup
0005 setlocal_OP__WC__0 2
0007 branchunless 22
0009 putself
0010 putobject "Am i a string? "
0012 putself
0013 opt_send_simple <callinfo!mid:myvar, argc:0, FCALL|VCALL|ARGS_SKIP> # call method myvar
0015 tostring
0016 concatstrings 2
0018 opt_send_simple <callinfo!mid:puts, argc:1, FCALL|ARGS_SKIP>
0020 leave
0021 pop
0022 putnil
0023 leave
但是
是在内核中定义的方法。下面是一个具有“未使用”名称和显式方法定义的示例:
def x
123
end
puts "x is a #{defined?(x)} with value #{x}" if x = 'foo'
#=> x is a method with value 123
这是由于Ruby的解析顺序。Ruby首先解析表达式,并将x
识别为一种方法。然后执行if
表达式,并分配一个局部变量x
。当评估放置
零件后,x
仍然引用该方法。(详情请参阅)
另一方面:
x = 123
puts "x is a #{defined?(x)} with value #{x}" if x = 'foo'
#=> x is a local-variable with value foo
这里,x
从一开始就是一个局部变量
请注意,局部变量x
在这两种情况下都存在:
def x
123
end
puts "#{send(:x)} #{binding.local_variable_get(:x)}" if x = 'foo'
#=> 123 foo
将变量从p
更改停止异常
塞尔吉奥·图兰采夫的回答是“正确的” 在使用p=
而不是p==
时,您将赋值给p
而不是检查相等性,这会将赋值返回到if
,并且该值对于字符串而言始终是真实的(或者除了false,nil
之外的任何内容。我刚开始键入。哈哈,是的,Ruby允许您使用方法成功作为条件。在这种情况下,方法是=
。您可以随时对变量调用.class来检查它是什么类型的类。@MichaelBerkowski调用了它……您使用的是=而不是==您的问题?好的-编辑这个问题的人完全改变了我所问问题的背景,让我看起来像个白痴。我很抱歉不清楚:我理解=vs==的用法。编辑这篇文章的人对\p=“我完全是一个字符串”发表了评论
在我提供的第二个代码块中。问题是,当预先声明p
时,如果p=“我是一个混乱的字符串”
更改,则相同行的结果将“我是一个字符串吗?{p}”放入。简单一点:声明变量p
(FixNum/string等)将更改放入的输出“我是一个字符串吗?{p}”如果p=“我是一个混乱的字符串”
你说的“正确”是什么意思,“正确”是100%正确:)啊。谢谢你的提醒。谢谢你展示了指令序列,太棒了。
def x
123
end
puts "x is a #{defined?(x)} with value #{x}" if x = 'foo'
#=> x is a method with value 123
x = 123
puts "x is a #{defined?(x)} with value #{x}" if x = 'foo'
#=> x is a local-variable with value foo
def x
123
end
puts "#{send(:x)} #{binding.local_variable_get(:x)}" if x = 'foo'
#=> 123 foo