新手问题 [已经解决,但有点好奇 +@ 怎么出现的] 这两行代码有区别吗??

yfractal · 2013年08月09日 · 最后由 Guest 回复于 2013年08月23日 · 4112 次阅读

body = article.body + "\n" + merge_with_article.body body = article.body +"\n" + merge_with_article.body

报错是 然后跑 rspec 的测试。就出现这个问题。。。 NoMethodError: undefined method `+@' for "\n":String 就在第二行

编辑器是 sublime

上面的一行就没报错,难道是一个空格的问题???

下午写 rspec,结果写着写着就变成全红了,我还以为我干了什么坏事呢。。。最后解决的办法是 bundle update。。。但不知道为什么。。。

我觉得这个帖子应该丢到瞎扯淡那!!!

首先,谢谢各位!

看了大家的回复,发现其实是有区别的,开始我以为这是个意外什么的。。。 简单说下,article 是一个 Article 的实例(instance)。然后,body 就是一个 method

22 楼是这样解释的 第二行

body = merge_a.body +"\n" + merge_with_a.body 等于 body = merge_a.body(+"\n") + merge_with_a.body http://stackoverflow.com/questions/15864068/string-concatenation-in-rails-3

19 楼有重现。

26 楼的解释是这样的 “原问题就是因为 + 这个运算符在不同类型上面的定义不同。“

29 楼说 Ruby 又两个可重定义的左连接修饰符 -@ 和 +@ (一会去查查这个东东。。。)

似乎这样的问题,只要多个空格就能解决。我一直以为空格 + 只是为了书写的工整(原来我其实一直有顺手加空格,最近写什么的时候发现写空格特别不舒服,就变成了有时候加有时候不加)。

merge_a.body的值是什么类型的啊?

有区别么,看不出区别来,还是我老到眼花了。就一个空格的话语法上是没区别的。

#1 楼 @iBachue thanks string,后面的也是 string 第二行我甚至写成这种 merge_a.body.to_s,也不成!!!

#2 楼 @hisea 谢谢!但确实报错了。比较郁闷,这种问题最郁闷了。。。

#2 楼 @hisea 有区别,区别大了。Ruby 的语法可以很诡异的

上一种可以被认为是 (+ merge_a.body "\n") 下一种可以被认为是 (call merge_a.body (to-positive "\n"))

#5 楼 @bhuztez 你别逗我阿!到底是不是真的??? 你要不告诉我,我会失眠的阿。。。

#5 楼 @bhuztez

区别在哪啊?难道真眼花了

#6 楼 @yfractal 楼主自己跑个 irb 试试不就知道了?

irb(main):001:0> "abc" + "\n" + "def"
=> "abc\ndef"
irb(main):002:0> "abc" +"\n" + "def"
=> "abc\ndef"

#5 楼 @bhuztez 我一开始也这样认为 但后来测了一下没法重现。。所以我也不知道了

#4 楼 @yfractal 楼主 Ruby 版本多少 哪个实现的?

#7 楼 @hisea

你试的代码不对

irb(main):001:0> x + "\n"
NameError: undefined local variable or method `x' for main:Object
    from (irb):1
    from /usr/bin/irb:12:in `<main>'
irb(main):002:0> x +"\n"
NoMethodError: undefined method `+@' for "\n":String
    from (irb):2
    from /usr/bin/irb:12:in `<main>'

#8 楼 @iBachue 能重现啊,Ruby 1.9 就可以

#12 楼 @hisea 看清楚了抛的是两种不同的错

#11 楼 @bhuztez 好吧。。。当 x 未定义的时候。。。。大神能说下为什么嘛?

看来你们都不会 Ruby 啊

#15 楼 @iBachue 和 x 有没有定义没关系

#17 楼 @bhuztez 我测下来只有在 x 未定义的时候才能重现

#18 楼 @iBachue

和 x 被定义成什么都关系

irb(main):001:0> def x
irb(main):002:1>   1
irb(main):003:1> end
=> nil
irb(main):004:0> x +"\n"
NoMethodError: undefined method `+@' for "\n":String
    from (irb):4
    from /usr/bin/irb:12:in `<main>'

特别是 + 前面是 method 的情况,无论这个 method 是否有定义都可以重现。

irb(main):001:0> class X
irb(main):002:1> def y
irb(main):003:2> 1
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> x = X.new
=> #<X:0x000000021b3670>
irb(main):007:0> x.y +"\n"
NoMethodError: undefined method `+@' for "\n":String
    from (irb):7
    from /usr/bin/irb:12:in `<main>'

#5 楼 @bhuztez 似乎有一点明白了。。。

@yfractal

第二行

body = merge_a.body +"\n" +  merge_with_a.body

等于

body = merge_a.body(+"\n") +  merge_with_a.body
23 楼 已删除
24 楼 已删除

#19 楼 @bhuztez 好吧。。不过我还是没明白为什么会这样。。+号为何会优先和后面的字符串结合? 难道是因为方法或是未定义变量由于不能在语义检查时确定类型因此就和后面的字符串优先结合了?如果能够确定类型则优先和前面结合?

#19 楼 @bhuztez 我式的,是 string 的情况下,因为楼主第二楼提出前后都是 string.

另外,我想说的意思是 ruby 对空白总体来说是不敏感的,但是正如你说的,+号是特例,因为他也用来做 single arity 的 operator.

来证明我的意图

irb(main):001:0> "abc" * "abv"
TypeError: no implicit conversion of String into Integer
    from (irb):1:in `*'
    from (irb):1
    from /Users/yinghai.zhao/.rbenv/versions/2.0.0-p195/bin/irb:12:in `<main>'
irb(main):002:0> "abc" *"abv"
TypeError: no implicit conversion of String into Integer
    from (irb):2:in `*'
    from (irb):2
    from /Users/yinghai.zhao/.rbenv/versions/2.0.0-p195/bin/irb:12:in `<main>'

另一个东西是,Ruby 是一个动态类型,但是是强类型的语言。 原问题就是因为 + 这个运算符在不同类型上面的定义不同。

#25 楼 @iBachue 都是方法调用可以不用括号惹的祸。还不总是和后面的结合,取决于加号边上有没有空格,加号前面的是什么,这才是真坑爹的地方,就是因为类似这样的设定,连写个简单的 ruby parser 都很难啊。

#27 楼 @bhuztez 好吧 上次那个视频也讲过 Ruby 语法很复杂 像foo /bar/g这样的代码根本判断不出后面是两个除法符号还是一个正则表达式。。

Ruby 又两个可重定义的左连接修饰符 -@+@

#28 楼 @iBachue ruby 语法看来真不像想象的那么简单

用惯用法可以避免不必要的坑,比如字符串连接通常如下:

body = "#{article.body}\n#{merge_with_article.body}"
body =  "%s\n%s" % [article.body, merge_with_article.body]

真诡异。在使用操作符的时候要注意 Ruby 的空格,要在操作符两边对称。

#28 楼 @iBachue 你说的是我的视频里面讲的吧?

body =  article.body +"\n" +  merge_with_article.body 
#=> 如下
body =  article.body (+"\n" +  merge_with_article.body)
#和这个是一样的
puts +1 + 2

#27 楼 @bhuztez 不过使用者是可以自己选择用不用.. 是不是可以得出个结论 语言中括号的数量和 parse 难度成反比...lisp?

#34 楼 @iBachue 你是看的哪个视频?51cto 的?你说的例子和我讲的一样哎

#37 楼 @blackanger Elixir 的作者讲的那个视频

#36 楼 @jjym asm 也没很多括号。。。

#38 楼 @iBachue 噢。Jose 大牛的视频啊。

#39 楼 @iBachue 仅限高级语言..

如果是前缀表达式就...

「Ruby 又两个可重定义的左连接修饰符 -@ 和 +@ 」 数字类型的正负符号而已。 后面加字符串又没有空格隔开,自然报错,换成数字就没问题了(当然不满足需求了)。

44 楼 已删除
需要 登录 后方可回复, 如果你还没有账号请 注册新账号