Вопросы о Списки и другие вещи в Clojure - PullRequest
3 голосов
/ 12 июля 2009

У меня есть несколько вопросов, касающихся списков, классов и переменных в clojure.

  1. Это может показаться довольно глупым, но как мне получить доступ к элементам в списке?

Я пишу программу, которая позволяет вам манипулировать телефонной книгой; Вы можете добавить запись, удалить одну или распечатать информацию о ней. Это приводит меня к двум вопросам:

  1. Есть ли способ создать класс "запись", который бы содержал переменные "имя", "адрес", "номер телефона"? или это невозможно в clojure (и функциональном программировании в целом?) Если у меня не может быть Списка объектов, содержащих эту информацию, как бы я справился с этой задачей?

  2. Я думал о том, чтобы иметь функцию, которая считывает вводимые пользователем данные, чтобы узнать, что пользователь хочет сделать (добавить запись, удалить запись или распечатать информацию), а затем вызывает соответствующую функцию, чтобы сделать то, что вызывает первую функцию, когда это сделано. Является ли передача в качестве параметра списка записей каждой функции правильной?

Ответы [ 4 ]

7 голосов
/ 13 июля 2009

Это может показаться довольно глупым, но как мне получить доступ к элементам в списке?

(nth coll index)

Например:

(nth [1 2 3 4] 2) ; -> 3 (since it uses zero-based indexing)

Есть ли способ создать класс "запись", который бы содержал переменные "имя", "адрес", "номер телефона"? или это невозможно в clojure (и функциональном программировании в целом?) Если у меня не может быть Списка объектов, содержащих эту информацию, как бы я справился с этой задачей?

Это возможно в Clojure, но не в форме. В Clojure основной абстракцией для объектов данных являются карты, а не классы (за исключением некоторых угловых случаев, когда необходимо прямое взаимодействие с платформами Java). Так что вы просто используете карту:

(def entry {:name "x" :address "y" :phone-number "z"})

Чтобы получить доступ к имени предмета, вы можете использовать

(:name entry)

или

(get entry :name)

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

Итак, для вашего примера ваша модель данных (телефонная книга) будет представлять собой последовательность (скажем, список или вектор) таких карт.

Я думал о том, чтобы иметь функцию, которая считывает вводимые пользователем данные, чтобы узнать, что пользователь хочет сделать (добавить запись, удалить запись или распечатать информацию), а затем вызывает соответствующую функцию, чтобы сделать то, что вызывает первую функцию, когда это сделано. Является ли передача в качестве параметра списка записей каждой функции правильным решением?

Поскольку ваша модель состоит только из одной основной структуры данных (телефонная книга seq), передача ее в качестве аргумента, безусловно, является подходящим способом для разработки ваших функций. Если вы ожидаете, что у вас будет больше видов контейнеров верхнего уровня (например, для более реальных приложений), я бы рекомендовал изучить шаблон контекста приложения , который на первый взгляд будет выглядеть немного пугающим (по крайней мере, это было для меня, и оно содержит много специфичного для Clojure жаргона), но оно того стоит, чтобы выучить.

5 голосов
/ 13 июля 2009

Рассматривали ли вы покупку книги Программирование Clojure ? PDF-версия стоит всего 21 доллар США. На мой взгляд, стоит денег.

2 голосов
/ 13 июля 2009
(entry :name)

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

(entry :name)

или

(:name entry)

или

(get entry :name)

, где

(def entry {:name "x" :address "y" :phone-number "z"})

Как упоминал Рейн, вторая форма возможна только в том случае, если ключ является ключевым словом. Вы можете использовать другую «короткую» форму с ключами других типов:

user=>(def my-map {"a" "b" "c" "d"})
user=>(my-map "c")
"d"
user=>(get my-map "a")
"b"
1 голос
/ 15 июля 2009

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

лучше всего массивы являются функциями индекса:

 (def a [1 2 3 4])
 (a 2) ==> 3

для частей 2 и 3 pmf ответьте на них очень красиво.

...