tutorial online example clojure

online - clojure vs scala



Clojure, defn, defn-, public/private, por defecto (4)

Como lo afirma @kotarak, no hay manera (que yo sepa) de hacer eso, ni es deseable.

Aquí es por qué no me gusta defn- :

Descubrí que al usar varias bibliotecas de Clojure a veces necesito modificar ligeramente una función para adaptarla a mis necesidades particulares. A menudo es algo bastante pequeño, y eso solo tiene sentido en mi caso particular. A menudo esto es sólo un char o dos.

Pero cuando esta función reutiliza las funciones privadas internas, hace que sea más difícil modificarla. Tengo que copiar y pegar todas esas funciones privadas.

Entiendo que esta es una manera para que el programador diga que "esto podría cambiar sin previo aviso".

En cualquier caso, me gustaría la convención opuesta:

  • Siempre usa defn , que hace que todo sea público.
  • use defn+ (que aún no existe) para especificar al programador qué funciones forman parte de la API pública que se supone que debe usar. defn+ debería ser diferente de defn contrario.

También tenga en cuenta que es posible acceder a funciones privadas de todos modos:

;; in namespace user user> (defn- secret [] "TOP SECRET") ;; from another namespace (#''user/secret) ;;=> "TOP SECRET"

  • defn = public
  • defn- = privado

Tal vez tenga un estilo de codificación de Clojure incorrecto, pero me parece que la mayoría de las funciones que escribo en Clojure son pequeñas funciones de ayuda que no quiero exponer.

¿Hay alguna opción de configuración, donde:

  • defn = privado por defecto,
  • Y para hacer algo público, tengo que hacer defn+ ?

¡Gracias!


La belleza de Clojure siendo un Lisp, es que puedes construir y adaptar el lenguaje para que se adapte a tus necesidades. Te recomiendo que leas On Lisp, de Paul Graham . Ahora él regala su libro de forma gratuita.

En cuanto a su sugerencia de defn + vs defn vs defn-. Esto me suena como un buen caso para escribir tu propia Macro. defn es una función y defn- es una macro. Puede simplemente redefinirlos como desee, o envolverlos en su propio nombre.

Aquí sigue una sugerencia de implementación, basada principalmente en la implementación propia de Clojure, que incluye una utilidad simple y una prueba.

(defmacro defn+ "same as Clojure''s defn, yielding public def" [name & decls] (list* `defn (with-meta name (assoc (meta name) :public true)) decls)) (defmacro defn "same as Clojure''s defn-, yielding non-public def" [name & decls] (list* `defn (with-meta name (assoc (meta name) :private true)) decls)) (defn mac1 "same as `macroexpand-1`" [form] (. clojure.lang.Compiler (macroexpand1 form))) (let [ ex1 (mac1 ''(defn f1 [] (println "Hello me."))) ex2 (mac1 ''(defn+ f2 [] (println "Hello World!"))) ] (defn f1 [] (println "Hello me.")) (defn+ f2 [] (println "Hello World!")) (prn ex1) (prn (meta #''f1)) (f1) (prn ex2) (prn (meta #''f2)) (f2) )


No no hay.

Un enfoque alternativo que podría o no funcionar para usted es declarar un espacio de nombres foo.bar.internal contenga todos los ayudantes privados que usa su espacio de nombres foo.bar . Esto tiene ventajas sobre las declaraciones de funciones privadas cuando desea utilizar funciones privadas en expansiones de macro.