Kyle R. Burton on 23 Aug 2007 01:43:55 -0000 |
While mentoring a guy today working in Perl, he asked if Perl had a switch statement. So I paraded out a common pattern (at least for me) in Perl: use strict; use warnings; {my %dispatch = ( positive => sub { $_[0]->{value} = [qw(foo)] }, negative => sub { $_[0]->{value} = [qw(bar)] }, both => sub { $_[0]->{value} = [qw(foo bar)] }, ); sub genTestData { my($type) = @_; my $fn = $dispatch{$type} or die "Unrecognized test data type: '$type' valid:(",join(",",keys %dispatch),")"; my $testData = { start => time(), value => [] }; $fn->($testData); return $testData; }} use Data::Dumper; foreach my $type (qw(positive negative both none)) { print "Data: ",Data::Dumper::Dumper(genTestData($type)),"\n"; } It was for some unit test code, where there was an object being constructed and then some post-construction initialization (via state modifiers, I know, not FP). The idea is that the keys in the dispatch map are kinda an enum (hence the 'or die'). The map provides the switch behavior (at least for values which are eq). Then I realized that I use a pattern for this in Scheme (Jscheme): aprog1 (anaphoric prog1, see also pg's on lisp which PCL also mentions), which I initially created for my unit tests (go figure) where I needed some Java data structure pre-populated with data for my test: (define-test (test-for-over-map) (let ((res (list))) (for each (key value) in-map (aprog1 (java.util.HashMap.) (.put it "foo" "bar") (.put it "qux" "baz")) (set! res (cons key res))) (assert-equal res '("foo" "qux")))) The aprog1 assigns the value of the first expression to the symbol 'it' (yes it is an unhygenic macro) so the rest of the form can reference it by that name, and then returns the value of 'it'. I like it as a pattern for wrapping Java construction/initialization into an expression. Then the evil thought hit me: the code would be more FP-ish if I had a prog1: sub prog1 { my($fn) = @_; sub { my(@args) = @_; $fn->(@args); return $args[0]; } } {my %dispatch = ( positive => prog1(sub { $_[0]->{value} = [qw(foo)] }), negative => prog1(sub { $_[0]->{value} = [qw(bar)] }), both => prog1(sub { $_[0]->{value} = [qw(foo bar)] }), ); sub genTestData { my($type) = @_; my $fn = $dispatch{$type} or die "Unrecognized test data type: '$type' valid:(",join(",",keys %dispatch),")"; return $fn->({ start => time(), value => [] }); }} Definitely not idiomatic Perl, but it 'felt' more FPish with the code ref (function) returning its first value after modification - while still keeping the fn's in the dispatch table very succinct. I constantly find myself opining for, and implementing, the patterns I find useful/powerful from the more expressive languages in the languages in which I tend to be stuck working. Do you mix things up like this? Or do you try to stick with the common paradigms of the culture of the language/technology you work in? Consing in King of Prussia, Kyle --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Philly Lambda" group. To unsubscribe from this group, send email to philly-lambda-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/philly-lambda?hl=en -~----------~----~----~----~------~----~------~--~---
|
|