[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Assigning a block to a variable in Ruby

ajmayo

12/15/2005 4:56:00 PM

I am new to Ruby and curious as to how you emulate the following
Javascript snippet
(example in Windows, hence the call to Echo)

var a = function(p) {WScript.Echo(p)}

bar(a);

function bar(z)
{
z(1);
WScript.Echo(z);
}

which would of course create an anonymous function, assign it to
variable a, pass this as a parameter to function bar() and then
evaluate the function with parameter 1, then attempt to print the
function itself (which Javascript will do, printing the text of the
block)

I found Ruby quite intuitive until I tried

a = {some block}

and found that this of course doesn't work as in this context {} refers
to a hash.

Ok, that's fine, but the 'yield' statement seems very funky and Perlish
to me. Effectively a block passed to a routine exists as a 'hidden'
argument so that

foo(100) {someblock}

in Ruby passes one parameter explicitly (as we would see from foo's
defined argument list) and a 'hidden' block which 'yield' inside the
body of foo() would evaluate.

(though, oddly, yield {someblock} is also not valid Ruby).

This seems horribly inelegant for a language touted as being The Next
Great Thing.

It is also unclear, how, then, I pass down a block as an argument and
then in turn pass it again to a child routine.

I can see how a parameter to a block works - this is clearly borrowed
from Smalltalk - but Javascript doesn't enforce separation of dynamic
code in the way Ruby appears to.

At present Javascript's syntax looks much cleaner. Am I missing
something?

Also, I presume Ruby is a forward-referencing language only, unlike
Javascript, where I can declare a function after code which calls it.
Ruby didn't seem to like that much.

25 Answers

Pete

12/15/2005 5:04:00 PM

0

Maybe you are looking for something like that?

> p = lambda {|num| puts num }

> p.call(123)
123




> --- Ursprüngliche Nachricht ---
> Von: ajmayo@my-deja.com
> An: ruby-talk@ruby-lang.org (ruby-talk ML)
> Betreff: Assigning a block to a variable in Ruby
> Datum: Fri, 16 Dec 2005 01:57:41 +0900
>
> I am new to Ruby and curious as to how you emulate the following
> Javascript snippet
> (example in Windows, hence the call to Echo)
>
> var a = function(p) {WScript.Echo(p)}
>
> bar(a);
>
> function bar(z)
> {
> z(1);
> WScript.Echo(z);
> }
>
> which would of course create an anonymous function, assign it to
> variable a, pass this as a parameter to function bar() and then
> evaluate the function with parameter 1, then attempt to print the
> function itself (which Javascript will do, printing the text of the
> block)
>
> I found Ruby quite intuitive until I tried
>
> a = {some block}
>
> and found that this of course doesn't work as in this context {} refers
> to a hash.
>
> Ok, that's fine, but the 'yield' statement seems very funky and Perlish
> to me. Effectively a block passed to a routine exists as a 'hidden'
> argument so that
>
> foo(100) {someblock}
>
> in Ruby passes one parameter explicitly (as we would see from foo's
> defined argument list) and a 'hidden' block which 'yield' inside the
> body of foo() would evaluate.
>
> (though, oddly, yield {someblock} is also not valid Ruby).
>
> This seems horribly inelegant for a language touted as being The Next
> Great Thing.
>
> It is also unclear, how, then, I pass down a block as an argument and
> then in turn pass it again to a child routine.
>
> I can see how a parameter to a block works - this is clearly borrowed
> >from Smalltalk - but Javascript doesn't enforce separation of dynamic
> code in the way Ruby appears to.
>
> At present Javascript's syntax looks much cleaner. Am I missing
> something?
>
> Also, I presume Ruby is a forward-referencing language only, unlike
> Javascript, where I can declare a function after code which calls it.
> Ruby didn't seem to like that much.
>
>


C Erler

12/15/2005 5:06:00 PM

0

On 15/12/05, ajmayo@my-deja.com <ajmayo@my-deja.com> wrote:
> I am new to Ruby and curious as to how you emulate the following
> Javascript snippet
> (example in Windows, hence the call to Echo)
>
> var a = function(p) {WScript.Echo(p)}
>
> bar(a);
>
> function bar(z)
> {
> z(1);
> WScript.Echo(z);
> }
>
> which would of course create an anonymous function, assign it to
> variable a, pass this as a parameter to function bar() and then
> evaluate the function with parameter 1, then attempt to print the
> function itself (which Javascript will do, printing the text of the
> block)
>
> I found Ruby quite intuitive until I tried
>
> a = {some block}
>
> and found that this of course doesn't work as in this context {} refers
> to a hash.
>
> Ok, that's fine, but the 'yield' statement seems very funky and Perlish
> to me. Effectively a block passed to a routine exists as a 'hidden'
> argument so that
>
> foo(100) {someblock}
>
> in Ruby passes one parameter explicitly (as we would see from foo's
> defined argument list) and a 'hidden' block which 'yield' inside the
> body of foo() would evaluate.
>
> (though, oddly, yield {someblock} is also not valid Ruby).
>
> This seems horribly inelegant for a language touted as being The Next
> Great Thing.
>
> It is also unclear, how, then, I pass down a block as an argument and
> then in turn pass it again to a child routine.
>
> I can see how a parameter to a block works - this is clearly borrowed
> from Smalltalk - but Javascript doesn't enforce separation of dynamic
> code in the way Ruby appears to.
>
> At present Javascript's syntax looks much cleaner. Am I missing
> something?
>
> Also, I presume Ruby is a forward-referencing language only, unlike
> Javascript, where I can declare a function after code which calls it.
> Ruby didn't seem to like that much.
>
>
>

Blocks that are objects are called procs, in Ruby (class Proc). To
make one the way you want to, you simply put proc in front of it :

my_block = proc { |vars| stuff_to_do }

To use proc variables as blocks for methods, put &my_block, which lets
Ruby know your proc isn't a normal parameter, it's the block :

array.each &my_block


C Erler

12/15/2005 5:17:00 PM

0

On 15/12/05, ajmayo@my-deja.com <ajmayo@my-deja.com> wrote:
> Also, I presume Ruby is a forward-referencing language only, unlike
> Javascript, where I can declare a function after code which calls it.
> Ruby didn't seem to like that much.

Ruby will usually wait until code is actually run to check if
something is defined. So, if Ruby says that something doesn't exist
in your code, the code is being run right then (like when you do stuff
inside class x ... end, all of it is run right away). So, you can do
things like have two classes that each make an object of the other
class, all without needing things like prototypes in C :

class A
def make_it
@b = B.new
end
end

class B
def make_it
@a = A.new
end
end

This is because those class names are just global variables
(technically, constants that can be changed) that have a classes
assigned to them. Thus, you can do weird things like assign classes
to variables :

a = Hash
h = a.new

This allows you to do things like pass classes into methods so that
those methods can do whatever they want with the classes.

Hope this helps.


C Erler

12/15/2005 5:26:00 PM

0

Sorry, missed this part :

On 15/12/05, ajmayo@my-deja.com <ajmayo@my-deja.com> wrote:
> It is also unclear, how, then, I pass down a block as an argument and
> then in turn pass it again to a child routine.

There are two ways to do this: the block variable way and the normal
parameter way.

If you want to pass it as a block (it has to be the last parameter) :

def method other_parameters, &the_block
use_the_block_as_a_regular_parameter_for_this_method(the_block)
use_the_block_as_a_block_for_this_method(&the_block)
end

method param { |vars| block }

If you want to pass it as a normal parameter (it doesn't have to be
the last parameter) :

def method other_parameters, the_parameter
use_the_block_as_a_regular_parameter_for_this_method(the_parameter)
use_the_block_as_a_block_for_this_method(&the_parameter)
end

my_proc = proc { |vars| block }
method param, my_proc

So, basically, & is the thing that makes a parameter the block (when
you're defining the method and when you're calling it).


Logan Capaldo

12/15/2005 5:33:00 PM

0


On Dec 15, 2005, at 11:57 AM, ajmayo@my-deja.com wrote:

> Also, I presume Ruby is a forward-referencing language only, unlike
> Javascript, where I can declare a function after code which calls it.
> Ruby didn't seem to like that much.

How did you run into problems with this?

irb(main):024:0> def a(x)
irb(main):025:1> g(x)
irb(main):026:1> end
=> nil
irb(main):027:0> def g(x)
irb(main):028:1> puts x
irb(main):029:1> end
=> nil
irb(main):030:0> a(5)
5
=> nil

As regards your other question

def bar(z)
puts z
end

a = lambda { |x| puts x }

bar(a)



Alternatively to pass a block to a function without yield...

def bar(&block)
block.call
end

bar { puts "hi!" } #=> prints hi

ajmayo

12/15/2005 5:38:00 PM

0

Amazing!. Couldn't be more than 10 mins since I posted and 3 replies!.

Thanks very much....

In that time, before I saw these posts, I came up with the following

def foo(p)
p.call(100)
end

a = Proc.new {|b| puts b}
foo(a)

but now I see that presumably proc (in lowercase) is presumably a
static class method and will work equally well.

i.e as you say

a = proc {|b| puts b}

Oddly, there is an inconsistency here

q = String("abc")

q = String.new("abc")

are both legal but

q = string("abc")

is not, which you would extrapolate by extension from the Proc/proc
analogy. (because

a=Proc {....}

is not legal.

In fact, perusing the documentation, I can't see how I would have
figured out the alternative mechanism using proc in lowercase - where
is this documented?

why I am keen to understand this is because languages like Perl are
infuriating because things like filehandles have special 'magic'
properties which get lost if you, for example, try to store them in a
hash, etc. This sort of thing destroys the illusion of completeness
that a truly great scripting language must provide, IMHO.

I see some hints of LISP here, too, with lambda!. A wonderful brew of
language features!

ajmayo

12/15/2005 5:44:00 PM

0

WRT forward references. My code was just

foo(100)

def foo(p)
puts p
end


this will not work unless the call to foo is placed after the function
definition.

Whereas in Javascript that would compile.

I can see that functions can forward reference, so I guess the logical
reason for this is, as you say, that Ruby wants to be able to resolve
as it executes, therefore

p = proc {foo(100)}

def foo(p)
puts p
end

p.call


will also compile, although foo() is a forward reference, because we
don't attempt to execute the call to foo until after Ruby has parsed
the function

Martin DeMello

12/15/2005 5:45:00 PM

0

ajmayo@my-deja.com wrote:
> evaluate the function with parameter 1, then attempt to print the
> function itself (which Javascript will do, printing the text of the
> block)

Ruby does not do this.

martin

Pete

12/15/2005 5:55:00 PM

0

> Whereas in Javascript that would compile.

there is no such thing as compilation in javascript or ruby...

wikipedia:
A compiler is a computer program that translates a series of statements
written in one computer language (called the source code) into a resulting
output in another computer language (often called the object or target
language).

> --- Ursprüngliche Nachricht ---
> Von: ajmayo@my-deja.com
> An: ruby-talk@ruby-lang.org (ruby-talk ML)
> Betreff: Re: Assigning a block to a variable in Ruby
> Datum: Fri, 16 Dec 2005 02:47:39 +0900
>
> WRT forward references. My code was just
>
> foo(100)
>
> def foo(p)
> puts p
> end
>
>
> this will not work unless the call to foo is placed after the function
> definition.
>
> Whereas in Javascript that would compile.
>
> I can see that functions can forward reference, so I guess the logical
> reason for this is, as you say, that Ruby wants to be able to resolve
> as it executes, therefore
>
> p = proc {foo(100)}
>
> def foo(p)
> puts p
> end
>
> p.call
>
>
> will also compile, although foo() is a forward reference, because we
> don't attempt to execute the call to foo until after Ruby has parsed
> the function
>
>


Esteban Manchado Velázquez

12/15/2005 6:01:00 PM

0

Hi,

On Fri, Dec 16, 2005 at 01:57:41AM +0900, ajmayo@my-deja.com wrote:
> I am new to Ruby and curious as to how you emulate the following
> Javascript snippet
> (example in Windows, hence the call to Echo)
>
> var a = function(p) {WScript.Echo(p)}
>
> bar(a);
>
> function bar(z)
> {
> z(1);
> WScript.Echo(z);
> }
>
> which would of course create an anonymous function, assign it to
> variable a, pass this as a parameter to function bar() and then
> evaluate the function with parameter 1, then attempt to print the
> function itself (which Javascript will do, printing the text of the
> block)
>
> I found Ruby quite intuitive until I tried
>
> a = {some block}
>
> and found that this of course doesn't work as in this context {} refers
> to a hash.

You can use:

a = lambda {some block}

> Ok, that's fine, but the 'yield' statement seems very funky and Perlish
> to me.

Sorry, I don't see the connection :-?

> Effectively a block passed to a routine exists as a 'hidden'
> argument so that
>
> foo(100) {someblock}
>
> in Ruby passes one parameter explicitly (as we would see from foo's
> defined argument list) and a 'hidden' block which 'yield' inside the
> body of foo() would evaluate.
>
> (though, oddly, yield {someblock} is also not valid Ruby).

yield is to _call_ a given block. You do things like:

def foo(bar)
yield "foo, #{bar}!"
end

foo("world") do |i|
puts i
end

> This seems horribly inelegant for a language touted as being The Next
> Great Thing.
>
> It is also unclear, how, then, I pass down a block as an argument and
> then in turn pass it again to a child routine.

Easy:

def some_method
yield "some value"
end

def foo(bar, &blk)
some_method(&blk)
end

foo(1) do |i|
puts i
end

I.e. every time you put an ampersand before a parameter when defining some
method, you get the block as a Proc object. Every time you put an ampersand
before a parameter when calling some method, the Proc object is received
as a regular block by the callee.

Take a look at the first edition of Pickaxe. It's publicly available at
http://www.ruby-doc.org/docs/Progra....

> I can see how a parameter to a block works - this is clearly borrowed
> from Smalltalk - but Javascript doesn't enforce separation of dynamic
> code in the way Ruby appears to.
>
> At present Javascript's syntax looks much cleaner. Am I missing
> something?

Hope the above clears up some confusion.

> Also, I presume Ruby is a forward-referencing language only, unlike
> Javascript, where I can declare a function after code which calls it.
> Ruby didn't seem to like that much.

So, why not just use Javascript? :-)

--
Esteban Manchado Velázquez <zoso@foton.es> - http://ww...
EuropeSwPatentFree - http://EuropeSwPatentFree.his...