Поиск…


S-Expression

Выражение в Схеме - это то, что собирается выполнить. S-выражение, как его обычно называют, начинается с ( и заканчивается на a ) . Первый член выражения - это то, что собирается выполнить. Следующий член выражения - это параметры, которые будут отправлены в выражение во время оценки выражения.

Например, добавление номеров:

(+ 1 2 3)

В этом случае символ + является символом функции add, которая принимает несколько параметров. 1 , 2 и 3 отправляются в функцию + .

S-выражение может содержать S-выражения в качестве параметров, как показано в следующем примере:

(if (< x y)
  x
  y)

Который может быть прочитан так, как если бы x меньше, чем y return x else return y . В этом примере мы вычисляем выражение условия, в зависимости от разрешенного значения, либо x, либо y будут возвращены. Его можно было бы оценить

(if #t x y)
x
(if #f x y)
y

Менее очевидным примером для новичков является S-выражение как часть первого члена S-выражения. Таким образом, мы можем изменить поведение метода, изменив функцию, которая будет вызываться без необходимости создания ветвей с теми же параметрами. Вот краткий пример выражения, которое добавляет или вычитает числа, если x меньше y.

((if (< x y) + -) 
  1 2 3)

Если x меньше y , выражение будет оцениваться как:

(+ 1 2 3)
6

иначе

(- 1 2 3)
-4

Как вы можете видеть, Scheme позволяет программисту создавать сложную часть кода, предоставляя программисту инструменты для предотвращения дублирования кода. На других языках мы могли видеть тот же пример, который был написан как таковой:

(если (<xy) (+ 1 2 3) (- 1 2 3))

Проблема с этим методом заключается в том, что мы дублируем много кода, в то время как единственное, что изменяется, - это вызываемый метод. Этот пример довольно прост, но с большим количеством условий мы могли бы увидеть много похожих строк, дублированных.

Простой макет

Пусть выражения в схеме являются макросами. Они могут быть выражены лямбдами. Простой пусть может выглядеть так:

(let ((x 1) (y 2))
  (+ x y))

Он вернет 3, когда возвращается значение последнего выражения тела let. Как вы можете видеть, выражение let-expression фактически выполняет что-то. Если мы переведем эту часть кода с lambdas, мы получим что-то вроде этого:

((lambda (x y) (+ x y)) 1 2)

Здесь мы видим, что мы вызываем анонимную лямбду с 1 и 2 напрямую. Таким образом, результат в этом случае также равен 3.

Имея это в виду, мы понимаем, что выражение let состоит из 2 частей. У него есть параметры и тело, подобное лямбда, но разница в том, что пусть выражение вызывается после сразу после их оценки.

Чтобы объяснить, как выражение let работает от абстрактного к конкретному виду, оно будет выглядеть так.

(let params body ...)
(let (param1 param2 ...) body ...)
(let ((p1 val1) (p2 val2) ...) body ...)

Параметры - это список пары (name value) которая будет использоваться в теле let .

Зачем использовать let выражение?

Пусть выражения особенно полезны для хранения переменных в методе, аналогично инициализации переменной в c-подобных языках. Это полезно для использования define потому что из выражения let переменные исчезают ... Использование define фактически добавляет переменную в текущую среду исполнения. Переменные, добавленные в глобальную среду, не могут быть удалены. Пусть выражение безопасно использовать в любом месте. Он также может использоваться для переменных-призраков, не касаясь родительских областей.

Например:

(let ((x 1))
  (let ((x 2) (y x))
    (display x)
    (display y))
  (display x))

Он напечатает:

2
1
1

В этом случае x определяются с 1, а затем с помощью призраки x во второй let со значением 2 . Переменная y начинается со значения x родительской области. После выполнения внутреннего выражения let оно отображает начальное значение x с 1. Внутреннее выражение let не меняет значение родительской области.

Всякий раз, когда вам нужно инициализировать переменные, вы должны использовать let выражения следующим образом:

(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))

Здесь в этом примере переменные инициализируются и используются в блоке кода несколько раз. И когда выражение let закончено, переменные автоматически освобождаются, поскольку они больше не нужны.

Пунктирный синтаксис для пар

Существует особый синтаксис, который позволяет нам писать cons cell более компактным способом, чем использование конструктора cons .

Пара может быть записана как таковая:

'(1 . 2) == (cons 1 2)

Большая разница в том, что мы можем создавать pairs используя цитату. В противном случае схема создала бы правильный список (1 . (2 . '())) .

Синтаксис точки заставит выражение иметь только 2 члена. Каждый член может быть любого типа, включая пары.

'(1 . (2 . (3 . 4)))
> (1 2 3 . 4)

Обратите внимание, что неправильный список должен отображаться с точкой в ​​конце, чтобы показать, что cdr последней пары списка не является пустым списком '() .

Этот способ отображения списков иногда запутывается, поскольку следующее выражение выражается не так, как можно было бы ожидать.

'((1 . 2) . ( 3 . 4))
> ((1 . 2) 3 . 4)

Поскольку список обычно пропускает . , первым аргументом списка будет (1 . 2) , второй аргумент будет 3 но поскольку список неправильный, последний . показано, что последний элемент списка не равен '() . Даже мысли, данные отображаются по-другому, внутренние данные, как он был создан.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow