How to call an object instance's method?

Dear Ruby Experts,

I’m somewhat new to Ruby and have got a problem which seems quite strange
to me. I intend to use a class as container for an array of instances of
an other class.

class A
def funA ()
puts "I’m alive!"
end
end

class B
def initialize ()
@aList = Array.new
end
def funB ()
# this code follows below
end
end

One time, my program creates an instance of B and calls funB:

b = B.new
b.funB

funB fills the list ‘aList’ with some instances of A:

def funB ()
# append a new element to the list
if @aList.empty?
# in fact, i check if array size is big enough and
# do the append if it doesn’t
@aList = @aList + Array.new(1, A)
end
# now we should have at least one instance of A in @aList, eh?
# let’s call the instance method
@aList[0].funA # this is line 20!
end
end

And I expected this to work properly and waited for the “I’m alive”. But
it doesn’t. I get this error:

test.rb:20:in funB': undefined methodfunA’ for A:Class (NameError)
from /home/pooh/bin/test.rb:33

and don’t know what it is intended to tell me.

I tried to find out more about @aList and its type and replaced line 20
with several checks:

 puts @aList.type » Array

I understand, so far.

 puts (@aList).type » A

This is confusing. Why the difference? Did I miss some special meaning of
"()"?

 puts "#{(@aList).type}" » Array

Should produce the same as above, but produces what I expected first. Hum?
But things are getting even more strange:

 puts @aList.at(0).type » Class
 puts @aList[0].type » Class

Wtf…? The Ruby book says “arr.at( anInteger ) -> anObject or nil” so I
expected to get “A” as type and not “Class”.

You might understand, I’m somewhat confused. The last statement at least
showed me the meaning of the top error message, because obviously
@aList[0] returns a “Class” not an object instance.

But what shall I do to get my method called?

Yours,
Rene

···


Dipl.-Inform. René Tschirley http://www.cs.tu-berlin.de/~pooh
TU Berlin, Computer Graphics and Computer Assisted Medicine research group

“Rene Tschirley” pooh@cs.tu-berlin.de schrieb im Newsbeitrag
news:b88tvk$1jg$1@news.cs.tu-berlin.de
Dear Ruby Experts,

I’m somewhat new to Ruby and have got a problem which seems quite strange
to me. I intend to use a class as container for an array of instances of
an other class.

class A
def funA ()
puts "I’m alive!"
end
end

class B
def initialize ()
@aList = Array.new
end
def funB ()
# this code follows below
end
end

One time, my program creates an instance of B and calls funB:

b = B.new
b.funB

funB fills the list ‘aList’ with some instances of A:

def funB ()
# append a new element to the list
if @aList.empty?
# in fact, i check if array size is big enough and
# do the append if it doesn’t
@aList = @aList + Array.new(1, A)
end
# now we should have at least one instance of A in @aList, eh?
# let’s call the instance method
@aList[0].funA # this is line 20!
end
end

The error is in this line:

@aList = @aList + Array.new(1, A)

You add an array containing the class instance of A not an instance of

A. Better do

@aList = @aList + Array.new(1, A.new)

Even better:

@aList << A.new

or

@aList.push A.new

And I expected this to work properly and waited for the “I’m alive”. But
it doesn’t. I get this error:

test.rb:20:in funB': undefined methodfunA’ for A:Class (NameError)
from /home/pooh/bin/test.rb:33

and don’t know what it is intended to tell me.

I tried to find out more about @aList and its type and replaced line 20
with several checks:

 puts @aList.type » Array

I understand, so far.

 puts (@aList).type » A

This is confusing. Why the difference? Did I miss some special meaning of
"()"?

Yes, the brackets in the line above are parsed as function invocation

brackets of “puts”:

 (puts (@aList)).type

 puts "#{(@aList).type}" » Array

Should produce the same as above, but produces what I expected first. Hum?
But things are getting even more strange:

 puts @aList.at(0).type » Class
 puts @aList[0].type » Class

Wtf…? The Ruby book says “arr.at( anInteger ) -> anObject or nil” so I
expected to get “A” as type and not “Class”.

You put A into the array not an instance of A so A's type is Class.

    robert

b.funB

funB fills the list ‘aList’ with some instances of A:

if @aList.empty?
# in fact, i check if array size is big enough and
# do the append if it doesn’t
@aList = @aList + Array.new(1, A)
end

That’s not what you’ve done; you have filled aList with the class A. Try
instead:

    @aList = @aList + [A.new]

or more Rubyesque,

    @aList << A.new

