http://www.perlmonks.org?node_id=1029954


in reply to RFC: Simulating Ruby's "yield" and "blocks" in Perl

Trouble is, I cannot see any use for this scary-action-at-a-distance feature that isn't more easily and clearly satisfied by passing a coderef. Can you?


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re^2: RFC: Simulating Ruby's "yield" and "blocks" in Perl
by LanX (Saint) on Apr 22, 2013 at 19:36 UTC

    1. It demonstrates Perl's flexibility ¹ and the power of syntactic sugar.

      In other words: Python has no chance to mimic this! (AFAIK)

    2. Technically it's better readable than repeatedly doing stuff like

      my ($c_ref) =@_; $c_ref->(1);

      When using idioms which heavily rely on passing code-blocks it's just a matter of huffman-optimization to abstract the repeated parts away.

      I think you can't "see the use", because Perl doesn't use such idioms as often as Ruby does.

      Without the performance penalty, I'd use it straight away.

      (Keep in mind that many people ignore how slow Ruby is, for the sake of "pretty syntax")

    3. It's a good counter argument for people daemonizing Perl and adoring Ruby.

      I just read the first chapter of "7 Languages in 7 Weeks" which was a funny/shocking experience.

      For instance it praised many features like post-fix if or unless which stem from Perl³ ... just as if Ruby invented it.²

      Why not pirating some of the hype for us?

    4. It shows that an alternative parser for Perl5 could have attracted the audience that Ruby gained.

      Ruby's success is about pretty syntax on Perl semantics. Ruby's success is still heavily shocking the Pythonistas, who believe that Guido is God's (= John von Neumann's?) last prophet.

      (Moose showed how to cover the object model, covering the functional part closes the gap.)

    5. And it demonstrates possibilities to prototype future features w/o ignoring backwards compability.

    6. Last but not least, I already expected you objecting. =)

      But rather about b{ } being superfluous and expensive, while "easily" replaced by sub { } w/o performance loss.

    Cheers Rolf

    ( addicted to the Perl Programming Language)

    ¹) "I'm every woman, its all in me" - Chaka Khan =)

    ²) Not talking about the strange and inflationary use of the term DSL within the Ruby community. If there is a mainstream language w/o Lisp's reader macros, which is predestinated to define DSLs, then it must be Perl. (Ok I don't know all maistream languages ... )

    ³) And are criticized in PBP! =)

      1... 2... 3... 4... 5...

      Hm. You've chosen describe reasoning for your doing the emulation; rather then what that emulation (or the original feature) would be useful for.

      6. I already expected you objecting

      I guess that just goes to show how easy it is to see what you expect to see.

      I meant the little used and not very useful Ruby feature, rather than your overly complex emulation of it.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        Perlers use regexes more often because they are better accessible in Perl.

        Codeblocks are easier accessible this way, thats why Ruby uses them very often.

        I have no problem, if you don't understand the aim of other paradigms and prefer to stick with your well known tools ... TIMTOWTDI. =)

        Cheers Rolf

        ( addicted to the Perl Programming Language)

      If you call the thing "$c_ref" then sure, it did not give you any advantage over the ill-named keyword. If on the other hand you use a descriptive name, the code gets must more readable. The Ruby syntax gives you no hint about what is the block supposed to do, what is it supposed to accept or return, it doesn't tell you anything! On one side you hear rubystas babble about how bad the Perl default variable $_ is and then they use something like this for something conceptually much more complicated and give you no chance to name the thing should you feel the need to. Perl let's you write foreach (@array) as well as foreach my $meaningful_name (@array), Ruby doesn't give you a chance to name the coderef/closure. It doesn't even admit there's one. To make things even funnier, it doesn't even tell you the method accepts a coderef (or block if you will) and the only way to find out is to read the method's body. The (&) at least tells you the subroutine expects a block, Ruby doesn't tell you anything.

      If you do not want to name the coderef, go ahead an use $_[-1]->(1), it's just as cryptic as yield.

      BTW, please translate these two to Ruby:

      sub search { my $wanted = shift; foreach my $path (@_) { print "Searching in '$path'\n"; find($wanted, $path); } } # I don't care about the File::Find ... how do you pass the block to a +nother subroutine/method?
      sub walk_tree { my ($self, $branch_handler, $leaf_handler) = @_; if ($self->isLeaf()) { $leaf_handler->($self->{data}); } else { $branch_handler->{$self->{data}}; foreach my $child ($self->children()) { $child->walk_tree($branch_handler, $leaf_handler); } } }

      Now how big is the leap from a single block to multiple in Perl and in Ruby? How hard is it to do something nontrivial in Perl and in Ruby? Ruby's syntax makes simple things short and awkward and hard things next to impossible.

      Jenda
      Enoch was right!
      Enjoy the last years of Rome.

        Upvoted for less emotions and more arguments! =)

        There is a misunderstanding, I'm neither a Ruby fanboy nor an expert.

        I already explained my motivation in detail, namely to show Perls strength.

        > BTW, please translate these two to Ruby:

        sub search { my $wanted = shift; foreach my $path (@_) { print "Searching in '$path'\n"; find($wanted, $path); } }

        ehm, maybe something like?

        paths.each do |path| puts "Searching in %{path}" find(wanted, path) end

        > Now how big is the leap from a single block to multiple in Perl and in Ruby? How hard is it to do something nontrivial in Perl and in Ruby? Ruby's syntax makes simple things short and awkward and hard things next to impossible.

        No idea. Again, my intention was to show that Perl is so flexible that it can even emulate Ruby. Ruby claims to be a DSL language, while Perl can "dsl" Ruby =).

        Why shouldn't we steal the sexy parts and add it to our portfolio?

        Cheers Rolf

        ( addicted to the Perl Programming Language)

        update

        > how do you pass the block to another subroutine/method?

        according to Passing Blocks in Ruby Without &block there are basically two possibilities:

        Either explicitly adding a &block in the signature or using Proc.new.

        update

        thats your question?

        irb(main):006:0> wanted = "c" => "c" irb(main):021:0> def search (paths, &block) irb(main):022:1> paths.each &block irb(main):023:1> end irb(main):028:0> search ["a", "b", "c"] do irb(main):029:1* |path| irb(main):030:1* puts "Searching in #{path}" irb(main):031:1> puts wanted == path irb(main):032:1> end Searching in a false Searching in b false Searching in c true
      FWIW, the equivalent in idiomatic Python3 is:
      def test() print("You are in the method") yield 1 print("You are again back to the method") yield 2 for a in test(): print("You are in the block #{}".format(a))
      As for anonymous multiline blocks, a while back a monstrosity was released...
        > FWIW, the equivalent in idiomatic Python3 is:

        Thanks, interesting idea to turn it inside out!¹ =)

        But why Python3, AFAIK generators were already introduced in 2.

        > while back a monstrosity was released...

        Thanks, even more fun! =)

        Especially the last line (after "bugs and limitations")

        Oh, and almost forgot: We are sorry, Guido. So sorry.

        Grin! xD

        Cheers Rolf

        ( addicted to the Perl Programming Language)

        update

        ¹) while its a bit cumbersome that you need to iterate over the yields... ... why not using a decorator to abstract the loop away?

        update

        this worked for me in Py 2.5.2

        >>> def test(): ... print("You are in the method") ... yield 1 ... print("You are again back to the method") ... yield 2 ... >>> for a in test(): ... print("You are in the block "+str(a)) ... You are in the method You are in the block 1 You are again back to the method You are in the block 2