Хобрук: Ваш путь к мастерству в программировании

Clojure: Имя переменных в списке

У меня есть что-то вроде этого:

(def a "text")
(def b "text")
(def c nil)
(def d 8)
(def e "")

(def testlist (list a b c d e ))

Теперь, есть ли способ получить строку имен переменных? Я предполагаю, что «нет» — наиболее вероятный ответ.

name не работает, поскольку возвращает только значение. Список содержит только значения после def?

РЕДАКТИРОВАТЬ: Что я забыл и что может быть важно для этого вопроса: я не могу ни использовать eval, ни использовать defmacro, оба не разрешены (по соображениям безопасности и т. д.). Так что да...

14.12.2017

  • Это предположение: я не знаю clojure. Но я подозреваю, что вы создаете список по значению, поэтому список содержит только значения, а не ссылки на переменные. 14.12.2017
  • Вы можете составить список символов: (list 'a 'b 'c 'd 'e) или переменных: (list #'a #'b #'c #'d #'e). 14.12.2017
  • Вам действительно нужен макрос, чтобы сделать это, и обычно, когда люди хотят это сделать, причина не очень веская и почти всегда не очень хорошая идея. 14.12.2017
  • @Josh, причина в том, что я хочу проверить наличие нуля и пустого значения, а затем вывести имена этих переменных. Идея в том, что я не знаю, сколько элементов в этом списке, просто каждый элемент проверяется и возвращается результат. 14.12.2017
  • Не могли бы вы использовать карту, { "a" a "b" b "c" c "d" d "e" e}? Таким образом, вы получите имя и значение... 14.12.2017
  • @Kris Да, я могу, я просто искал ленивый способ не делать этого. 14.12.2017

Ответы:


1

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

user> (defmacro list+ [& syms]
        `(with-meta (list ~@syms) {:vars (quote ~syms)}))
#'user/list+

user> (def testlist (list+ a b c d e))
#'user/testlist

user> (-> testlist meta :vars)
(a b c d e)

user> (defn nil-vals-names [data]
        (for [[v name] (map vector data (-> data meta :vars))
              :when (nil? v)]
          name))
#'user/nil-vals-names

user> (nil-vals-names testlist)
(c)
14.12.2017

2

Вы не сможете получить строку из имен переменных, так как Clojure оценит их как можно скорее, чтобы создать testlist

=> (def testlist (a b c d e ))
("text" "text" nil 8 "")

Однако вы можете заключить список в кавычки, чтобы получить символ, связанный с именем каждой переменной.

=> (def testlist (quote (a b c d e ))) ;; equivalent to '(a b c d e ))
(a b c d e)

А затем преобразовать эти символы в строки с помощью функции str

=> (map str testlist)
("a" "b" "c" "d" "e")

Позже вы можете eval этот список получить значение в контексте вашего пространства имен.

=> (map eval testlist)
("text" "text" nil 8 "")

Обратите внимание, что использование eval с внешним вводом (например, read-line) может создать угроза безопасности в Clojure и других языках.

Более того, список должен оцениваться в том же пространстве имен, что и его определение. В противном случае Clojure не сможет разрешить символы.

=> (ns otherns)
=> (map eval user/testlist)
 java.lang.RuntimeException: Unable to resolve symbol: a in this context

В большинстве случаев лучше всего использовать макросы.

14.12.2017

3

Совершенно неясно, чего вы пытаетесь достичь, но все же есть возможный способ.

Функция meta берет ссылку и возвращает карту с полем :name, содержащим строку с именем переменной:

user=> (def foo 42)
#'user/foo

user=> (meta #'foo)
{:line 1, :column 1, 
 :file "/some/tmp/file.clj", 
 :name foo, 
 :ns #namespace[user]}
14.12.2017
Новые материалы

Учебные заметки JavaScript Object Oriented Labs
Вот моя седьмая неделя обучения программированию. После ruby ​​и его фреймворка rails я начал изучать самый популярный язык интерфейса — javascript. В отличие от ruby, javascript — это более..

Разбор строк запроса в vue.js
Иногда вам нужно получить данные из строк запроса, в этой статье показано, как это сделать. В жизни каждого дизайнера/разработчика наступает момент, когда им необходимо беспрепятственно..

Предсказание моей следующей любимой книги 📚 Благодаря данным Goodreads и машинному обучению 👨‍💻
«Если вы не любите читать, значит, вы не нашли нужную книгу». - J.K. Роулинг Эта статья сильно отличается от тех, к которым вы, возможно, привыкли . Мне очень понравилось поработать над..

Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

Как настроить Selenium в проекте Angular
Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

Аргументы прогрессивного улучшения почти всегда упускают суть
В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

Введение в Джанго Фреймворк
Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..