Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Lisp is More Evaluatable

by princepawn (Parson)
on May 24, 2001 at 07:04 UTC ( #82803=perlmeditation: print w/ replies, xml ) Need Help??

Perl

my $z; my $x = sub { $z = 2 + 2 } ; eval $x; # doesnt run the sub routine! $x->(); # oh, you mean I have to do THIS to #eval THIS, but I use eval to eval # other things. not so consistent print $z;

Scheme/Lisp

(setq closure (delay (setq z (+ 2 2)))) (eval closure) ;;; works

Comment on Lisp is More Evaluatable
Select or Download Code
Re: Lisp is More Evaluatable
by chromatic (Archbishop) on May 24, 2001 at 08:05 UTC
    my $scalar_ref = \42; my $array_ref = [ 1 .. 10 ]; my $hash_ref = { key => 'value' }; my $sub_ref = sub {}; eval $scalar_ref; # doesn't dereference the scalar eval $array_ref; # doesn't dereference the array eval $hash_ref; # doesn't dereference the hash eval $sub_ref; # doesn't ______ the ______
Re: Lisp is More Evaluatable
by mikfire (Deacon) on May 24, 2001 at 08:13 UTC
    I may be approaching this a little simplisticly, but I do not usually think of using a function reference as eval'ing ( pardon me while I make up a few words ).

    The reason eval $x; doesn't "work" is that you are using a reference in scalar context, which has the well defined behaviour of stringifying the reference. I like this feature - it makes it easy to figure out how to access information deep withing a complex data structure.

    The $x->() format tells perl to dereference instead of stringify. This is again a standard syntax in perl. $x->{foo} access that key from a hash reference. Similarly from an array reference. Why do you expect a different syntax simply because it is a function reference?

    eval is there for two purposes:

    • Roughly equivalent to "try/catch" in other languages. This allows me to do something potentially fatal ( like use a module that doesn't exist ) without hurting myself. I most often use this construct in DBI code when I need to roll back a transaction if it fails.
    • To run code generated at runtime. Personally, I haven't yet had the need to use eval in this form, but I am certain other monks can expand on this point.

    I am not a perl fanatic. I fully recognize each language has its purpose. I have never used lisp in any sense other than a college class, but I thought it was pretty fun. If you understand lisp better than perl, and it does the job you need, than by all means use it.

    Comparing one language to another seems pretty useless to me - each language is designed to solve a unique problem space. Would you also claim that a hammer is better than a screw driver? I guess I am asking, with respect, what the point of this node was?

    mikfire

      ...and that is the essence of perl

      Let's get on with the perl instead of these comparisons....
      what next, perl vs. awk|sed ?
Re: Lisp is More Evaluatable
by davorg (Chancellor) on May 24, 2001 at 11:49 UTC

    You keep using the word "eval". I do not think it means what you think it means.

    --
    <http://www.dave.org.uk>

    "Perl makes the fun jobs fun
    and the boring jobs bearable" - me

Re (tilly) 1: Lisp is More Evaluatable
by tilly (Archbishop) on May 24, 2001 at 16:03 UTC
    Since the Perl has been commented on enough, I will comment on the Lisp.

    First of all I suspect that delay is not doing what you think it is doing. For a start in, say, Common Lisp your code crashes and burns because delay is a special form in Scheme, but not Common Lisp. But beyond that delay is meant to be used with force, which you are not doing. If you look at this description you will find that when you use a delay without force the result is implementation dependent, but may be indistinguishable from the immediate value. Even if it is not indistinguishable, the code will run at most once and be memoized.

    Therefore your Lisp code is more portably and less deceptively written as:

    (setq closure (setq z (+ 2 2))) (eval closure) ;;; works
    because the code that defined closure is now evaluated by having been used, and further "evals" of it should no longer affect the value of z. (ie The promise set up by delay in your code was redeemed in handing a 4 to eval. Further evals will continue to eval 4, but will not run the promise again.)

    Furthermore if you try to make the Lisp more like the Perl, for instance by making closure an anonymous function, you will find that the call semantics no longer work through an eval. As people have pointed out, that is because your Perl appears to reflect a deep misunderstanding about what all of these programming constructs should be doing.

    So while I believe that Lisp is more evaluatable than Perl, I do not think this is an example that illustrates the principle.

    BTW further stylistic points. In Lisp it is considered bad style to write code with side effects. As the advice goes, pretend that operations like setq have a penalty for use, and try to avoid them. Your pretend example of trying to set up a closure that will modify a global at a later date is indescribably bad - I would shudder to face code like that. In any language.

    Secondly in Lisp it is almost never a good idea to actually use eval. Use macros instead. Just as much power delivered in a more structured form.

    What both of these points get at is that writing debuggable code is a good idea. You seem to evaluate constructs on the basis of their ability to get very complex. You seem to entirely discount any notions that lead to debuggable code. I am coming to the conclusion that if the general programming world judged like you seem to, then goto would have never fallen out of favour...

      It's really not bad style to write code with side effects (depending, I suppose, on your precise definition thereof). Of course, it's (usually) bad style to write code with random, unpredictable, or unclear side effects, just as in any language. But look in any well-regarded Lisp book like Norvig or one of Graham's and you'll see side effects, setfs, etc. It'd be hard to use CLOS, for example, without them. If one's intent is to use primarily the functional features of Lisp, then I guess I agree, but in practice, one uses the imperative and OO features just as much, it seems.

      You're spot on about eval, though.

      Oh, one other thing. For the code to do what (I guess) is actually desired, one needs to quote the form to be evaled:

      (setq closure '(setq z (+ 2 2))) (eval closure) ;;; works

      As originally written, both closure and z would be set to 4, and the eval form would simply eval 4 to get 4

        Perhaps "bad style" is too strongly put.

        But it is certainly considered good style to avoid side-effects. And the advice of thinking of setq as having a penalty associated is straight from On Lisp by Graham. It is not a religious rule. But it is worth thinking about. In fact I think about it in Perl as well, though I am not as extreme because Perl cannot optimize tail recursion.

        As for the other point, perhaps I was unclearly verbose. But that is exactly what I was getting at with the phrase "...should no longer affect the value of z."

Re: Lisp is More Evaluatable
by johannz (Hermit) on May 25, 2001 at 03:10 UTC

    Personally, I think the normal dereference syntax is quite readable:

    my $z; my $x = sub { $z = 2 + 2 } ; &$x; # Oh, I derefernce it like I do other references, # with the standard subroutine prefix. Gotcha.... print $z;

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://82803]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (14)
As of 2014-12-18 18:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (59 votes), past polls