operator - ¿Por qué no funciona(aplicar o[verdadero falso]) en Clojure?
reduce in clojure (5)
Por lo que entiendo sobre apply, descomprime una lista y convierte los elementos en argumentos para una función.
Veo que (aplicar + [1 2 3]) funciona como se esperaba, es decir, es equivalente a (+ 1 2 3).
¿Por qué entonces es (apply o [true false]) inválido? ¿No es equivalente a (o verdadero falso)?
Como alternativa o puede usar ( algún predicado coll).
clojure.core / some ([pred coll])
Devuelve el primer valor verdadero lógico de (pred x) para cualquier x en coll, sino nil. Una expresión común es usar un conjunto como pred, por ejemplo, esto devolverá: fred if: fred está en la secuencia, de lo contrario nil: (some # {: fred} coll)
Puedes probar algunos con verdad? y falso? predicados,
user=> (some true? [true false false])
true
user=> (not (some true? [true false false]))
false
user=> (some false? [true false false])
true
user=> (not (some false? [true false false]))
false
Porque or
es una macro, no es una función normal. Puede obtener el mismo efecto con (some identity [true false])
.
o es una macro, que no puedes usar como valor.
Crea una función anónima, expandiendo o en tiempo de ejecución a través de eval:
(apply #(eval (list* ''or %&)) [true false])
Una de las cosas importantes a tener en cuenta es el modelo de evaluación. or
cortocircuitos, por lo tanto: (or true :some random expression that never gets evaluated:)
nunca evalúa la última. or
se usa tradicionalmente tanto como una estructura de control como ''lógica o''.
En el modelo tradicional de (fxyz)
, se evalúan x, y y z, y se les aplica f.
En el uso de (apply f vec)
los contenidos del vector no se evalúan, se toman como están. Esto es más claramente visible con un vector de símbolos, no evalúan en este contexto sus enlaces. Sin embargo, esto está oscurecido por el hecho de que el modelo de Clojure para la creación de vectores es algo diferente de otros cefaleas, [abcd]
produce un vector que contiene las evaluaciones de los símbolos a
, b
, c
y d
. Contrastando la mayoría de Lisps, donde #(abcd)
no evalúa los símbolos, y es idéntica a la evaluación (vector ''a ''b ''c ''d)
(o de hecho (apply vector ''(abcd))
).
Entonces, incluso si fuera posible aplicar formas sintácticas especiales, su resultado tendría una semántica opaca. or
primero evalúa su primer argumento, si es verdadero, se detiene y lo devuelve; de lo contrario, pasa al segundo y se repite hasta el último. En el caso de aplicar, los argumentos ya están todos evaluados, ¿debería evaluarlos por segunda vez? Lo más probable es que resulte en un error de tiempo de ejecución en el camino?
Desde la perspectiva de la implementación, sería muy restrictivo en el rendimiento si la sintaxis fuera también "objetos" y requeriría un modelo de evaluación mucho más complejo. Por lo tanto, no se resuelven en tiempo de ejecución, sino que se vuelven a escribir en primitivas de compilación en tiempo de compilación.
Pero, por esta misma razón, cuando or
se usa lógicamente en lugar de como una estructura de control, me resulta útil tener funciones or/f
, and/f
, if/f
, etc. disponibles, que son procedimientos verdaderos y evaluar todos sus argumentos y por lo tanto se pueden aplicar.