Szukaj…
Wyrażenie S.
Wyrażenie w schemacie jest tym, co zostanie wykonane. Wyrażenie S, jak zwykle nazywane, zaczyna się od ( i kończy na a ) . Pierwszym elementem wyrażenia jest to, co zostanie wykonane. Następujący element wyrażenia to parametry, które zostaną wysłane do wyrażenia podczas oceny wyrażenia.
Na przykład dodając liczby:
(+ 1 2 3)
W takim przypadku + jest symbolem funkcji dodawania, która przyjmuje wiele parametrów. 1 , 2 i 3 są wysyłane do funkcji + .
Wyrażenie S może zawierać wyrażenia S jako parametry, jak pokazano w poniższym przykładzie:
(if (< x y)
x
y)
Który można odczytać tak, jakby x był mniejszy niż y zwraca x inaczej zwraca y . W tym przykładzie oceniamy wyrażenie warunkowe, w zależności od wartości rozstrzygniętej, zwracane będzie x lub y. Można to ocenić
(if #t x y)
x
(if #f x y)
y
Mniej oczywistym przykładem dla początkujących jest posiadanie S-Expression jako części pierwszego członka S-Expression. W ten sposób możemy zmienić zachowanie metody, zmieniając funkcję, która zostanie wywołana bez konieczności tworzenia rozgałęzień o tych samych parametrach. Oto szybki przykład wyrażenia, które dodaje lub odejmuje liczby, jeśli x jest poniżej y.
((if (< x y) + -)
1 2 3)
Jeśli x jest poniżej y , wyrażenie zostanie ocenione jako:
(+ 1 2 3)
6
Inaczej
(- 1 2 3)
-4
Jak widać, Schemat pozwala programiście zbudować złożony fragment kodu, jednocześnie dając programistom narzędzia zapobiegające powielaniu kodu. W innych językach możemy zobaczyć ten sam przykład napisany jako taki:
(jeśli (<xy) (+ 1 2 3) (- 1 2 3))
Problem z tą metodą polega na tym, że duplikujemy dużo kodu, a jedyną zmianą jest wywoływana metoda. Ten przykład jest dość prosty, ale z większym warunkiem możemy zobaczyć wiele podobnych linii powielonych.
Proste niech makro
Wyrażenia let w schemacie są w rzeczywistości makrami. Można je wyrazić za pomocą lambdas. Prosty niech może wyglądać następująco:
(let ((x 1) (y 2))
(+ x y))
Zwróci 3 jako wartość ostatniego wyrażenia let let body. Jak widać, wyrażenie-wyrażenie faktycznie coś wykonuje. Gdybyśmy przetłumaczyli tę część kodu za pomocą lambdas, otrzymalibyśmy coś takiego:
((lambda (x y) (+ x y)) 1 2)
Tutaj widzimy, że nazywamy bezpośrednio anonimową lambda z 1 i 2. Wynik w tym przypadku wynosi również 3.
Mając to na uwadze, rozumiemy, że wyrażenie let składa się z 2 części. Ma parametry i ciało jak lambda, ale różnica polega na tym, że wyrażenie jest wywoływane zaraz po ich ocenie.
Aby wyjaśnić, w jaki sposób wyrażenie let działa od widoku abstrakcyjnego do konkretnego, wyglądałoby to tak.
(let params body ...)
(let (param1 param2 ...) body ...)
(let ((p1 val1) (p2 val2) ...) body ...)
Parametry to lista par (name value) mają być użyte w treści let .
Dlaczego warto korzystać z wyrażenia?
Niech wyrażenia są szczególnie przydatne do przechowywania zmiennych w metodzie takiej jak inicjalizacja zmiennej w językach podobnych do c. Korzystne jest użycie define ponieważ z wyrażenia let zmienne zniknęły ... Użycie definicji polega na dodaniu zmiennej do bieżącego środowiska wykonawczego. Zmiennych dodanych do środowiska globalnego nie można usunąć. Niech ekspresja jest bezpieczna w użyciu w dowolnym miejscu. Można go również użyć do zmiennych ducha bez dotykania zakresów nadrzędnych.
Na przykład:
(let ((x 1))
(let ((x 2) (y x))
(display x)
(display y))
(display x))
Wydrukuje:
2
1
1
W tym przypadku x jest zdefiniowane za pomocą 1, a następnie zamglone przez x w drugim let z wartością 2 . Zmienna y jest inicjowana wartością x zakresu nadrzędnego. Po wykonaniu wewnętrznego wyrażenia let wyświetla wartość początkową x pomocą 1. Wewnętrzne wyrażenie let nie zmienia wartości zakresu nadrzędnego.
Ilekroć potrzebujesz zainicjować zmienne, powinieneś używać wyrażeń let w następujący sposób:
(let (
(user (get-current-user session))
(db (get-current-db session))
(ids (get-active-ids session))
)
(mark-task-completed db user ids)
(change-last-logged db user)
(db-commit db))
W tym przykładzie zmienne są inicjowane i używane wielokrotnie w bloku kodu. Po zakończeniu wyrażenia let zmienne są automatycznie zwalniane, ponieważ nie są już potrzebne.
Kropkowana składnia dla par
Istnieje szczególna składnia, która pozwala nam pisać komórkę cons w bardziej zwarty sposób niż przy użyciu konstruktora cons .
Para może być zapisana jako taka:
'(1 . 2) == (cons 1 2)
Duża różnica polega na tym, że możemy tworzyć pairs za pomocą cytatu. W przeciwnym razie Schemat utworzyłby odpowiednią listę (1 . (2 . '())) .
Składnia kropkowa wymusza, aby wyrażenie miało tylko 2 elementy. Każdy członek może być dowolnego typu, w tym parami.
'(1 . (2 . (3 . 4)))
> (1 2 3 . 4)
Zauważ, że niewłaściwa lista powinna być wyświetlana z kropką na końcu, aby pokazać, że cdr ostatniej pary listy nie jest pustą listą '() .
Ten sposób wyświetlania list jest czasami mylący, ponieważ następujące wyrażenie byłoby wyrażone inaczej niż można by się tego spodziewać.
'((1 . 2) . ( 3 . 4))
> ((1 . 2) 3 . 4)
Ponieważ lista zwykle pomija . , pierwszym argumentem listy będzie (1 . 2) , drugim argumentem będzie 3 ale ponieważ lista jest niewłaściwa, ostatni . pokazuje, że ostatnim elementem listy nie jest '() . Nawet sądząc, dane są wyświetlane w inny sposób, dane wewnętrzne są takie, jak zostały utworzone.