What are the differences between Ruby's blocks and Python's lambdas?

As was mentioned, Ruby has lambdas, but they are commonly called “procs”.
This rhymes with “blocks” for a reason.

A block is really just syntax sugar for defining a proc and passing it into
a function. Ruby allows for one block to be passed in to each method
(though you can, of course, pass as many procs as you want in the parameter
list). It’s a convenience, nothing more.

So, my answer is that there is no difference but syntax between Ruby
lambdas and blocks. Knowing no Python, I can only assume there’s no
significant difference there.

Chris

For the record:

There’s one thing Ruby’s closures do and Python’s cannot, as described in
[ruby-talk:67618]. Doesn’t seem to make a difference in praxis and there
is a workaround to solve that, though.

···

On Thu, Mar 27, 2003 at 12:50:04AM +0900, Chris Pine wrote:

As was mentioned, Ruby has lambdas, but they are commonly called “procs”.
This rhymes with “blocks” for a reason.

A block is really just syntax sugar for defining a proc and passing it into
a function. Ruby allows for one block to be passed in to each method
(though you can, of course, pass as many procs as you want in the parameter
list). It’s a convenience, nothing more.

So, my answer is that there is no difference but syntax between Ruby
lambdas and blocks. Knowing no Python, I can only assume there’s no
significant difference there.


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

BTW: I have a better name for the software … Microsoft Internet
Exploder.
– George Bonser grep@cris.com

This isn’t entirely true. I can write the following ruby code:

make_counter = proc { |start|
proc { |inc| start += inc }
}

counter = make_counter[0]
p counter[3] # ==> 3
p counter[2] # ==> 5

and the following Python code would be equivalent:

def make_counter(start):
l = lambda inc, v=vars(): (
v.update({‘start’ : v[‘start’] + inc}), v[‘start’])[1]
return l

counter = make_counter(0)
print counter(3)
print counter(2)

I really don’t know Python very well, so there’s probably a much better
way to write this. The idea, though is that all local vars are stored
in a dict; that dict is accessible using the vars() function. I can
store that dict for use later (and thus retain access to all the local
variables, as in a real closure) by using default arguments to the lambda.

Note that I used v.update() instead of v= because in Python, a=b is a
statement, and lambdas in Python only work with expressions. Ruby
doesn’t make a significant distinction between expressions and
statements, so there is a big difference between what is allowed in a
lambda in Python and what is allowed in a lambda in Ruby.

Another big difference is that lambdas in Python can take only one
expression. To get around that limitation, I had to use a tuple (I
found this trick on http://p-nand-q.com/lambda.htm). Ruby’s lambdas
allow multiple expressions to be chained together with carriage returns
or semicolons, and thus do not have this problem.

In Python’s defense, Python lambdas are callable the same way that
functions are called. Ruby requires special syntax (either f or
f.call()) to call a lambda. This is only a minor nuisance in practice,
since it’s always possible to create a Method object that is callable
the same way that a lambda is called.

Paul

···

On Thu, Mar 27, 2003 at 01:01:25AM +0900, Mauricio Fernández wrote:

For the record:

There’s one thing Ruby’s closures do and Python’s cannot, as described in
[ruby-talk:67618]. Doesn’t seem to make a difference in praxis and there
is a workaround to solve that, though.

For the record:

There’s one thing Ruby’s closures do and Python’s cannot, as described in
[ruby-talk:67618]. Doesn’t seem to make a difference in praxis and there
is a workaround to solve that, though.

This isn’t entirely true. I can write the following ruby code:

Don’t know Python, was just copying something I thought was agreed on :slight_smile:

make_counter = proc { |start|
proc { |inc| start += inc }
}

counter = make_counter[0]
p counter[3] # ==> 3
p counter[2] # ==> 5

and the following Python code would be equivalent:

def make_counter(start):
l = lambda inc, v=vars(): (
v.update({‘start’ : v[‘start’] + inc}), v[‘start’])[1]
return l

counter = make_counter(0)
print counter(3)
print counter(2)

I really don’t know Python very well, so there’s probably a much better
way to write this. The idea, though is that all local vars are stored
in a dict; that dict is accessible using the vars() function. I can
store that dict for use later (and thus retain access to all the local
variables, as in a real closure) by using default arguments to the lambda.

Do you know if any optimization is done on access to outer scope
locals? That looks nice but apparently slow (construction of a dict,
copying table of locals…)

In Python’s defense, Python lambdas are callable the same way that
functions are called. Ruby requires special syntax (either f or
f.call()) to call a lambda. This is only a minor nuisance in practice,
since it’s always possible to create a Method object that is callable
the same way that a lambda is called.

I don’t understand what you mean by the last sentence

batsman@tux-chan:~$ ruby -e “p Method.instance_methods.sort”
[“”, “arity”, “call”, “clone”, “inspect”, “to_proc”, “to_s”, “unbind”]

how do I call a Method object the same way as a lambda?

···

On Thu, Mar 27, 2003 at 02:20:48AM +0900, Paul Brannan wrote:

On Thu, Mar 27, 2003 at 01:01:25AM +0900, Mauricio Fernández wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

<|ryan|> I don’t use deb
u poor man
netgod: heh
apt-get install task-p0rn

Do you know if any optimization is done on access to outer scope
locals? That looks nice but apparently slow (construction of a dict,
copying table of locals…)

I don’t know for sure, but I suspect that it’s not much slower than
Ruby. Ruby does quite a lot behind the scenes when a Proc is
constructed.

I don’t think the table of locals is copied; only the reference to the
table of locals should be copied.

how do I call a Method object the same way as a lambda?

l = lambda { |x| x + 42}

def foo(x); return x + 42; end
m = Object.method(:foo)

p l.call(42) #=> 84
p m.call(42) #=> 84

Paul

···

On Thu, Mar 27, 2003 at 04:40:40AM +0900, Mauricio Fernández wrote:

Do you know if any optimization is done on access to outer scope
locals? That looks nice but apparently slow (construction of a dict,
copying table of locals…)

I don’t know for sure, but I suspect that it’s not much slower than
Ruby. Ruby does quite a lot behind the scenes when a Proc is
constructed.

I had the feeling Ruby could be faster essentially because the work
happens behind the scenes, ie at C speed :-).

