Revision as of 09:48, 12 July 2012 editTea2min (talk | contribs)Extended confirmed users, Pending changes reviewers21,805 edits ←Redirected page to Scope (computer science)#Let-expressions | Revision as of 14:48, 27 March 2014 edit undoThepigdog (talk | contribs)Extended confirmed users5,174 editsNo edit summaryNext edit → | ||
Line 1: | Line 1: | ||
A "let expression" associates a function with a restricted ]. Let expressions may be defined from ] of for computer science. | |||
The let expression may be considered as a ] applied to a value. A let expression may also be considered as a ] of expressions, within an ] which restricts the scope of the variable. | |||
The let expression is present in many functional languages to allow the local definition of expression, for use in defining another expression. The let-expression is present in many functional languages in two forms; let or "letrec". Letrec is an extension of the let expression which uses the ] to implement ]. | |||
== History == | |||
] ]<ref group="note">"PCF is a programming language for computable functions, based on LCF, Scott’s logic of computable functions" {{harv|Plotkin|1977}}. ''Programming Computable Functions'' is used by {{harv|Mitchell|1996}}. It is also referred to as ''Programming with Computable Functions'' or ''Programming language for Computable Functions''.</ref> was a stage in the evolution of lambda calculus into modern functional languages. This language introduce the let expression, which has appeared in most functional languages since that time. | |||
The languages ], ], and more recently ] have evolved based on LCF. | |||
State-full imperative languages such as and ] essentially implement a let expression, to implement restricted scope of functions, in block structures. | |||
== Definition == | |||
A lambda abstraction represents a function without a name. This is source of the inconsistency in the definition of a lambda abstraction. However lambda abstractions may be composed to represent a function with a name. In this form the inconsistency is removed. The lambda term, | |||
:<math> (\lambda f.z)\ (\lambda x.y) </math> | |||
is equivalent to defining the function <math>f</math> by <math>f\ x = y</math> in the expression <math>z</math>, which may be written as the ''let'' expression; | |||
:<math>\operatorname{let} f\ x = y \operatorname{in} z</math> | |||
The let expression is understandable as a natural language expression. Used in ] ]<ref group="note">"PCF is a programming language for computable functions, based on LCF, Scott’s logic of computable functions" {{harv|Plotkin|1977}}. ''Programming Computable Functions'' is used by {{harv|Mitchell|1996}}. It is also referred to as ''Programming with Computable Functions'' or ''Programming language for Computable Functions''.</ref> the let expression represents the substitution of a variable for a value. The substitution rule describes the implications of equality as substitution. The let expression is the conjunction of two expressions, with the substitution rule from one expression applied to the other. | |||
=== Let definition === | |||
The ''let'' expression is the conjunction of expressions. In functional languages the let expression is also used to limit scope. In mathematics scope is described by quantifiers. The let expression is a conjunction within an existential quantifier. | |||
:<math> (\exists x E \and F) \iff \operatorname{let} x : E \operatorname{in} F </math> | |||
The meaning of the ''let'' expression allows the substitution to be applied to another expression. This substitution may be applied within a restricted scope, to a sub expression. The natural use of the let expression is in application to a restricted scope. These results may be derived to describe how the scope may be restricted; | |||
:<math> x \not \in \operatorname{FV}(E) \and x \in \operatorname{FV}(F) \to \operatorname{let} x : G \operatorname{in} E\ F = E\ (\operatorname{let} x : G \operatorname{in} F)</math> | |||
:<math> x \in \operatorname{FV}(E) \and x \not \in \operatorname{FV}(F) \to \operatorname{let} x : G \operatorname{in} E\ F = (\operatorname{let} x : G \operatorname{in} E)\ F</math> | |||
:<math> x \not \in \operatorname{FV}(E) \and x \not \in \operatorname{FV}(F) \to \operatorname{let} x : G \operatorname{in} E\ F = E\ F</math> | |||
From this definition the following standard definition of a let expression, as used in a functional language may be derived. | |||
:<math> x \not \in \operatorname{FV}(y) \to (\operatorname{let} x : x = y \operatorname{in} z) = z = \lambda x.z\ y </math> | |||
To derive this result, first assume, | |||
:<math> x \not \in \operatorname{FV}(L) </math> | |||
then | |||
:<math> L\ (\operatorname{let} x : x = y \operatorname{in} z) </math> | |||
:<math> \iff (\operatorname{let} x : x = y \operatorname{in} L\ z) </math> | |||
:<math> \iff x = y \and L\ z </math> | |||
Using the rule of substitution, | |||
:<math> \iff x = y \and(L\ z)</math> | |||
:<math> \iff x = y \and(L\ z)</math> | |||
:<math> \iff x = y \and L\ z</math> | |||
:<math> \implies L\ z</math> | |||
so for all ''L'', | |||
:<math> L \operatorname{let} x : x = y \operatorname{in} z \implies L\ z</math> | |||
Let <math> L\ X = (X = K) </math> where ''K'' is a new variable. then, | |||
:<math> (\operatorname{let} x : x = y \operatorname{in} z) = K \implies z = K </math> | |||
So, | |||
:<math> \operatorname{let} x : x = y \operatorname{in} z = z</math> | |||
But from the mathematical interpretation of a beta reduction, | |||
:<math> \lambda x.z\ y = z</math> | |||
Here if y is a function of a variable x, it is not the same x as in z. Alpha renaming may be applied. So we must have, | |||
: <math> x \not \in \operatorname{FV}(y) </math> | |||
so, | |||
:<math> x \not \in \operatorname{FV}(y) \to \operatorname{let} x : x = y \operatorname{in} z = \lambda x.z\ y</math> | |||
This result is represented in a functional language in an abbreviated form, where the meaning is unambiguous; | |||
:<math> x \not \in \operatorname{FV}(y) \to (\operatorname{let} x = y \operatorname{in} z) = z = \lambda x.z\ y </math> | |||
Here the variable ''x'' is implicitly recognised as both part of the equation defining x, and the variable in the existential quantifier. | |||
=== Joining let expressions === | |||
Let expressions may be defined with multiple variables, | |||
:<math> (\exists v ... \exists w \exists x E \and F) \iff \operatorname{let} v, ... ,w , x : E \operatorname{in} F </math> | |||
then it can be derived, | |||
:<math> x \not \in FV(E) \to (\exists v ... \exists w \exists x E \and F) \iff (\exists v ... \exists w (E \and \exists x F)) </math> | |||
so, | |||
:<math> x \not \in FV(E) \to (\operatorname{let} v, ..., w, x : E \and F \operatorname{in} L \equiv \operatorname{let} v, ..., w: E \operatorname{in} \operatorname{let} x : F \operatorname{in} L) </math> | |||
== Conversion between lambda calculus and let expressions == | |||
The following rules describe the equivalence of lambda and let expressions, | |||
{| class="wikitable" | |||
|- | |||
! Name !! Law | |||
|- | |||
| Eta-reduction equivalence || <math>f\ x = y \equiv f = \lambda x.y </math> | |||
|- | |||
| Let-Lambda equivalence || <math> f \not \in FV(E) \to (\operatorname{let} f : f = E \operatorname{in} L \equiv (\lambda f.L)\ E) </math> (where f is a variable name). | |||
|- | |||
| Let combination | |||
| <math> w \not \in FV(E) \to (\operatorname{let} v, w : E \and F \operatorname{in} L \equiv \operatorname{let} v: E \operatorname{in} \operatorname{let} w : F \operatorname{in} L) </math> (where f is a variable name). | |||
|} | |||
Meta-functions will be given that describe the conversion between ''lambda'' and ''let'' expressions. A meta-function is a function that takes a program as a parameter. The program is data for the meta-program. The program and the meta program are at different meta-levels. | |||
The following conventions will be used to distinguish program from the meta program, | |||
* Square brackets will be used to represent function application in the meta program. | |||
* Capital letters will be used for variables in the meta program. Lower case letters represent variables in the program. | |||
* <math> \equiv </math> will be used for equals in the meta program. | |||
* <math> \_ </math> represents a dummy variable, or an unknown value. | |||
For simplicity the first rule given that matches will be applied. The rules also assume that the lambda expressions have been pre-processed so that each lambda abstraction has a unique name. | |||
The substitution operator is used extensively. The expression <math> L </math> means substitute every occurrence of ''G'' in ''L'' by ''S'' and return the expression. The definition used is extended to cover the substitution of expressions, from the definition given on the ] page. The matching of expressions should compare expressions for alpha equivalence (renaming of variables). | |||
=== Conversion from lambda to let expressions === | |||
The following rules describe how to convert from a Lambda expression to a ''let'' expression, without altering the structure. | |||
# <math> \operatorname{de-lambda} \equiv V </math> | |||
# <math> \operatorname{de-lambda} \equiv \operatorname{de-lambda}\ \operatorname{de-lambda} </math> | |||
# <math> \operatorname{de-lambda} \equiv \operatorname{de-lambda} </math> | |||
# <math> \operatorname{de-lambda} \equiv \operatorname{de-lambda} = \operatorname{de-lambda} </math> | |||
# <math> \operatorname{de-lambda} \equiv \operatorname{let-combine} \operatorname{in} E] </math> | |||
# <math> V \not \in \operatorname{FV} \to \operatorname{de-lambda} \equiv \operatorname{let-combine} \operatorname{in} V] </math> | |||
# <math> V \ne W \to \operatorname{let-combine} \equiv \operatorname{let} V, W : E \and F \operatorname{in} G </math> | |||
# <math> \operatorname{let-combine} \equiv \operatorname{let} V : E \operatorname{in} F </math> | |||
Rule 6 creates a unique variable V, as a name for the function. | |||
==== Example ==== | |||
For example the ], | |||
: <math>\lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x)) </math> | |||
is converted to, | |||
: <math>\operatorname{let} p : p\ f = \operatorname{let} x : x\ q = f\ (q\ q) \operatorname{in} f\ (x\ x) \operatorname{in} p </math> | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! Rule !! Lambda Expression | |||
|- | |||
| 6 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math>\operatorname{de-lambda} </math> | |||
|- | |||
| <math> V \not \in \operatorname{FV} \to \operatorname{de-lambda} </math> | |||
|- | |||
| <math> V = p, F = f, E = \lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x) </math> | |||
|- | |||
| <math> \operatorname{let-combine} \operatorname{in} V] </math> | |||
|} | |||
|- | |||
| 4 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> \operatorname{let-combine} \operatorname{in} p] </math> | |||
|- | |||
| <math> \operatorname{de-lambda} </math> | |||
|- | |||
| <math> \operatorname{de-lambda} </math> | |||
|- | |||
| <math> E = p\ f, F = (\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x)) </math> | |||
|- | |||
| <math> \operatorname{de-lambda} = \operatorname{de-lambda} </math> | |||
|- | |||
| <math> \operatorname{de-lambda} = \operatorname{de-lambda} </math> | |||
|- | |||
! <math> \operatorname{let-combine} = \operatorname{de-lambda} \operatorname{in} p] </math> | |||
|} | |||
|- | |||
| 5 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> \operatorname{let-combine} = \operatorname{de-lambda} \operatorname{in} p] </math> | |||
|- | |||
| <math> \operatorname{de-lambda} </math> | |||
|- | |||
| <math> \operatorname{de-lambda} </math> | |||
|- | |||
| <math> F = x, E = f\ (x\ x), L = (\lambda x.f\ (x\ x)) </math> | |||
|- | |||
| <math> \operatorname{let-combine} \operatorname{in} E] </math> | |||
|- | |||
| <math> \operatorname{let-combine} \operatorname{in} f\ (x\ x)] </math> | |||
|} | |||
|- | |||
| 3 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> \operatorname{let-combine} = \operatorname{let-combine} \operatorname{in} f\ (x\ x)] \operatorname{in} p] </math> | |||
|- | |||
| <math> \operatorname{de-lambda}</math> | |||
|- | |||
| <math> \operatorname{de-lambda} </math> | |||
|- | |||
| <math> F = x, P = x, E = f\ (x\ x) </math> | |||
|- | |||
| <math> \operatorname{de-lambda} </math> | |||
|- | |||
| <math> \operatorname{de-lambda} </math> | |||
|} | |||
|- | |||
| 9 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> \operatorname{let-combine} = \operatorname{let-combine} \operatorname{in} f\ (x\ x)] \operatorname{in} p] </math> | |||
|- | |||
| <math> \operatorname{let-combine} \operatorname{in} f\ (x\ x)] </math> | |||
|- | |||
| <math> \operatorname{let-combine} </math> | |||
|- | |||
| <math> Y = \operatorname{let} x : \operatorname{de-lambda} \operatorname{in} f\ (x\ x) </math> | |||
|- | |||
| <math> Y </math> | |||
|- | |||
| <math> \operatorname{let} x : \operatorname{de-lambda} \operatorname{in} f\ (x\ x) </math> | |||
|} | |||
|- | |||
| 9 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> \operatorname{let-combine} = \operatorname{let} x : \operatorname{de-lambda} \operatorname{in} f\ (x\ x) \operatorname{in} p] </math> | |||
|- | |||
| <math> \operatorname{let-combine} </math> | |||
|- | |||
| <math> Y = \operatorname{let} p : \operatorname{de-lambda} \operatorname{in} f\ (x\ x)] \operatorname{in} p </math> | |||
|- | |||
| <math> Y </math> | |||
|- | |||
| <math> \operatorname{let} p : p\ f = \operatorname{let} x : \operatorname{de-lambda} \operatorname{in} f\ (x\ x) \operatorname{in} p </math> | |||
|} | |||
|- | |||
| 4 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> \operatorname{let} p : \operatorname{de-lambda} = \operatorname{let} x : \operatorname{de-lambda} \operatorname{in} f\ (x\ x) \operatorname{in} p </math> | |||
|- | |||
| <math> \operatorname{de-lambda} </math> | |||
|- | |||
| <math> \operatorname{de-lambda} </math> | |||
|- | |||
| <math> E = x\ x, F = f\ (x\ x) </math> | |||
|- | |||
| <math> \operatorname{de-lambda} = \operatorname{de-lambda} </math> | |||
|- | |||
| <math> \operatorname{de-lambda} = \operatorname{de-lambda} </math> | |||
|} | |||
|- | |||
| 2 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> \operatorname{let} p : \operatorname{de-lambda} = \operatorname{let} x : \operatorname{de-lambda} = \operatorname{de-lambda} \operatorname{in} f\ (x\ x) \operatorname{in} p </math> | |||
|- | |||
| <math> \operatorname{de-lambda}, \operatorname{de-lambda} </math> | |||
|- | |||
| <math> \operatorname{de-lambda}, \operatorname{de-lambda}, \operatorname{de-lambda}, </math> | |||
|- | |||
| <math> M_1 = p, N_1 = f, M_2 = x, N_2 = x, M_3 = f, N_3 = x\ x </math> | |||
|- | |||
| <math> \operatorname{de-lambda}\ \operatorname{de-lambda}, \operatorname{de-lambda}\ \operatorname{de-lambda}, \operatorname{de-lambda}\ \operatorname{de-lambda} </math> | |||
|- | |||
| <math> \operatorname{de-lambda}\ \operatorname{de-lambda}, \operatorname{de-lambda}\ \operatorname{de-lambda}, \operatorname{de-lambda}\ \operatorname{de-lambda}\ \operatorname{de-lambda} </math> | |||
|} | |||
|- | |||
| 1 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> \operatorname{let} p : \operatorname{de-lambda}\ \operatorname{de-lambda} = \operatorname{let} x : \operatorname{de-lambda}\ \operatorname{de-lambda} = \operatorname{de-lambda}\ (\operatorname{de-lambda}\ \operatorname{de-lambda}) \operatorname{in} f\ (x\ x)] \operatorname{in} p </math> | |||
|- | |||
| <math> \operatorname{de-lambda} </math> | |||
|- | |||
| <math> V </math> | |||
|} | |||
|- | |||
| || <math> \operatorname{let} p : p\ f = \operatorname{let} x : x\ x = f\ (x\ x) \operatorname{in} f\ (x\ x)] \operatorname{in} p </math> | |||
|} | |||
=== Conversion from let to lambda expressions === | |||
These rule reverse the conversion described above. They convert from a ''let'' expression to a Lambda expression, without altering the structure. Not all let expressions may be converted using these rules. The rules assume that the expressions are already arranged as if they had been generated by ''de-lambda''. | |||
# <math> \operatorname{get-lambda} = \operatorname{get-lambda} </math> | |||
# <math> \operatorname{get-lambda} = \operatorname{de-let} </math> | |||
# <math> \operatorname{de-let} \equiv \lambda V.\operatorname{de-let} </math> | |||
# <math> \operatorname{de-let} \equiv \operatorname{de-let}\ \operatorname{de-let} </math> | |||
# <math> \operatorname{de-let} \equiv V </math> | |||
# <math> V \not \in FV] \to \operatorname{de-let} \equiv \operatorname{get-lambda} </math> | |||
# <math> V \not \in FV] \to \operatorname{de-let} \equiv (\lambda V.\operatorname{de-let})\ \operatorname{get-lambda} </math> | |||
# <math> W \not \in \operatorname{FV}] \to \operatorname{de-let} \equiv \operatorname{de-let} </math> | |||
# <math> V \in \operatorname{FV}] \to \operatorname{de-let} \equiv \operatorname{de-let} \operatorname{in} L] </math> | |||
# <math> W \in \operatorname{FV}] \to \operatorname{de-let} \equiv \operatorname{de-let} \operatorname{in} \operatorname{let} W: F \operatorname{in} L] </math> | |||
There is no exact structural equivalent in lambda calculus for ''let'' expressions that have free variables that are used recursively. In this case some addition of parameters is required. The last two rules add these parameters. | |||
==== Examples ==== | |||
For example the ''let'' expression obtained from the ], | |||
: <math>\operatorname{let} p : p\ f = \operatorname{let} x : x\ q = f\ (q\ q) \operatorname{in} f\ (x\ x) \operatorname{in} p </math> | |||
is converted to, | |||
: <math>\lambda f.(\lambda x.f\ (x\ x))\ (\lambda q.f\ (q\ q)) </math> | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! Rule !! Lambda Expression | |||
|- | |||
| 6 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math>\operatorname{de-let} </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> V = p, E = p\ f = \operatorname{let} x : x\ q = f\ (q\ q) \operatorname{in} f\ (x\ x) </math> | |||
|- | |||
| <math> \operatorname{get-lambda} </math> | |||
|} | |||
|- | |||
| 1 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> \operatorname{get-lambda} </math> | |||
|- | |||
| <math> \operatorname{get-lambda} </math> | |||
|- | |||
| <math> F = p, G = p, V = f, E = \operatorname{let} x : x\ q = f\ (q\ q) \operatorname{in} f\ (x\ x) </math> | |||
|- | |||
| <math> \operatorname{get-lambda} </math> | |||
|} | |||
|- | |||
| 2 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> \operatorname{get-lambda} </math> | |||
|- | |||
| <math> \operatorname{get-lambda} </math> | |||
|- | |||
| <math> F = p, E = \lambda f.\operatorname{let} x : x\ q = f\ (q\ q) \operatorname{in} f\ (x\ x) </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|} | |||
|- | |||
| 3 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> V = f, E = \operatorname{let} x : x\ q = f\ (q\ q) \operatorname{in} f\ (x\ x) </math> | |||
|- | |||
| <math> \lambda V.\operatorname{de-let} </math> | |||
|} | |||
|- | |||
| 7 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> \lambda f.\operatorname{de-let} </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> V \not \in FV] \to \operatorname{de-let} </math> | |||
|- | |||
| <math> V = x, E = x\ q = f\ (q\ q), L = f\ (x\ x) </math> | |||
|- | |||
| <math> (\lambda V.\operatorname{de-let})\ \operatorname{get-lambda} </math> | |||
|} | |||
|- | |||
| 4 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> (\lambda x.\operatorname{de-let})\ \operatorname{get-lambda} </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> M = f, N = (x\ x) </math> | |||
|- | |||
| <math> \operatorname{de-let}\ \operatorname{de-let} </math> | |||
|- | |||
| <math> \operatorname{de-let}\ \operatorname{de-let} </math> | |||
|} | |||
|- | |||
| 4 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> (\lambda x.\operatorname{de-let}\ \operatorname{de-let})\ \operatorname{get-lambda} </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> M = x, N = x </math> | |||
|- | |||
| <math> \operatorname{de-let}\ \operatorname{de-let} </math> | |||
|- | |||
| <math> \operatorname{de-let}\ \operatorname{de-let} </math> | |||
|} | |||
|- | |||
| 5 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> (\lambda x.\operatorname{de-let}\ (\operatorname{de-let}\ \operatorname{de-let}))\ \operatorname{get-lambda} </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> V </math> | |||
|} | |||
|- | |||
| 1 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> (\lambda x.f\ (x\ x))\ \operatorname{get-lambda} </math> | |||
|- | |||
| <math> \operatorname{get-lambda} </math> | |||
|- | |||
| <math> \operatorname{get-lambda} </math> | |||
|- | |||
| <math> F = x, G = x, V = q, E = f\ (q\ q) </math> | |||
|- | |||
| <math> \operatorname{get-lambda} </math> | |||
|- | |||
| <math> \operatorname{get-lambda} </math> | |||
|} | |||
|- | |||
| 2 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> (\lambda x.f\ (x\ x))\ \operatorname{get-lambda} </math> | |||
|- | |||
| <math> \operatorname{get-lambda} </math> | |||
|- | |||
| <math> \operatorname{get-lambda} </math> | |||
|- | |||
| <math> F = x, E = \lambda q.f\ (q\ q) </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|} | |||
|- | |||
| 3 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> (\lambda x.f\ (x\ x))\ \operatorname{de-let} </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> V = q, E = f\ (q\ q) </math> | |||
|- | |||
| <math> \lambda V.\operatorname{de-let} </math> | |||
|- | |||
| <math> \lambda q.\operatorname{de-let} </math> | |||
|} | |||
|- | |||
| 4 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> (\lambda x.f\ (x\ x))\ (\lambda q.\operatorname{de-let}) </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> M_1 = f, N_1 = q\ q </math> | |||
|- | |||
| <math> \operatorname{de-let}\ \operatorname{de-let} </math> | |||
|- | |||
| <math> \operatorname{de-let}\ \operatorname{de-let} </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> M_2 = q, N_2 = q </math> | |||
|- | |||
| <math> \operatorname{de-let}\ \operatorname{de-let} </math> | |||
|} | |||
|- | |||
| 5 || | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! <math> (\lambda x.f\ (x\ x))\ (\lambda q.\operatorname{de-let}\ (\operatorname{de-let}\ \operatorname{de-let})) </math> | |||
|- | |||
| <math> \operatorname{de-let} </math> | |||
|- | |||
| <math> </math> | |||
|- | |||
| <math> V </math> | |||
|} | |||
|- | |||
| || <math> (\lambda x.f\ (x\ x))\ (\lambda q.f\ (q\ q)) </math> | |||
|} | |||
For a second example take the lifted version of the ], derived in ] | |||
:<math>\operatorname{let}p, q : p\ f\ x = f\ (x\ x) \and q\ p\ f = (p\ f)\ (p\ f) \operatorname{in} q\ p </math> | |||
is converted to, | |||
: <math> (\lambda p.(\lambda q.q\ p)\ \lambda p.\lambda f.(p\ f)\ (p\ f))\ \lambda f.\lambda x.f\ (x\ x) </math> | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! Rule !! Lambda Expression | |||
|- | |||
| 8 || <math>\operatorname{de-let} </math> | |||
|- | |||
| 7 || <math>\operatorname{de-let} </math> | |||
|- | |||
| 1, 2 || <math> (\lambda p.\operatorname{de-let})\ \operatorname{get-lambda} </math> | |||
|- | |||
| 7, 4, 5 || <math> (\lambda p.\operatorname{de-let})\ \lambda f.\lambda x.f\ (x\ x) </math> | |||
|- | |||
| 1, 2 || <math> (\lambda p.(\lambda q.q\ p)\ \operatorname{get-lambda})\ \lambda f.\lambda x.f\ (x\ x) </math> | |||
|- | |||
| || <math> (\lambda p.(\lambda q.q\ p)\ \lambda p.\lambda f.(p\ f)\ (p\ f))\ \lambda f.\lambda x.f\ (x\ x) </math> | |||
|} | |||
For a third example the translation of, | |||
: <math> \operatorname{let} x: x\ f = f\ (x\ f) \operatorname{in} x </math> | |||
is, | |||
: <math> (\lambda x.x\ x)\ (\lambda x.\lambda f.f\ (x\ x\ f)) </math> | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|- | |||
! Rule !! Lambda Expression | |||
|- | |||
| 9 || <math> \operatorname{let} x : x\ f = f\ (x\ f) \operatorname{in} x </math> | |||
|- | |||
| 1 || <math> \operatorname{let} x : \operatorname{get-lambda} \operatorname{in} x </math> | |||
|- | |||
| 2 || <math> \operatorname{let} x : \operatorname{get-lambda} \operatorname{in} x\ x </math> | |||
|- | |||
| || <math> \operatorname{let} x : (x = \lambda f.f\ (x\ f)) \operatorname{in} x\ x </math> | |||
|- | |||
| 7 || <math> \operatorname{let} x : (x\ x = \lambda f.f\ (x\ x\ f)) \operatorname{in} x\ x </math> | |||
|- | |||
| 1 || <math> (\lambda x.x\ x)\ \operatorname{get-lambda} </math> | |||
|- | |||
| 2 || <math> (\lambda x.x\ x)\ \operatorname{get-lambda} </math> | |||
|- | |||
| || <math> (\lambda x.x\ x)\ (\lambda x.\lambda f.f\ (x\ x\ f)) </math> | |||
|} | |||
== References == | |||
{{reflist}} | |||
{{reflist|group=note}} | |||
] |
Revision as of 14:48, 27 March 2014
A "let expression" associates a function with a restricted ]. Let expressions may be defined from Mathematics of for computer science.
The let expression may be considered as a lambda abstraction applied to a value. A let expression may also be considered as a conjunction of expressions, within an existential quantifier which restricts the scope of the variable.
The let expression is present in many functional languages to allow the local definition of expression, for use in defining another expression. The let-expression is present in many functional languages in two forms; let or "letrec". Letrec is an extension of the let expression which uses the Fixed-point combinator to implement recursion.
History
Dana Scotts LCF language was a stage in the evolution of lambda calculus into modern functional languages. This language introduce the let expression, which has appeared in most functional languages since that time.
The languages Miranda, ML, and more recently Haskel have evolved based on LCF.
State-full imperative languages such as and Pascal essentially implement a let expression, to implement restricted scope of functions, in block structures.
Definition
A lambda abstraction represents a function without a name. This is source of the inconsistency in the definition of a lambda abstraction. However lambda abstractions may be composed to represent a function with a name. In this form the inconsistency is removed. The lambda term,
is equivalent to defining the function by in the expression , which may be written as the let expression;
The let expression is understandable as a natural language expression. Used in Dana Scotts LCF language the let expression represents the substitution of a variable for a value. The substitution rule describes the implications of equality as substitution. The let expression is the conjunction of two expressions, with the substitution rule from one expression applied to the other.
Let definition
The let expression is the conjunction of expressions. In functional languages the let expression is also used to limit scope. In mathematics scope is described by quantifiers. The let expression is a conjunction within an existential quantifier.
The meaning of the let expression allows the substitution to be applied to another expression. This substitution may be applied within a restricted scope, to a sub expression. The natural use of the let expression is in application to a restricted scope. These results may be derived to describe how the scope may be restricted;
From this definition the following standard definition of a let expression, as used in a functional language may be derived.
To derive this result, first assume,
then
Using the rule of substitution,
so for all L,
Let where K is a new variable. then,
So,
But from the mathematical interpretation of a beta reduction,
Here if y is a function of a variable x, it is not the same x as in z. Alpha renaming may be applied. So we must have,
so,
This result is represented in a functional language in an abbreviated form, where the meaning is unambiguous;
Here the variable x is implicitly recognised as both part of the equation defining x, and the variable in the existential quantifier.
Joining let expressions
Let expressions may be defined with multiple variables,
then it can be derived,
so,
Conversion between lambda calculus and let expressions
The following rules describe the equivalence of lambda and let expressions,
Name | Law |
---|---|
Eta-reduction equivalence | |
Let-Lambda equivalence | (where f is a variable name). |
Let combination | (where f is a variable name). |
Meta-functions will be given that describe the conversion between lambda and let expressions. A meta-function is a function that takes a program as a parameter. The program is data for the meta-program. The program and the meta program are at different meta-levels.
The following conventions will be used to distinguish program from the meta program,
- Square brackets will be used to represent function application in the meta program.
- Capital letters will be used for variables in the meta program. Lower case letters represent variables in the program.
- will be used for equals in the meta program.
- represents a dummy variable, or an unknown value.
For simplicity the first rule given that matches will be applied. The rules also assume that the lambda expressions have been pre-processed so that each lambda abstraction has a unique name.
The substitution operator is used extensively. The expression means substitute every occurrence of G in L by S and return the expression. The definition used is extended to cover the substitution of expressions, from the definition given on the Lambda calculus page. The matching of expressions should compare expressions for alpha equivalence (renaming of variables).
Conversion from lambda to let expressions
The following rules describe how to convert from a Lambda expression to a let expression, without altering the structure.
Rule 6 creates a unique variable V, as a name for the function.
Example
For example the Y combinator,
is converted to,
Rule | Lambda Expression | |||||||
---|---|---|---|---|---|---|---|---|
6 |
| |||||||
4 |
| |||||||
5 |
| |||||||
3 |
| |||||||
9 |
| |||||||
9 |
| |||||||
4 |
| |||||||
2 |
| |||||||
1 |
| |||||||
Conversion from let to lambda expressions
These rule reverse the conversion described above. They convert from a let expression to a Lambda expression, without altering the structure. Not all let expressions may be converted using these rules. The rules assume that the expressions are already arranged as if they had been generated by de-lambda.
There is no exact structural equivalent in lambda calculus for let expressions that have free variables that are used recursively. In this case some addition of parameters is required. The last two rules add these parameters.
Examples
For example the let expression obtained from the Y combinator,
is converted to,
Rule | Lambda Expression | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
6 |
| |||||||||
1 |
| |||||||||
2 |
| |||||||||
3 |
| |||||||||
7 |
| |||||||||
4 |
| |||||||||
4 |
| |||||||||
5 |
| |||||||||
1 |
| |||||||||
2 |
| |||||||||
3 |
| |||||||||
4 |
| |||||||||
5 |
| |||||||||
For a second example take the lifted version of the Y combinator, derived in Lambda lifting
is converted to,
Rule | Lambda Expression |
---|---|
8 | |
7 | |
1, 2 | |
7, 4, 5 | |
1, 2 | |
For a third example the translation of,
is,
Rule | Lambda Expression |
---|---|
9 | |
1 | |
2 | |
7 | |
1 | |
2 | |
References
- "PCF is a programming language for computable functions, based on LCF, Scott’s logic of computable functions" (Plotkin 1977) harv error: no target: CITEREFPlotkin1977 (help). Programming Computable Functions is used by (Mitchell 1996) harv error: no target: CITEREFMitchell1996 (help). It is also referred to as Programming with Computable Functions or Programming language for Computable Functions.
- "PCF is a programming language for computable functions, based on LCF, Scott’s logic of computable functions" (Plotkin 1977) harv error: no target: CITEREFPlotkin1977 (help). Programming Computable Functions is used by (Mitchell 1996) harv error: no target: CITEREFMitchell1996 (help). It is also referred to as Programming with Computable Functions or Programming language for Computable Functions.