Can We Pass Block from Function to Function?

Hi,

I have two functions that each takes a block:

def func1 (arg1, &arg2)
    ....
end

def func2 (arg1, &arg2)
    ....
    func1 (x, ???) ???
    ....
end

Can we pass the block from func2 to func1? If yes, how? (It seems there
is no way to convert back from a Proc object to a block.)

Regards,

Bill

Prefix the Proc with “&” to convert it back to a block:

def func2 (arg1, &proc)
func1 (x, &proc)
end

Cheers,
Nat.

···

On Fri, 2002-08-30 at 15:35, William Djaja Tjokroaminata wrote:

I have two functions that each takes a block:

def func1 (arg1, &arg2)
    ....
end

def func2 (arg1, &arg2)
    ....
    func1 (x, ???) ???
    ....
end

Can we pass the block from func2 to func1? If yes, how? (It seems there
is no way to convert back from a Proc object to a block.)


Dr. Nathaniel Pryce, Technical Director, B13media Ltd.
Studio 3a, 22-24 Highbury Grove, London N5 2EA, UK
http://www.b13media.com

[…]

 def func1 (arg1, &arg2)
     ....
 end

 def func2 (arg1, &arg2)
     func1(arg1, &arg2)
 end

Can we pass the block from func2 to func1? If yes, how? (It seems there
is no way to convert back from a Proc object to a block.)

Make it the last argument, and prefix it with “&” as above. Another
example (it has needless overhead in creating a Proc object only to
discard it, but illustrates the point):

10.times &proc{|x| p x}

Hope this helps.

		Reimer Behrends
···

William Djaja Tjokroaminata (billtj@y.glue.umd.edu) wrote:

Can we pass the block from func2 to func1? If yes, how? (It seems there
is no way to convert back from a Proc object to a block.)

this brings up some interesting notions, when i first read pickaxe, this
was the one thing i did not like about ruby. why are there three diffent
things for essentially the same construction: block, procs, and methods?
methods, i can see have a distinction in that they are tied on an
object, like an instance variable is, but still.

so then one is also left thinking, why not multiple blocks?

personally i wish { } brackets always represented a proc and that we
could pass them easily (and also not require a #call to execute them):

def ameth(proc1, proc2)
  proc1()
  proc2()
end

ameth({puts 'hello'},{puts 'world'})

> hello
    > world

then a proc…excuse me, a block, is just a Yeild-able proc. yes, that’s
it.

~transami

···

On Fri, 2002-08-30 at 08:35, William Djaja Tjokroaminata wrote:

Thanks a lot. It works! When I checked the methods of class Proc in the
"Programming Ruby" book, they cover only “new”, “[]”, “arity”, and
"call". Probably this use of “&” to convert back is described in the “The
Ruby Language” section.

Logically, does this “&” operator belong to the Proc class, the Object
class, or the Kernel module?

Regards,

Bill

···

============================================================================
Reimer Behrends behrends@cse.msu.edu wrote:

Can we pass the block from func2 to func1? If yes, how? (It seems there
is no way to convert back from a Proc object to a block.)

Make it the last argument, and prefix it with “&” as above. Another
example (it has needless overhead in creating a Proc object only to
discard it, but illustrates the point):

10.times &proc{|x| p x}

Hope this helps.

  	Reimer Behrends

The advantage of using a call method, rather than some special syntax,
is that it’s always possible to implement your own class that
understands call(…), and objects of that class are then
interchangeable with Procs, Methods and any other callable object.

On a related note, I wish that the Ruby interpreter performed automagic
optimisation on Procs/blocks, in the same way that it optimises integers
behind the scenes.

I’d like it if there was no visible difference between a proc and a
block. At the language level, you would only use proc objects, and
invoke them with the call method. Internally, the Ruby interpreter
would decide whether to use a block as an optimisation, or instantiate a
Proc object.

Cheers,
Nat.

···

On Fri, 2002-08-30 at 17:03, Tom Sawyer wrote:

personally i wish { } brackets always represented a proc and that we
could pass them easily (and also not require a #call to execute them):

def ameth(proc1, proc2)
proc1()
proc2()
end

ameth({puts ‘hello’},{puts ‘world’})

hello
world

then a proc…excuse me, a block, is just a Yeild-able proc. yes, that’s
it.


Dr. Nathaniel Pryce, Technical Director, B13media Ltd.
Studio 3a, 22-24 Highbury Grove, London N5 2EA, UK
http://www.b13media.com

[…]

Logically, does this “&” operator belong to the Proc class, the Object
class, or the Kernel module?

It is not a standard operator like “+” that is converted into a method
call (and thus can’t be redefined, either), so it isn’t listed as part
of the Proc class. “&” is essentially syntactic sugar to tell the
compiler to use the Proc object as a block, much like the “*” prefix is
used with arrays to handle a variable number of arguments.

		Reimer Behrends
···

William Djaja Tjokroaminata (billtj@y.glue.umd.edu) wrote:

Hi,

Thanks for your response. The reason I asked is because usually when I
know the class, I can write it in C as

rb_funcall (rb_cKlass, rb_intern ("the operator"), n, ...);

Can you help to write the statement

func1 (arg1, &arg2)

in C? I am still struggling on how to covert this Proc “&” operator to
C. (Well, everything else fails, there is always that
"rb_eval_string()" ultimate weapon :slight_smile: )

Regards,

Bill

···

==========================================================================
Reimer Behrends behrends@cse.msu.edu wrote:

William Djaja Tjokroaminata (billtj@y.glue.umd.edu) wrote:
[…]

Logically, does this “&” operator belong to the Proc class, the Object
class, or the Kernel module?

It is not a standard operator like “+” that is converted into a method
call (and thus can’t be redefined, either), so it isn’t listed as part
of the Proc class. “&” is essentially syntactic sugar to tell the
compiler to use the Proc object as a block, much like the “*” prefix is
used with arrays to handle a variable number of arguments.

  	Reimer Behrends

William Djaja Tjokroaminata wrote:

Can you help to write the statement

func1 (arg1, &arg2)

in C? I am still struggling on how to covert this Proc “&” operator to
C. (Well, everything else fails, there is always that
"rb_eval_string()" ultimate weapon :slight_smile: )

Maybe rb_iterate is what you’re looking for. From the Pickaxe:

VALUE rb_iterate(VALUE (*method)(), VALUE args, VALUE (*block)(),
VALUE arg2)

Invokes method with argument args and block block. A yield from
that method will invoke block with the argument given to yield, and
a second argument arg2.

So you would have to wrap your method, func1, and your proc, arg2,
inside two C functions, and pass pointers to them as method and block in
the prototype.

I wish there were an rb_iterate2 or something which accepted a symbol
and a proc as VALUEs, to save you from having to wrap them in functions.