For instance ruby can transform variable names into symbols as it
creates the AST (not really sure about this, but could be possible),
whereas it seems in Python this must be done at run time, on each
access to the table of locals.

I don’t think the table of locals is copied; only the reference to the
table of locals should be copied.

Believe you’re right :slight_smile:

how do I call a Method object the same way as a lambda?

l = lambda { |x| x + 42}

def foo(x); return x + 42; end
m = Object.method(:foo)

p l.call(42) #=> 84
p m.call(42) #=> 84

ahah, I was thinking the other way around, sorry :slight_smile:
Something like “how do I call a proc the same way as a method (downcase)?”
ie., some way to do
pp = proc { |x| x + 1 }
… MAGIC …
pp(1)

···

On Thu, Mar 27, 2003 at 05:17:47AM +0900, Paul Brannan wrote:

On Thu, Mar 27, 2003 at 04:40:40AM +0900, Mauricio Fernández wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

It’s easy to get on the internet and forget you have a life
– Topic on #LinuxGER

I think what you want is to add a singleton method to the current object
(self), but one which is able to reference the local variable ‘pp’. I’d be
interested to know how to do that, too.

You can do this:

self.class.instance_eval { define_method(:pp, pp) }

pp(9)  # >> 10

but that adds pp to the class, rather than the current object.

Regards,

Brian.

···

On Thu, Mar 27, 2003 at 06:00:09PM +0900, Mauricio Fernández wrote:

ahah, I was thinking the other way around, sorry :slight_smile:
Something like “how do I call a proc the same way as a method (downcase)?”
ie., some way to do
pp = proc { |x| x + 1 }
… MAGIC …
pp(1)

“Mauricio Fernández” batsman.geo@yahoo.com schrieb im Newsbeitrag
news:20030327090007.GC902@student.ei.uni-stuttgart.de

ahah, I was thinking the other way around, sorry :slight_smile:
Something like “how do I call a proc the same way as a method
(downcase)?”
ie., some way to do
pp = proc { |x| x + 1 }
… MAGIC …
pp(1)

I think you can’t other than something like

@pp = proc { |x| x + 1 }

def pp(*args)
@pp.call(*args)
end

pp(1)

The reason is that ruby tries to find a method “pp” in the current
instance if you directly issue pp(1).

regards

robert

    self.class.instance_eval { define_method(:pp, pp) }

       class << self; self end

give you the singleton class

Guy Decoux

That’s fine, but then how do I define the method in the singleton class
rather than in the parent class? I can’t use ‘def’ because the local
variable pp drops out of scope.

class Foo
def addmeth(m,x)
self.class.instance_eval { define_method(m,x) }
end
end

a = Foo.new
b = Foo.new

class <<a; end

