Require!

#1

It (finally) clicked now, ‘require’ is just a method…

Boy do I feel stupid. :expressionless:

On another note, though, I also found out that calling amethod(*args)
works with anything with ‘each’ (any Enumerable?), which made me smile.
It
was the post about ranges that made me get that :slight_smile:

Thanks!

#2

Hi –

On Thu, 1 Dec 2005, Ross B. wrote:

It (finally) clicked now, ‘require’ is just a method…

Boy do I feel stupid. :expressionless:

Don’t. That’s a pretty traditional rite of passage :slight_smile:

On another note, though, I also found out that calling amethod(*args) works
with anything with ‘each’ (any Enumerable?), which made me smile. It was the
post about ranges that made me get that :slight_smile:

Interesting. The mind boggles at the side-effect and hard-to-find bug
possibilities :slight_smile: But it’s quite cool, and I’d never known of it
before.

class E
include Enumerable
def each
3.times {|i| puts “Hello!”; yield i }
end
end

def x(*args)
p *args
end

x(*E.new)

:slight_smile:

David

#3

Hi Ross, actually as Florian recently taught me, *obj works for any
object with #to_ary defined --if that is what you mean.

T.

#4

On Nov 30, 2005, at 11:32 PM, Trans wrote:

Hi Ross, actually as Florian recently taught me, *obj works for any
object with #to_ary defined --if that is what you mean.

Actually, I think the * operator looks for #to_a not #to_ary.

Gary W.

#5

On Thu, 01 Dec 2005 04:30:28 -0000, Trans removed_email_address@domain.invalid wrote:

Hi Ross, actually as Florian recently taught me, *obj works for any
object with #to_ary defined --if that is what you mean.

T.

:slight_smile: I see… I was pretty happy when I realised it did it at all, and of
course it makes complete sense with hindsight. Thanks for pointing the
way.

#6

On Thu, 01 Dec 2005 05:45:53 -0000, removed_email_address@domain.invalid wrote:

On Nov 30, 2005, at 11:32 PM, Trans wrote:

Hi Ross, actually as Florian recently taught me, *obj works for any
object with #to_ary defined --if that is what you mean.

Actually, I think the * operator looks for #to_a not #to_ary.

Gary W.

Some quick experiments just now suggest it looks first for to_ary, then
to_a. As I say, I was pretty pleased to find it did it at all so I
didn’t
carry on playing with it …

Cheers,

#7

Trans a écrit :

Hi Ross, actually as Florian recently taught me, *obj works for any
object with #to_ary defined --if that is what you mean.

T.

AFAIK may change in ruby2.


Lionel T.

Personal web site: http://users.skynet.be/lthiry/

#8

Actually * looks for a to_a.

Does calling amethod(*x) have the same meaning as calling
amethod(x.to_a)? If is it what is the benefit of using the (less
clear) first way?

Brian B.

#9

On Nov 30, 2005, at 7:52 PM, Ross B. wrote:

On another note, though, I also found out that calling amethod
(*args) works with anything with ‘each’ (any Enumerable?), which
made me smile. It was the post about ranges that made me get that :slight_smile:

Actually * looks for a to_a.

James Edward G. II

#10

Hi –

On Fri, 2 Dec 2005, Brian B. wrote:

Actually * looks for a to_a.

Does calling amethod(*x) have the same meaning as calling
amethod(x.to_a)? If is it what is the benefit of using the (less
clear) first way?

They’re not the same. * is actually a unary unnary operator:

def x(*args)
p args
end

a = [1,2,3]
x(a) # [[1,2,3,]]
x(*a) # [1,2,3]

David

#11

On Thu, 01 Dec 2005 13:40:51 -0000, James Edward G. II
removed_email_address@domain.invalid wrote:

:slight_smile: I was pretty surprised it worked for non-arrays to be honest, so I
didn’t dare imagine it might be even more flexible. Ruby just keeps on
getting better the more I get to know it - I’ve not been so pleasantly
surprised, so often, for a very long time…

Cheers,

#12

a = [1,2,3]
x(a) # [[1,2,3,]]
x(*a) # [1,2,3]

x(*a) # [1,2,3]
x(a.to_a) # also [1,2,3]

