Created
August 25, 2018 02:32
-
-
Save joinr/c6ec925c2f13ce8d4c6c2eaba6f36df9 to your computer and use it in GitHub Desktop.
for/fold from racket interpreted to clojure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns forfold) | |
;;From racket example | |
;;https://docs.racket-lang.org/reference/for.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for%2Ffold%29%29 | |
;; (for/fold ([acc '()] | |
;; [seen (hash)] | |
;; #:result (reverse acc)) | |
;; ([x (in-list '(0 1 1 2 3 4 4 4))]) | |
;; (cond | |
;; [(hash-ref seen x #f) | |
;; (values acc seen)] | |
;; [else (values (cons x acc) | |
;; (hash-set seen x #t))])) | |
;; '(0 1 2 3 4) | |
;;we can opt in using macros... | |
(defmacro for-fold [bindings for-clause & body] | |
(let [binds (partition 2 bindings) | |
[pairs [[_ result]]] | |
(partition-by (fn [[l _]] | |
(= l :result)) binds) | |
result-expr (second result) | |
vars (mapv first pairs) | |
inits (mapv second pairs) | |
iter (first for-clause) | |
res (gensym "res")] | |
`(let [[~@vars :as ~res] | |
(reduce (fn [[~@vars] ~iter] | |
~@body) | |
~inits (for ~for-clause | |
~iter))] | |
~(or result | |
res)))) | |
;; (for-fold [acc '() | |
;; seen #{} | |
;; :result (reverse acc)] | |
;; [x '(0 1 1 2 3 4 4 4)] | |
;; (cond (seen x) [acc seen] | |
;; :else [(cons x acc) (conj seen x)])) | |
;; (0 1 2 3 4) | |
;;or use reduce... | |
(->> '(0 1 1 2 3 4 4 4) | |
(reduce (fn [[acc seen :as res] x] | |
(if (seen x) res | |
[(cons x acc) (conj seen x)])) | |
['() #{}]) | |
first | |
reverse) | |
;;or use a vector...no need to reverse. | |
(->> '(0 1 1 2 3 4 4 4) | |
(reduce (fn [[acc seen :as res] x] | |
(if (seen x) res | |
[(conj acc x) (conj seen x)])) | |
[[] #{}]) | |
first) | |
;;or use state + filter | |
(let [seen (atom #{})] | |
(->> '(0 1 1 2 3 4 4 4) | |
(filter (fn [x] (when-not (@seen x) | |
(do (swap! seen conj x) | |
x)))))) | |
;;or define our own stateful filter | |
(defn filter-once | |
([pred] | |
(let [f (atom #{})] | |
(fn [x] (when-not (@f x) | |
(do (swap! f conj x) | |
(pred x)))))) | |
([] (filter-once identity))) | |
;;and use transducers via into | |
(into [] (filter (filter-once)) '(0 1 1 2 3 4 4 4)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment