That's Ruby, Virginia!

H

Henry Savr

Well, you wrote a great Array Analyzer
Here it is:

def array_101
for i in [0 ... self.length]
puts "#{i} => #{self}"
end
end

And prepared the following array for test:

a = ['a','s','d']

What do you think, it will print?

Yeeees, you are right.
And the answer is...

0...3 => asd

:)))))))))

try it at home:

irb(main):001:0> def array_101
irb(main):002:1> for i in [0 ... self.length]
irb(main):003:2> puts "#{i} => #{self}"
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> a = ['a','s','d']
=> ["a", "s", "d"]
irb(main):007:0> a.array_101
0...3 => asd
=> [0...3]
;-)
 
T

Tom Rauchenwald

Henry Savr said:
Well, you wrote a great Array Analyzer
Here it is:

def array_101
for i in [0 ... self.length]
puts "#{i} => #{self}"
end
end


for i in 0 ... self.length
does what you would expect. In your example you iterate over an array
with one element, and this element is a range. So the result isn't really
unexpected.

Tom
 
W

William James

Henry said:
Here it is:

def array_101
for i in [0 ... self.length]
puts "#{i} => #{self}"
end
end


class Array
def array_101
each_with_index{|e,i|
puts "#{i} => #{e}"
}
end
def array_102
puts (0...self.size).zip(self).map{|a| a.join(' => ')}
end
end
 
M

Max Muermann

Henry said:
Here it is:

def array_101
for i in [0 ... self.length]
puts "#{i} => #{self}"
end
end


class Array
def array_101
each_with_index{|e,i|
puts "#{i} => #{e}"
}
end
def array_102
puts (0...self.size).zip(self).map{|a| a.join(' => ')}
end
end


Much better this way.

To fix the original code, use (0..self.length) - note these are not
square brackets. Alternatively, you can use (0..10).to_a to turn a
range into an array.

Max
 
H

Hal Fulton

Henry said:
Well, you wrote a great Array Analyzer
Here it is:

def array_101
for i in [0 ... self.length]
puts "#{i} => #{self}"
end
end

And prepared the following array for test:

a = ['a','s','d']

What do you think, it will print?

Yeeees, you are right.
And the answer is...

0...3 => asd



:) Well, it did exactly what you said
it should do. It iterated over the
contents of the array [0...self.length]
(which has only one element, the range
0...self.length).


Cheers,
Hal
 
M

Morton Goldberg

Your code only works in irb. You get an error, as you should, if you
run it 'real' Ruby.
In irb 'array_101' gets added to Array. That's the only reason
'a.array_101' doesn't produce an error. In "real" Ruby, the following
produces your result, as it should.

<code>
#! /usr/bin/ruby -w

class Array
def array_101
for i in [0...length]
p self ### prints the array because i = 0...length, not 0.
puts "#{i} => #{self}"
end
end
end

a = %w[a s d]

a.array_101
</code>

<result>
["a", "s", "d"]
0...3 => asd
</result>

The only thing I don't understand is why 'array_101' gets added to
Array in irb.

Regards, Morton
 
R

Rick DeNatale

Your code only works in irb. You get an error, as you should, if you
run it 'real' Ruby.
In irb 'array_101' gets added to Array. That's the only reason
'a.array_101' doesn't produce an error. In "real" Ruby, the following
produces your result, as it should.

<code>
#! /usr/bin/ruby -w

class Array
def array_101
for i in [0...length]
p self ### prints the array because i = 0...length, not 0.
puts "#{i} => #{self}"
end
end
end

a = %w[a s d]

a.array_101
</code>

<result>
["a", "s", "d"]
0...3 => asd
</result>

The only thing I don't understand is why 'array_101' gets added to
Array in irb.


It doesn't it gets added to the Kernel module, just like in real Ruby.

The difference is that in irb, it's a public method and in real Ruby
it's private, I think that this came up in another context in the past
few days.

== file array_101.rb ==
def array_101
for i in [0..self.length]
puts "#{i} => #{self}"
end
end

a = ['a', 's', 'd']
p a
p a.array_101

class X
end

