Clojure: Внутреннее устройство списков, пары, cons, nil
Все списки, с которыми вы имели дело до этого момента, либо создавались с помощью литералов и функции list либо являлись результатами вычисления каких-то выражений. Во всех этих случаях список выглядит, как нечто неделимое, цельное. Именно так работает абстракция: для работы со списками достаточно думать о списке, как о самостоятельной и самодостаточной сущности!
Тем из вас, кто сталкивался в других языках с массивами, могло показаться, что и в Clojure списки, это те же массивы — отдельные участки памяти компьютера, хранящие все значения рядом.
На самом же деле во всех языках семейства lisp, да и в большинстве других языков, располагающих к функциональному подходу, списки — это цепочки вложенных пар. А вот пара уже является неделимой структурой. И чтобы понять списки, нужно сначала освоить пары. Однако! В Clojure ситуация со списками немного иная, в списках используются обычный связный список с головой и хвостом. Если хочется лучше понять смысл пар, крайне рекомендуется прочесть Структуру и Интерпретацию Компьютерных Программ (SICP).
Для работы со списками существуют функции first, rest, last:
(def my-list '(1 2 3))
(first my-list) ; => 1
(last my-list) ; => 3
(rest my-list) ; => '(2 3)Помимо перечисленных функций выше, есть еще упрощающие обработку списков:
(count (list 1 2 3)) ; => 3
(empty? (list)) ; => true
(empty? (list 1 2 3)) ; => false
(list? (list 1 2 3)) ; => true
; нумерация для nth идет с нуля
(nth '(1 2 3) 1) ; => 2Задание
Реализуйте функцию lookup, которая бы должна принимать аргумент-ключ и список пар "ключ-значение" и возвращать либо пару "ключ-значение", где ключ равен первому аргументу, либо возвращать false, если подходящих пар в списке не нашлось. Если подходящих пар найдётся несколько, вернуть нужно первую.
Примеры:
(def user-ages
(list (list "Tom" 31)
(list "Alice" 22)
(list "Bob" 42)))
(lookup "Bob" user-ages) ; '("Bob" . 42)
(lookup "Tom" user-ages) ; '("Tom" . 31)
(lookup "Moe" user-ages) ; falseClojure: Внутреннее устройство списков, пары, cons, nil
Все списки, с которыми вы имели дело до этого момента, либо создавались с помощью литералов и функции list либо являлись результатами вычисления каких-то выражений. Во всех этих случаях список выглядит, как нечто неделимое, цельное. Именно так работает абстракция: для работы со списками достаточно думать о списке, как о самостоятельной и самодостаточной сущности!
Тем из вас, кто сталкивался в других языках с массивами, могло показаться, что и в Clojure списки, это те же массивы — отдельные участки памяти компьютера, хранящие все значения рядом.
На самом же деле во всех языках семейства lisp, да и в большинстве других языков, располагающих к функциональному подходу, списки — это цепочки вложенных пар. А вот пара уже является неделимой структурой. И чтобы понять списки, нужно сначала освоить пары. Однако! В Clojure ситуация со списками немного иная, в списках используются обычный связный список с головой и хвостом. Если хочется лучше понять смысл пар, крайне рекомендуется прочесть Структуру и Интерпретацию Компьютерных Программ (SICP).
Для работы со списками существуют функции first, rest, last:
(def my-list '(1 2 3))
(first my-list) ; => 1
(last my-list) ; => 3
(rest my-list) ; => '(2 3)Помимо перечисленных функций выше, есть еще упрощающие обработку списков:
(count (list 1 2 3)) ; => 3
(empty? (list)) ; => true
(empty? (list 1 2 3)) ; => false
(list? (list 1 2 3)) ; => true
; нумерация для nth идет с нуля
(nth '(1 2 3) 1) ; => 2Задание
Реализуйте функцию lookup, которая бы должна принимать аргумент-ключ и список пар "ключ-значение" и возвращать либо пару "ключ-значение", где ключ равен первому аргументу, либо возвращать false, если подходящих пар в списке не нашлось. Если подходящих пар найдётся несколько, вернуть нужно первую.
Примеры:
(def user-ages
(list (list "Tom" 31)
(list "Alice" 22)
(list "Bob" 42)))
(lookup "Bob" user-ages) ; '("Bob" . 42)
(lookup "Tom" user-ages) ; '("Tom" . 31)
(lookup "Moe" user-ages) ; falseВаше упражнение проверяется по этим тестам
(ns list-internals-test
(:require [test-helper :refer [assert-solution]]
[index :refer [lookup]]))
(assert-solution
[["foo" nil]
["foo" (list (list "foo" "bar"))]
["foo" (list (list "bar" "foo"))]
[42 (list (list 42 0)
(list 30 0)
(list 42 100500))]]
[false '("foo" "bar") false '(42 0)]
lookup)Решение учителя откроется через:
20:00
