Range Parser Clojure 😱

👨‍💻 Aprendizaje
📅 2021-04-27

Bueno lo primero que he de decir es que es un lenguaje el cuál te explota la cabeza lo más grande, es el festival del paréntesis y todo se declara en el aire. Enlace al kata

Esté video y mucha documentación tanto de StackOverflow como de la página oficial. Mi experiencia es qué te saca de tu zonita de confort de un golpe, nada que ver con lenguajes anteriores, se parece a programación funcional de javascript. A medida qué fui buscando por google fui encontrando trocitos de código e ideas para añadirlas.

Empezamos a explicar el Kata

Lo primero es que si vamos a definir más funciones es mejor declararlas encima de dónde se vaya a usar.

Lo primero que hago es separar quitando los espacios en blanco y aplicamos “mapcat” que devuelve el resultado de aplicar concat al resultado de aplicar el mapa.

(defn range-parser [s]
  (->> (clojure.string/split s #"\s*,\s*")
       (mapcat parse-range)))

Con esto definido llamamos a lo que sería el equivalente directo sería un switch case. El “:else” es el default si solo tiene un valor lo pasamos a entero y lo devolvemos dentro de un vector.

(defn parse-range
  [v]
  (cond
    (clojure.string/includes? v ":") (parse-step-range v)
    (clojure.string/includes? v "-") (parse-single-range v)
    :else [(Integer. v)]))

En el caso de que sea un rango, bueno empiezo a explicar un poquito de la función en clojure, el string es el comentario de la función y “[v]” es el valor ya parseado dela primera función. El uso de “let” nos permite declara variables dentro del rango de su paréntesis. Uso range porque devuelve una secuencia diferida de números desde el inicio incluido hasta el final excluido. Estos valores aún son strings así que los convierto.

(defn parse-single-range
  "Token x-y"
  [v]
  (let [[start end] (clojure.string/split v #"-")]
    (range (Integer. start) (inc (Integer. end)))))

Finalmente nos vamos con la última opción la que tiene “x-y: n”. Aquí en ves de separar por el guion como el anterior, lo separo por el numero, quedarían 3 números, “[x y n]” así que los asignamos a “start” “end” y “step”. La parte step nos permite ir saltando el iterador por ese valor.

(defn parse-step-range
  "Token x-y:s"
  [v]
  (let [[start end step] (clojure.string/split v #"[^0-9]")]
    (range (Integer. start) (inc (Integer. end)) (Integer. step))))

Y vemos el resultado:

result-of-tests

Conclusión

Honestamente me puse a ver el video y tampoco fue suficiente, hace falta algo así para lograr el ejercicio o más como es mi caso:

historial

A mi déjenme con mi javascript mi C# que yo eso de los paréntesis para todos lados no me va, me he pegado el 50% del ejercicio así…

console-errors

Pero me parece un lenguaje curioso y se pueden usar las librerías de java, lo cual lo hace más fácil. Si os gusta probar algo nuevo sin pegaros un tiro en el proceso está chulo. Es poco intuitivo pero al cabo del tiempo te das cuenta que es perfecto para modificar datos sin esfuerzo.