http://qs321.pair.com?node_id=1030873


in reply to Re^7: RFC: Simulating Ruby's "yield" and "blocks" in Perl (Python)
in thread RFC: Simulating Ruby's "yield" and "blocks" in Perl

Thanx, it's clear now.

I was just surprised that you need two decorators!

I thought you could simply do something like

 test(def _(x): print("You are in block %s" % x))

(like  test sub { print("You are in block $_[0]") } in Perl)

Just to get closer to the Ruby feeling and to achieve this

>>> def _(x): ... print("You are in block %s" % x) ... >>> test(_) In test You are in block 1 back in test You are in block 2 test lambda a: print("You are in block %s" % a)

But one needs decorators to manipulate a literal function.

Obviously, there is only this way to do it.

FWIW Python decorators could quite easily be simulated in Perl with attributes.

I will post this soon (if I can't find it already on CPAN) =)

Cheers Rolf

( addicted to the Perl Programming Language)

Replies are listed 'Best First'.
Re^9: RFC: Simulating Ruby's "yield" and "blocks" in Perl (Python)
by MonkOfAnotherSect (Sexton) on Apr 27, 2013 at 14:11 UTC
    If you used a non-keyword such as "send" instead of "yield" you could do Evil and avoid the first decorator. This is left as an exercise. As for the second decorator, sure 'test(lambda a: print("You are in block %s" % a))' will work, but when you require more than one line you're back to using a decorator unless you want to do something truly horrible.

    Don't want to do something truly horrible.

    -T. "A gentleman is someone who knows how to play the bagpipes but doesn't."

      > As for the second decorator, sure test(lambda a: print("You are in block %s" % a)) will work,

      not for me...

      lanx@nc10-ubuntu:~$ python Python 2.5.2 (r252:60911, Jan 20 2010, 23:16:55) [GCC 4.3.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> def rubyyielder(gen): ... def wrapped_gen(block): ... for elem in gen(): ... block(elem) ... return wrapped_gen ... >>> @rubyyielder ... def test(): ... print("In test") ... yield 1 ... print("back in test") ... yield 2 ... >>> test(lambda a: print("You are in block %s" % a)) File "<stdin>", line 1 test(lambda a: print("You are in block %s" % a)) ^ SyntaxError: invalid syntax

      I suppose the lamda syntax has more restrictions...

      > If you used a non-keyword such as "send" instead of "yield" you could do Evil and avoid the first decorator. This is left as an exercise.

      Simple, I can just port the semantic of my OP and let send execute the callback which is passed to @test.¹

      Cheers Rolf

      ( addicted to the Perl Programming Language)

      Update

      ¹) at second thought this would require a possibility to access the arguments of the caller. I suppose the caller is an object where arguments are accessible.

      Update

      deleted undiplomatic irony =)

        Ah, you're using an old version where print was still a statement not a function; Python is finicky about how statements are used. v2.6-v2.7 allows "from __future__ import print_function", and in v3.0+ it is a function. If you really must use a lambda in v2.5- then "import sys" and use "sys.stdout.write()"... no you mustn't.

        -T. "We now return you to your regularly scheduled Perl"