精华帖 (0) :: 良好帖 (9) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-06-28
lllyq 写道 讨论研究是相互的,你是不是太自信了,事实上你的每一行代码我从一开始都试过了才回贴的,希望看到这里的朋友也试试看,LZ不愿意尝试也没问题,你们自己试试看是怎样,否则可能会被这个标题误导
另外关于define的问题还有另一个解释,一般我们都在方法体用,就不存在define的问题,因为如果未定义会自动使用local变量 老实说不是我不愿意尝试,而是我不知道如何根据你的说法来尝试. 其实对于这个问题我自己也是一肚子疑惑, 所以才会发文, 看看大家是否还有更好的解释? Quake Wang就纠正了我的结论. 但从你的回复中,我实在不知道如何去根据你的"说法"转换成展开式, 恕我愚钝, 请指点, 希望继续讨论 |
|
返回顶楼 | |
发表时间:2008-06-28
你可以试试看新开irb,执行
if a then a else a = 2 end 这个效果跟新开irb,执行 a || a = 2 效果是一样的,ruby 版本是1.8.6 非要用一个准确的展开式下面这个应该可以 if defined?(a) then (a || a = b) else a = nil end |
|
返回顶楼 | |
发表时间:2008-06-28
lllyq 写道 你可以试试看新开irb,执行
if a then a else a = 2 end 这个效果跟新开irb,执行 a || a = 2 效果是一样的,ruby 版本是1.8.6 非要用一个准确的展开式下面这个应该可以 if defined?(a) then (a || a = b) else a = nil end rubynroll的意思是 你新开irb 执行a ||= 2和 新开irb执行a || a = 2的结果是不一样的,所以这2个公式不是等价的 这样说来我前面的公式也不行... |
|
返回顶楼 | |
发表时间:2008-06-28
Quake Wang 写道 lllyq 写道 你可以试试看新开irb,执行
if a then a else a = 2 end 这个效果跟新开irb,执行 a || a = 2 效果是一样的,ruby 版本是1.8.6 非要用一个准确的展开式下面这个应该可以 if defined?(a) then (a || a = b) else a = nil end rubynroll的意思是 你新开irb 执行a ||= 2和 新开irb执行a || a = 2的结果是不一样的,所以这2个公式不是等价的 这样说来我前面的公式也不行... 这个我没有否定,我一开始只是说不用搞这么复杂去涉及define的问题,而且他的结论展开式为 if a then a else a = 2 end 是不对的,看我第一个回帖的分析,以及上一个回帖的说明 |
|
返回顶楼 | |
发表时间:2008-06-29
好,也用代码说事:
先执行一边楼主的代码 h = Hash.new(1) # 生成一个新的Hash,缺省值为1 => {} h[:x] => 1 # h[:x]未定义,所以返回1 h[:x] ||= 2 => 1 h => {} h[:x] || h[:x] = 2 => 1 h => {} #恩,还是{} 可见针对楼主hash的代码,david观点没错。 楼主应该知道,hash的[]是个方法,用个简单的类模拟一下 class A def [] defined?(@a) ? @a : 1 end def []=(a) @a = a end end 试一下: a = A.new a[] # => 1 undefined. a[] ||= 2 # => 1 undefined. a[] || a[] = 2 # => 1 还是一样的 #当然如果没有[]方法中 defined? 的保护,直接执行 a || a = 2 #肯定是要有错误的,因为a未定义 当然,我前面说的相当于 a = nil #定义 a || a = b 是不能满足上边A的例子的(同样对楼主hash的例子有问题),但是如果根据上边的理解,david说的 a ||= b 相当于 a || a = b没什么问题。 所以我说支持 lllyq 的观点,可能是 ||= 因为随后就是赋值操作,没有raise undefined错误?这可能真得看了源码才知道了。 |
|
返回顶楼 | |
发表时间:2008-06-29
rubynroll 写道 lllyq 写道 这个h[:x]行为有什么特别么?跟预期的行为一致啊
h[:x] ||= 2 并没有对h[:x]赋值,相当于h[:x] || h[:x] = 2,而h[:x] = nil是有一个赋值动作 我举的那个例子就是为了反驳 caryl 写道 同意楼上,感觉应该相当于 a = nil a || a = b caryl说的"楼上"就是 lllyq 写道 a || a = b 就是 a || a = b,本来就没考虑defined?的问题,跟 if a then a else a = b end 一样的,如果你执行下来不一样那估计是你连续执行的问题,前一句相当于做了define
另外, h[:x] ||= 2 相当于h[:x] || h[:x] = 2在这里之所以成立,是因为h这个Hash是已经定义过了. 对于一个通用的 a ||= b, 并不能简单地展开成 a || a = b, 因为这里的a如果未定义就会是个例外. 注意, 这里探讨的是"完全等同"的展开式, 因为如果存在特例, 除非语言规范明白地告诉你"这是个特例", 否则'陷阱'就有可能在那里等着你. |
|
返回顶楼 | |
发表时间:2008-06-30
lllyq 写道 你可以试试看新开irb,执行
if a then a else a = 2 end 这个效果跟新开irb,执行 a || a = 2 效果是一样的,ruby 版本是1.8.6 效果不一样, 至少在版本是1.8.6. 1.8.7上是不一样的, 后者会raise undefined error. lllyq 写道 非要用一个准确的展开式下面这个应该可以 if defined?(a) then (a || a = b) else a = nil end 这就是我所想要的讨论的,一个准确的展开式. 但是这个式子还是有问题, 应该是这样才对: if defined?(a) then (a || a = b) else a = b end 所以结论是不是这样: 1) a ||= b 不等效于: a = a || b 2) 在a已经定义过时, a ||= b等效于a || a = b 3) 在a未定义时, a ||= b等效于a = b 所以归纳起来,准确的展开式应该是: if defined?(a) then (a || a = b) else a = b end 意见?? |
|
返回顶楼 | |
发表时间:2008-06-30
rubynroll 写道 lllyq 写道 你可以试试看新开irb,执行
if a then a else a = 2 end 这个效果跟新开irb,执行 a || a = 2 效果是一样的,ruby 版本是1.8.6 效果不一样, 至少在版本是1.8.6. 1.8.7上是不一样的, 后者会raise undefined error. 根据你的回复我估计你还是没去试,显然,无论在1.8.6, 1.8.7,后者都会raise undefined error. 前者你试过了么?试过后你就知道为什么我会回第一个帖了\ 我说的更清楚一点就是你测试下来两者行为不一样,那是因为你的测试方法不对,你没有每次都新开irb来测试,所以测试方法不对你看到的结果就不对,得出的结论也就不对了 |
|
返回顶楼 | |
发表时间:2008-06-30
lllyq 写道 rubynroll 写道 lllyq 写道 你可以试试看新开irb,执行
if a then a else a = 2 end 这个效果跟新开irb,执行 a || a = 2 效果是一样的,ruby 版本是1.8.6 效果不一样, 至少在版本是1.8.6. 1.8.7上是不一样的, 后者会raise undefined error. 根据你的回复我估计你还是没去试,显然,无论在1.8.6, 1.8.7,后者都会raise undefined error. 前者你试过了么?试过后你就知道为什么我会回第一个帖了\ 我说的更清楚一点就是你测试下来两者行为不一样,那是因为你的测试方法不对,你没有每次都新开irb来测试,所以测试方法不对你看到的结果就不对,得出的结论也就不对了 哈哈我真是搞糊涂了,我试的是a ||= 2和a || a = 2, 比较的太多了,连自己都弄糊涂了, 看来此贴应该归新手贴才对:( 至于结论, 你认为 a ||= b最终展开为 if defined?(a) then (a || a = b) else a = b end 还有问题么? |
|
返回顶楼 | |
发表时间:2008-06-30
:) 没问题,或者
a = defined?(a) ? (a || a = b) : b |
|
返回顶楼 | |