Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

PERLISP meditations

by protist (Monk)
on Sep 29, 2012 at 13:08 UTC ( [id://996373]=perlmeditation: print w/replies, xml ) Need Help??

I watched an MIT lecture on youtube demonstrating some of the abstraction power of LISP. Then I tried my hand at duplicating the functionality in Perl. Below I will post the LISP code, and the Perl equivalent.

LISP

(DEFINE (SUM TERM A NEXT B) (IF (> A B) 0 (+ (TERM A) (SUM TERM (NEXT A) NEXT B)))) (DEFINE (SUM-INT A B) (DEFINE (IDENTITY X) X) (SUM INDENTITY A 1+ B)) (DEFINE (SUM-SQ A B) (SUM SQUARE A 1+ B)) (DEFINE (SQUARE A) (* A A)) (SUM-INT 3 5) (SUM-SQ 3 5)

Perl

#!/usr/bin/perl use warnings; use strict; use feature "state"; sub sum # TERM A NEXT B { state $sum; my ($TERM, $A, $NEXT, $B) = @_; if ($A>$B){ my $temp=$sum; $sum=0; return $temp ; } $sum+=&{$TERM}($A); sum( $TERM, &{$NEXT}($A) ,$NEXT, $B); } sub identity{ shift; } sub square{ ((shift)**2); } sub sumint { sum(\&identity,shift,sub {((shift)+1)},shift)} sub sumsq { sum(\&square,shift,sub {((shift)+1)},shift)} #a normal sum from 3-5 print sumint(3,5) . "\n"; #a sum of squares from 3-5 print sumsq(3,5) . "\n";

Replies are listed 'Best First'.
Re: PERLISP meditations
by moritz (Cardinal) on Sep 29, 2012 at 13:33 UTC

      I haven't read it yet, but it is definitely on my list. In fact, it is on my desk, waiting for me to finish other books. :)

Re: PERLISP meditations
by LanX (Saint) on Sep 29, 2012 at 14:24 UTC
    Thats what you want?
    my $sq = sub { $_[0]**2 }; my $id = sub { $_[0] }; sub sum { my ($a,$b,$func) =@_; $func //= $id; my $sum; $sum += $func->($_) for ($a..$b); return $sum; } sub sum_sq{ sum($_[0],$_[1],$sq)} $,=","; print sum(3,5),sum_sq(3,5); # 12,50

    I skipped the &next sub for integer stepping, but shouldn't be to difficult with a while loop checking $a<$b.

    (UPDATE: I'm puzzled... if "&next" is necessary to get the next element of an iterator one must also provide a &cmp for checking $a<$b in the loop-condition)

    Better avoid Lisp-recursion in Perl, when you can use "real" loops, we don't automatically optimize them to loops like Lisp does.

    Cheers Rolf

      The idea was to use the same logic, that is, recursive logic. Also the iterator is supplied to the sum subroutine in my example (as it is given in the LISP version). By using codereferences instead of normal subroutines, you simplified the passing of arguments. This has the effect, however, of making $sq and $id no longer callable in the same fashion as sum_sq is.

      I like your use of //=, but I think the brevity of your code is due to simplification of, and less-strict adherence to, the LISP example.

        Yes but LISP has no builtin loops thats why you need recursions there which are optimized at compile-time. Perl can't do this (see Tail call) even gotos are no big help here.

        You didn't provide much explanation thats why I replied with my interpretation.

        Regarding iterators and next please see my update in my first post, a flexible next() is of little use if there isn't also a cmp() for abitrary iterators/data structures.

        Cheers Rolf

Re: PERLISP meditations
by remiah (Hermit) on Oct 03, 2012 at 22:25 UTC

    Hello, protist.

    This is second time I saw the name 'High Order Perl'. It took me much time to remember the days with common lisp, but I tried anyway. I wonder what does mit classes uses for lisp? It seems different from common lisp...

    Tested with clisp.

    (defun sum_from_to(TERM from NEXT to) (IF (> from to) 0 (+ (funcall TERM from) (sum_from_to TERM (funcall NEXT from) NEXT to)))) (defun addone (c) (+ 1 c)) (defun self(x) x) (defun square (A) (* A A)) (defun sum-int (A B) (sum_from_to #'self A #'addone B)) (defun sum-sq(A B) (sum_from_to #'square A #'addone B)) (print (sum-int 3 5)) (print (sum-sq 3 5))
    And exact same migration from list to perl would work.
    #!/usr/bin/perl use strict; use warnings; use feature qw(say); sub sum_from_to{ my ($TERM, $from, $NEXT, $to)=@_; if( $from > $to ){ 0; } else { $TERM->($from) + sum_from_to( $TERM, $NEXT->($from), $NEXT, $to ); } } sub addone{ return 1 + $_[0]} sub self{ return $_[0]} sub square{ return $_[0] * $_[0]} sub sum_int { my($A,$B)=@_; sum_from_to( \&self, $A, \&addone, $B); } sub sum_sq { my($A,$B)=@_; sum_from_to( \&square, $A, \&addone, $B); } say sum_int(3,5); say sum_sq(3,5);
    regards.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://996373]
Approved by moritz
Front-paged by davido
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2024-03-28 22:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found