Как переименовать операцию в Clojure? - PullRequest
1 голос
/ 14 мая 2010

В моем списке, кроме того, операция + выглядит как #. Как я могу сделать это в точности как +? Когда я его оцениваю, он также должен работать точно так же, как +.

Полагаю, это также применимо ко всем видам функций в Clojure ... Спасибо, ребята.

Ответы [ 2 ]

5 голосов
/ 14 мая 2010

Символ # просто не является допустимым символом в именах символов в Clojure (список допустимых символов см. на этой странице ), и хотя иногда он может работать (как это часто бывает), он это не очень хорошая практика, чтобы использовать его. Кроме того, это определенно не будет работать в начале символа (на самом деле это литерал, вы все равно можете сделать (symbol "#"), хотя, вероятно, в этом нет никакого смысла). Поскольку читатель Clojure в настоящее время стоит, с этим ничего не поделаешь (кроме, возможно, взлома считывателя открытым, чтобы он воспринимал # (это '#' с пробелом) как символ # - или просто + - хотя это то, что вы действительно не должны делать, поэтому я почти чувствую себя виноватым за предоставление ссылки на инструкции о том, как это сделать).

Если вы хотите присвоить псевдониму какое-либо другое имя, которое является допустимым в Clojure, может оказаться удобным использовать макрос clojure.contrib.def/defalias вместо простого def; это дает дополнительное преимущество установки метаданных для вас (и должно обрабатывать макросы, хотя, похоже, есть ошибка, которая предотвращает это в настоящее время, по крайней мере, в 1.2 HEAD).


И в случае, если вы захотите переопределить некоторые встроенные имена при создании псевдонимов ... (Если вы этого не сделаете, остальное может не относиться к вам.)

Во-первых, если вы работаете с Clojure 1.1 или более ранней версией и хотите предоставить собственную привязку для имени из clojure.core, вам нужно будет использовать :refer-clojure при определении пространства имен. Например. если вы хотите предоставить свой +:

(ns foo.bar
  (:refer-clojure :exclude [+]))

;; you can now define your own +
(defn + [x y]
  (if (zero? y)
    x
    (recur (inc x) (dec y))))

;; examples
(+ 3 5)
; => 8
(+ 3 -1)
; => infinite loop
(clojure.core/+ 3 -1)
; => 2

Необходимость этого вытекает из Clojure 1.1, запрещающего повторное связывание имен, которые ссылаются на Vars в других пространствах имен; ns-unmap обеспечивает обходной путь, подходящий для использования REPL, тогда как (:refer-clojure :exclude ...), (:use :exclude ...) и (:use :only ...) предоставляют средства систематически, чтобы в первую очередь предотвращать импорт нежелательных имен из других пространств имен.

В текущих снимках 1.2 есть политика "last-var-in wins", так что вы можете обойтись без :refer-clojure; тем не менее, он по-прежнему генерирует предупреждение компилятора, и его лучше использовать :refer-clojure, плюс нет гарантии, что эта политика сохранится в реальной версии 1.2.

1 голос
/ 14 мая 2010

Операция - это просто фрагмент кода, назначенный переменной. Если вы хотите перепривязать операцию, просто перепривязайте эту переменную:

(def - +)
(- 1 2 3)
# => 6

Единственная проблема здесь в том, что символ # является особенным в Clojure. Я не уверен, что вы можете использовать # в качестве имени переменной для всех , по крайней мере, вам нужно будет заключить его в кавычки при связывании и, вероятно, также при вызове:

(def # +)
# => java.lang.Exception: No dispatch macro for: 

К сожалению, я недостаточно знаком с Clojure, чтобы знать, как его процитировать.

...