Lambda Lifting
   HOME

TheInfoList



OR:

Lambda lifting is a meta-process that restructures a
computer program A computer program is a sequence or set of instructions in a programming language for a computer to execute. Computer programs are one component of software, which also includes documentation and other intangible components. A computer program ...
so that functions are defined independently of each other in a global
scope Scope or scopes may refer to: People with the surname * Jamie Scope (born 1986), English footballer * John T. Scopes (1900–1970), central figure in the Scopes Trial regarding the teaching of evolution Arts, media, and entertainment * Cinem ...
. An individual "lift" transforms a local
function Function or functionality may refer to: Computing * Function key, a type of key on computer keyboards * Function model, a structured representation of processes in a system * Function object or functor or functionoid, a concept of object-oriente ...
into a global function. It is a two step process, consisting of; * Eliminating
free variables In mathematics, and in other disciplines involving formal languages, including mathematical logic and computer science, a free variable is a notation (symbol) that specifies places in an expression where substitution may take place and is not ...
in the function by adding parameters. * Moving functions from a restricted scope to broader or global scope. The term "lambda lifting" was first introduced by Thomas Johnsson around 1982 and was historically considered as a mechanism for implementing
functional programming language In computer science, functional programming is a programming paradigm where programs are constructed by applying and composing functions. It is a declarative programming paradigm in which function definitions are trees of expressions that m ...
s. It is used in conjunction with other techniques in some modern
compiler In computing, a compiler is a computer program that translates computer code written in one programming language (the ''source'' language) into another language (the ''target'' language). The name "compiler" is primarily used for programs that ...
s. Lambda lifting is not the same as closure conversion. It requires all
call site In programming, a spot of a function or subroutine is the location (line of code) where the function is called (or may be called, through dynamic dispatch). A call site is where zero or more arguments are passed to the function, and zero or more r ...
s to be adjusted (adding extra arguments to calls) and does not introduce a closure for the lifted lambda expression. In contrast, closure conversion does not require call sites to be adjusted but does introduce a closure for the lambda expression mapping free variables to values. The technique may be used on individual functions, in
code refactoring In computer programming and software design, code refactoring is the process of restructuring existing computer code—changing the '' factoring''—without changing its external behavior. Refactoring is intended to improve the design, structur ...
, to make a function usable outside the scope in which it was written. Lambda lifts may also be repeated, in order to transform the program. Repeated lifts may be used to convert a program written in
lambda calculus Lambda calculus (also written as ''λ''-calculus) is a formal system in mathematical logic for expressing computation based on function abstraction and application using variable binding and substitution. It is a universal model of computation ...
into a set of recursive functions, without lambdas. This demonstrates the equivalence of programs written in lambda calculus and programs written as functions. However it does not demonstrate the soundness of lambda calculus for deduction, as the
eta reduction Lambda calculus (also written as ''λ''-calculus) is a formal system in mathematical logic for expressing computation based on function abstraction and application using variable binding and substitution. It is a universal model of computation ...
used in lambda lifting is the step that introduces cardinality problems into the lambda calculus, because it removes the value from the variable, without first checking that there is only one value that satisfies the conditions on the variable (see
Curry's paradox Curry's paradox is a paradox in which an arbitrary claim ''F'' is proved from the mere existence of a sentence ''C'' that says of itself "If ''C'', then ''F''", requiring only a few apparently innocuous logical deduction rules. Since ''F'' is arbi ...
). Lambda lifting is expensive on processing time for the compiler. An efficient implementation of lambda lifting is O(n^2) on processing time for the compiler. In the
untyped lambda calculus Lambda calculus (also written as ''λ''-calculus) is a formal system in mathematical logic for expressing computation based on function abstraction and application using variable binding and substitution. It is a universal model of computation tha ...
, where the basic types are functions, lifting may change the result of
beta reduction Lambda calculus (also written as ''λ''-calculus) is a formal system in mathematical logic for expressing computation based on function abstraction and application using variable binding and substitution. It is a universal model of computation t ...
of a lambda expression. The resulting functions will have the same meaning, in a mathematical sense, but are not regarded as the same function in the untyped lambda calculus. See also intensional versus extensional equality. The reverse operation to lambda lifting is lambda dropping. Lambda dropping may make the compilation of programs quicker for the compiler, and may also increase the efficiency of the resulting program, by reducing the number of parameters, and reducing the size of stack frames. However it makes a function harder to re-use. A dropped function is tied to its context, and can only be used in a different context if it is first lifted.


Algorithm

The following algorithm is one way to lambda-lift an arbitrary program in a language which doesn't support closures as
first-class object In programming language design, a first-class citizen (also type, object, entity, or value) in a given programming language is an entity which supports all the operations generally available to other entities. These operations typically include ...
s: # Rename the functions so that each function has a unique name. # Replace each free variable with an additional argument to the enclosing function, and pass that argument to every use of the function. # Replace every local function definition that has no free variables with an identical global function. # Repeat steps 2 and 3 until all free variables and local functions are eliminated. If the language has closures as first-class objects that can be passed as arguments or returned from other functions, the closure will need to be represented by a data structure that captures the bindings of the free variables.


Example

The following
OCaml OCaml ( , formerly Objective Caml) is a general-purpose programming language, general-purpose, multi-paradigm programming language which extends the Caml dialect of ML (programming language), ML with object-oriented programming, object-oriented ...
program computes the sum of the integers from 1 to 100: let rec sum n = if n = 1 then 1 else let f x = n + x in f (sum (n - 1)) in sum 100 (The let rec declares sum as a function that may call itself.) The function f, which adds sum's argument to the sum of the numbers less than the argument, is a local function. Within the definition of f, n is a free variable. Start by converting the free variable to a parameter: let rec sum n = if n = 1 then 1 else let f w x = w + x in f n (sum (n - 1)) in sum 100 Next, lift f into a global function: let rec f w x = w + x and sum n = if n = 1 then 1 else f n (sum (n - 1)) in sum 100 The following is the same example, this time written in
JavaScript JavaScript (), often abbreviated as JS, is a programming language that is one of the core technologies of the World Wide Web, alongside HTML and CSS. As of 2022, 98% of Website, websites use JavaScript on the Client (computing), client side ...
: // Initial version function sum(n) // After converting the free variable n to a formal parameter w function sum(n) // After lifting function f into the global scope function f(w, x) function sum(n)


Lambda lifting versus closures

Lambda lifting and closure are both methods for implementing block structured programs. It implements block structure by eliminating it. All functions are lifted to the global level. Closure conversion provides a "closure" which links the current frame to other frames. Closure conversion takes less compile time. Recursive functions, and block structured programs, with or without lifting, may be implemented using a
stack Stack may refer to: Places * Stack Island, an island game reserve in Bass Strait, south-eastern Australia, in Tasmania’s Hunter Island Group * Blue Stack Mountains, in Co. Donegal, Ireland People * Stack (surname) (including a list of people ...
based implementation, which is simple and efficient. However a stack frame based implementation must be strict (eager). The stack frame based implementation requires that the life of functions be last-in, first-out (LIFO). That is, the most recent function to start its calculation must be the first to end. Some functional languages (such as
Haskell Haskell () is a general-purpose, statically-typed, purely functional programming language with type inference and lazy evaluation. Designed for teaching, research and industrial applications, Haskell has pioneered a number of programming lan ...
) are implemented using
lazy evaluation In programming language theory, lazy evaluation, or call-by-need, is an evaluation strategy which delays the evaluation of an expression until its value is needed (non-strict evaluation) and which also avoids repeated evaluations (sharing). The b ...
, which delays calculation until the value is needed. The lazy implementation strategy gives flexibility to the programmer. Lazy evaluation requires delaying the call to a function until a request is made to the value calculated by the function. One implementation is to record a reference to a "frame" of data describing the calculation, in place of the value. Later when the value is required, the frame is used to calculate the value, just in time for when it is needed. The calculated value then replaces the reference. The "frame" is similar to a
stack frame In computer science, a call stack is a stack data structure that stores information about the active subroutines of a computer program. This kind of stack is also known as an execution stack, program stack, control stack, run-time stack, or mac ...
, the difference being that it is not stored on the stack. Lazy evaluation requires that all the data required for the calculation be saved in the frame. If the function is "lifted", then the frame needs only record the
function pointer A function pointer, also called a subroutine pointer or procedure pointer, is a pointer that points to a function. As opposed to referencing a data value, a function pointer points to executable code within memory. Dereferencing the function poin ...
, and the parameters to the function. Some modern languages use
garbage collection Waste collection is a part of the process of waste management. It is the transfer of solid waste from the point of use and disposal to the point of treatment or landfill. Waste collection also includes the curbside collection of recyclable m ...
in place of stack based allocation to manage the life of variables. In a managed, garbage collected environment, a closure records references to the frames from which values may be obtained. In contrast a lifted function has parameters for each value needed in the calculation.


Let expressions and lambda calculus

The
Let expression In computer science, a "let" expression associates a function definition with a restricted scope. The "let" expression may also be defined in mathematics, where it associates a Boolean condition with a restricted scope. The "let" expression may b ...
is useful in describing lifting and dropping, and in describing the relationship between recursive equations and lambda expressions. Most functional languages have let expressions. Also, block structured programming languages like
ALGOL ALGOL (; short for "Algorithmic Language") is a family of imperative computer programming languages originally developed in 1958. ALGOL heavily influenced many other languages and was the standard method for algorithm description used by the ...
and
Pascal Pascal, Pascal's or PASCAL may refer to: People and fictional characters * Pascal (given name), including a list of people with the name * Pascal (surname), including a list of people and fictional characters with the name ** Blaise Pascal, Fren ...
are similar in that they too allow the local definition of a function for use in a restricted
scope Scope or scopes may refer to: People with the surname * Jamie Scope (born 1986), English footballer * John T. Scopes (1900–1970), central figure in the Scopes Trial regarding the teaching of evolution Arts, media, and entertainment * Cinem ...
. The ''let'' expression used here is a fully mutually recursive version of ''let rec'', as implemented in many functional languages. Let expressions are related to
Lambda calculus Lambda calculus (also written as ''λ''-calculus) is a formal system in mathematical logic for expressing computation based on function abstraction and application using variable binding and substitution. It is a universal model of computation ...
. Lambda calculus has a simple syntax and semantics, and is good for describing Lambda lifting. It is convenient to describe lambda lifting as a translations from ''lambda'' to a ''let'' expression, and lambda dropping as the reverse. This is because ''let'' expressions allow mutual recursion, which is, in a sense, more lifted than is supported in lambda calculus. Lambda calculus does not support mutual recursion and only one function may be defined at the outermost global scope. Conversion rules which describe translation without lifting are given in the
Let expression In computer science, a "let" expression associates a function definition with a restricted scope. The "let" expression may also be defined in mathematics, where it associates a Boolean condition with a restricted scope. The "let" expression may b ...
article. The following rules describe the equivalence of lambda and let expressions, Meta-functions will be given that describe lambda lifting and dropping. 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. * \equiv 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 L := S 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 Lambda calculus (also written as ''λ''-calculus) is a formal system in mathematical logic for expressing computation based on function abstraction and application using variable binding and substitution. It is a universal model of computation ...
page. The matching of expressions should compare expressions for alpha equivalence (renaming of variables).


Lambda lifting in lambda calculus

Each lambda lift takes a lambda abstraction which is a sub expression of a lambda expression and replaces it by a function call (application) to a function that it creates. The free variables in the sub expression are the parameters to the function call. Lambda lifts may be used on individual functions, in
code refactoring In computer programming and software design, code refactoring is the process of restructuring existing computer code—changing the '' factoring''—without changing its external behavior. Refactoring is intended to improve the design, structur ...
, to make a function usable outside the scope in which it was written. Such lifts may also be repeated, until the expression has no lambda abstractions, in order to transform the program.


Lambda lift

A lift is given a sub-expression within an expression to lift to the top of that expression. The expression may be part of a larger program. This allows control of where the sub-expression is lifted to. The lambda lift operation used to perform a lift within a program is, : \operatorname , L, P=P _:=_\operatorname[S,_L_ The_sub_expression_may_be_either_a_lambda_abstraction,_or_a_lambda_abstraction_applied_to_a_parameter. Two_types_of_lift_are_possible. *_ _:=_\operatorname[S,_L_ The_sub_expression_may_be_either_a_lambda_abstraction,_or_a_lambda_abstraction_applied_to_a_parameter. Two_types_of_lift_are_possible. *_#Anonymous_lift">Anonymous_lift *_#Named_lift.html" ;"title="#Anonymous_lift.html" ;"title=",_L.html" ;"title=" := \operatorname[S, L"> := \operatorname[S, L The sub expression may be either a lambda abstraction, or a lambda abstraction applied to a parameter. Two types of lift are possible. * #Anonymous lift">Anonymous lift * #Named lift">Named lift An anonymous lift has a lift expression which is a lambda abstraction only. It is regarded as defining an anonymous function. A name must be created for the function. A named lift expression has a lambda abstraction applied to an expression. This lift is regarded as a named definition of a function.


Anonymous lift

An anonymous lift takes a lambda abstraction (called ''S''). For ''S''; * Create a name for the function that will replace ''S'' (called ''V''). Make sure that the name identified by ''V'' has not been used. * Add parameters to ''V'', for all the free variables in ''S'', to create an expression ''G'' (see ''make-call''). The lambda lift is the substitution of the lambda abstraction ''S'' for a function application, along with the addition of a definition for the function. : \operatorname[S, L] \equiv \operatorname V: \operatorname = S\operatorname L[S:=G] The new lambda expression has ''S'' substituted for G. Note that ''L''[''S'':=''G''] means substitution of ''S'' for ''G'' in ''L''. The function definitions has the function definition ''G = S'' added. In the above rule ''G'' is the function application that is substituted for the expression ''S''. It is defined by, : G = \operatorname , \operatorname[S where ''V'' is the function name. It must be a new variable, i.e. a name not already used in the lambda expression, : V \not \in \operatorname[\operatorname F \operatorname L] where \operatorname is a meta function that returns the set of variables used in ''E''.


= Constructing the call

= The function call ''G'' is constructed by adding parameters for each variable in the free variable set (represented by ''V''), to the function ''H'', * X \in V \to \operatorname
, V The comma is a punctuation mark that appears in several variants in different languages. It has the same shape as an apostrophe or single closing quotation mark () in many typefaces, but it differs from them in being placed on the baseline (t ...
\equiv \operatorname , V \cap \neg \ X * \operatorname , \\equiv H


Named lift

The named lift is similar to the anonymous lift except that the function name ''V'' is provided. : \operatorname \lambda V.E)\ S, L\equiv \operatorname V : \operatorname = S\operatorname L \lambda V.E)\ S:=E[V:=G As for the anonymous lift, the expression ''G'' is constructed from ''V'' by applying the free variables of ''S''. It is defined by, : G = \operatorname , \operatorname[S


Lambda-lift transformation

A lambda lift transformation takes a lambda expression and lifts all lambda abstractions to the top of the expression. The abstractions are then translated into recursive functions, which eliminates the lambda abstractions. The result is a functional program in the form, * \operatorname M \operatorname N where ''M'' is a series of function definitions, and ''N'' is the expression representing the value returned. For example, : \operatorname[\lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x))] \equiv \operatorname p\ f\ x = f\ (x\ x) \land q\ p\ f = (p\ f)\ (p\ f) \operatorname q\ p The ''de-let'' meta function may then be used to convert the result back into lambda calculus. : \operatorname operatorname[\lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x)) \equiv (\lambda p.(\lambda q.q\ p)\ \lambda p.\lambda f.(p\ f)\ (p\ f))\ \lambda f.\lambda x.f\ (x\ x) The processing of transforming the lambda expression is a series of lifts. Each lift has, * A sub expression chosen for it by the function ''lift-choice''. The sub expression should be chosen so that it may be converted into an equation with no lambdas. * The lift is performed by a call to the ''lambda-lift'' meta function, described in the next section, :\begin \operatorname[L] = \operatorname[\operatorname[\operatorname[L]\\ \operatorname[L] = \operatorname[\operatorname[L],L]\\ \operatorname[\operatorname, L] = L\\ \operatorname[S, L] = \operatorname[\operatorname[S, L \end After the lifts are applied the lets are combined together into a single let. :\begin \operatorname operatorname V : E \operatorname \operatorname W : F \operatorname G= \operatorname operatorname V, W : E \land F \operatorname G\\ \operatorname = E \end Then Parameter dropping is applied to remove parameters that are not necessary in the "let" expression. The let expression allows the function definitions to refer to each other directly, whereas lambda abstractions are strictly hierarchical, and a function may not directly refer to itself.


Choosing the expression for lifting

There are two different ways that an expression may be selected for lifting. The first treats all lambda abstractions as defining anonymous functions. The second, treats lambda abstractions which are applied to a parameter as defining a function. Lambda abstractions applied to a parameter have a dual interpretation as either a let expression defining a function, or as defining an anonymous function. Both interpretations are valid. These two predicates are needed for both definitions. ''lambda-free'' - An expression containing no lambda abstractions. :\begin \operatorname
lambda F.X Lambda (}, ''lám(b)da'') is the 11th letter of the Greek alphabet, representing the voiced alveolar lateral approximant . In the system of Greek numerals, lambda has a value of 30. Lambda is derived from the Phoenician Lamed . Lambda gave rise ...
= \operatorname \\ \operatorname = \operatorname \\ \operatorname \ N= \operatorname \land \operatorname \end ''lambda-anon'' - An anonymous function. An expression like \lambda x_1.\ ...\ \lambda x_n.X where X is lambda free. :\begin \operatorname
lambda F.X Lambda (}, ''lám(b)da'') is the 11th letter of the Greek alphabet, representing the voiced alveolar lateral approximant . In the system of Greek numerals, lambda has a value of 30. Lambda is derived from the Phoenician Lamed . Lambda gave rise ...
= \operatorname \lor \operatorname \\ \operatorname = \operatorname \\ \operatorname \ N= \operatorname \end


= Choosing anonymous functions only for lifting

= Search for the deepest anonymous abstraction, so that when the lift is applied the function lifted will become a simple equation. This definition does not recognize a lambda abstractions with a parameter as defining a function. All lambda abstractions are regarded as defining anonymous functions. ''lift-choice'' - The first anonymous found in traversing the expression or ''none'' if there is no function. # \operatorname \to \operatorname = X # \operatorname
lambda F.X Lambda (}, ''lám(b)da'') is the 11th letter of the Greek alphabet, representing the voiced alveolar lateral approximant . In the system of Greek numerals, lambda has a value of 30. Lambda is derived from the Phoenician Lamed . Lambda gave rise ...
= \operatorname /math> # \operatorname \ne \operatorname \to \operatorname \ N= \operatorname # \operatorname \ N= \operatorname # \operatorname = \operatorname For example,


= Choosing named and anonymous functions for lifting

= Search for the deepest named or anonymous function definition, so that when the lift is applied the function lifted will become a simple equation. This definition recognizes a lambda abstraction with an actual parameter as defining a function. Only lambda abstractions without an application are treated as anonymous functions. ; ''lambda-named'' : A named function. An expression like (\lambda F.M)\ N where M is lambda free and N is lambda free or an anonymous function. :: \begin \operatorname \lambda F.M)\ N= \operatorname \land \operatorname \\ \operatorname
lambda F.X Lambda (}, ''lám(b)da'') is the 11th letter of the Greek alphabet, representing the voiced alveolar lateral approximant . In the system of Greek numerals, lambda has a value of 30. Lambda is derived from the Phoenician Lamed . Lambda gave rise ...
= \operatorname \\ \operatorname = \operatorname \end ; ''lift-choice'' : The first anonymous or named function found in traversing the expression or ''none'' if there is no function. :# \operatorname \lor \operatorname \to \operatorname = X :# \operatorname
lambda F.X Lambda (}, ''lám(b)da'') is the 11th letter of the Greek alphabet, representing the voiced alveolar lateral approximant . In the system of Greek numerals, lambda has a value of 30. Lambda is derived from the Phoenician Lamed . Lambda gave rise ...
= \operatorname /math> :# \operatorname \ne \operatorname \to \operatorname \ N= \operatorname :# \operatorname \ N= \operatorname :# \operatorname = \operatorname For example,


Examples

For example, the
Y combinator Y Combinator (YC) is an American technology startup accelerator launched in March 2005. It has been used to launch more than 3,000 companies, including Airbnb, Coinbase, Cruise, DoorDash, Dropbox, Instacart, Quora, PagerDuty, Reddit, Str ...
, : \lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x)) is lifted as, : \operatorname x\ f\ y = f\ (y\ y) \land q\ x\ f = f\ ((x\ f)\ (x\ f)) \operatorname q\ x and after Parameter dropping, : \operatorname x\ f\ y = f\ (y\ y) \land q\ f = f\ ((x\ f)\ (x\ f)) \operatorname q As a lambda expression (see Conversion from let to lambda expressions), : (\lambda x.(\lambda q.q)\ \lambda f.f\ (x\ f)\ (x\ f))\ \lambda f.\lambda y.f\ (y\ y) If lifting anonymous functions only, the Y combinator is, : \operatorname p\ f\ x = f\ (x\ x) \land q\ p\ f = (p\ f)\ (p\ f) \operatorname q\ p and after Parameter dropping, : \operatorname p\ f\ x = f\ (x\ x) \land q\ f = (p\ f)\ (p\ f) \operatorname q As a lambda expression, : (\lambda p.(\lambda q.q)\ \lambda f.(p\ f)\ (p\ f))\ \lambda f.\lambda x.f\ (x\ x) The first sub expression to be chosen for lifting is \lambda x.f\ (x\ x) . This transforms the lambda expression into \lambda f.(p\ f)\ (p\ f) and creates the equation p\ f\ x = f (x\ x) . The second sub expression to be chosen for lifting is \lambda f.(p\ f)\ (p\ f). This transforms the lambda expression into q\ p and creates the equation q\ p\ f = (p\ f)\ (p\ f) . And the result is, : \operatorname p\ f\ x = f\ (x\ x) \land q\ p\ f = (p\ f)\ (p\ f) \operatorname q\ p\ Surprisingly this result is simpler than the one obtained from lifting named functions.


Execution

Apply function to , :\begin \lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x))\ K & \ \operatorname\ p\ f\ x = f\ (x\ x) \land q\ p\ f = (p\ f)\ (p\ f) \ \operatorname\ q\ p\ K \\ (\lambda x.K\ (x\ x))\ (\lambda x.K\ (x\ x)) & \ \operatorname\ p\ f\ x = f\ (x\ x) \land q\ p\ f = (p\ f)\ (p\ f) \ \operatorname\ p\ K\ (p\ K) \\ K\ ((\lambda x.K\ (x\ x))\ (\lambda x.K\ (x\ x))) & \ \operatorname\ p\ f\ x = f\ (x\ x) \land q\ p\ f = p\ f\ (p\ f) \ \operatorname\ K\ (p\ K\ (p\ K)) \\ \end So, : (\lambda x.K\ (x\ x))\ (\lambda x.K\ (x\ x)) = K\ ((\lambda x.K\ (x\ x))\ (\lambda x.K\ (x\ x))))\ or : p\ K\ (p\ K) = K\ (p\ K\ (p\ K)) The Y-Combinator calls its parameter (function) repeatedly on itself. The value is defined if the function has a fixed point. But the function will never terminate.


Lambda dropping in lambda calculus

Lambda dropping is making the scope of functions smaller and using the context from the reduced scope to reduce the number of parameters to functions. Reducing the number of parameters makes functions easier to comprehend. In the
Lambda lifting Lambda lifting is a meta-process that restructures a computer program so that functions are defined independently of each other in a global scope. An individual "lift" transforms a local function into a global function. It is a two step process ...
section, a meta function for first lifting and then converting the resulting lambda expression into recursive equation was described. The Lambda Drop meta function performs the reverse by first converting recursive equations to lambda abstractions, and then dropping the resulting lambda expression, into the smallest scope which covers all references to the lambda abstraction. Lambda dropping is performed in two steps, * Sinking * Parameter dropping


Lambda drop

A Lambda drop is applied to an expression which is part of a program. Dropping is controlled by a set of expressions from which the drop will be excluded. : \operatorname , P, X= P _:=_\operatorname[\operatorname[L,_X.html" ;"title="operatorname[L,_X.html" ;"title=" := \operatorname[\operatorname[L, X"> := \operatorname[\operatorname[L, X">operatorname[L,_X.html" ;"title=" := \operatorname[\operatorname[L, X"> := \operatorname[\operatorname[L, X where, : ''L'' is the lambda abstraction to be dropped. : ''P'' is the program : ''X'' is a set of expressions to be excluded from dropping.


Lambda drop transformation

The lambda drop transformation sinks all abstractions in an expression. Sinking is excluded from expressions in a set of expressions, : \operatorname , X= \operatorname[\operatorname[\operatorname[L, X] where, : ''L'' is the expression to be transformed. : ''X'' is a set of sub expressions to be excluded from the dropping. ''sink-tran'' sinks each abstraction, starting from the innermost, :\begin \operatorname \lambda N.B)\ Y, X= \operatorname \lambda_N.\operatorname[B\_\operatorname[Y.html" ;"title=".html" ;"title="\lambda N.\operatorname[B">\lambda N.\operatorname[B\ \operatorname[Y">.html" ;"title="\lambda N.\operatorname[B">\lambda N.\operatorname[B\ \operatorname[Y X] \\ \operatorname[\lambda N.B, X] = \lambda N.\operatorname[B, X] \\ \operatorname[M\ N, X] = \operatorname[M, X]\ \operatorname[M, X] \\ \operatorname[V, X] = V \end


Abstraction sinking

Sinking is moving a lambda abstraction inwards as far as possible such that it is still outside all references to the variable. Application - 4 cases. :\begin E \not \in \operatorname \land E \not \in \operatorname \to \operatorname \lambda E.G\ H)\ Y, X= G\ H \\ E \not \in \operatorname \land E \in \operatorname \to \operatorname \lambda E.G\ H)\ Y, X= \operatorname \ \operatorname[(\lambda E.H)\ Y, X \\ E \in \operatorname \land E \not \in \operatorname \to \operatorname \lambda E.G\ H)\ Y, X= (\operatorname[(\lambda E.G)\ Y, X])\ H \\ E \in \operatorname \land E \in \operatorname \to \operatorname \lambda E.G\ H)\ Y, X= (\lambda E.G\ H)\ Y \end Abstraction. Use renaming to insure that the variable names are all distinct. :V \ne W \to \operatorname \lambda V.\lambda W.E)\ Y, X= \lambda W.\operatorname \lambda V.E)\ Y, X Variable - 2 cases. :E \ne V \to \operatorname \lambda E.V)\ Y, X= V :E = V \to \operatorname \lambda E.V)\ Y, X= Y Sink test excludes expressions from dropping, : L \in X \to \operatorname , X= L : L \not \in X \to \operatorname , X= \operatorname , X


Example


Parameter dropping

Parameter dropping is optimizing a function for its position in the function. Lambda lifting added parameters that were necessary so that a function can be moved out of its context. In dropping, this process is reversed, and extra parameters that contain variables that are free may be removed. Dropping a parameter is removing an unnecessary parameter from a function, where the actual parameter being passed in is always the same expression. The free variables of the expression must also be free where the function is defined. In this case the parameter that is dropped is replaced by the expression in the body of the function definition. This makes the parameter unnecessary. For example, consider, : \lambda m,p,q.(\lambda g.\lambda n.(n\ (g\ m\ p\ n)\ (g\ q\ p\ n)))\ \lambda x.\lambda o.\lambda y.o\ x\ y In this example the actual parameter for the formal parameter ''o'' is always ''p''. As ''p'' is a free variable in the whole expression, the parameter may be dropped. The actual parameter for the formal parameter ''y'' is always ''n''. However ''n'' is bound in a lambda abstraction. So this parameter may not be dropped. The result of dropping the parameter is, : \operatorname[\lambda m,p,q.(\lambda g.\lambda n.n\ (g\ m\ p\ n)\ (g\ q\ p\ n))\ \lambda x.\lambda o.\lambda y.o\ x\ y :::::: \equiv \lambda m,p,q.(\lambda g.\lambda n.n\ (g\ m\ n)\ (g\ q\ n))\ \lambda x.\lambda y.p\ x\ y For the main example, : \operatorname[ \lambda f.(\lambda p.(p\ f)\ (p\ f))\ (\lambda f.\lambda x.f\ (x\ x))] :::::: \equiv \lambda f.(\lambda p.p\ p)\ (\lambda x.f\ (x\ x)) The definition of ''drop-params-tran'' is, :\operatorname[L] \equiv (\operatorname[L, D, FV[L], [) where, : \operatorname , D, V, \_


Build parameter lists

For each abstraction that defines a function, build the information required to make decisions on dropping names. This information describes each parameter; the parameter name, the expression for the actual value, and an indication that all the expressions have the same value. For example, in, : \lambda m,p,q.(\lambda g.\lambda n.(n\ (g\ m\ p\ n)\ (g\ q\ p\ n)))\ \lambda x.\lambda o.\lambda y.o\ x\ y the parameters to the function ''g'' are, Each abstraction is renamed with a unique name, and the parameter list is associated with the name of the abstraction. For example, ''g'' there is parameter list. : D = x, \operatorname, \_ , \_, p , \_, n ''build-param-lists'' builds all the lists for an expression, by traversing the expression. It has four parameters; * The lambda expression being analyzed. * The table parameter lists for names. * The table of values for parameters. * The returned parameter list, which is used internally by the Abstraction - A lambda expression of the form (\lambda N.S)\ L is analyzed to extract the names of parameters for the function. :\begin \operatorname \lambda N.S)\ L, D, V, R\equiv \operatorname , D, V, R\land \operatorname ,_D,_V,_D[N_\\ \operatorname[\lambda_N.S,_D,_V,_R.html" ;"title=".html" ;"title=", D, V, D[N">, D, V, D[N \\ \operatorname[\lambda N.S, D, V, R">.html" ;"title=", D, V, D[N">, D, V, D[N \\ \operatorname[\lambda N.S, D, V, R\equiv \operatorname , D, V, R \end Locate the name and start building the parameter list for the name, filling in the formal parameter names. Also receive any actual parameter list from the body of the expression, and return it as the actual parameter list from this expression :\begin \operatorname[\lambda P.B, D, V, [X, \_, \_]::L] \equiv \operatorname[B, D, V, L] \\ \operatorname[B, D, V, [ \equiv \operatorname[B, D, V, \_] \end Variable - A call to a function. : \operatorname , D, V, D[N For a function name or parameter start populating actual parameter list by outputting the parameter list for this name. Application - An application (function call) is processed to extract actual parameter details. : \operatorname \ P, D, V, R\equiv \operatorname , D, V, T\land \operatorname , D, V, K :: \land T = , S, A:R \land (S \implies (\operatorname , P\land V = A)) \land D = K Retrieve the parameter lists for the expression, and the parameter. Retrieve a parameter record from the parameter list from the expression, and check that the current parameter value matches this parameter. Record the value for the parameter name for use later in checking. :\begin \operatorname , N\equiv A = N \lor (\operatorname [N_\land_A_=_V[N.html"_;"title=".html"_;"title="[N">[N_\land_A_=_V[N">.html"_;"title="[N">[N_\land_A_=_V[N_&_\textN\text_\\ \operatorname[A,_E.html" ;"title="">[N_\land_A_=_V[N.html" ;"title=".html" ;"title="[N">[N \land A = V[N">.html" ;"title="[N">[N \land A = V[N & \textN\text \\ \operatorname[A, E">">[N_\land_A_=_V[N.html" ;"title=".html" ;"title="[N">[N \land A = V[N">.html" ;"title="[N">[N \land A = V[N & \textN\text \\ \operatorname[A, E\equiv A = E & \text \end The above logic is quite subtle in the way that it works. The same value indicator is never set to true. It is only set to false if all the values cannot be matched. The value is retrieved by using ''S'' to build a set of the Boolean values allowed for ''S''. If true is a member then all the values for this parameter are equal, and the parameter may be dropped. : \operatorname \equiv S \in \ Similarly, ''def'' uses set theory to query if a variable has been given a value; : \operatorname \equiv , \, Let - Let expression. : \operatorname operatorname V: E \operatorname L, D, V, \_\equiv \operatorname , D, V, \_\land \operatorname , D, V, \_ And - For use in "let". : \operatorname \land F, D, V, \_\equiv \operatorname , D, V, \_\land \operatorname , D, V, \_/math>


= Examples

= For example, building the parameter lists for, : \lambda m,p,q.(\lambda g.\lambda n.(n\ (g\ m\ p\ n)\ (g\ q\ p\ n)))\ \lambda x.\lambda o.\lambda y.o\ x\ y gives, : D = x, \operatorname, \_ , \operatorname, p , \operatorname, n and the parameter o is dropped to give, : \lambda m,p,q.(\lambda g.\lambda n.(n\ (g\ m\ n)\ (g\ q\ n)))\ \lambda x.\lambda y.p\ x\ y Another example is, : \lambda f.((\lambda p.f\ (p\ p\ f))\ (\lambda q.\lambda x.x\ (q\ q\ x)) Here x is equal to f. The parameter list mapping is, : D = q, \_, p , \_, f and the parameter x is dropped to give, : \lambda f.((\lambda q.f\ (q\ q))\ (\lambda q.f\ (q\ q))


Drop parameters

Use the information obtained by Build parameter lists to drop actual parameters that are no longer required. ''drop-params'' has the parameters, * The lambda expression in which the parameters are to be dropped. * The mapping of variable names to parameter lists (built in Build parameter lists). * The set of variables free in the lambda expression. * The returned parameter list. A parameter used internally in the algorithm. Abstraction : \operatorname \lambda N.S)\ L, D, V, R\equiv (\lambda N.\operatorname , D, F, R\ \operatorname [N_L,_F.html"_;"title=".html"_;"title="[N">[N_L,_F">.html"_;"title="[N">[N_L,_F_ where, :__F_=_FV[(\lambda_N.S)\_L.html" ;"title="">[N_L,_F.html" ;"title=".html" ;"title="[N">[N L, F">.html" ;"title="[N">[N L, F where, : F = FV[(\lambda N.S)\ L">">[N_L,_F.html" ;"title=".html" ;"title="[N">[N L, F">.html" ;"title="[N">[N L, F where, : F = FV[(\lambda N.S)\ L : \operatorname[\lambda N.S, D, V, R] \equiv (\lambda N.\operatorname , D, F, R where, : F = FV lambda N.S Variable : \operatorname , D, V, D[N \equiv N For a function name or parameter start populating actual parameter list by outputting the parameter list for this name. Application - An application (function call) is processed to extract : (\operatorname \land \operatorname \land FV \subset V) \to \operatorname \ P, D, V, R\equiv \operatorname[E, D, V, , S, A:R] : \neg (\operatorname \land \operatorname \land FV \subset V) \to \operatorname \ P, D, V, R\equiv \operatorname ,_S,_A:R.html" ;"title=", D, V, , S, A:R">, D, V, , S, A:R \operatorname , D, V, \_ Let - Let expression. :\operatorname operatorname V: E \operatorname L\equiv \operatorname V: \operatorname ,_D,_FV[E_[.html"_;"title=".html"_;"title=",_D,_FV[E">,_D,_FV[E_[">.html"_;"title=",_D,_FV[E">,_D,_FV[E_[_\operatorname_\operatorname[L,_D,_FV[L.html" ;"title="">,_D,_FV[E_[.html" ;"title=".html" ;"title=", D, FV[E">, D, FV[E [">.html" ;"title=", D, FV[E">, D, FV[E [ \operatorname \operatorname[L, D, FV[L">">,_D,_FV[E_[.html" ;"title=".html" ;"title=", D, FV[E">, D, FV[E [">.html" ;"title=", D, FV[E">, D, FV[E [ \operatorname \operatorname[L, D, FV[L [ And - For use in "let". : \operatorname \land F, D, V, \_\equiv \operatorname , D, V, \_\land \operatorname , D, V, \_/math>


= Drop formal parameters

= ''drop-formal'' removes formal parameters, based on the contents of the drop lists. Its parameters are, * The drop list, * The function definition (lambda abstraction). * The free variables from the function definition. ''drop-formal'' is defined as, # (\operatorname \land FV \subset V) \to \operatorname ,_S,_A:Z,_\lambda_F.Y,_V.html" ;"title=", S, A:Z, \lambda F.Y, V">, S, A:Z, \lambda F.Y, V\equiv \operatorname ,_S,_A:Z,_Y[F:=A.html" ;"title=", S, A:Z, Y[F:=A">, S, A:Z, Y[F:=A L] # \neg (\operatorname \land FV \subset V) \to \operatorname ,_S,_A:Z,_\lambda_F.Y,_V.html" ;"title=", S, A:Z, \lambda F.Y, V">, S, A:Z, \lambda F.Y, V\equiv \lambda F.\operatorname ,_S,_A:Z,_Y,_V.html" ;"title=", S, A:Z, Y, V">, S, A:Z, Y, V # \operatorname , Y, V\equiv Y Which can be explained as, # If all the actual parameters have the same value, and all the free variables of that value are available for definition of the function then drop the parameter, and replace the old parameter with its value. # else do not drop the parameter. # else return the body of the function.


Example

Starting with the function definition of the Y-combinator, :\operatorname p\ f\ x = f\ (x\ x) \land q\ p\ f = (p\ f)\ (p\ f) \operatorname q\ p\ Which gives back the
Y combinator Y Combinator (YC) is an American technology startup accelerator launched in March 2005. It has been used to launch more than 3,000 companies, including Airbnb, Coinbase, Cruise, DoorDash, Dropbox, Instacart, Quora, PagerDuty, Reddit, Str ...
, : \lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x))


See also

*
Let expression In computer science, a "let" expression associates a function definition with a restricted scope. The "let" expression may also be defined in mathematics, where it associates a Boolean condition with a restricted scope. The "let" expression may b ...
*
Fixed-point combinator In mathematics and computer science in general, a '' fixed point'' of a function is a value that is mapped to itself by the function. In combinatory logic for computer science, a fixed-point combinator (or fixpoint combinator) is a higher-order fu ...
*
Lambda calculus Lambda calculus (also written as ''λ''-calculus) is a formal system in mathematical logic for expressing computation based on function abstraction and application using variable binding and substitution. It is a universal model of computation ...
*
Deductive lambda calculus Deductive lambda calculus considers what happens when lambda terms are regarded as mathematical expressions. One interpretation of the untyped lambda calculus is as a programming language where evaluation proceeds by performing reductions on an ex ...
*
Supercombinator A supercombinator is a mathematical expression which is Free variables and bound variables, fully bound and self-contained. It may be either a constant (mathematics), constant or a combinator where all the subexpressions are supercombinators. Su ...
*
Curry's paradox Curry's paradox is a paradox in which an arbitrary claim ''F'' is proved from the mere existence of a sentence ''C'' that says of itself "If ''C'', then ''F''", requiring only a few apparently innocuous logical deduction rules. Since ''F'' is arbi ...


References


External links


Explanation on Stack Overflow, with a JavaScript example
*{{cite web , first=Ken , last=Slonneger , first2=Barry , last2=Kurtz , url=http://homepage.cs.uiowa.edu/~slonnegr/plf/Lecture05.pdf , title=5. Some discussion of let expressions , work=Programming Language Foundations , publisher=University of Iowa Implementation of functional programming languages Lambda calculus Compiler construction