and everything is fine.

Useful debugging tip: try using ‘p’ in your code. e.g.

    @aList << A.new
    p @aList

This is more or less the same as puts @aList.inspect

With your version the output would be
[A] <<<<< element is the class A

with the modified version you will get something like:
[#<A:0x810d258>] <<<<< an instance of A

puts @aList.type ? Array

I understand, so far.

puts (@aList).type ? A

This is confusing. Why the difference? Did I miss some special meaning of
“()”?

Yes… it’s the “poetry mode” ambiguity, and a bit nasty. Basically if you
put an open bracket after a method call, it thinks you are bracketing the
method parameters, and the rest of the expression is outside. So what you
have there is:

 ( puts (@aList) ).type

i.e. you are printing the array @aList itself, not its type. The return
value of puts is ‘nil’, and you are then getting the type of it (which is
NilClass), and then throwing that information away.

Use the -w flag to Ruby:

#!/usr/local/bin/ruby -w

or

ruby -w <scriptname>

and a lot of this sort of bug will become apparent much more easily.

I think Matz has hinted in the past that perhaps -w should be mandatory, and
you would have a different flag to turn it off. I think I agree :slight_smile:

Regards,

Brian.

···

On Fri, Apr 25, 2003 at 12:10:15AM +0900, Rene Tschirley wrote:

Robert Klemme wrote:

@aList = @aList + Array.new(1, A)

You add an array containing the class instance of A not an instance of

A.

Oh, shit. I knew, it would be something really stupid. :slight_smile:

@aList << A.new

Ok, that will be my favorite.

Yes, the brackets in the line above are parsed as function invocation

brackets of “puts”:

Hmm, the book told me to understand that ruby’s association somewhat
difficult and to use parentheses if needed. Should better give examples
and explain the parsing. On the other hand, it looks quite similar to
functional programming. sigh

Thanks, you’re great!

Bye,
Rene

···


Dipl.-Inform. René Tschirley http://www.cs.tu-berlin.de/~pooh
TU Berlin, Computer Graphics and Computer Assisted Medicine research group

Brian Candler wrote:

That’s not what you’ve done; you have filled aList with the class A.

Now, as I think about that, that opens a new dimension of what’s possible
with ruby. Well, I think, I start to like it :slight_smile:

Useful debugging tip: try using ‘p’ in your code. e.g.

That’s fine, thanks!

BTW: which kind of language reference do you use? I found out that the
Ruby book is not that good for quick references as well as for tips and
tricks. Found many tutorials on the web. Any favourite references?

Yes… it’s the “poetry mode” ambiguity, and a bit nasty.

I’d wonder if that ain’t an FAQ :slight_smile:

Yours,
Rene

···


Dipl.-Inform. René Tschirley http://www.cs.tu-berlin.de/~pooh
TU Berlin, Computer Graphics and Computer Assisted Medicine research group

Hi –

Robert Klemme wrote:
Hmm, the book told me to understand that ruby’s association somewhat
difficult and to use parentheses if needed. Should better give examples
and explain the parsing. On the other hand, it looks quite similar to
functional programming. sigh

Well, the language has changed in this area, and the book (assuming
you mean the Pickaxe book) is still in its first edition. Be
patient :slight_smile:

Here’s an illustration of recent changes, as I understand them… In
1.6.8, the whitespace between the method call and the arglist was
ignored, but warned about:

candle:~$ ruby -vwe ‘puts(3).class’
ruby 1.6.8 (2002-12-24) [i686-linux]
3
candle:~$ ruby -vwe ‘puts (3).class’
ruby 1.6.8 (2002-12-24) [i686-linux]
-e:1: warning: puts (…) interpreted as method call
3

but in 1.8.0, the whitespace is taken to mean that you want the
parenthetical expression to associate to the right:

candle:~$ ruby/1.8.0/bin/ruby -vwe ‘puts(3).class’
ruby 1.8.0 (2003-03-03) [i686-linux]
3
candle:~$ ruby/1.8.0/bin/ruby -vwe ‘puts (3).class’
ruby 1.8.0 (2003-03-03) [i686-linux]
-e:1: warning: (…) interpreted as grouped expression
Fixnum

David

···

On Fri, 25 Apr 2003, Rene Tschirley wrote:


David Alan Black
home: dblack@superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

I found the Pickaxe the only book I needed. However the web version is not
particularly useful as a reference, because of the lack of a comprehensive
index and cross-referencing (although it’s OK if you download a local copy
and use grep, or go straight to the file you need since they all have
sensible names, e.g. ref_c_array.html or ref_m_enumerable.html)

A paper copy makes a fine reference.

Regards,

Brian.

···

On Fri, Apr 25, 2003 at 04:32:51AM +0900, Rene Tschirley wrote:

BTW: which kind of language reference do you use? I found out that the
Ruby book is not that good for quick references as well as for tips and
tricks. Found many tutorials on the web. Any favourite references?

Thanks for that explanation. FWIW I think it’s really a bad idea for
whitespace to play a significant role like that, and I hope that this
decision is reconsidered before 1.8 is released.

I think expressions should parse one way regardless of white space, and if
you want the other way then you do so by adding printing characters:

puts(3).class  =>  (puts(3)).class    # the default
               or  puts((3).class)    # the other way

In particular, many people are going to write
puts( 3 )
or
puts (3)
purely as stylistic variations, and I think it’s a bad idea that you can get
different syntax trees being generated! (Warning or no warning)

Regards,

Brian.

···

On Fri, Apr 25, 2003 at 01:07:33AM +0900, dblack@superlink.net wrote:

Here’s an illustration of recent changes, as I understand them… In
1.6.8, the whitespace between the method call and the arglist was
ignored, but warned about:

candle:~$ ruby -vwe ‘puts(3).class’
ruby 1.6.8 (2002-12-24) [i686-linux]
3
candle:~$ ruby -vwe ‘puts (3).class’
ruby 1.6.8 (2002-12-24) [i686-linux]
-e:1: warning: puts (…) interpreted as method call
3

but in 1.8.0, the whitespace is taken to mean that you want the
parenthetical expression to associate to the right:

candle:~$ ruby/1.8.0/bin/ruby -vwe ‘puts(3).class’
ruby 1.8.0 (2003-03-03) [i686-linux]
3
candle:~$ ruby/1.8.0/bin/ruby -vwe ‘puts (3).class’
ruby 1.8.0 (2003-03-03) [i686-linux]
-e:1: warning: (…) interpreted as grouped expression
Fixnum

Thanks for that explanation. FWIW I think it’s really a bad idea
for
whitespace to play a significant role like that, and I hope that
this
decision is reconsidered before 1.8 is released.

I agree, and not just because I highly respect Mr. Candler’s
contributions to the group.

···

Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo

Hi,

In particular, many people are going to write
puts( 3 )
or
puts (3)
purely as stylistic variations

Don’t. And if you don’t, you will be happy.

Thanks for that explanation. FWIW I think it’s really a bad idea for
whitespace to play a significant role like that, and I hope that this
decision is reconsidered before 1.8 is released.

It’s bad for who don’t care white spaces. Care what you write.
“puts( 3 )” and “puts (3)” are not same.

“puts (a+b).abs” as “(puts(a+b)).abs” really made me mad.

						matz.
···

In message “Re: How to call an object instance’s method?” on 03/04/25, Brian Candler B.Candler@pobox.com writes:

“puts (a+b).abs” as “(puts(a+b)).abs” really made me mad.

···

----- Original Message -----
From: “Yukihiro Matsumoto” matz@ruby-lang.org
To: “ruby-talk ML” ruby-talk@ruby-lang.org


Yes, but was this true with other methods?

‘one:two:three’.split (’:’).each {|x| puts x}

It seems to me that we expect different precedence from ‘puts’, for some
reason.

(That code does look a little funny, though. Of course, I like to put
spaces before the `.’ when I’m chaining method calls, but that’s just me…)

In any case, since this is the Way It Is now, it seems that our
documentation should probably change to reflect this, especially our
introductory materials. We may not tend to think of whitespace as syntax,
but it was (to a small degree) before, and is even moreso now. Someone
coming from C is bound to be surprised by this; it even keeps biting more
experience Rubyists.

<sleepy_ramble>
It seems that most of the issues around whitespace involve trying to
determine the beginnings and ends of parameter/argument lists. On the other
hand:

class Foo end

Without a newline in there, this generates a SyntaxError; newline (or a
semicolon) is part of the syntax. Why is this? I thought Ruby had no
statements, only expressions. Well, they are some of the statementiest
expressions I’ve ever seen. Why can’t I do this?

foo.something( with, lots, of, long, arguments… )
.whatever( with, even, more, long, arguments… )

Because whitespace is syntax. (Yes, I know about `’ at the end of the
line.)
</sleepy_ramble>

Chris

Yes, that I can sympathise with. It upsets poetry mode if the first
character after a method call is an opening parenthesis, but you were only
using it to group terms in one method argument.

I think we have a new gotcha, which replaces an old one. The old gotcha:

puts (a+b).abs => both treated
puts(a+b).abs / as (puts(a+b)).abs !!

The new gotcha:

sin(a) + b => (sin(a)) + b
sin (a) + b => treated as sin( a+b ) !!

puts(a+b).abs => still treated as (puts(a+b).abs) !!

The new gotcha might catch you out less often, but I think only if you’re
aware of it already, and you are careful with the space bar. Deep down
something tells me “the first case is more consistent! It’s less
surprising!”

I think the fundamental problem is that parentheses are being used for two
different functions:

  1. as an optional grouping of arguments to a method
  2. to group terms within an expression, e.g. to override operator precedence

IIUC, the old rule was that an opening parenthesis was always taken as case
(1). Now it’s case (1) if there is no space, or case (2) if there is a
space.

I expect it would be too radical to suggest that a different symbol be used
for case (1), grouping arguments - e.g. sin |a| + b

Thinking aloud here. Consider methods which take only one parameter:

foo x
foo (x)
foo(x)

These can all be treated the same; it doesn’t matter in this case whether
the parentheses are part of the expression, or the argument list.

Now, introduce another term, how is it grouped?

foo x + y # method foo, argument x + y
foo(x) + y # method foo, argument x

That’s fine, but alternatively we could consider the second case as

foo((x) + y) # method foo, argument (x) + y

The first case is probably what you expect for
sin(a)+b
the second case is what you expect for
puts (3).class

You could make the second case the default, but that would annoy
mathematicians, who would have to start writing their code like this:

(sin a) + b # instead of sin(a) + b

Let’s assume we are happy to annoy mathematicians for the moment. For a
single argument, we could say “parentheses are always part of an expression”
(case 2 above), and resolve

foo (x) + y

as
foo( (x)+y )

Now, suppose foo takes two arguments? What to do with

foo(x,z) + y

We could always outlaw that in favour of

(foo x,z) + y

but if the parser were clever enough to note that a comma cannot be used
within an expression, it could realise that

foo (x,z) + y

must really mean

(foo (x),(z)) + y

In fact with a comma I think there is no ambiguity:

puts (“hello”,“world”).class

can only be interpreted in one possible way. So maybe we should insist that
all methods take at least two arguments :-))

