Cond loop vs iterator and scope questions


#1

Hello, just 2 simple questions…

  1. Why is it that you cannot have an iterator nested inside a
    conditional loop? I’m sure there’s a good reason, but it escapes me.

  2. Is it possible in Ruby, from within a block, to modify variables
    that belong to the calling object? Something similar to Array#map! Or
    must this be done in C?

Thanks,
Todd


#2

On Nov 19, 2005, at 1:07 PM, Todd wrote:

Hello, just 2 simple questions…

  1. Why is it that you cannot have an iterator nested inside a
    conditional loop? I’m sure there’s a good reason, but it escapes me.

You can. Please show us the code and we’ll help you find the problem.

  1. Is it possible in Ruby, from within a block, to modify variables
    that belong to the calling object? Something similar to
    Array#map! Or
    must this be done in C?

Ruby’s blocks are closures and thus can modify local variables from
the binding of the caller. Here again if you show us the code, we
can probably help you find The Ruby Way of achieving your goal…

James Edward G. II


#3

On 19/11/05, Todd removed_email_address@domain.invalid wrote:

Hello, just 2 simple questions…

  1. Why is it that you cannot have an iterator nested inside a
    conditional loop? I’m sure there’s a good reason, but it escapes me.

As james said, you can.

  1. Is it possible in Ruby, from within a block, to modify variables
    that belong to the calling object? Something similar to Array#map! Or
    must this be done in C?

Array.map! could be implemented like this. (In reality its part of
Enumerable, but that does not matter here)

class Array
def map!(&block)
changed = false
self.each_with_index do | element, index |
self[index] = block[element]
changed ||= (self[index] == element)
end
if changed
self
else
nil
end
end
end

or even more concise

class Array
def map!(&block)
changed = nil
self.each_with_index do | element, index |
changed ||= ((self[index] = block[element]) == element)
end
self if changed
end
end

but the middle line would I would consider to be golfed too much and
badly readable, though I like the last line.

cheers,

Brian

Thanks,
Todd


http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/


#4

James Edward G. II wrote:

On Nov 19, 2005, at 1:07 PM, Todd wrote:

Hello, just 2 simple questions…

  1. Why is it that you cannot have an iterator nested inside a
    conditional loop? I’m sure there’s a good reason, but it escapes me.

You can. Please show us the code and we’ll help you find the problem.

irb(main):001:0> f=[1,2]
=> [1, 2]
irb(main):002:0> while 1 do
irb(main):003:1* f.each do |i|
irb(main):004:1* end
SyntaxError: compile error
(irb):004: syntax error
from (irb):004

It seems like irb is trying to close the while with that first end
instead of the f.each. Same thing happens with syntax coloring in vim.

Todd


#5

On Nov 19, 2005, at 3:22 PM, Todd wrote:

irb(main):001:0> f=[1,2]
=> [1, 2]
irb(main):002:0> while 1 do

There’s a syntax error in the above line. It’s just while … end,
not while do … end.

Hope that helps.

James Edward G. II


#6

Todd wrote:

irb(main):001:0> f=[1,2]
=> [1, 2]
irb(main):002:0> while 1 do

                       ^^ No "do" here.

irb(main):003:1* f.each do |i|
irb(main):004:1* end
SyntaxError: compile error
(irb):004: syntax error
from (irb):004

irb(main):001:0> f=[1,2]
=> [1, 2]
irb(main):002:0> while 1
irb(main):003:1> f.each do |i|
irb(main):004:2* end
irb(main):005:1> end
IRB::Abort: abort then interrupt!!
from /usr/local/lib/ruby/1.8/irb.rb:81:in irb_abort' from /usr/local/lib/ruby/1.8/irb.rb:241:insignal_handle’
from /usr/local/lib/ruby/1.8/irb.rb:66:in start' from /usr/local/lib/ruby/1.8/irb.rb:65:incall’
from (irb):2


#7

On Saturday 19 November 2005 22:22, Todd wrote:
[…]

irb(main):001:0> f=[1,2]
=> [1, 2]
irb(main):002:0> while 1 do
^^
remove this “do”

irb(main):003:1* f.each do |i|
irb(main):004:1* end
SyntaxError: compile error
^^^^^^^^^^^
(irb):004: syntax error
from (irb):004

It’s a syntax error, as correctly identified.
Syntax of “while” expression is:

while

end

Your example:

while 1
f.each do |i|
# do something with i and eventually break
end
end

or:

loop do
f.each do |i|
# do something with i and eventually break
end
end

HTH,
Stefan


#8

On Nov 19, 2005, at 3:47 PM, Todd wrote:

say add 1
a
end

foo { #some code here }

=> 2

Use block parameters for this:

def foo
a = 1
a = yield a
p a
end
=> nil

foo do |var| var + 1 end
2
=> nil

After looking at your code, I think I can accomplish this more
elegantly (by inheriting from Array).

It can be tricky, inheriting from Ruby’s core classes and thus is
probably better avoided. Favor composition over inheritance.

James Edward G. II


#9

James Edward G. II wrote:

yield

def foo
a = 1
a = yield a
p a
end
=> nil

foo do |var| var + 1 end
2
=> nil

This is in fact how I’m doing it now, but I guess I was trying to avoid
having to do:

a = yield a

since this will be a large iteration and I’m worried the GC won’t keep
up.

It can be tricky, inheriting from Ruby’s core classes and thus is
probably better avoided. Favor composition over inheritance.

Yeah, I suppose have some pondering to do.

James Edward G. II

Thanks again,
Todd


#10

Brian Schröder wrote:

that belong to the calling object? Something similar to Array#map! Or
self[index] = block[element]
or even more concise

but the middle line would I would consider to be golfed too much and
badly readable, though I like the last line.

cheers,

Brian

OK, maybe I’m going about it the wrong way. I specified it wrong in
the original post anyway. What I want to do is have the block be able
to modify the variables in the method that’s yielding to it.

Like:

def foo
a = 1
yield
#block does something with a, such that this a is now a new value,
say add 1
a
end

foo { #some code here }

=> 2

After looking at your code, I think I can accomplish this more
elegantly (by inheriting from Array). But out of curiosity, is it
possible to do the above?

Thanks,
Todd