Кіріспе
Жаһандық мета-процесс Ламбда-лифтинг – компьютерлік бағдарламаны функциялардың бір-бірінен тәуелсіз түрде жаһандық ауқымда анықталуын қамтамасыз ету үшін қайта құрылымдайтын мета-процесс. Жеке "лифт" жергілікті функцияны жаһандық функцияға айналдырады. Бұл екі қадамдық процесс, оған мыналар кіреді: Функциядағы еркін айнымалыларды параметрлерді қосу арқылы жою. Функцияларды шектеулі ауқымнан кеңірек немесе жаһандық ауқымға көшіру. "Ламбда-лифтинг" термині алғаш рет 1982 жылы Томас Джонсон енгізген, және тарихи тұрғыдан функционалдық бағдарламалау тілдерін іске асыру механизмі ретінде қарастырылған. Ол кейбір заманауи компиляторларда басқа техникалармен бірге қолданылады. Ламбда-лифтинг жабық түрлендірумен бірдей емес. Ол барлық шақыру орындарын түзетуді қажет етеді (шақыруларға қосымша аргументтер қосу) және лифттелген ламбда өрнегі үшін жабылуды енгізбейді. Керісінше, жабық түрлендіру шақыру орындарын түзетуді қажет етпейді, бірақ еркін айнымалыларды мәндерге бейімдейтін ламбда өрнегі үшін жабылуды енгізеді. Бұл техника жеке функцияларда, кодты қайта құруда, функцияны жазылған ауқымынан тыс қолдану үшін пайдаланылуы мүмкін. Бағдарламаны өзгерту үшін ламбда-лифттерді қайталап қолдануға болады. Қайталап қолданылатын лифттер ламбдалық есептеуде жазылған бағдарламаны ламбдасыз рекурсивті функциялар жиынтығына түрлендіру үшін қолданылуы мүмкін. Бұл ламбдалық есептеу және функциялар түрінде жазылған бағдарламалардың эквиваленттілігін көрсетеді. Алайда, ол ламбдалық есептеудің логикалық тұрғыдан дұрыстығын көрсетпейді, себебі ламбда-лифтингте қолданылатын эта-редукция – бұл ламбдалық есептеуге кардиналдық проблемаларды енгізетін қадам, өйткені ол айнымалыға қатысты шарттарды қанағаттандыратын бір ғана мән бар екенін тексермей, айнымалыдан мәнді алып тастайды (Карридің парадоксына қараңыз). Ламбда-лифтинг компилятордың өңдеу уақытына қатысты едәуір шығынды тудырады. Ламбда-лифтингті тиімді іске асыру компилятор үшін өңдеу уақытын азайтады. Типтелмеген ламбдалық есептеуде, негізгі типтері функциялар болатын жағдайда, лифтинг ламбда өрнегінің бета-редукция нәтижесін өзгерте алады. Нәтижедегі функциялар математикалық мағынада бірдей мағынаға ие болады, бірақ типтелмеген ламбдалық есептеуде бірдей функция ретінде қарастырылмайды. Сондай-ақ, интенсионалдық және экстенсионалдық теңдікті қараңыз. Ламбда-лифтингке кері операция – ламбданы түсіру. Ламбданы түсіру компилятор үшін бағдарламаларды құрастыру жылдамдығын арттыруы мүмкін, сонымен қатар параметрлер санын азайту және стек фреймдерінің көлемін кішірейте отырып, нәтижедегі бағдарламаның тиімділігін арттыруы мүмкін. Алайда, бұл функцияларды қайта пайдалануды қиындатады. Түсірілген функция өзінің контекстіне байланысты, және оны тек алдымен лифттелген жағдайда ғана басқа контексте қолдануға болады.
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, consisting of;
Eliminating free variables 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 languages. It is used in conjunction with other techniques in some modern compilers. Lambda lifting is not the same as closure conversion. It requires all call sites 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, 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 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 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). Lambda lifting is expensive on processing time for the compiler. An efficient implementation of lambda lifting is on processing time for the compiler. In the untyped lambda calculus, where the basic types are functions, lifting may change the result of beta reduction 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.
Ламбданы көтеру және жабу
Ламбда көтеру және жабу – блок құрылымды бағдарламаларды іске асырудың екі әдісі. Ол блок құрылымын жою арқылы іске асырады. Барлық функциялар жаһандық деңгейге көтеріледі. Жабу түрлендіруі ағымдағы кадрды басқа кадрлармен байланыстыратын "жабуды" қамтамасыз етеді. Жабу түрлендіруі кодты құрастыру кезінде аз уақыт алады. Рекурсивті функциялар және блок құрылымды бағдарламалар, көтерумен немесе көтерусіз, стекке негізделген, қарапайым және тиімді іске асыру арқылы жүзеге асырылуы мүмкін. Дегенмен, стек-кадрға негізделген іске асыру қатаң (кідіріссіз) болуы керек. Стек-кадрға негізделген іске асыру функциялардың өмірлік циклі соңғы кірген, бірінші шыққан (LIFO) принципіне сәйкес болуын қажет етеді. Яғни, есептеуін бастаған ең соңғы функция ең бірінші аяқталуы тиіс. Кейбір функционалдық тілдер (мысалы, Haskell) жалқау бағалауды қолдана отырып іске асырылады, бұл мән қажет болғанға дейін есептеуді кейінге қалдырады. Жалқау іске асыру стратегиясы бағдарламалаушыға икемділік береді. Жалқау бағалау функцияның есептелген мәніне сұраныс түскенге дейін функцияға шақыруды кейінге қалдыруды талап етеді. Бір іске асыру әдісі – мәннің орнына есептеуді сипаттайтын деректердің "кадрына" сілтеме жасау. Кейіннен, мән қажет болған кезде, кадр сол мәнді есептеу үшін қолданылады, дәл қажет болған сәтте. Есептелген мән осы кезде сілтемені алмастырады. "Кадр" стек-кадрға ұқсас, бірақ ол стекте сақталмайды. Жалқау бағалау есептеу үшін қажетті барлық деректердің кадрда сақталуын талап етеді. Егер функция "көтерілген" болса, кадрда тек функцияның мекенжайы мен функцияға берілетін параметрлер ғана тіркеледі. Кейбір заманауи тілдер айнымалылардың өмірлік циклін басқару үшін стекке негізделген бөлудің орнына қоқыс жинауды қолданады. Басқарылатын, қоқыс жиналатын ортада жабу кадрларға сілтеме жасайды, олардан мәндер алынуы мүмкін. Керісінше, көтерілген функцияда есептеу үшін қажетті әрбір мәнге сәйкес параметрлер болады.
Ламбдалық есептеудегі Ламбдалық көтеру
Әрбір ламбда-көтеру, ламбда-өрешенің ішкі өрнесі болып табылатын ламбда-абстракцияны алып, оны өзі жасайтын функцияға шақыру (қолдану) арқылы ауыстырады. Ішкі өрнестегі еркін айнымалылар функцияға шақырудың параметрлері болып табылады. Ламбда-көтерулер жеке функцияларда немесе кодты қайта құру кезінде, функцияны жазылған аумақтан тыс қолдану үшін пайдаланылуы мүмкін. Бағдарламаны өзгерту үшін мұндай көтерулер өрнекте ламбда-абстракциялар қалмайынша қайталанып тұруы мүмкін.
Анонимді көтеру
Анонимді лифт Ламбда абстракциясын қабылдайды (S деп аталады). S үшін; S-ты алмастыратын функцияға атау беріңіз (V деп аталады). V таңбасымен белгіленген атау бұрын қолданылмағанын қамтамасыз етіңіз. S-тегі барлық еркін айнымалылар үшін V-ге параметрлер қосып, G өрнегін жасаңыз (шақыру жасауға қараңыз). Ламбда лифті – функцияның анықтамасымен бірге функция қолданбасы үшін S-ты алмастыру. Жаңа ламбда өрнегінде S, G-мен алмастырылады. L[S:=G] – L-де S-ты G-мен алмастыруды білдіреді. Функция анықтамаларына G = S функция анықтамасы қосылады. Жоғарыдағы ережеде G – S өрнесінің орнына қойылған функция қолданбасы. Ол V функциясының атымен анықталады. Бұл жаңа айнымалы болуы керек, яғни ламбда өрнегінде бұрын қолданылмаған атау, мұнда E-де қолданылған айнымалылар жиынтығын қайтаратын мета-функция. Анонимді лифт үшін мысал. Мысалы, de lambda-ны ламбдадан let өрнектеріне түрлендіруде қараңыз. Нәтижесі:
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. 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,
where V is the function name. It must be a new variable, i. e. a name not already used in the lambda expression,
where is a meta function that returns the set of variables used in E.
Example for anonymous lift. For example,
See de lambda in Conversion from lambda to let expressions. The result is,
Көтергіштің сөзін таңдау
Көтермелеу үшін өрнекті таңдаудың екі түрлі жолы бар. Біріншісі барлық ламбда абстракцияларын анонимді функциялар ретінде қарастырады. Екіншісі, параметрге қолданылатын ламбда абстракцияларын функция ретінде қарастырады. Параметрге қолданылатын ламбда абстракциялары функцияны анықтайтын let өрнегі немесе анонимді функция ретінде екі жақты түсіндіріледі. Екі түсінік те дұрыс. Бұл екі предикат екі анықтама үшін де қажет. lambda free – Ламбда абстракциялары жоқ өрнек. lambda anon – Анонимді функция. Мысалы, X – ламбдадан бос өрнек.