But when might the 1st way (using the unary operator) be preferred to
the more explicit 2nd way?

Brian B.

#13

On Thu, 01 Dec 2005 15:01:05 -0000, Brian B.
removed_email_address@domain.invalid wrote:

Actually * looks for a to_a.

Does calling amethod(*x) have the same meaning as calling
amethod(x.to_a)? If is it what is the benefit of using the (less
clear) first way?

Brian B.

It ‘unwraps’ a supplied [anything] to multiple declared arguments.
Imagine:

def amethod(one,two,three)
  puts one, two, three
end

If you call that with:

amethod((1..3).to_a)

you’ll get an error, because you only supplied one argument - the array.
If you specify the ‘*’, however:

amethod(*(1..3))

The range first gets converted to an array with to_a, and then that is
expanded into the method’s argument list.

You can double-check by specifying either 1…2 or 1…4, which gives an
ArgumentError.

#14

Hi –

On Fri, 2 Dec 2005, Brian B. wrote:

a = [1,2,3]
x(a) # [[1,2,3,]]
x(*a) # [1,2,3]

x(*a) # [1,2,3]
x(a.to_a) # also [1,2,3]

But when might the 1st way (using the unary operator) be preferred to
the more explicit 2nd way?

I did leave off the to_a, though array.to_a is a no-op so it shouldn’t
matter.

More to the point: what version of Ruby are you using? Here’s the
output with 1.8.3:

$ cat args2.rb
def x(*args)
p args
end

a = [1,2,3]
x(a.to_a)
x(*a)

$ ruby -v args2.rb
ruby 1.8.3 (2005-09-21) [powerpc-darwin8.3.0]
[[1, 2, 3]]
[1, 2, 3]

David

#15

But when might the 1st way (using the unary operator) be preferred to
the more explicit 2nd way?

Oops. Scratch that last question.

#16

More to the point: what version of Ruby are you using? Here’s the
output with 1.8.3:

I am an older version (1.8.2) but I am getting the same result as you.
I didn’t realize you’d intentionally omitted to noop to_a. That and
with Ross’s explanation, now I get it.

#17

James Edward G. II wrote:

On Nov 30, 2005, at 7:52 PM, Ross B. wrote:

On another note, though, I also found out that calling amethod (*args)
works with anything with ‘each’ (any Enumerable?), which made me
smile. It was the post about ranges that made me get that :slight_smile:

Actually * looks for a to_a.

I always thought it looked for to_ary… now someone says it looks
first for to_ary, then to_a.

And I had no idea that it would work with just #each defined.

“Curiouser and curiouser,” said Alice.

Hal

#18

On Dec 2, 2005, at 12:13 AM, Hal F. wrote:

And I had no idea that it would work with just #each defined.
It doesn’t:

class NoArr
def each
yield 1
yield 2
yield 3
end
undef to_a
end
=> nil

def multi( one, two, three )
p one
p two
p three
end
=> nil

multi( *NoArr.new )
NoMethodError: undefined method `to_a’ for #NoArr:0x30d980
from (irb):14

James Edward G. II

#19

On Fri, 02 Dec 2005 06:13:38 -0000, Hal F.
removed_email_address@domain.invalid
wrote:

And I had no idea that it would work with just #each defined.

When I kicked this thread off, I’d just done some quick tests that
suggested it worked like above, and on anything with each, and I guessed
that (since Enumerable defines to_a, and everything is in terms of each)
that it must work that way.
I’m still pretty sure it does to_ary followed by to_a, but as others
showed me, it doesn’t actually work with just ‘each’.

class Clazz
def each
yield 1
yield 2
yield 3
end
end

c = Clazz.new
c = [*c]
p c => [#Clazz:0xb7f7ccdc]

That’s I think coming from the default to_a, and with the 1.9 snapshot I
have it gives a TypeError (‘Cannot convert Clazz into Array’ - the
default
to_a is gone). It does seem to work on anything with each if you
include
Enumerable, but that’s because Enumerable defines everything (including
to_a) in terms of ‘each’. If you add ‘include Enumerable’ to the class
definition above, you get [1,2,3] as expected.