Soy nuevo en Clojure. Puedo entender el código que escribo pero se vuelve demasiado difícil de entender más tarde.
Se hace difícil hacer coincidir los paréntesis.
¿Cuáles son las convenciones genéricas a seguir con respecto a las convenciones de nomenclatura y la sangría en diversas situaciones?
Por ejemplo, escribí un ejemplo de desestructuración de muestra para entender, pero parece completamente ilegible la segunda vez.
(defn f [{x :x y :y z :z [a b c] :coll}] (print x " " y " " z " " a " " b " " c))
En caso de desestructuración, ¿es mejor hacerlo directamente a nivel de parámetro o iniciar un formulario let y luego continuar allí?
readability
clojure
Amogh Talpallikar
fuente
fuente
Respuestas:
Convenciones de nombres
use
-
para la separación silábica (lo que sería un guión bajo o un caso de camello en otros idiomas).(defn add-one [i] (inc i))
Los predicados (es decir, las funciones que devuelven verdadero o falso) terminan con
?
Ejemplos:odd?
even?
nil?
empty?
Los procedimientos de cambio de estado terminan en
!
. Te acuerdasset!
verdad? oswap!
Elija longitudes cortas de nombres variables según su alcance. Eso significa que si tiene una variable auxiliar realmente pequeña, a menudo puede usar un nombre de una letra.
(map (fn [[k v]] (inc v)) {:test 4 :blub 5})
elija nombres de variables más largos según sea necesario, especialmente si se usan para muchas líneas de código y no puede adivinar de inmediato su propósito. (mi opinión).Siento que muchos programadores de clojure tienden a usar nombres genéricos y cortos. Pero, por supuesto, esto no es realmente una observación objetiva. El punto es que muchas funciones de clojure son en realidad bastante genéricas.
drop
,take
,assoc
, etc A continuación, hay un buen artículo que describe maneras de elegir un nombre significativo: http://ecmendenhall.github.io/blog/blog/2013/09/ 02 / clean-clojure-significativo-nombres /Funciones lambda
En realidad, puede nombrar funciones lambda. Esto es conveniente para depurar y perfilar (mi experiencia aquí es con ClojureScript).
(fn square-em [[k v]] {k (* v v)})
Utilice las funciones lambda en línea
#()
como sea convenienteEspacio en blanco
No debe haber líneas solo para padres. Es decir, cerrar los paréntesis de inmediato. Recuerde que los parens están ahí para el editor y el compilador, la sangría es para usted.
Las listas de parámetros de funciones van a una nueva línea
Esto tiene sentido si piensas en las cadenas de documentos. Están entre el nombre de la función y los parámetros. La siguiente cadena de documentos probablemente no sea la más sabia;)
(También puedes ingresar
,
como quieras pero esto se siente incómodo).Para la sangría, use un editor suficientemente bueno. Hace años, esto era emacs para la edición lisp, vim también es genial hoy. Los IDE de clojure típicos también deberían proporcionar esta funcionalidad. Simplemente no use un editor de texto aleatorio.
En vim en modo comando, puede usar el
=
comando para sangrar correctamente.Si el comando se alarga demasiado (anidado, etc.), puede insertar una nueva línea después del primer argumento. Ahora el siguiente código no tiene mucho sentido, pero ilustra cómo puedes agrupar y sangrar expresiones:
Una buena sangría significa que no tiene que contar los corchetes. Los corchetes son para la computadora (para interpretar el código fuente y sangrarlo). La sangría es para su fácil comprensión.
Funciones de orden superior vs.
for
ydoseq
formasViniendo de un fondo de Scheme, estaba bastante orgulloso de haber entendido
map
y funciones lambda, etc. Muy a menudo, escribía algo como esto(map (fn [[k x]] (+ x (k data))) {:a 10 :b 20 :c 30})
Esto es bastante difícil de leer. La
for
forma es mucho mejor:`map tiene muchos usos y es realmente agradable si está utilizando funciones con nombre. Es decir
Usar macros de subprocesos
Utilice las macros de subprocesos
->
y->>
tambiéndoto
cuando corresponda.El punto es que las macros de subprocesos hacen que el código fuente parezca más lineal que la composición de funciones. El siguiente fragmento de código es bastante ilegible sin la macro de subprocesos:
Comparar con
Al usar la macro de subprocesos, normalmente se puede evitar la introducción de variables temporales que solo se usan una vez.
Otras cosas
fuente
doc
osource
en un REPL). Fin de la diatriba, por una excelente respuestaapples
lugar dexs
, pensabas que era específico de las manzanas. Entonces, también consideraría que los nombres de argumentos de funciones son más amplios que digamos una variable de bucle for. así que si es necesario, puede tenerlos por más tiempo. Como último pensamiento: te dejo con "Código de nombre, no valores" concatenative.org/wiki/view/Concatenative%20language/…