p X.new.array_101
=== end of file array101.rb===
$ ruby array101.rb
["a", "s", "d"]
array101.rb:9: private method `array_101' called for ["a", "s",
"d"]:Array (NoMethodError)

but change the file to wrap the method in the Kernel module
module Kernel
def array_101
...
end
end

$ ruby array101.rb
["a", "s", "d"]
0..3 => asd
[0..3]
array101.rb:3:in `array_101': undefined method `length' for
#<X:0xb7e1f7b4> (NoMethodError)
from array101.rb:16

Note that we are getting through a.array_101, but now we blow up on
X.new.array_101, but INSIDE the array_101 method, because since it's
in Kernel, and class Object includes Kernel, makes it available to ALL
objects.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

IPMS/USA Region 12 Coordinator
http://ipmsr12.denhaven2.com/

Visit the Project Mercury Wiki Site
http://www.mercuryspacecraft.com/
 
M

Morton Goldberg

Thanks. You've cleared up my confusion as to why array_101 accepts an
array as a receiver in irb. Since it gets added as public method of
Kernel, it appears as a public method of _every_ class in irb. I
think that's evil enough to be regarded as a bug.

Regards, Morton

Your code only works in irb. You get an error, as you should, if you
run it 'real' Ruby.
In irb 'array_101' gets added to Array. That's the only reason
'a.array_101' doesn't produce an error. In "real" Ruby, the following
produces your result, as it should.

<code>
#! /usr/bin/ruby -w

class Array
def array_101
for i in [0...length]
p self ### prints the array because i = 0...length,
not 0.
puts "#{i} => #{self}"
end
end
end

a = %w[a s d]

a.array_101
</code>

<result>
["a", "s", "d"]
0...3 => asd
</result>

The only thing I don't understand is why 'array_101' gets added to
Array in irb.


It doesn't it gets added to the Kernel module, just like in real Ruby.

The difference is that in irb, it's a public method and in real Ruby
it's private, I think that this came up in another context in the past
few days.

== file array_101.rb ==
def array_101
for i in [0..self.length]
puts "#{i} => #{self}"
end
end

a = ['a', 's', 'd']
p a
p a.array_101

class X
end

p X.new.array_101
=== end of file array101.rb===
$ ruby array101.rb
["a", "s", "d"]
array101.rb:9: private method `array_101' called for ["a", "s",
"d"]:Array (NoMethodError)

but change the file to wrap the method in the Kernel module
module Kernel
def array_101
...
end
end

$ ruby array101.rb
["a", "s", "d"]
0..3 => asd
[0..3]
array101.rb:3:in `array_101': undefined method `length' for
#<X:0xb7e1f7b4> (NoMethodError)
from array101.rb:16

Note that we are getting through a.array_101, but now we blow up on
X.new.array_101, but INSIDE the array_101 method, because since it's
in Kernel, and class Object includes Kernel, makes it available to ALL
objects.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

IPMS/USA Region 12 Coordinator
http://ipmsr12.denhaven2.com/

Visit the Project Mercury Wiki Site
http://www.mercuryspacecraft.com/
 
H

Henry Savr

Thank you, guys for trying to fix the code. Sure, I had 1001 way to fix
it and I did.
The reason for the post was to inform community about the case. For me
with a long dinosaur’s tail of various languages it is unexpectable yet,
however I could understand the logic behind it.

Is it a bug or feature, I do not know. At least it was something, people
should know ;-)

Thank you
Henry
 
H

Henry Savr

Well, that is a modification. No public\private\irb etc... :)))

=============Program ====================
#Version 2. For native Ruby
puts "Source is: #$0"
puts "File is: #{__FILE__}"

class Array
def array_101A
for i in [0 ... self.length]
puts "#{i} => #{self}"
end
end
end

a = ['a','s','d']
a.array_101A

=========== Results ======================
C:\Documents and Settings\Admin>ruby -w c:/PJ/play/test/lib/t3.rb
Source is: c:/PJ/play/test/lib/t3.rb
File is: c:/PJ/play/test/lib/t3.rb
0...3 => asd
 
M

Morton Goldberg

I don't want to rain on your parade, especially because I can't
figure out why you're having a parade. I could understand a newbie
being puzzled about this code (because he wrote [0 ... length] where
he should used 0 ... length) and posting it so someone could explain
why it works the way it does, but you say that's not your situation.
Could you be more explicit about what amuses, delights, intrigues, or
otherwise motivates you to bring this to our attention?

