There runs now a topic on moscow.pm list on how to calculate a sum of numbers in a list, basically this:
```my \$sum = 0;
\$sum += \$_ for @list;
but without using extra vars and modules (nurture your inner purist, yes :) Now I believe I found a line that wasn't discovered before:

```print sub { (map {splice @_, 0, 2, \$_ + (\$_ // 0)} @_)[-1] }-> (
+1,2,3,4,5);

Hopefully you'll find it amusing :)

Replies are listed 'Best First'.
Re: (almost) foldl
by Fox (Pilgrim) on Jun 08, 2011 at 14:25 UTC
No recursion ?

sub sum { (shift()//0) + (@_ ? sum(@_) : 0) };

I came up with a similar, and arguably neater implementation:

```sub sum{ ( shift()//return 0 ) + &sum }

print sum( 1,2,3);;
6

print sum( 1 .. 100 );;
Deep recursion on subroutine "main::sum" at
5050

but rejected it because 'sum' is a (glob) variable.

In theory, it is possible to avoid the naming of the sub, thereby achieving "anonymous recursion", by using the Y-combinator. And the Y-combinator has been achieved in Perl by a former regular here.

Putting it together you get:

```print Y( sub{my\$rec=shift; sub{(shift()//return 0) + &\$rec }})->(1 ..
+100);;
5050

But whilst that achieves the Y-combinators goal of recursion without adding the sub to the permanent namespace, it still requires the naming of the pesky closure \$rec.

And of course, requires you to add the Y-combinator to the permanent namespace first:

```sub Y {
my ( \$curried_rec ) = @_;
sub {
my ( \$f1 ) = @_;
\$curried_rec->( sub { \$f1->( \$f1 )->( @_ ) } )
}->( sub {
my ( \$f2 ) = @_;
\$curried_rec->( sub { \$f2->( \$f2 )->( @_ ) } )
} )
}

And that's already more obfuscation as I want to wrap my brain around, even in an obfuscation section post!

My final thought is that the simplest mechanism that fits the OPs breif is just:

```C:\test>perl -Mstrict -wE"say eval join'+',()"

C:\test>perl -Mstrict -wE"say eval join'+',0"
0

C:\test>perl -Mstrict -wE"say eval join'+',-1"
-1

C:\test>perl -Mstrict -wE"say eval join'+',-1..+3"
5

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.
Nice! But print eval join "+", ("1e", 6) yields 1000000, whereas my aforementioned solution: print sub {eval 'pop(@_)+' x (\$#_ + 1) . '0';}->("1e", 6); prints the expected result, 7. Ok, ok, I'm quibbling.
Great! There was once a YAPC auction selling off a built-in name in a future perl, at the buyer's choice. IIRC it has never actualized, but now I wish it was Y )
This method is extremely elegant, and therefore doubleplus unsuitable for the "Obfuscated code" section. Just kidding, sorry if it sounds harsh :-)
cool! ++
Re: (almost) foldl
by ikegami (Pope) on Jun 07, 2011 at 22:14 UTC

First, it's not equivalent since you don't handle the empty list.

```my \$sum = sub { (map {splice @_, 0, 2, \$_ + (\$_ // 0)} @_)[-1] }
+->(@list);

should be

```my \$sum = sub { (map {splice @_, 0, 2, \$_ + (\$_ // 0)} @_)[-1] }
+->(0, @list);

A general form of this exists as reduce in List::Util. It's is easier to use (since handling one-element lists is easier) and easier to read (since it uses \$a and \$b instead of \$_ and \$_ and uses less extraneous code).

```my \$sum = reduce { \$a + \$b } 0, @list;
no extra modules! )
Are core modules like List::Util "extra" or not?

Your reply doesn't make sense. I pointed out that someone already wrote your code, and wrote it way better. The choice isn't between using a module and using no module, the choice is between using your code and using List::Util's.

Re: (almost) foldl
by Grimy (Pilgrim) on Jun 07, 2011 at 22:57 UTC
Well, in unary, summing is as simple as concatenating. And Perl has a built-in decimal-to-unary converter (the x operator), as well as a built-in unary-to-decimal converter (the length function). Putting all this together:
```my @list = (1, 2, 3, 4, 5);
print length join "", map{"1" x \$_} @list; #prints 15
But your implementation sure is fun :-) EDIT: Look at tye's code instead. This one is stupid. Don't know what I had in mind when I wrote 'length join "", '.
```my @list = ( 1..6 );
print 0+map{(1)x\$_}@list;

- tye

negative numbers?
```my @list = ( -4 .. 6 );
print map((1)x\$_,@list) - map((1)x-\$_,@list);

- tye

```sub sum { eval 'pop(@_)+' x (\$#_ + 1) . '0'; }

@list = (-4, 15, -5, 2.5);
print sum @list;            # 8.5, as expected
print sum -4, 15, -5, 2.5;  # Works the same
print sum;                  # 0 (not undef)
EDIT: replaced \$#list with \$#_ , so that it works with lists of any length. Silly me.
Re: (almost) foldl
by ikegami (Pope) on Jun 07, 2011 at 22:50 UTC

```sub { ( map { splice @_, 0, 2, \$_ + (\$_ // 0) } @_ )[-1] }->(0,
+@list)

such that one is left with a single splice and without the extra loop pass that necessitates // 0.

```sub { ( splice(@_, 0, 0, 0), ( map \$_ += \$_, @_) )[-1] }->(@list)

Of course, that's really just the same as

```sub { splice(@_, 0, 0, 0); map \$_ += \$_, @_; \$_ }->(@list)

At which point, you a can give a better name to the variables you do create (despite claims to the contrary).

```sub { my \$acc = 0; map \$acc += \$_, @_; \$acc }->(@list)

Finally, canonise.

```sub { my \$acc = 0; \$acc += \$_ for @_; \$acc }->(@list)
and no extra vars ))))
Are you saying that creating vars named \$_ (like you did) is better than creating a var named \$acc, or did you just not read my post?
Re: (almost) foldl
by BrowserUk (Pope) on Jun 11, 2011 at 08:41 UTC

Not as elegant, but waaaaaaay more efficient:

```print sub{ unshift@_,0; \$_+= pop while @_>1; return @_ }->( 1..1e6)
+;;
500000500000

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.
Re: (almost) foldl
by BrowserUk (Pope) on Jun 11, 2011 at 07:29 UTC

He he :)

```print \$_->(1,2,3) for sub{ (shift//return 0) + &\$_ };
6