difficulty with blocks

J

Johannes Ahl-mann

i am still in my early stages of ruby, so please forgive me any
blatantly lacking insight ;-))

i wonder how to divide responsibilities of block-driven methods in ruby.
in python i can divide the responsibilities of creating data and
filtering it using generators and the functional itertools. although
this is a lot of lately tacked on functionality i am struggling to
implement something similar in ruby.

--- python code (untested code, but should run ;-) ---

def fib:
a, b = 1, 1
while true:
yield a
a, b = b, a+b

import itertools
def fibUpTo(n):
return itertools.takeWhile(lambda i: i < n, fib())

--- a unified solution in ruby: ---

def fibUpTo n, &block
a, b = 1, 1
while a < n
block.call(a)
a, b = b, a+b
end
end

--- snip ---

i would really like to separate the creation of the fibonacci series
from the filtering. this should be possible in ruby, i just can't see it
right now ;-))
is maybe building a generator with the generator module an option?a

thx,
Johannes
 
J

Johannes Ahl-mann

hi,

sorry for answering my own post, but i am adopting ruby at an incredible
rate. i know python quite well and it took me literally mere minutes to
get the BASIC hang of blocks... i've been programming in ruby for 3
hours now and it already feels like home! not much cosier than python,
but the block closures and the possibility of continuations drags me
into ruby nonetheless ;-)

well, i've got a rather satisfactory solution to my problem and would now like
to ask whether my implementation can be considered "the ruby way" or if it
feels rather strange to the senior rubiists (i.e. people who have
programmed in ruby for more than 3 hours) *ggg*


### snip ###


def fib_block &block
a, b = 1, 1
while true:
block.call(a)
a, b = b, a+b
end
end

require 'generator'
def fibUpTo n, &block
fibs = Generator.new do |g|
fib_block {|val| g.yield val}
end

while (f = fibs.next()) < n
block.call(f)
end
end

def into(anArray)
return proc {|val| anArray << val}
end
fibUpTo 20, &into(a = [])
puts a


### snip ###

thx and forgive me for answering my own questions. i really shouldn't do
that ;-))

Johannes

P.S.: what is it with the implicit blocks in ruby. i am aware that many
people seem not to be explicitely passing the block into a function, but
i really find that distracting and too much of a perl idiom. is my way
alright, or was it unidiomatic??

P.P.S: is there a better way to write "fib_block {|val| g.yield val}"?
maybe something like "fib_block.apply(g.yield)" or so. i guess not, but
the repetition bothers me!
 
S

Stefan Lang

Johannes said:
hi,

sorry for answering my own post, but i am adopting ruby at an incredible
rate. i know python quite well and it took me literally mere minutes to
get the BASIC hang of blocks... i've been programming in ruby for 3
hours now and it already feels like home! not much cosier than python,
but the block closures and the possibility of continuations drags me
into ruby nonetheless ;-)

well, i've got a rather satisfactory solution to my problem and would now
like to ask whether my implementation can be considered "the ruby way" or
if it feels rather strange to the senior rubiists (i.e. people who have
programmed in ruby for more than 3 hours) *ggg*


### snip ###


def fib_block &block
a, b = 1, 1
while true:
block.call(a)
a, b = b, a+b
end
end

require 'generator'
def fibUpTo n, &block
fibs = Generator.new do |g|
fib_block {|val| g.yield val}
end

while (f = fibs.next()) < n
block.call(f)
end
end

def into(anArray)
return proc {|val| anArray << val}
end
fibUpTo 20, &into(a = [])
puts a

A shorter version without the generator library would be:
##################################################
#!/usr/bin/ruby

def fib
a, b = 1, 1
loop {
yield a
a, b = b, a + b
}
end

def fibUpTo n
fib { |val|
break if val > n
yield val
}
end

a = []
fibUpTo(20) { |val| a << val }
puts a
##################################################
 
J

Johannes Ahl-mann

A shorter version without the generator library would be:
##################################################
#!/usr/bin/ruby

def fib
a, b = 1, 1
loop {
yield a
a, b = b, a + b
}
end

def fibUpTo n
fib { |val|
break if val > n
yield val
}
end

a = []
fibUpTo(20) { |val| a << val }
puts a
##################################################

thx, this helped a lot. i wasn't aware that one could use "break" inside
a block... this looks very readable and natural.

Johannes
 

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
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top