This isn't really obfuscation, it's even vaguely useful, but see if you can figure out what Pipes.pm must be doing, given that this prints o-l-l-e-H

use strict; use warnings; use Pipes; print "hello" | fn { ucfirst($_[0]) } | fn { [ split('', $_[0]) ] } | fn { [ reverse(@{$_[0]}) ] } | fn { join('-', @{$_[0]}) } | fn { $_[0] . "\n" };
Bill H
perl -e 'print sub { "Hello @{[shift->()]}!\n" }->(sub{"World"})'

Replies are listed 'Best First'.
Re: Functional Composition
by ikegami (Patriarch) on Dec 17, 2009 at 21:10 UTC

    '|' is left associative, and the left argument is evaluated first

    Left-associative means that

    a | b | c
    is equivalent to
    ( a | b ) | c
    and not
    a | ( b | c )

    It says nothing about the order in which a, b and c are evaluated in relation to each other. In fact, the operand evaluation order is undefined for most Perl operators including the "|" operator.

    Perl is free to evaluate

    a | b | c
    as follows:
    push @stack, c; push @stack, b; push @stack, a; push @stack, pop(@stack) | pop(@stack); push @stack, pop(@stack) | pop(@stack); pop @stack;

    The left pipe is evaluated before the right pipe, so the operator is left-associative, but note how c is evaluated before b, which is evaluated before a.

    Your code is relying on undefined functionality. It's not guaranteed to work. You'd have to switch to || if you wanted predictable results. || is guaranteed to evaluate its LHS argument before its RHS argument due to its short-circuiting nature.

    That's the official line, anyway. In reality, |'s LHS arg is always evaluated before its RHS, and I don't see that ever changing.

      I stand corrected, I chose '|' pretty arbitrarily to mimic unix pipes, and assumed that the left operand would always be evaluated first. I do know what "left associative" means though, there was an "and" in that sentance :-)

      Bill H
      perl -e 'print sub { "Hello @{[shift->()]}!\n" }->(sub{"World"})'

        there was an "and" in that sentance

        There was a possibility that you meant "and therefore". If not, then you can ignore the top half while others benefit from it.

Re: Functional Composition
by BrowserUk (Patriarch) on Dec 17, 2009 at 21:04 UTC

    The same as this, but very, very slowly!

    c:\test>perl -E"say join'-',split'', reverse ucfirst 'hello';" o-l-l-e-H

    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.

      You're right of course, but I chose perl builtins to keep the example short. If you consider that each of those 'fn's could be arbitrarily complex and require braces around their arguments that would become

      perl -E"say(join('-', split('', reverse(ucfirst('hello')))))"

      Plus I have to admit I kind of screwed up, "functional composition" really means "take two functions and produce a third", like

      compose(sub{ ucfirst $[0] }, sub { $_[0] . "\n" });

      would return a function that would ucfirst its arg and append a newline, whereas my code invokes the functions directly. Still, it looks pretty.

      Bill H
      perl -e 'print sub { "Hello @{[shift->()]}!\n" }->(sub{"World"})'