Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

Re: Iterating over verbatim hash reference

by rubasov (Friar)
on Jan 21, 2010 at 17:16 UTC ( #818767=note: print w/replies, xml ) Need Help??

in reply to Iterating over verbatim hash reference

I think this is possible, however my solution is cryptic and ugly, but it works. I recommend you to copy-paste the following snippets to a syntax-highlighting editor, otherwise you will get lost. Let's start with an easier version that still uses a variable for holding a coderef to an anonymous sub, later on we will eliminate it.
#! /usr/bin/perl use strict; use warnings; my $f = sub { return @_ == 1 ? undef : ( [ splice @_, -2 ], @_ == 1 ? () : &{ $_[0] }(@_) ); }; map { print "$_->[0] -> $_->[1]\n" } $f->( $f, %{ { x => 5, y => 8, z => 42 } } );
A little explanation: I'm defining a recursive anonymous sub, that gets its coderef as its first argument, and the hash listified as the following arguments. Then returns undef for the recursion base case (@_==1), or returns an arrayref for its last two args, and calls itself for the remaining args (if there are enough remaining args). Okay, try it, the result is this:
z -> 42 x -> 5 y -> 8
Then eliminate the var for the coderef: replace the occurances of $f in the map statement with the former sub{} definition and we get this:
#! /usr/bin/perl use strict; use warnings; map { print "$_->[0] -> $_->[1]\n" } &{ sub { return @_ == 1 ? undef : ( [ splice @_, -2 ], @_ == 1 ? () : &{ $_[0] }(@_) ); } }( sub { return @_ == 1 ? undef : ( [ splice @_, -2 ], @_ == 1 ? () : &{ $_[0] }(@_) ); }, %{ { x => 5, y => 8, z => 42 } } );
I'm sure you don't want to use this in real code, however this shows the idea. And sorry but I cannot see any easier solution at this moment.

Replies are listed 'Best First'.
Re^2: Iterating over verbatim hash reference
by rovf (Priest) on Jan 22, 2010 at 11:04 UTC
    I'm sure you don't want to use this in real code
    Except, maybe, on a day I am very angry to my co-workers :-P I really appreciate your elaborate idea (wonderful analysis!), but it bites us from behind: By the replication step in your transformation, you introduce two anonymous subs which are exactly identical, so being good programmers, we will of course give a name to the sub and end up with only one copy of the subroutine; but as soon we do this, we have just traded the name of a hash for a name of a sub (and indeed, this can be done with any other data element as well), so it's not a real gain...

    Ronald Fischer <>

      That duplication trick is really not nice, but I don't see a way how can this be avoided in perl5 (probably a wiser monk may shed some light on this).

      Some other languages have nicer constructs for recursive anonymous functions without this trickery, look at a few examples at

      However I treated the challange of "eliminating named variables", more as a (math-like) challange of using functional programming concepts in perl5, rather than "how to achieve tha same results in real code".

      we have just traded the name of a hash for a name of a sub [...], so it's not a real gain
      That's true for the particular code above, however think of this issue more generally. If we insist on retaining the sub identifier, that still has its advantages, because in lots of code, we traded lots of hash identifiers for one sub identifier.
        more as a (math-like) challange of using functional programming concepts
        I see it more like a challenge too. In functional programming, there is usually a concept employed known as Y combinator. The idea is very similar like yours (including the repetition of the code), but once you define this combinator, you can use it for producing anonymous recursive functions at will. In Haskell, for instance, it is builtin and called fix (finding the fixpoint of a recursion).

        Sadly, I don't have any experience with this :-(
        Ronald Fischer <>

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://818767]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (7)
As of 2016-10-26 07:55 GMT
Find Nodes?
    Voting Booth?
    How many different varieties (color, size, etc) of socks do you have in your sock drawer?

    Results (336 votes). Check out past polls.