Теперь, когда вы знаете о переменных и функциях, обратимся к спискам в 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
возвращает первый элемент списка (голова списка). Список не может быть пустой. Следующее выражение вернёт первое значение:
(car '("первый" 2 "третий"))
то есть
"первый"
cdr
возвращает остаток списка после первого элемента (хвост списка). Если в списке только один элемент, то возвращается пустой список.
(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!
Замечание | |
---|---|
В Scheme точка с запятой ( |