Hmm, don’t think I’m really getting anywhere here - except I think I
understand a bit better where the problem arises.

I can probably talk myself into the current solution. Poetry mode generally
requires a space between the method and its argument, simply to separate
the tokens, as in

puts x.class

So you can argue that “puts (x).class” is poetry in the same way, whereas
“puts(x).class” has an argument list (x) for puts. It still doesn’t sit
comfortably with me though.

Cheers,

Brian.

···

On Fri, Apr 25, 2003 at 03:44:31AM +0900, Yukihiro Matsumoto wrote:

It’s bad for who don’t care white spaces. Care what you write.
“puts( 3 )” and “puts (3)” are not same.

“puts (a+b).abs” as “(puts(a+b)).abs” really made me mad.

Hi,

“puts (a+b).abs” as “(puts(a+b)).abs” really made me mad.

Yes, but was this true with other methods?

‘one:two:three’.split (‘:’).each {|x| puts x}

True for my eyes. Perhaps my eys are influenced too much by Ruby.

It seems to me that we expect different precedence from ‘puts’, for some
reason.

I don’t see any good reason to put space before parentheses here. But
I met “puts (a+b).abs” case in real programming.

In any case, since this is the Way It Is now, it seems that our
documentation should probably change to reflect this, especially our
introductory materials. We may not tend to think of whitespace as syntax,
but it was (to a small degree) before, and is even moreso now. Someone
coming from C is bound to be surprised by this; it even keeps biting more

Yep. I (or we) need to prepare definitive document maybe via Wiki,
just like we’ve done in Japanese.

						matz.
···

In message “Re: How to call an object instance’s method?” on 03/04/25, “Chris Pine” nemo@hellotree.com writes:

Chris Pine wrote:

Yes, but was this true with other methods?

‘one:two:three’.split (‘:’).each {|x| puts x}

But then again there’s

irb(main):007:0> -100.div(2+4).abs
=> 17
irb(main):008:0> -100.div (2+4).abs
=> -17

Here the Ruby whitespace rules align with (at least some definition) of
natural precedence: the whitepace before the (2.4).abs chunks it off
into the parameter to #div.

So, if we have to have significant whitespace, then I think the rules as
they stand now are a good compromise.

However… I’m not at all convinced that whitespace should be
significant. Personally, I’d go with /\s*(/ == /method(/ and
drop the cleverness: there is a lot of scope for confusion otherwise.

Cheers

Dave

Hi,

···

At Fri, 25 Apr 2003 05:44:26 +0900, Brian Candler wrote:

I expect it would be too radical to suggest that a different symbol be used
for case (1), grouping arguments - e.g. sin |a| + b

You can use begin…end instead, always no ambiguities :).

sin begin a end + b


Nobu Nakada

But then again there’s

irb(main):007:0> -100.div(2+4).abs
=> 17
irb(main):008:0> -100.div (2+4).abs
=> -17
···

----- Original Message -----
From: “Dave Thomas” dave@pragprog.com


Yuck!! This is what’s wrong with significant whitespace. We are never
going to hear the end of the complaints from new users, and maybe not from
the rest of us, either.

I also wonder if people are going to think of this as "whitespace as syntax"
or if they will think of it as “Ruby forces me to code in this certain
style”.

I would personally prefer the end of poetry mode (which I do enjoy) to this.


So, if we have to have significant whitespace, then I think the rules as
they stand now are a good compromise.

However… I’m not at all convinced that whitespace should be
significant. Personally, I’d go with /\s*(/ == /method(/ and
drop the cleverness: there is a lot of scope for confusion otherwise.

Newlines have always been significant whitespace… did you mean them, too?
(I don’t like any significant whitespace except as token separators.)

Yes, many of us agree; but there’s no getting over the fact that this really
bugs matz:

puts (a+b).abs
(puts(a+b)).abs

Chris

Hmm, that’s new to me… but I don’t think that’s argument grouping, as it
doesn’t work for methods which take multiple parameters:

puts begin “hello”,“world” end #>> syntax error

So it must be for expression grouping. In that case we could give
parentheses to the mathematicians for argument lists:
sin(a) + b

and use begin/end everywhere else:

 puts begin "hello"+"world" end . size

 puts begin a+b end . abs

Not pretty :slight_smile:

Cheers,

Brian.

···

On Fri, Apr 25, 2003 at 09:54:19AM +0900, nobu.nokada@softhome.net wrote:

Hi,

At Fri, 25 Apr 2003 05:44:26 +0900, > Brian Candler wrote:

I expect it would be too radical to suggest that a different symbol be used
for case (1), grouping arguments - e.g. sin |a| + b

You can use begin…end instead, always no ambiguities :).

sin begin a end + b

“Dave Thomas” dave@pragprog.com schrieb im Newsbeitrag
news:3EA84176.9000904@pragprog.com

However… I’m not at all convinced that whitespace should be
significant. Personally, I’d go with /\s*(/ == /method(/ and
drop the cleverness: there is a lot of scope for confusion otherwise.

I’d blow into the same horn. Bugs stemming from wrongly used white space
are hard to find and it is quite uncommon for programming languages to
attach such significance to white space.

Regards

robert

Yuck!! This is what’s wrong with significant whitespace. We are
never
going to hear the end of the complaints from new users, and maybe
not from
the rest of us, either.

I also wonder if people are going to think of this as “whitespace
as syntax”
or if they will think of it as “Ruby forces me to code in this
certain
style”.

Uh-oh… isn’t this what…Python does? Ick. I agree that this
doesn’t seem to be the right road to take.

Yes, many of us agree; but there’s no getting over the fact that
this really
bugs matz:

puts (a+b).abs
(puts(a+b)).abs

what about that bugs him? I’m not sure I understand; are the 2 lines
equivalent, and that is bad?)

···

Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo

I think it’s that it doesn’t Do The Right Thing[TM], i.e. in this case you
might expect

 puts (a+b).abs

to do

 puts ((a+b).abs)

and in 1.8.0p2, it does - but only if you remember the space after ‘puts’

The more I think about this, the more I think that either:

  • the 1.6.8 behaviour is better, or
  • make poetry mode compulsory: that is, disallow parentheses around
    argument lists altogether, to eliminate the ambiguity.

The latter would make the language less C-like, and would force you to write

(sin a) + b

instead of

sin(a) + b

What do people think of that??

Regards,

Brian.

···

On Fri, Apr 25, 2003 at 09:54:16PM +0900, Michael Campbell wrote:

Yes, many of us agree; but there’s no getting over the fact that
this really
bugs matz:

puts (a+b).abs
(puts(a+b)).abs

what about that bugs him? I’m not sure I understand; are the 2 lines
equivalent, and that is bad?)