Skip to content

Instantly share code, notes, and snippets.

@cjfrisz
cjfrisz / gist:8375980
Created January 11, 2014 20:01
Example of CPSing variadic Clojure fn expression with compatibility for non-CPS calls
(fn [w x y & z] z)
(let [empty-k (with-meta identity {:kont true})]
(fn foo
;; need a compatibility overload for if someone called
;; using only required parameters.
([w x y] (foo empty-k w x y))
;; acts as its own compatibility layer, since we can't
;; have another variadic overload
([k w x y & z]
@cjfrisz
cjfrisz / gist:8149003
Created December 27, 2013 16:02
Slight augment to Clojure's update-in function
;; the following function works much like clojure.core/update-in, but
;; also works in the case that the nested data structure being traversed
;; includes a list from which you want to get the first element.
;; it's woefully incapable of handling anything more complex, as the
;; aforementioned use case was the only one I had when I wrote it.
(defn update-in+
"Similar to clojure.core/update-in, except coll may include lists and
key* may include references to clojure.core/first so that lists in coll
can be traversed."
[coll key* f & arg*]
@cjfrisz
cjfrisz / gist:8088647
Last active January 1, 2016 03:59
Macros as text-rearrangers
;; It often makes sense to think about macros as taking names as arguments.
;; This is in contrast to functions which take values as arguments.
;; Consider this macro (by a user in the #clojure IRC)
(defmacro getter [obj nm]
`((memfn ~(read-string (str "get" nm))) ~obj))
;; It takes two names, obj and nm.
;; Nothing really interesting happens to obj, so let's focus on what happens with nm:
(read-string (str "get" nm))
@cjfrisz
cjfrisz / gist:7594736
Created November 22, 2013 04:09
The symbol 1
user=> (symbol "1")
1
user=> (number? (symbol "1"))
false
user=> (symbol? (symbol "1"))
true
user=> (= (symbol "1") 1)
false
user=> (= (symbol "1") '1)
false
@cjfrisz
cjfrisz / gist:6618190
Created September 19, 2013 01:54
Tangla point-free
(defn update-game!
[system-atom]
;; NB: write-only code
(let [game-env ((comp (partial apply game-env/update-player)
(juxt identity
(comp move-player
(partial apply player/update-cur-speed)
(juxt identity
(comp accelerate player/get-cur-speed))
game-env/get-player))
@cjfrisz
cjfrisz / gist:6414524
Last active December 22, 2015 04:08
Multiple return values in clojure
(defn return-multi [a b] (mapv inc [a b]))
(defn accept-multi [x]
(let [[a b] (return-multi x x)]
(+ a b)))
(accept-multi 1)
;; -> 4
@cjfrisz
cjfrisz / recur-really-special.clj
Created November 5, 2012 21:43
Recur effectively disallowed as local function binding
;; Does this bother anybody else?
((fn [x] (let [recur (dec x)] (if (zero? x) 42 (recur recur)))) 5)
;;=> 42
;; Similarly
((fn [x] (let [recur (fn [y] 350)] (if (zero? x) 42 (recur (dec x))))) 5)
;;=> 42
;; Apparently 'recur' in function position *always* refers to the 'recur' special form
@cjfrisz
cjfrisz / extend-multi.clj
Created October 7, 2012 03:07
Quick and dirty macro to extend multiple types/records at once with the same protocol implementation syntax as defrecord
(defmacro extend-multi
"Like extend, but takes a set of types/classes which will all be extended with
the given protocol and method map pairs using the same syntax as defrecord for
protocol function implementations."
[atype* & proto+mmap*]
(loop [proto+mmap* proto+mmap*
fn-map* []
ext-body []]
(if (nil? (seq proto+mmap*))
`(let ~fn-map* ~@(map (fn [a] `(extend ~a ~@ext-body)) atype*))