Regards, Morton
 
M

Max Muermann

Thank you, guys for trying to fix the code. Sure, I had 1001 way to fix
it and I did.
The reason for the post was to inform community about the case. For me
with a long dinosaur's tail of various languages it is unexpectable yet,
however I could understand the logic behind it.

Is it a bug or feature, I do not know. At least it was something, people
should know ;-)

It was a bug in your code. You used [0..value] when you should have
used (0..value).

Cheers,
Max
 
H

Henry Savr

Max said:
Thank you, guys for trying to fix the code. Sure, I had 1001 way to fix
it and I did.
The reason for the post was to inform community about the case. For me
with a long dinosaur's tail of various languages it is unexpectable yet,
however I could understand the logic behind it.

Is it a bug or feature, I do not know. At least it was something, people
should know ;-)

It was a bug in your code. You used [0..value] when you should have
used (0..value).

Cheers,
Max
Why,
The Programming Ruby suggests using *for* for Array. Unfortunately I
don't have the book with me. I will tell you the page. And it is logical
to use it for array.
Cheers,
Henry
 
H

Henry Savr

Morton said:
I don't want to rain on your parade, especially because I can't
figure out why you're having a parade. I could understand a newbie
being puzzled about this code (because he wrote [0 ... length] where
he should used 0 ... length) and posting it so someone could explain
why it works the way it does, but you say that's not your situation.
Could you be more explicit about what amuses, delights, intrigues, or
otherwise motivates you to bring this to our attention?

Regards, Morton

Well,
I bring it to your attention because:
It mentioned in Programming Ruby, that *for* works with array. They gave
the example of song array. All languages, which I am familiar with work
the same way. They
- take an item from Array,
- execute the block,
- and then take another item

So as [0 ... len] is a new Array, I expected the same behaviour.
But it was not so obvious. It took the whole array and executes the
statement ones. I would expect this behaviour if the code were

for i = [0 ... len]

So, my question was to persons, who realy UNDERSTAND Ruby internal
logic, what was it, a bug or undocumented (or may be documented, but I
just missed it) feature?

Regards,
Henry
 
L

Logan Capaldo

Morton said:
I don't want to rain on your parade, especially because I can't
figure out why you're having a parade. I could understand a newbie
being puzzled about this code (because he wrote [0 ... length] where
he should used 0 ... length) and posting it so someone could explain
why it works the way it does, but you say that's not your situation.
Could you be more explicit about what amuses, delights, intrigues, or
otherwise motivates you to bring this to our attention?

Regards, Morton

Well,
I bring it to your attention because:
It mentioned in Programming Ruby, that *for* works with array. They
gave
the example of song array. All languages, which I am familiar with
work
the same way. They
- take an item from Array,
- execute the block,
- and then take another item

So as [0 ... len] is a new Array,

It's a new array of size 1 though.

0...len is a _single_ object
what you wrote was
x = 0...len

for i in [x]

Ruby is not perl, ... does not construct lists.
I expected the same behaviour.
But it was not so obvious. It took the whole array and executes the
statement ones. I would expect this behaviour if the code were

for i = [0 ... len]

So, my question was to persons, who realy UNDERSTAND Ruby internal
logic, what was it, a bug or undocumented (or may be documented, but I
just missed it) feature?

It's neither a bug or a feature. You just didn't grasp the syntax.
 
R

Rimantas Liubertas

So as [0 ... len] is a new Array, I expected the same behaviour.
But it was not so obvious. It took the whole array and executes the
statement ones.

[0...len] is Array. Which holds only one Range object:
a = [1...5] => [1...5]
a.class => Array
a.length => 1
a[0].class
=> Range


Regards,
Rimantas
 
H

Henry Savr

Logan said:
0...len is a _single_ object
what you wrote was
x = 0...len

for i in [x]

Ruby is not perl, ... does not construct lists.


Thank you very much, Logan Capaldo.

That was the open eyes explanation, I wanted to get.
The case is closed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,211
Messages
2,571,092
Members
47,693
Latest member
david4523

Latest Threads

Top