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

Каким образом можно преобразовать ключевое слово clojure с именами в строку?

Когда используется функция name, она правильно возвращает имя ключевого слова в виде строки, например:

(name :k) => "k"

Проблема возникает при использовании name для ключевого слова с именами, например:

(name :n/k) => "k"

Я могу использовать функцию namespace, чтобы правильно получить строку, которую я ищу:

(str (namespace :n/k) "/" (name :n/k)) => "n/k"

Но по какой-то причине я чувствую, что должен быть лучший способ получить полностью соответствующую строку.

Каким будет лучший способ сделать это?

4b9b3361

Ответ 1

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

(str (.-sym :foo/bar))
;= "foo/bar"

Ответ 2

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

(string/join "/" ((juxt namespace name) k))

Ответ 3

(subs (str :foo/k) 1)
;=> "foo/k"

Ответ 4

Основываясь на реализации name:

user=> (source name)
(defn name
  "Returns the name String of a string, symbol or keyword."
  {:tag String
   :added "1.0"
   :static true}
  [x]
  (if (string? x) x (. ^clojure.lang.Named x (getName))))
nil
user=>

И учитывая, что интерфейс clojure.lang.Named имеет метод getNamespace:

https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Named.java

Итак, вы можете сделать это:

(defn full-name [k] (str (.getNamespace k) "/" (.getName k)))