Conheça Hy!
Já quis desfrutar da velocidade do Python unido da legibilidade do Lisp/Clojure?
Se você respondeu Sim, então seus problemas acabaram! Eu lhe apresento a linguagem Hy.
Hy é um dialeto Lisp que se traduz para a Abstract Syntax Tree to Python.
Maneiro, hein? Logo eu devo criar um Jupyter Notebook simples explorando o que essa linguagem tem a oferecer.
Por ora, deixo aqui uma implementação do clássico problema FizzBuzz, pra que você possa ter uma ideia de como a linguagem se parece primeiro.
Ah, mas um detalhe. Minhas duas soluções são um pouco “inusitadas”.
Na primeira eu usei um esquema de “Divisão e Conquista” (mais ou menos).
;; The only way to tackle such a complex problem: Divide and Conquer (sort of).
;; You can call fizzbuzz with debug = True if it helps you grasp the solution.
;; Author: @atgmello
(require [hy.contrib.walk [let]])
(import [math [floor]])
(defn fizz-buzz [until &optional [debug False]]
(setv result (list (range 0 until)))
(defn devide-fizz-conquer-buzz [ini end]
(if (= ini end)
(let [res (list)]
(do
(if debug
(print (.format "Leaf reached.\nValue: {}\n" ini)))
(if (zero? (% ini 3))
(.append res "Fizz"))
(if (zero? (% ini 5))
(.append res "Buzz"))
(if (zero? (len res))
(.append res (str ini)))
(setv (get result (- ini 1)) (str.join "" res))
(if debug
(print (.format "Results so far:\n{}\n" result)))))
(let [pivot (floor (/ (+ ini end) 2))]
(do
(if debug (print
(.format
"Dividing:\nIni: {} Pivot: {} End: {}\n"
ini pivot end)))
(if debug (print
(.format
"First recursion:\nIni: {}. End: {}\n"
ini pivot end)))
(devide-fizz-conquer-buzz ini pivot)
(if debug (print
(.format
"Second recursion:\nIni: {}. End: {}\n"
(+ pivot 1) end)))
(devide-fizz-conquer-buzz (+ pivot 1) end))))
(return result))
(for [n (devide-fizz-conquer-buzz 1 until)] (print n)))
(fizz-buzz 100)
Já a segunda é um código Hy com notação de tipo e paralelo. E é muito mais limpo que o primeiro. Isso mostra como é trivial paralelizar um código que embaraçosamente paralelo (embarassingly parallel) usando conceitos da programação funcional. Mas isso não quer dizer que você deva sair implementando isso pra qualquer coisa.
;; Type annotated, parallel implementation of the fizzbuzz problem.
;; Author: @atgmello
(import [concurrent.futures [ProcessPoolExecutor]])
(import [os [cpu-count]])
(defn fizzbuzz? [^int n] (zero? (+ (% n 3) (% n 5))))
(defn fizz? [^int n] (zero? (% n 3)))
(defn buzz? [^int n] (zero? (% n 5)))
(defn check-which [^int n] (cond [(fizzbuzz? n) "FizzBuzz"]
[(fizz? n) "Fizz"]
[(buzz? n) "Buzz"]
[True n]))
(defn fizzbuzz [^int n]
(setv ^ProcessPoolExecutor executor
(ProcessPoolExecutor :max-workers (cpu-count)))
(setv ^list res (.map executor check-which (range 1 (+ n 1))))
(.shutdown executor)
(for [r res] (print r)))
(fizzbuzz 100)
Você pode encontrar essas e outras implementações interessantes no repositório:
Envie a sua também! :)
PS: Os créditos para a piadinha no começo do texto vai para @hlissner. Aliás, se você usa (ou está pensando em usar) Emacs, dê uma olhada na sua distribuição de Emacs, o Doom Emacs. Tenho a usado por algum tempo e recomendo fortemente!