Теперь, когда вы знаете о переменных и функциях, обратимся к спискам в Scheme.
До разговора о списках необходимо упомянуть разницу между неделимыми значениями и списками.
В предыдущем уроке вы уже видели неделимые значения, которые мы присвоили переменным. Неделимое значение — это одно-единственное значение. Так, мы можем присвоить переменной «x
» значение 8 следующим утверждением:
(let* ( (x 8) ) x)
Мы добавили выражение x
в конце, чтобы вывести значение переменной x
. Обычно этого не требуется. Заметьте, что оператор let*
ведёт себя как функция: возвращается значение последнего выражения.
Переменная также может содержать спискок значений вместо одного значения. Чтобы присвоить переменной x
список значений 1, 3, 5, нужно ввести:
(let* ( (x '(1 3 5))) x)
Попробуйте ввести оба утверждения в консоль Script-Fu и посмотрите, что они выводят.
8
При вводе второго утверждения, выводится следующее:
(1 3 5)
Когда вывелось значение 8, это значит, что переменная x
содержит неделимое значение 8. Однако, когда вывелось (1 3 5)
, это значит, что переменная x
содержит не одно значение, а список значений. Заметьте, что ни в декларации или присвоении, ни в выведенном результате нет запятых.
Синтаксис для создания списка следующий:
'(a b c)
Где a
, b
и c
— одиночные значения. Мы используем апостроф ('
) чтобы указать, что за ним в скобках следует список одиночных значений, а не функция или выражение.
Пустой список создаётся так:
'()
или так:
()
Списки могут содержать как неделимые значения, так и другие листы:
(let* ( (x '("GIMP" (1 2 3) ("is" ("great" () ) ) ) ) ) x )
Заметьте, что после первого апострофа не надо больше ставить апостроф перед внутренними списками. Введите это выражение и посмотрите, что получится.
Вы заметите, что возвращённый результат — не список одиночных неделимых значений, а список, содержащий буквальное значение (The GIMP)
, список (1 2 3)
и т.д.
Полезно думать о списках, как состоящих из «головы» и «хвоста». Голова — первый элемент списка, хвост — остаток списка. Вы увидите, почему это важно, как речь пойдёт о сложении списков и о доступе к элементам списка.
Наиболее употребляемая функция это функция cons. Она берёт любое значение и добавляет его ко второму параметру, списку. Если использовать терминологию вышесказанного, это функция добавляет значение в голове списка. Поэтому список можно создать следующим образом:
(cons 1 '(2 3 4) )
В результате получается список (1 2 3 4)
.
Можно также создать список с одним элементом:
(cons 1 () )
Можно использовать ранее декларированные переменные вместо буквальных значений.
Создать список из буквальных значений и переменных можно с помощью функции list
:
(list 5 4 3 a b c)
Это создаст и вернёт список, содержащий значения переменных a
, b
и c
. На пример:
(let* ( (a 1) (b 2) (c 3) ) (list 5 4 3 a b c) )
Этот сценарий создаёт список (5 4 3 1 2 3)
.
Чтобы достать значения из списка, используйте функции car
и cdr
, которые возвращают первый элемент списка и остаток списка, соответственно. Назначение этих функций совпадает с терминологией голова-хвост, описанной выше.
car
returns the first element of the list (the
head of the list). The list needs to be non-null (not empty). Thus, the
following returns the first element of the list:
(car '("первый" 2 "третий"))
то есть
"первый"
cdr
returns the remainder of the list after the
first element (the tail of the list). If there is only one element in
the list, it returns an empty list.
(cdr '("первый" 2 "третий"))
возвращает
(2 "третий")
тогда как
(cdr '("один единственный"))
возвращает
()
Теперь, когда мы можем достать первый элемент списка и всё остальное, поговорим о том, как достать другие элементы (второй, третий, …) списка. Существует несколько вспомогательных функций, позволяющие достать, например, голову хвоста списка (caadr
) или хвост хвоста списка (cddr
), и т.д.
Номенклатура названий проста: a означает голова, d означает хвоста, поэтому
(car (cdr (car x) ) )
можно написать как:
(cadar x)
Для практики по доступу к спискам, попробуйте ввести следующее (всё на одной линии, если используете консоль) и, используя функции car
и cdr
, достать разные элементы из списка:
(let* ( (x '( (1 2 (3 4 5) 6) 7 8 (9 10) ) ) ) ; поместите своё выражение с car/cdr здесь )
Попробуйте достать число 3 из списка при помощи только двух вызовов функций. Если сможете, то вы на правильном пути стать мастером Script-Fu!
Примечание | |
---|---|
In Scheme, a semicolon ( |