Подтвердить что ты не робот

Clojure: определить, объявлена ​​ли переменная

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

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

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

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

4b9b3361

Ответ 1

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

 
(resolve 'meaning)
nil

(def meaning 42)
#'user/meaning

(resolve 'meaning)
#'user/meaning

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

(boolean (resolve 'meaning))
true

Ответ 2

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

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

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

Ответ 3

Как говорили другие, resolve вернет var для символа, если есть один определенный или nil. Кроме того, вы можете проверить, имеет ли значение 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

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

Это орехи. Вы действительно хотите, чтобы тест сказал: "Ой! Ты забыл определить foobar!" вместо того, чтобы просто запускать foobar и видеть сообщение clojure "Невозможно разрешить символ"?

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