Ответ 1
Я перейду с высокого уровня до вашей конкретной проблемы:
Как Clojure (или LISP) обычно работают
REPLs, или Read-Eval-Print Loops - суть того, как проектируются LISP:
- reader преобразует поток символов в структуры данных (называемые формами Reader).
- Оценщик принимает коллекцию форм читателей и оценивает их.
- Принтер испускает результаты оценки.
Поэтому, когда вы вводите текст в REPL, он проходит каждый из этих шагов для обработки вашего ввода и возврата вывода к вашему терминалу.
Формы чтения
Сначала создаются некоторые, Clojure. Это будет крайне кратким, я рекомендую вам read или смотреть (часть 1, часть 2).
A символ в Clojure - это форма, которая может представлять конкретное значение (например, переменную). Символы сами могут проходить как данные. Они похожи на указатели в c, только без материалов управления памятью.
Символ с двоеточием перед ним является ключевым словом . Ключевые слова похожи на символы, за исключением того, что значение ключевого слова всегда само по себе - подобно строкам или цифрам. Они идентичны символам Ruby (которые также имеют префикс двоеточий).
A quote перед формой сообщает, что оценщик оставляет структуру данных как-есть:
user=> (list 1 2)
(1 2)
user=> '(1 2)
(1 2)
user=> (= (list 1 2) '(1 2))
true
Хотя цитирование может применяться к нескольким спискам, оно в основном используется для списков, поскольку оценщик Clojure обычно выполняет списки как функцию-вызов. Использование '
является сокращением макроса цитаты:
user=> (quote (1 2)) ; same as '(1 2)
(1 2)
Цитата в основном указывает структуру данных для возврата, а не фактический код для выполнения. Таким образом, вы можете цитировать символы, которые относятся к символу.
user=> 'foo ; not defined earlier
foo
И цитирование является рекурсивным. Таким образом, все данные внутри тоже цитируются:
user=> '(foo bar)
(foo bar)
Чтобы получить поведение (foo bar)
без цитирования, вы можете его оценить:
user=> (eval '(foo bar)) ; Remember, foo and bar weren't defined yet.
CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:1)
user=> (def foo identity)
#'user/foo
user=> (def bar 1)
#'user/bar
user=> (eval '(foo bar))
1
Здесь гораздо больше ссылок, но из этой области.
Требуя
Что касается требовательных утверждений, я предполагаю, что вы нашли первое в виде:
(ns my.namespace
(:require [clojure.set :as set]))
ns
является macro, который преобразует выражение require: в выражение, которое вы описали:
(require '[clojure.set :as set])
Наряду с некоторыми работами по расширению имен. Основы описаны при запросе документов ns в REPL.
user=> (doc ns)
-------------------------
clojure.core/ns
([name docstring? attr-map? references*])
Macro
Sets *ns* to the namespace named by name (unevaluated), creating it
if needed. references can be zero or more of: (:refer-clojure ...)
(:require ...) (:use ...) (:import ...) (:load ...) (:gen-class)
with the syntax of refer-clojure/require/use/import/load/gen-class
respectively, except the arguments are unevaluated and need not be
quoted. (:gen-class ...), when supplied, defaults to :name
corresponding to the ns name, :main true, :impl-ns same as ns, and
:init-impl-ns true. All options of gen-class are
supported. The :gen-class directive is ignored when not
compiling. If :gen-class is not supplied, when compiled only an
nsname__init.class will be generated. If :refer-clojure is not used, a
default (refer 'clojure) is used. Use of ns is preferred to
individual calls to in-ns/require/use/import:
Использование REPL
В общем случае не используйте ns
в REPL и просто используйте функции require
и use
. Но в файлах используйте макрос ns
для выполнения этих действий.