How to Be Correct, Lazy and Efficient ?

How to Be Correct, Lazy and Efficient ?

How to be correct, lazy and efficient ? C. Recanati Université Paris 13, av. JB. Clément, 1. Lambdix and the semantic problems 93430, Villetaneuse, of Lisp France This paper is an introduction to In this section the semantical defects of Lambdix, a lazy Lisp interpreter lisp1 are reviewed and shown not to exist implemented at the Research Laboratory in Lambdix. These defects are of the University of Paris XI (Laboratoire characteristic of early versions of lisp, but de Recherche en Informatique, Orsay). Lambdix was devised in the course of an they are still present in current versions investigation into the relationship between (although, of course, not all defects are the semantics of programming languages present in all versions); this is why we and their implementation; it was used to demonstrate that in the Lisp domain, think this little overview is not out of date semantic correctness is consistent with even if some of points we make are now efficiency, contrary to what has often been well-known. claimed. The first part of the paper is an overview of well-known semantic 1.1. The functional argument problem difficulties encountered by Lisp as well as an informal presentation of Lambdix; it is shown that the difficulties which Lisp Lisp was first thought of as being an encouters do not arise in Lambdix. The implementation of the lambda calculus. Its second part is about efficiency in syntax allows the definition of functions implementation models. It explains why Lambdix is better suited for lazy by means of lambda expressions, as for evaluation than previous models. The instance section ends by giving comparative execution time tables. (lambda (x y) (+ x y)) 1 By 'lisp' here we mean a family of languages rather than a particular language belonging to this family. page 1 for addition. This is a fundamental feature when the function returns the lambda of Lisp. Now serious problems arise when expression; consequently, when the these lambda expressions are used as anonymous lambda function is applied, x functional arguments - when a function recovers its previous value - which is 456 takes another function as argument, and or not defined. also when a function returns such a function as value. Example 2 $ (define apply (f x) (f x) ) Example 1 $ ( define Identity ( x ) $ ( define BuildConstFunc (x) ( apply (lambda (y) x) 2)) ( lambda(y) x )) The Identity function defined here The function BuildConstFunc is is constructed by applying a function supposed to return a function lambda of y, returning x. In Lambdix, a call to ( which returns x. This lambda function Identity 45) returns 45 but in lisp: ought to be a constant function since its argument y is not used. Then a call to ( $ ( Identity 45) (BuildConstFunc 0) 1) => 2 ought to return 0, as well as This is even more surprising since only y ( (BuildConsFunc 0) 2). This is of course seems bound to 2. The source of the the case in Lambdix, but not in Lisp trouble is the use of the name x in the where: definition of apply. Had apply been $ ((BuildConsFunc 0) 1) defined as => ** error - x not defined ** or $ (setq x 456) $ ( define apply (f z) $ ((BuildConsFunc 0) 1) (f z) ) => 456 the problem would have disappeared. Here The reason for this surprising it is not because the stack has been popped answer is the following. In most lisps too early that the binding fails, but environments (bindings between names because an intermediate binding has been and values) are represented in a stack inserted: x is first bound to 45; then the which is popped when the execution of the evaluation of apply inserts the binding of function terminates. The binding of x to 0 x to 2. The lambda is evaluated with y in the application of BuildConsFunc is lost page 2 bound to 2 and it returns x - which is now part of the benefits of functional bound to 2. programming is lost. Because of these functional argument problems, Lisp is not a true 1.2. Lexical scope vs dynamic scope second order functional language1, and The foregoing examples show that the names of formal parameters are of major 1 Some lisps proposed a function to solve importance in Lisp. This feature is due to the functional argument problem. This the type of variable binding used in Lisp, function, sometimes called closure, takes called 'most recent binding' (MRB, for two arguments - a list of formal short). MRB was perhaps, as Gowan has parameters and an expression - and returns wittily said, the 'most recent error' the application of a lambda expression. ([GOW72]). Originally motivated by the For instance, the value returned by the technical advantages of the closure function applied to the list '(x) implementation, dynamic scoping of the and an expression Expr - in an type illustrated by MRB has disastrous environment where x is bound to 2 - is consequences for the safety of the given by : language. How can you trust a language $ ( closure '(x) 'Expr ) when x =2 in which the names of formal parameters => ((lambda (x) Expr) '2 ) must be taken into account? The use of dynamic scoping in Although this can punctually solve the Lisp conflicts with the original model problem, many critics can be made to this introduced by Church, which was at the solution. First, it is not very efficient source of Lisp. In lambda calculus, a rule because it adds function calls and requires known as the ß-rule allows the reduction the evaluation of all the parameters to be of terms along the following pattern: saved. Moreover, it is an ad hoc solution. It requires the programmer to know when ( ( λ x . expr ) val ) the closure function is necessary since → expr [ x ← val ] the call to the closure function must be explicit. Furthermore, lisp distinguishing between an f-value and a c-value, some particular attention must be given on the way the interpreter pass the arguments. value interpretation and this additional call This requires the use of a special function must also be explicit. (called funcall ) to force the functional page 3 The ß-rule takes as input the application to allows the use of functional arguments and a value val of a lambda expression with is therefore a true second order language. formal parameter x and yields as output the same expression in which all tokens of 1.3. Evaluation order x have been replaced by val. The substitution is supposed to be determined 1.3.1. Call by need and call by value by the inner lambda binding in the (program) text, i.e. lexically. In lambda calculus, a term t defined by In most cases, dynamic scope and lexical scope yield the same result, but it (λ x y . x) A ((λ u . u u) (λ u . u u)) is very easy to construct cases with reduces to A because the first reduction diverging answers1 . This is why - like (the substitution of A to x) yields a term, λ many functional languages today y . A, which always reduces to A because (Common Lisp, Scheme, ML, etc.) - y does not occur in the core of this lambda Lambdix consistently uses lexical scope expression. But in Lisp the interpreter for formal parameters. Lambdix also computes the values of the arguments before the core of the function. This strategy of parameter evaluation is known 1 For instance the term t defined by as call by value. Since in the evaluation of t ≡ ( λ x . ( λ y . ( λ x . y) B ) x) A t all arguments are calculated first, the would reduced to A by ß-reduction calculation of the second argument - the t → ( λ y . ( λ x . y) B ) A) term (( λ u . u u) ( λ u . u u)) - generates → ( λ x . A) B ) an infinite loop: → A y ≡ (( λ u . u u) ( λ u . u u)) while it would reduced to B in the → (( λ u . u u) ( λ u . u u)) dynamic model: → (( λ u . u u) ( λ u . u u)) ( λ x . ( λ y . ( λ x . y) B ) x) A: → ... Stack ( λ y . ( λ x . y) B ) x) [ x – A ] In the framework of the lambda ( λ x . y) B ) [ x – A ][ y – x ] calculus, call by value can be understood y [ x – A ][ y – x ][ x – B ] as a strategy governing the order in which B the ß-reductions are performed. This A formal demonstration of the non strategy guarantees that if there is a unique equivalence of the two models can be solution, the calculus will converge on it. found in A. Eick and E. Fehr [EIC85]. Unfortunately it also guarantees that the page 4 calculus will never return if there is also arguments and if the latter were calculated an infinite derivation. Thus for terms only when necessary. Such a strategy of having both a finite and an infinite evaluation is known as call by need. For derivation, this strategy guarantees that the instance, the function f defined by finite derivation will not be found. Hence it is not a winning strategy. The winning ( de f (x y) strategy of the lambda-calculus requires (if (< x 0) that the leftmost inner term be reduced 1 first. If there is a finite solution, the (f (- x 1) (f x y)))) calculus will converge on it (the will never terminate from a call to (f 1 2) confluence property guarantees the unicity if the interpreter conforms to the call by of the finite solution). This strategy value strategy, but it returns 1 if the corresponds to call by need. interpreter conforms go the other strategy Functions in Lisp are strict1, (call by need ).

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    21 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us