Extrage behaviour when concatenating a string pointed from a constant and a string (with no space af

Large subject.

Could you tell me why the NoMethodError is happening? I’m using Ruby
2.1.2
in Ubuntu 14.04.

Thanks in advance!

2.1.2 :020 > A = ‘A’
=> “A”
2.1.2 :021 > B = ‘B’
=> “B”
2.1.2 :022 > ‘A’ + ‘B’
=> “AB”
2.1.2 :023 > ‘A’ +‘B’
=> “AB”
2.1.2 :024 > A + B
=> “AB”
2.1.2 :025 > A +B
NoMethodError: undefined method +@' for "B":String from (irb):25 from /home/juanjo/.rvm/rubies/ruby-2.1.2/bin/irb:11:in
2.1.2 :026 > A +‘B’
NoMethodError: undefined method +@' for "B":String from (irb):26 from /home/juanjo/.rvm/rubies/ruby-2.1.2/bin/irb:11:in
2.1.2 :027 > ‘A’ +B
=> “AB”
2.1.2 :028 > a = ‘a’
=> “a”
2.1.2 :029 > a +‘B’
=> “aB”

Greets!

On Jul 19, 2014, at 17:02, Juanjo C. [email protected] wrote:

2.1.2 :025 > A +B
NoMethodError: undefined method +@' for "B":String from (irb):25 from /home/juanjo/.rvm/rubies/ruby-2.1.2/bin/irb:11:in

RubyParser.new.parse “A + B”
=> s(:call, s(:const, :A), :+, s(:const, :B))

RubyParser.new.parse “A +B”
=> s(:call, nil, :A, s(:call, s(:const, :B), :+@))

So it is seeing “A(+B)” where “+” is a unary method, much like “-”.

Same as if you typed N +4, it’d see N(+4), call unary + on 4, then
pass that as an arg to N.

Right, thanks. But why that is not happening with a +“B”?

2014-07-19 22:45 GMT-03:00 Ryan D. [email protected]:

On Jul 19, 2014, at 18:50, Juanjo C. [email protected] wrote:

Right, thanks. But why that is not happening with a +“B”?

Because you’ve already taught the interpreter that ‘a’ is a local
variable, so it knows it isn’t a(+"B"), but a + "B":

pp RubyParser.new.parse “a = ‘a’; a +B”
s(:block,
s(:lasgn, :a, s(:str, “a”)),
s(:call, s(:lvar, :a), :+, s(:const, :B)))

I got it!

A can’t be a method, because it’s upcase!

2014-07-19 23:10 GMT-03:00 Ryan D. [email protected]:

Dear Juanjo C.,

def UPCASEMETHODISNOTAPROBLEM(arg)
puts arg
end

UPCASEMETHODISNOTAPROBLEM “although not recommended”

Abinoam Jr.

You’re right.

2014-07-20 23:46 GMT-03:00 Abinoam Jr. [email protected]:

On 21 July 2014 12:09, Juanjo C. [email protected] wrote:

​​
I got it!

A can’t be a method, because it’s upcase!

​Note quite​, upcase methods are allowed; see:
Module: Kernel (Ruby 2.1.2) Try
running: Integer -4.2

​Consider this code:

a + 1
# we've never seen 'a =' before, so we assume it's a function​
# first call a(), then on the resulting object call .+(1)
# same as: a().+(1)

a +1
# <word> <space> <plus> <any> = function call
# same as: a(1.+@())

C + 1
# C starts with a capital, so we assume it's a const
# same as: C.+(1)

C +1
# <word> <space> <plus> <any> = function call
# same as: C(1.+@())

b = 2
b + 1
# we *have* seen 'b =' before, so we know it's an lvar
# same as: b.+(1)

b +1
# <lvar> <space> <plus> <any> = *not* function call
# same as "b + 1": b.+(1)

​You could do a similar​ thing with @x, @@y, or $z. Those are
unambiguously
variable names, so they’d never be interpreted as a function.

Have a think about what’s going on here, if it helps:

irb(main):001:0> def a(*args) p [:a, *args]; end
irb(main):002:0> def b(*args) p [:b, *args]; end
irb(main):003:0> def C(*args) p [:C, *args]; end
irb(main):004:0> b = 1
irb(main):005:0> C = 99
irb(main):006:0> a +1
[:a, 1]
=> [:a, 1] # a(1.+@())
irb(main):007:0> b +1
=> 2 # b.+(1)
irb(main):008:0> C +1
[:C, 1]
=> [:C, 1] # C(1.+@)
irb(main):009:0> a + 1
[:a]
TypeError: no implicit conversion of Fixnum into Array
from (irb):9:in +' from (irb):9 from /usr/local/bin/irb-trunk:11:in

a().+(1)

irb(main):010:0> b + 1
=> 2 # b.+(1)
irb(main):011:0> C + 1
=> 100 # C.+(1)

Ok… can I say that a method in upercase with no arguements can’t be
called?

2.1.2 :010 > def Aja(*args)
2.1.2 :011?> puts ‘aja’
2.1.2 :012?> end
=> :Aja
2.1.2 :013 > Aja
NameError: uninitialized constant Aja
from (irb):13
from /home/juanjo/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `’
2.1.2 :014 > Aja 1
aja
=> nil

2014-07-20 23:46 GMT-03:00 Abinoam Jr. [email protected]:

On 21 July 2014 13:20, Juanjo C. [email protected] wrote:

from /home/juanjo/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'

2.1.2 :014 > Aja 1
aja
=> nil

​You can add parentheses:

irb(main):001:0> def Aja *args
irb(main):002:1> puts ‘aja’
irb(main):003:1> end
=> :Aja
irb(main):004:0> Aja()
aja
=> nil

But generally speaking, yes, you need the arguments list to tell the
parser
that it’s a function call.

This email is really clear. Thanks!

2014-07-20 23:56 GMT-03:00 Matthew K. [email protected]: