Podnoszenie lambdy
Podnoszenie lambda to metaproces , który restrukturyzuje program komputerowy , tak aby funkcje były definiowane niezależnie od siebie w zasięgu globalnym . Pojedyncza „winda” przekształca funkcję lokalną w funkcję globalną. Jest to proces dwuetapowy, składający się z;
- Eliminacja wolnych zmiennych w funkcji poprzez dodanie parametrów.
- Przenoszenie funkcji z zakresu ograniczonego do zakresu szerszego lub globalnego.
Termin „podnoszenie lambda” został po raz pierwszy wprowadzony przez Thomasa Johnssona około 1982 roku i był historycznie uważany za mechanizm wdrażania funkcjonalnych języków programowania . Jest używany w połączeniu z innymi technikami w niektórych nowoczesnych kompilatorach .
Podnoszenie lambda to nie to samo, co konwersja domknięcia. Wymaga dostosowania wszystkich witryn wywołań (dodania dodatkowych argumentów do wywołań) i nie wprowadza domknięcia dla podniesionego wyrażenia lambda. W przeciwieństwie do tego konwersja domknięcia nie wymaga dostosowania miejsc wywołań, ale wprowadza domknięcie wyrażenia lambda odwzorowującego wolne zmienne na wartości.
Technika ta może być stosowana na poszczególnych funkcjach, w refaktoryzacji kodu , aby funkcja była użyteczna poza zakresem, w którym została napisana. Wyciągi lambda mogą być również powtarzane w celu przekształcenia programu. Powtarzane windy mogą być użyte do przekształcenia programu napisanego w rachunku lambda w zestaw funkcji rekurencyjnych , bez lambd. Pokazuje to równoważność programów napisanych w rachunku lambda i programów napisanych jako funkcje. Jednak nie dowodzi to przydatności rachunku lambda do dedukcji, jak redukcja eta używany w podnoszeniu lambda jest krokiem, który wprowadza problemy liczności do rachunku lambda, ponieważ usuwa wartość ze zmiennej, bez uprzedniego sprawdzenia, czy istnieje tylko jedna wartość, która spełnia warunki zmiennej (patrz paradoks Curry'ego ).
Podnoszenie lambda jest kosztowne w czasie przetwarzania dla kompilatora. Wydajna implementacja podnoszenia lambda kompilator
W nietypowanym rachunku lambda , gdzie podstawowymi typami są funkcje, podniesienie może zmienić wynik redukcji beta wyrażenia lambda. Wynikowe funkcje będą miały to samo znaczenie w sensie matematycznym, ale nie są uważane za tę samą funkcję w nietypowanym rachunku lambda. Zobacz także równość intencjonalna i ekstensjonalna .
Operacją odwrotną do podnoszenia lambda jest opuszczanie lambda .
Upuszczanie lambda może przyspieszyć kompilację programów dla kompilatora, a także może zwiększyć wydajność wynikowego programu poprzez zmniejszenie liczby parametrów i zmniejszenie rozmiaru ramek stosu. Jednak utrudnia to ponowne użycie funkcji. Upuszczona funkcja jest powiązana ze swoim kontekstem i może być użyta w innym kontekście tylko wtedy, gdy zostanie najpierw podniesiona.
Algorytm
Poniższy algorytm jest jednym ze sposobów podnoszenia lambda dowolnego programu w języku, który nie obsługuje domknięć jako obiektów pierwszej klasy :
- Zmień nazwy funkcji, aby każda funkcja miała unikalną nazwę.
- Zastąp każdą wolną zmienną dodatkowym argumentem funkcji otaczającej i przekaż ten argument przy każdym użyciu funkcji.
- Zastąp każdą definicję funkcji lokalnej, która nie ma wolnych zmiennych, identyczną funkcją globalną.
- Powtarzaj kroki 2 i 3, aż wszystkie wolne zmienne i funkcje lokalne zostaną wyeliminowane.
Jeśli język ma domknięcia jako obiekty pierwszej klasy, które mogą być przekazywane jako argumenty lub zwracane z innych funkcji, domknięcie będzie musiało być reprezentowane przez strukturę danych, która przechwytuje powiązania wolnych zmiennych.
Przykład
Poniższy program OCaml oblicza sumę liczb całkowitych od 1 do 100:
niech rec suma n = jeśli n = 1 to 1 inaczej niech f x = n + x in f ( suma ( n - 1 )) w sumie 100
( Let rec
deklaruje sum
jako funkcję, która może wywoływać samą siebie.) Funkcja f, która dodaje argument sumy do sumy liczb mniejszych od argumentu, jest funkcją lokalną. W definicji f n jest zmienną wolną. Zacznij od konwersji wolnej zmiennej na parametr:
niech rec suma n = jeśli n = 1 to 1 inaczej niech f w x = w + x in f n ( suma ( n - 1 )) w sumie 100
Następnie podnieś f do funkcji globalnej:
niech rec f w x = w + x i suma n = jeśli n = 1 to 1 inaczej f n ( suma ( n - 1 ) ) suma 100
Poniżej znajduje się ten sam przykład, tym razem napisany w JavaScript :
// Wersja początkowa function sum ( n ) { function f ( x ) { return n + x ; } jeśli ( n == 1 ) zwróć 1 ; w przeciwnym razie zwróć f ( suma ( n - 1 )); } // Po przekonwertowaniu zmiennej wolnej n na parametr formalny w funkcji sum ( n
) { funkcja fa ( w , x ) { powrót w + x ; } jeśli ( n == 1 ) zwróć 1 ; w przeciwnym razie zwróć f ( n , suma ( n - 1 )); } // Po podniesieniu funkcji f do globalnego zasięgu function f ( w , x ) {
powrót w + x ; } funkcja suma ( n ) { jeśli ( n == 1 ) powrót 1 ; w przeciwnym razie zwróć f ( n , suma ( n - 1 )); }
Podnoszenie lambdy a domknięcia
zamykanie lambda to metody wdrażania programów o strukturze blokowej . Implementuje strukturę blokową, eliminując ją. Wszystkie funkcje są podniesione do poziomu globalnego. Konwersja zamknięcia zapewnia „zamknięcie”, które łączy bieżącą ramkę z innymi ramkami. Konwersja zamknięcia zajmuje mniej czasu kompilacji.
Funkcje rekurencyjne i programy o strukturze blokowej, z podnoszeniem lub bez, mogą być implementowane przy użyciu implementacji opartej na stosie , która jest prosta i wydajna. Jednak implementacja oparta na ramkach stosu musi być ścisła (chętna) . Implementacja oparta na ramkach stosu wymaga, aby czas życia funkcji był ostatni na wejściu, pierwszy na wyjściu (LIFO). Oznacza to, że najnowsza funkcja, która rozpoczęła obliczenia, musi być pierwszą do końca.
Niektóre języki funkcjonalne (takie jak Haskell ) są implementowane przy użyciu leniwej oceny , która opóźnia obliczenia do momentu, gdy wartość jest potrzebna. Strategia leniwej implementacji daje programiście elastyczność. Ocena z opóźnieniem wymaga opóźnienia wywołania funkcji do momentu żądania wartości obliczonej przez funkcję. Jedną z implementacji jest zapisanie odniesienia do „ramki” danych opisujących obliczenie zamiast wartości. Później, gdy wartość jest wymagana, ramka jest używana do obliczenia wartości, dokładnie na czas, kiedy jest potrzebna. Następnie obliczona wartość zastępuje odniesienie.
„Ramka” jest podobna do ramki stosu , z tą różnicą, że nie jest przechowywana na stosie. Leniwa ocena wymaga zapisania w ramce wszystkich danych wymaganych do obliczeń. Jeśli funkcja jest „podnoszona”, wówczas ramka wymaga jedynie zapisania wskaźnika funkcji i parametrów funkcji. Niektóre współczesne języki używają wyrzucania elementów bezużytecznych zamiast alokacji opartej na stosie do zarządzania życiem zmiennych. W zarządzanym, usuwanym bezużytecznie środowisku, zamknięcie rejestruje odniesienia do ramek, z których można uzyskać wartości. Natomiast podniesiona funkcja ma parametry dla każdej wartości potrzebnej do obliczenia.
Niech wyrażenia i rachunek lambda
Wyrażenie Let jest przydatne do opisywania podnoszenia i upuszczania oraz do opisywania relacji między równaniami rekurencyjnymi a wyrażeniami lambda. Większość języków funkcjonalnych ma wyrażenia let. Również języki programowania o strukturze blokowej, takie jak ALGOL i Pascal , są podobne, ponieważ również pozwalają na lokalną definicję funkcji do użycia w ograniczonym zakresie .
wyrażenie let jest w pełni wzajemnie rekurencyjną wersją let rec zaimplementowaną w wielu językach funkcjonalnych.
Niech wyrażenia są powiązane z rachunkiem Lambda . Rachunek lambda ma prostą składnię i semantykę i jest dobry do opisywania podnoszenia lambda. Wygodnie jest opisać podnoszenie lambda jako translację z lambda na let , a opuszczanie lambda jako odwrotność. Dzieje się tak, ponieważ let pozwalają na wzajemną rekurencję, która jest w pewnym sensie bardziej zniesiona niż jest obsługiwana w rachunku lambda. Rachunek lambda nie obsługuje rekurencji wzajemnej i tylko jedna funkcja może być zdefiniowana w najbardziej zewnętrznym zasięgu globalnym.
Reguły konwersji , które opisują translację bez podnoszenia, podano w artykule Let expression .
Poniższe reguły opisują równoważność wyrażeń lambda i let,
Nazwa | Prawo |
---|---|
Równoważność redukcji eta | |
Równoważność Let-Lambda | |
Niech kombinacja |
Podane zostaną metafunkcje opisujące podnoszenie i opuszczanie lambda. Meta-funkcja to funkcja, która przyjmuje program jako parametr. Program jest danymi dla metaprogramu. Program i metaprogram znajdują się na różnych metapoziomach.
Następujące konwencje będą używane do odróżnienia programu od metaprogramu,
- Nawiasy kwadratowe [] będą używane do reprezentowania zastosowania funkcji w metaprogramie.
- Wielkie litery będą używane dla zmiennych w metaprogramie. Małe litery reprezentują zmienne w programie.
- będzie używane dla równości w metaprogramie.
- lub nieznaną wartość.
Dla uproszczenia zastosowana zostanie pierwsza reguła, zgodnie z którą zostaną zastosowane dopasowania. Reguły zakładają również, że wyrażenia lambda zostały wstępnie przetworzone, dzięki czemu każda abstrakcja lambda ma unikalną nazwę.
Operator podstawienia jest szeroko stosowany. Wyrażenie oznacza wystąpienia w L S . _ Zastosowana definicja została rozszerzona o podstawianie wyrażeń, z definicji podanej na stronie rachunku Lambda . Dopasowywanie wyrażeń powinno porównywać wyrażenia pod kątem równoważności alfa (zmiana nazw zmiennych).
Podnoszenie lambda w rachunku lambda
Każda winda lambda pobiera abstrakcję lambda, która jest podwyrażeniem wyrażenia lambda i zastępuje ją wywołaniem funkcji (aplikacją) do funkcji, którą tworzy. Wolne zmienne w wyrażeniu podrzędnym są parametrami wywołania funkcji.
Podnośniki lambda mogą być używane w poszczególnych funkcjach, w refaktoryzacji kodu , aby funkcja była użyteczna poza zakresem, w którym została napisana. Takie windy mogą być również powtarzane, dopóki wyrażenie nie ma abstrakcji lambda, w celu przekształcenia programu.
Winda lambdy
Winda otrzymuje podwyrażenie w wyrażeniu, które ma podnieść na górę tego wyrażenia. Wyrażenie może być częścią większego programu. Pozwala to kontrolować, gdzie podwyrażenie jest podnoszone. Operacja podnoszenia lambda używana do wykonywania podnoszenia w programie to:
Wyrażenie podrzędne może być abstrakcją lambda lub abstrakcją lambda zastosowaną do parametru.
Możliwe są dwa rodzaje windy.
Anonimowa winda ma wyrażenie windy, które jest tylko abstrakcją lambda. Jest to traktowane jako definiowanie funkcji anonimowej. Dla funkcji należy utworzyć nazwę.
Nazwane wyrażenie podnoszenia ma abstrakcję lambda zastosowaną do wyrażenia. Ten wzrost jest traktowany jako nazwana definicja funkcji.
Anonimowa winda
Anonimowa winda pobiera abstrakcję lambda (zwaną S ). dla S ;
- Utwórz nazwę funkcji, która zastąpi S (zwanej V ). Upewnij się, że nazwa identyfikowana przez V nie została użyta.
- Dodaj parametry do V , dla wszystkich wolnych zmiennych w S , aby utworzyć wyrażenie G (zobacz make-call ).
Podniesienie lambda to zastąpienie abstrakcji lambda S w aplikacji funkcji wraz z dodaniem definicji funkcji.
Nowe wyrażenie lambda ma S podstawione na G. Zauważ, że L [ S := G ] oznacza podstawienie S na G w L. Do definicji funkcji dodano definicję funkcji G = S.
W powyższej regule G jest aplikacją funkcji, która zastępuje wyrażenie S . jest określony przez,
gdzie V to nazwa funkcji. Musi to być nowa zmienna, czyli nazwa nie używana jeszcze w wyrażeniu lambda,
gdzie jest metafunkcją, która zwraca zestaw zmiennych używanych w E .
Przykład anonimowej windy. |
---|
Na przykład Zobacz de-lambda w Conversion from lambda to let expressions . Wynik to, |
Konstruowanie połączenia
Wywołanie funkcji G jest konstruowane przez dodanie parametrów dla każdej zmiennej w zbiorze zmiennych wolnych (reprezentowanym przez V ) do funkcji H ,
Przykład konstrukcji wywołania. |
---|
|
Nazwana winda
Nazwana winda jest podobna do windy anonimowej, z tą różnicą, że podano nazwę funkcji V.
Jeśli chodzi o wzrost anonimowy, wyrażenie G jest konstruowane z V przez zastosowanie wolnych zmiennych S . jest określony przez,
Przykład dla nazwanej windy. |
---|
Na przykład, Zobacz de-lambda w Conversion from lambda to let expressions . Wynik to, daje, |
Transformacja wzniosu lambda
Transformacja wyciągu lambda pobiera wyrażenie lambda i podnosi wszystkie abstrakcje lambda na początek wyrażenia. Abstrakcje są następnie tłumaczone na funkcje rekurencyjne , co eliminuje abstrakcje lambda. Rezultatem jest funkcjonalny program w postaci
gdzie M to seria definicji funkcji, a N to wyrażenie reprezentujące zwróconą wartość.
Na przykład,
Metafunkcja de-let może być następnie użyta do przekształcenia wyniku z powrotem w rachunek lambda.
Przetwarzanie przekształcania wyrażenia lambda to seria wyciągów. Każda winda posiada
- Podwyrażenie wybrane dla niego przez funkcję lift-choice . Podwyrażenie powinno być tak dobrane, aby można je było przekształcić w równanie bez lambd.
- Winda jest wykonywana przez wywołanie metafunkcji lambda-lift , opisanej w następnej sekcji,
Po zastosowaniu wyciągów, płaty są łączone w jeden.
Następnie stosowane jest usuwanie parametrów w celu usunięcia parametrów, które nie są konieczne w wyrażeniu „let”. Wyrażenie let umożliwia definicjom funkcji bezpośrednie odwoływanie się do siebie, podczas gdy abstrakcje lambda są ściśle hierarchiczne, a funkcja może nie odnosić się bezpośrednio do siebie.
Wybór wyrażenia do podnoszenia
Istnieją dwa różne sposoby wybierania wyrażenia do podnoszenia. Pierwsza traktuje wszystkie abstrakcje lambda jako definiujące funkcje anonimowe. Drugi traktuje abstrakcje lambda, które są stosowane do parametru, jako definiujące funkcję. Abstrakcje lambda zastosowane do parametru mają podwójną interpretację jako wyrażenie let definiujące funkcję lub definiujące funkcję anonimową. Obie interpretacje są prawidłowe.
Te dwa predykaty są potrzebne dla obu definicji.
lambda-free — wyrażenie nie zawierające abstrakcji lambda.
lambda-anon — funkcja anonimowa. Wyrażenie takie jak gdzie X jest wolny od
Wybieranie anonimowych funkcji tylko do podnoszenia
Szukaj najgłębszej anonimowej abstrakcji, aby po zastosowaniu windy podniesiona funkcja stała się prostym równaniem. Ta definicja nie uznaje abstrakcji lambda z parametrem za definicję funkcji. Wszystkie abstrakcje lambda są uważane za definiujące funkcje anonimowe.
lift-choice — Pierwszy anonim znaleziony podczas przechodzenia przez wyrażenie lub żaden , jeśli nie ma funkcji.
Na przykład,
Reguła | typ funkcji | wybór |
---|---|---|
2 | ||
3 | ||
1 | zaraz | |
Reguła | typ funkcji | wybór |
---|---|---|
2 | zaraz | |
2 |
Wybór funkcji nazwanych i anonimowych do podnoszenia
Wyszukaj najgłębszą nazwaną lub anonimową definicję funkcji, tak aby po zastosowaniu windy funkcja podniesiona stała się prostym równaniem. Ta definicja rozpoznaje abstrakcję lambda z rzeczywistym parametrem jako definiującą funkcję. Tylko abstrakcje lambda bez aplikacji są traktowane jako funkcje anonimowe.
- lambda-named
- Nazwana funkcja. Wyrażenie takie jak gdzie M jest wolne od lambda, a N jest wolne od lambda lub funkcja anonimowa.
- wybór windy
- Pierwsza anonimowa lub nazwana funkcja znaleziona podczas przechodzenia przez wyrażenie lub brak , jeśli nie ma żadnej funkcji.
Na przykład,
Reguła | typ funkcji | wybór |
---|---|---|
2 | ||
1 | o imieniu | |
Reguła | typ funkcji | wybór |
---|---|---|
1 | zaraz | |
Przykłady
Na przykład kombinator Y ,
podnosi się jako,
i po opuszczeniu parametru ,
Jako wyrażenie lambda (patrz Konwersja wyrażeń let na lambda ),
Wyrażenie lambda | Funkcjonować | Z | Do | Zmienne | |
---|---|---|---|---|---|
1 | PRAWDA | ||||
2 |
|
||||
3 | |||||
4 | |||||
5 |
W przypadku podnoszenia tylko funkcji anonimowych kombinatorem Y jest:
i po zrzuceniu parametru ,
Jako wyrażenie lambda,
Wyrażenie lambda | Funkcjonować | Z | Do | Zmienne | |
---|---|---|---|---|---|
1 | PRAWDA | ||||
2 | |||||
3 | |||||
4 | |||||
5 |
Pierwszym podwyrażeniem, które należy wybrać do podnoszenia, jest . To przekształca wyrażenie lambda na i tworzy równanie .
Drugim podwyrażeniem, które należy wybrać do podnoszenia, jest . To przekształca wyrażenie lambda w i tworzy równanie .
A rezultatem jest,
Co zaskakujące, ten wynik jest prostszy niż ten uzyskany z podnoszenia nazwanych funkcji.
Wykonanie
Zastosuj funkcję do K ,
Więc,
Lub
Kombinator Y wielokrotnie wywołuje swój parametr (funkcję) na sobie. Wartość jest zdefiniowana, jeśli funkcja ma punkt stały . Ale funkcja nigdy się nie zakończy.
Spadająca lambda w rachunku lambda
Upuszczanie lambdy polega na zmniejszaniu zakresu funkcji i wykorzystywaniu kontekstu ze zmniejszonego zakresu do zmniejszenia liczby parametrów funkcji. Zmniejszenie liczby parametrów ułatwia zrozumienie funkcji.
W części podnoszącej Lambda została opisana metafunkcja służąca najpierw do podnoszenia, a następnie przekształcania wynikowego wyrażenia lambda na równanie rekurencyjne. Metafunkcja Lambda Drop wykonuje działanie odwrotne, najpierw konwertując równania rekurencyjne na abstrakcje lambda, a następnie upuszczając wynikowe wyrażenie lambda do najmniejszego zakresu, który obejmuje wszystkie odniesienia do abstrakcji lambda.
Spuszczanie lambdy odbywa się w dwóch krokach,
Spadek lambdy
Kropla Lambda jest stosowana do wyrażenia, które jest częścią programu. Upuszczanie jest kontrolowane przez zestaw wyrażeń, z których upuszczanie zostanie wykluczone.
Gdzie,
- L jest abstrakcją lambda, którą należy usunąć.
- P to program
- X to zbiór wyrażeń, które mają być wykluczone z usuwania.
Transformacja kropli lambda
Transformacja kropli lambda zatapia wszystkie abstrakcje w wyrażeniu. Sinking jest wykluczony z wyrażeń w zbiorze wyrażeń,
Gdzie,
- L jest wyrażeniem do przekształcenia.
- X to zestaw wyrażeń podrzędnych, które mają być wykluczone z upuszczania.
sink-tran pochłania każdą abstrakcję, zaczynając od najgłębszej,
Zatonięcie abstrakcji
Tonięcie to przesuwanie abstrakcji lambda tak daleko, jak to możliwe, tak aby nadal znajdowała się poza wszelkimi odniesieniami do zmiennej.
Aplikacja - 4 przypadki.
Abstrakcja . Użyj zmiany nazwy, aby upewnić się, że nazwy zmiennych są różne.
Zmienna - 2 przypadki.
Sink test wyklucza odrzucanie wyrażeń,
Przykład
Przykład zatonięcia | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Na przykład,
|
Spadek parametrów
Upuszczanie parametrów optymalizuje funkcję pod kątem jej pozycji w funkcji. Podnoszenie lambda dodało parametry, które były niezbędne do wyjęcia funkcji z kontekstu. Podczas usuwania proces ten jest odwracany, a dodatkowe parametry zawierające zmienne, które są wolne, mogą zostać usunięte.
Upuszczenie parametru polega na usunięciu niepotrzebnego parametru z funkcji, gdzie rzeczywisty parametr przekazywany jest zawsze tym samym wyrażeniem. Wolne zmienne wyrażenia muszą być również wolne tam, gdzie zdefiniowana jest funkcja. W tym przypadku usuwany parametr jest zastępowany wyrażeniem w treści definicji funkcji. To sprawia, że parametr jest zbędny.
Weźmy na przykład pod uwagę,
W tym przykładzie aktualnym parametrem formalnego parametru o jest zawsze p . Ponieważ p jest zmienną wolną w całym wyrażeniu, parametr może zostać usunięty. Właściwym parametrem formalnego parametru y jest zawsze n . Jednak n jest związane w abstrakcji lambda. Dlatego ten parametr nie może zostać usunięty.
Rezultatem upuszczenia parametru jest,
Dla głównego przykładu
Definicja drop-params-tran to:
Gdzie,
Zbuduj listy parametrów
Dla każdej abstrakcji, która definiuje funkcję, zbuduj informacje wymagane do podjęcia decyzji o porzuceniu nazw. Ta informacja opisuje każdy parametr; nazwa parametru, wyrażenie określające rzeczywistą wartość oraz wskazanie, że wszystkie wyrażenia mają tę samą wartość.
Na przykład w
parametry funkcji g to,
Parametr formalny | Wszystkie te same wartości | Rzeczywiste wyrażenie parametru |
---|---|---|
X | FAŁSZ | _ |
o | PRAWDA | P |
y | PRAWDA | N |
Każda abstrakcja otrzymuje unikalną nazwę, a lista parametrów jest powiązana z nazwą abstrakcji. Na przykład g istnieje lista parametrów.
build-param-lists buduje wszystkie listy dla wyrażenia, przechodząc przez wyrażenie. Ma cztery parametry;
- Analizowane wyrażenie lambda.
- Lista parametrów tabeli dla nazw.
- Tabela wartości parametrów.
- Zwrócona lista parametrów, która jest używana wewnętrznie przez program
Abstrakcja postaci nazw parametrów funkcji
Znajdź nazwę i rozpocznij tworzenie listy parametrów dla nazwy, wypełniając formalne nazwy parametrów. Odbierz również rzeczywistą listę parametrów z treści wyrażenia i zwróć ją jako rzeczywistą listę parametrów z tego wyrażenia
Zmienna — wywołanie funkcji.
W przypadku nazwy funkcji lub parametru zacznij zapełniać rzeczywistą listę parametrów, wyświetlając listę parametrów dla tej nazwy.
Aplikacja — aplikacja (wywołanie funkcji) jest przetwarzana w celu wyodrębnienia rzeczywistych szczegółów parametrów.
Pobierz listy parametrów dla wyrażenia i parametru. Pobierz rekord parametru z listy parametrów z wyrażenia i sprawdź, czy bieżąca wartość parametru jest zgodna z tym parametrem. Zapisz wartość nazwy parametru do późniejszego wykorzystania podczas sprawdzania.
Powyższa logika jest dość subtelna w sposobie, w jaki działa. Ten sam wskaźnik wartości nigdy nie jest ustawiony na wartość true. Jest ustawiana na false tylko wtedy, gdy nie można dopasować wszystkich wartości. Wartość jest pobierana przy użyciu S w celu zbudowania zestawu wartości logicznych dozwolonych dla S . Jeśli true jest członkiem, wszystkie wartości tego parametru są równe i parametr może zostać usunięty.
Podobnie, def używa teorii mnogości do sprawdzenia, czy zmiennej nadano wartość;
Let - Let wyrażenie.
I - Do użytku w „niech”.
Przykłady
Na przykład budowanie list parametrów dla,
daje,
a parametr o jest odrzucany, aby dać,
Zbuduj listę parametrów dla | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Przykład tworzenia listy parametrów | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
daje,
Ponieważ nie ma definicji, , wtedy równanie można uprościć do, Usuwając niepotrzebne wyrażenia,
Porównując dwa wyrażenia dla , pobierz, Jeśli ; Jeśli nie ma implikacji Więc co oznacza, że może to być prawda lub fałsz. Jeśli prawdą Jeśli prawdą Więc jest fałszywe. Wynik jest następujący:
Za pomocą podobnych argumentów, jak użyte powyżej, get, i z poprzednio |
Innym przykładem jest
Tutaj x jest równe f. Mapowanie listy parametrów to,
a parametr x jest odrzucany, aby dać,
Zbuduj listę parametrów dla | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
W tym trudniejszym przykładzie zastosowano logikę in equate .
Po wspólnym zebraniu wyników Z dwóch definicji dla ; Więc re i porównując z powyższym, Więc, W, zmniejsza się do, Również, zmniejsza się do, Tak więc lista parametrów dla p jest efektywnie; |
Upuść parametry
Użyj informacji uzyskanych za pomocą list parametrów kompilacji, aby usunąć rzeczywiste parametry, które nie są już potrzebne. drop-params ma parametry,
- Wyrażenie lambda, w którym parametry mają zostać usunięte.
- Mapowanie nazw zmiennych na listy parametrów (wbudowane w listy parametrów Build).
- Zestaw zmiennych dowolnych w wyrażeniu lambda.
- Zwrócona lista parametrów. Parametr używany wewnętrznie w algorytmie.
Abstrakcja
Gdzie,
Gdzie,
Zmienny
W przypadku nazwy funkcji lub parametru zacznij zapełniać rzeczywistą listę parametrów, wyświetlając listę parametrów dla tej nazwy.
Aplikacja — aplikacja (wywołanie funkcji) jest przetwarzana w celu wyodrębnienia
Let - Let wyrażenie.
I - Do użytku w „niech”.
Upuść parametry z aplikacji | |||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Z wyników zestawień parametrów budynku; Więc, Więc,
|
Porzuć parametry formalne
drop-formal usuwa parametry formalne na podstawie zawartości list rozwijanych. Jego parametry to m.in.
- Lista upuszczania,
- Definicja funkcji (abstrakcja lambda).
- Wolne zmienne z definicji funkcji.
formalny jest zdefiniowany jako,
Co można wytłumaczyć jako,
- Jeśli wszystkie rzeczywiste parametry mają tę samą wartość, a wszystkie wolne zmienne tej wartości są dostępne do zdefiniowania funkcji, usuń parametr i zastąp stary parametr jego wartością.
- w przeciwnym razie nie upuszczaj parametru.
- w przeciwnym razie zwróć treść funkcji.
Stan | Wyrażenie |
---|---|
) | |
Przykład
Zaczynając od definicji funkcji kombinatora Y,
Transformacja | Wyrażenie |
---|---|
streszczenie * 4 | |
lambda-abstrakcyjny-tran | |
zlew-trans | |
zlew-trans | |
drop-param | |
beta-redeks |
Co zwraca kombinator Y ,
Zobacz też
- Niech wyrażenie
- Kombinator punktów stałych
- rachunek lambda
- Dedukcyjny rachunek lambda
- Superkombinator
- Paradoks Curry'ego
Linki zewnętrzne
- Wyjaśnienie dotyczące przepełnienia stosu z przykładem JavaScript
- Sloneger, Ken; Kurtz, Barry. „5. Omówienie wyrażeń let” (PDF) . Podstawy języka programowania . Uniwersytet Iowa.