Clojure: определить, объявлена ​​ли переменная - PullRequest
12 голосов
/ 20 октября 2011

Как я могу проверить, была ли переменная объявлена ​​или назначена (то есть проверить, определено ли «a», когда я ожидаю, что программа вызовет некоторый код, подобный этому (def a (create-a))?

И связанный --- как ответ на этот вопрос связан с проблемой разрешения символа (то есть функции), который был объявлен? Clojure: определить, существует ли функция

Кажется, что определенная переменная должна проверяться в том же смысле, что и определенная функция, но я нахожу, что решения для определения, существует ли функция, недостаточно для определения, существует ли переменная.

Некоторый контекст: я пишу модульные тесты для проекта с несколькими разработчиками и хочу убедиться, что тестовые данные и методы в разных классах были определены. Поскольку не существует хорошей поддержки IDE для clojure, мне кажется, что, учитывая ее слабую структуру, перед проверкой их выходных данных / содержимого полезно проверить имена методов и имена переменных.

Ответы [ 4 ]

12 голосов
/ 20 октября 2011

Вы можете использовать resol , чтобы увидеть, была ли переменная привязана / определена:

(resolve 'meaning)
nil

(def meaning 42)
#'user/meaning

(resolve 'meaning)
#'user/meaning

или вы можете проверить ее логическое значение, если вам нужно true / false:

(boolean (resolve 'meaning))
true
4 голосов
/ 20 октября 2011

Как уже говорили другие, resolve вернет переменную для символа, если он определен, или ноль.Кроме того, вы можете проверить, имеет ли var значение, связанное с ним, используя bound?.

user=> (resolve 'foo)
nil
user=> (def foo)
#'user/foo
user=> (resolve 'foo)
#'user/foo
user=> (bound? #'foo)
false
user=> (def foo 5)
#'user/foo
user=> (bound? #'foo)
true
4 голосов
/ 20 октября 2011

Один из способов сделать это - использовать ns-resol , например:

user=> (def a "hello a")
user=> (ns-resolve *ns* 'a)
#'user/a
user=> (ns-resolve *ns* 'b)
;nil                    ; This assumes b hasn't been defined before...

Обратите внимание, что если вы квалифицируете пространство имен для символа, который нужно проверить, то то, что вы передаете какПервый аргумент (*ns* в приведенном выше примере) не имеет значения:

user=> (ns-resolve 'user 'a)
#'user/a
user=> (ns-resolve 'other 'a)
nil
user=> (ns-resolve 'other 'user/a)
#'user/a

Функция resol , упомянутая @tolitius, фактически является сокращением для ns-resolve, где аргумент пространства именвсегда оценивается как нс , в зависимости от варианта использования это может быть более удобно.

1 голос
/ 20 октября 2011

Поскольку нет хорошей поддержки IDE для clojure, мне кажется, что учитывая его свободную структуру, хорошо проверить имена методов и существование имен переменных перед проверкой их выходов / содержимого.

Это орехи. Вы действительно хотите, чтобы тест сказал "Ой! Вы забыли определить foobar!" вместо того, чтобы просто пытаться запустить foobar и увидеть сообщение Clojure «Unable to resolve»?

Что вы получаете от этого? Вы теряете трассировку стека, что может быть полезно, если, например, тесту передано неправильное имя функции другим кодом. Гораздо лучше узнать, какая строка неправильно написана для foobar, чем искать во всем тестовом пространстве имен.

...