Top.Mail.Ru
? ?
Shlomif's Technical Posts Community [entries|archive|friends|userinfo]
Shlomif's Technical Posts Community

[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Links
[Links:| Shlomi Fish's Homepage Main Journal Homesite Blog Planet Linux-IL Amir Aharoni in Unicode open dot dot dot ]

A Valid Use of Ampersand-func? [Aug. 27th, 2009|07:36 pm]
Shlomif's Technical Posts Community

shlomif_tech

[shlomif]
[Tags|, , , , , , , ]
[Current Location |Home]
[Current Music |Harold Faltermeyer - Axel F (Beverly Hills Cop)]

I was talking on #perl one day, when someone joined and asked:

foldr (\(a,b) -> (a:).(b:)) [] $ uncurry zip \
    ("Hv o edyu IPtdy","aeyura orSC oa?") 
    <- What would this be in Perl? (It outputs 
    "Have you read your SICP today?")

In case you don't know your Haskell, what it does is interleave the two strings and have 1 letter from here and the other one from here. In Perl, strings are not lists or sequences, so we understood we'd need to split them first to do something like that. Furthermore, we recalled the "zip" function from List-MoreUtils that may prove to be useful.

Eventually, someone came with this Perl 5 solution:

perl -MList::MoreUtils=zip -e 'my @former = split //, "Hv o edyu IPtdy"; 
  my @latter = split //, "aeyura orSC oa?"; 
  print join "", zip @former, @latter'

Assigning to array variables was necessary because zip has a prototype. Then I figured out that we can avoid that by over-riding the protoype using "&zip", and proposed this solution:

perl -MList::MoreUtils=zip -e 'print join "", &zip(map { [split//, $_] } 
    "Hv o edyu IPtdy","aeyura orSC oa?")'

Which was much shorter and clearer but used "&zip". What happens is that we pass it the arrays directly as references. I was able to golf it somewhat into:

perl -MList::MoreUtils=zip -E 'say&zip(map[split//],"Hv o edyu IPtdy",
"aeyura orSC oa?")'

So we got what appears to be a valid use of "&func" to over-ride a pesky prototype. Now, Perl 6 hackers are invited to contribute a Perl 6 solution.

LinkReply

Comments:
From: ext_205211
2009-08-27 05:13 pm (UTC)

Perl 6 solution

As discussed on #perl6:

perl6 -e 'say "Hv o edyu IPtdy".comb Z"aeyura orSC oa?".comb'

(Reply) (Thread)
[User Picture]From: shlomif
2009-09-08 03:51 am (UTC)

Re: Perl 6 solution


It's not too bad, but I still find it inelegant that the .comb method is called twice. Any solution to this problem?

(Reply) (Parent) (Thread)
From: ext_205283
2009-08-28 11:09 am (UTC)

Not really, more like a problem with List::MoreUtils

The prototype for zip is expecting a container type for arrays, when it has no reason to except for providing silly syntactic sugar (it's not mutating anything, it's just that the less general form is aesthetically appealing). If it just required two scalar arguments which had to be array references that would be a lot more useful.



A more complicated instance is prototypes like \[$@%] which take a reference to anything as their first argument. Without using the &foo form you need to unroll. Compare:



if ( reftype $ref eq 'SCALAR' ) {
    foo($$ref);
} elsif ( reftype $ref eq 'HASH" ) {
    foo(%$ref);
} elsif ( reftype $ref eq 'ARRAY' ) {
    foo(@$ref);
}


vs.

&foo($ref)


But even so this is just a symptom of the lack of foresight in that module's API.



I don't think that has much to do with Perl as a language, except that its irky syntax features get abused from time to time. In Perl 6 this is solved by superseding prototypes with proper function signatures.


(Reply) (Thread)