f# clojure pipeline

f# - -> Operador en Clojure



pipeline (4)

¿Es el operador -> en Clojure (y cómo se llama este operador en Clojure-speak?) Equivalente al operador de tubería |> en F #? Si es así, ¿por qué necesita una definición de macro tan compleja, cuando (|>) se define como

let inline (|>) x f = f x

O si no, ¿existe el operador de tubería de F # en Clojure, o cómo definiría tal operador en Clojure?


Al leer el código fuente (especialmente cuando se habla), siempre pronuncio el operador -> como "thread-first", y el operador ->> como "thread-last".

Tenga en cuenta que ahora hay un operador as-> que es más flexible que cualquiera -> o ->>. El formulario es:

(as-> val name (form1 arg1 name arg2)...)

El valor val se evalúa y asigna al name símbolo de marcador de posición, que el usuario puede colocar en CUALQUIER posición en las siguientes formas. Generalmente elijo la palabra "it" para el símbolo de marcador de posición. Podemos imitar el hilo primero -> así:

user=> (-> :a (vector 1)) [:a 1] user=> (as-> :a it (vector it 1) ) [:a 1]

Podemos imitar thread-last ->> así:

user=> (->> :a (vector 2)) [2 :a] user=> (as-> :a it (vector 2 it) ) [2 :a]

O bien, podemos combinarlos en una sola expresión:

user=> (as-> :a it (vector it 1) (vector 2 it)) [2 [:a 1]] user=> (as-> :a it (vector it 1) (vector 2 it) (vector "first" it "last")) ["first" [2 [:a 1]] "last"]


No, no son lo mismo. Clojure realmente no necesita |> porque todas las llamadas a funciones están incluidas en listas, como (+ 1 2) : no hay magia que puedas hacer para que 1 + 2 funcione de forma aislada . 1

-> es para reducir la anidación y simplificar patrones comunes. Por ejemplo:

(-> x (assoc :name "ted") (dissoc :size) (keys))

Se expande a

(keys (dissoc (assoc x :name "ted") :size))

El primero suele ser más fácil de leer, porque conceptualmente estás realizando una serie de operaciones en x ; el código anterior está "configurado" de esa manera, mientras que el último necesita un poco de desentrañamiento mental para funcionar.

1 Puedes escribir una macro que sorta haga que esto funcione. La idea es envolver su macro alrededor del árbol de origen completo que desea transformar y dejar que busque |> símbolos; A continuación, puede transformar la fuente en la forma que desee. Hiredman ha hecho posible escribir código de una manera muy parecida a Haskell, con su paquete functional .


Se llama el operador "hilo". Se escribe como una macro en lugar de una función normal por razones de rendimiento y para que pueda proporcionar una buena sintaxis, es decir, aplica la transformación en el momento de la compilación.

Es algo más poderoso que el operador |> que usted describe, ya que pretende pasar un valor a través de varias funciones, donde cada valor sucesivo se "inserta" como primer parámetro de las siguientes funciones. Aquí hay un ejemplo un tanto artificial:

(-> [1] (concat [2 3 4]) (sum) ((fn [x] (+ x 100.0)))) => 110.0

Si desea definir una función exactamente como el operador F # que ha descrito, puede hacer:

(defn |> [x f] (f x)) (|> 3 inc) => 4

No estoy seguro de lo útil que es realmente, pero de todas formas estás :-)

Finalmente, si desea pasar un valor a través de una secuencia de funciones, siempre puede hacer algo como lo siguiente en clojure:

(defn pipeline [x & fns] ((apply comp fns) x)) (pipeline 1 inc inc inc inc) => 5


También vale la pena señalar que hay una macro - >> que enlaza el formulario como el último argumento:

(->> a (+ 5) (let [a 5] ))

The Joy of Clojure, capítulo 8.1 habla un poco sobre este tema.