pp = proc { |x| x+1 }
a.addmeth(:pp,pp)
p a.pp(10) # >> 11
p b.pp(10) # >> 11 (Oops, I didn’t want that)

Regards,

Brian.

···

On Thu, Mar 27, 2003 at 09:07:47PM +0900, ts wrote:

self.class.instance_eval { define_method(:pp, pp) }
   class << self; self end

give you the singleton class

class Foo
  def addmeth(m,x)
    self.class.instance_eval { define_method(m,x) }

       class << self; self end.instance_eval { define_method(m,x) }

  end
end

a = Foo.new
b = Foo.new

class <<a; end

   # class <<a; end # useless

pp = proc { |x| x+1 }
a.addmeth(:pp,pp)
p a.pp(10) # >> 11
p b.pp(10) # >> 11 (Oops, I didn't want that)

Guy Decoux

I tried ‘class <<a; def zzz; end; end’ but it doesn’t help.

Let me ask the question in a different way. This is what I want to do: add a
singleton method to an existing object, bound to a proc object in local
scope.

a = Foo.new

pp = proc { |x| x+1 }
def a.foo(*args) # create a singleton method of ‘a’
pp.call(*args) # doesn’t work
end

a.foo(10)

But I can’t do it like that, because the local variable pp goes out of scope
as soon as you go inside ‘def’. pp is a Proc so it can’t be inserted
usefully into string eval, as far as I can see.

Is there a solution? I think I want ‘define_singleton_method’ but it doesn’t
seem to be there. I should probably install 1.8 preview and see if it’s been
added.

Regards,

Brian.

···

On Thu, Mar 27, 2003 at 10:03:14PM +0900, ts wrote:

class <<a; end

class <<a; end # useless

Let me ask the question in a different way.

I don't understand sorry. You have the response in [ruby-talk:68053] (the
message that you quote)

pigeon% cat b.rb
#!/usr/bin/ruby
class Foo
  def addmeth(m,x)
    class << self; self end.instance_eval { define_method(m,x) }
  end
end

a = Foo.new
b = Foo.new

pp = proc { |x| x+1 }
a.addmeth(:pp,pp)
p a.pp(10) # >> 11
p b.pp(10) # >> 11 (Oops, I didn't want that)
pigeon%

pigeon% b.rb
11
./b.rb:14: undefined method `pp' for #<Foo:0x401ad3c4> (NameError)
pigeon%

  a = Foo.new

  pp = proc { |x| x+1 }
  def a.foo(*args) # create a singleton method of 'a'
    pp.call(*args) # doesn't work
  end

  a.foo(10)

pigeon% cat b.rb
#!/usr/bin/ruby
class Foo
end

a = Foo.new
pp = proc {|x| x + 1}
class << a; self end.instance_eval { define_method(:foo, pp) }
p a.foo(11)
pigeon%

pigeon% b.rb
12
pigeon%

Guy Decoux

I apologise, I missed that because at a glance it seemed to be what I had
written.

I had no idea that you could use the result of ‘class…end’ in that way…
neat!

pp = proc { |x| x+1 }
addmeth(:pp,pp)
pp(3) # >> 4

Wonderful.

Cheers,

Brian.

···

On Thu, Mar 27, 2003 at 11:19:09PM +0900, ts wrote:

def addmeth(m,x)
class << self; self end.instance_eval { define_method(m,x) }
end

In article 20030327184433.A14861@linnet.org,

···

Brian Candler B.Candler@pobox.com wrote:

On Thu, Mar 27, 2003 at 11:19:09PM +0900, ts wrote:

def addmeth(m,x)
class << self; self end.instance_eval { define_method(m,x) }
end

I apologise, I missed that because at a glance it seemed to be what I had
written.

I had no idea that you could use the result of ‘class…end’ in that way…
neat!

pp = proc { |x| x+1 }
addmeth(:pp,pp)
pp(3) # >> 4

Wonderful.

Cheers,

I guess I’m not quite catching this… but there does seem to be
something quite useful here. Could someone write this up on the wiki?

Phil

I have just added

which includes the above example at the end. Does it help?

Cheers,

Brian.

···

On Fri, Mar 28, 2003 at 06:55:01AM +0900, Phil Tomson wrote:

>I had no idea that you could use the result of 'class...end' in that way...
>neat!
>
> pp = proc { |x| x+1 }
> addmeth(:pp,pp)
> pp(3) # >> 4
>
>Wonderful.
>
>Cheers,

I guess I'm not quite catching this.... but there does seem to be
something quite useful here. Could someone write this up on the wiki?