|
164 | 164 | (def reduce (fn [rf init col] |
165 | 165 | (-reduce col rf init))) |
166 | 166 |
|
| 167 | +(def instance? (fn ^{:doc "Checks if x is an instance of t. |
| 168 | + |
| 169 | + When t is seqable, checks if x is an instance of |
| 170 | + any of the types contained therein." |
| 171 | + :signatures [[t x]]} |
| 172 | + instance? [t x] |
| 173 | + (if (-satisfies? ISeqable t) |
| 174 | + (let [ts (seq t)] |
| 175 | + (if (not ts) false |
| 176 | + (or (-instance? (first ts) x) |
| 177 | + (instance? (rest ts) x)))) |
| 178 | + (-instance? t x)))) |
| 179 | + |
| 180 | +(def satisfies? (fn ^{:doc "Checks if x satisfies the protocol p. |
| 181 | + |
| 182 | + When p is seqable, checks if x satisfies all of |
| 183 | + the protocols contained therein." |
| 184 | + :signatures [[t x]]} |
| 185 | + satisfies? [p x] |
| 186 | + (if (-satisfies? ISeqable p) |
| 187 | + (let [ps (seq p)] |
| 188 | + (if (not ps) true |
| 189 | + (and (-satisfies? (first ps) x) |
| 190 | + (satisfies? (rest ps) x)))) |
| 191 | + (-satisfies? p x)))) |
| 192 | + |
167 | 193 | (def into (fn ^{:doc "Add the elements of `from` to the collection `to`." |
168 | 194 | :signatures [[to from]] |
169 | 195 | :added "0.1"} |
@@ -751,7 +777,6 @@ there's a value associated with the key. Use `some` for checking for values." |
751 | 777 | ~then |
752 | 778 | (cond ~@clauses)))) |
753 | 779 |
|
754 | | - |
755 | 780 | (defmacro try [& body] |
756 | 781 | (loop [catch nil |
757 | 782 | catch-sym nil |
@@ -802,7 +827,7 @@ If further arguments are passed, invokes the method named by symbol, passing the |
802 | 827 | (defn string? [v] (instance? String v)) |
803 | 828 | (defn keyword? [v] (instance? Keyword v)) |
804 | 829 |
|
805 | | -(defn list? [v] (instance? PersistentList v)) |
| 830 | +(defn list? [v] (instance? [PersistentList Cons] v)) |
806 | 831 | (defn set? [v] (instance? PersistentHashSet v)) |
807 | 832 | (defn map? [v] (satisfies? IMap v)) |
808 | 833 | (defn fn? [v] (satisfies? IFn v)) |
@@ -861,17 +886,21 @@ If further arguments are passed, invokes the method named by symbol, passing the |
861 | 886 | ([x y] (not (f x y))) |
862 | 887 | ([x y & more] (not (apply f x y more)))))) |
863 | 888 |
|
864 | | -(defn some |
865 | | - {:doc "Checks if the predicate is true for any element of the collection. |
| 889 | +(defn constantly [x] |
| 890 | + {:doc "Return a function that always returns x, no matter what it is called with." |
| 891 | + :examples [["(let [f (constantly :me)] [(f 1) (f \"foo\") (f :abc) (f nil)])" |
| 892 | + nil [:me :me :me :me]]]} |
| 893 | + (fn [& _] x)) |
866 | 894 |
|
867 | | -Stops if it finds such an element." |
| 895 | +(defn some |
| 896 | + {:doc "Returns the first true value of the predicate for the elements of the collection." |
868 | 897 | :signatures [[pred coll]] |
869 | 898 | :added "0.1"} |
870 | 899 | [pred coll] |
871 | | - (cond |
872 | | - (nil? (seq coll)) false |
873 | | - (pred (first coll)) true |
874 | | - :else (recur pred (next coll)))) |
| 900 | + (if-let [coll (seq coll)] |
| 901 | + (or (pred (first coll)) |
| 902 | + (recur pred (next coll))) |
| 903 | + false)) |
875 | 904 |
|
876 | 905 | (extend -count MapEntry (fn [self] 2)) |
877 | 906 | (extend -nth MapEntry (fn map-entry-nth [self idx] |
@@ -1053,7 +1082,7 @@ Creates new maps if the keys are not present." |
1053 | 1082 | ([test msg] |
1054 | 1083 | `(if ~test |
1055 | 1084 | nil |
1056 | | - (throw (str "Assert failed " ~msg))))) |
| 1085 | + (throw (str "Assert failed: " ~msg))))) |
1057 | 1086 |
|
1058 | 1087 | (defmacro resolve |
1059 | 1088 | {:doc "Resolve the var associated with the symbol in the current namespace." |
@@ -1243,6 +1272,17 @@ and implements IAssociative, ILookup and IObject." |
1243 | 1272 | ([n x] |
1244 | 1273 | (take n (repeat x)))) |
1245 | 1274 |
|
| 1275 | +(defn repeatedly |
| 1276 | + {:doc "Returns a lazy seq that contains the return values of repeated calls to f. |
| 1277 | + |
| 1278 | + Yields an infinite seq with one argument. |
| 1279 | + With two arguments n specifies the number of elements." |
| 1280 | + :examples [["(into '(:batman!) (repeatedly 8 (fn [] :na)))" |
| 1281 | + nil (:na :na :na :na :na :na :na :na :batman!)]] |
| 1282 | + :signatures [[f] [n f]]} |
| 1283 | + ([f] (lazy-seq (cons (f) (repeatedly f)))) |
| 1284 | + ([n f] (take n (repeatedly f)))) |
| 1285 | + |
1246 | 1286 | (defmacro doseq |
1247 | 1287 | {:doc "Evaluates all elements of the seq, presumably for side effects. Returns nil." |
1248 | 1288 | :added "0.1"} |
@@ -1476,6 +1516,13 @@ The new value is thus `(apply f current-value-of-atom args)`." |
1476 | 1516 | (recur (dec n) (next s)) |
1477 | 1517 | s))) |
1478 | 1518 |
|
| 1519 | +(defn split-at |
| 1520 | + {:doc "Returns a vector of the first n elements of the collection, and the remaining elements." |
| 1521 | + :examples [["(split-at 2 [:a :b :c :d :e])" nil |
| 1522 | + [(:a :b) (:c :d :e)]]]} |
| 1523 | + [n coll] |
| 1524 | + [(take n coll) (drop n coll)]) |
| 1525 | + |
1479 | 1526 | (defmacro while |
1480 | 1527 | {:doc "Repeatedly executes body while test expression is true. Presumes |
1481 | 1528 | some side-effect will cause test to become false/nil. Returns nil" |
@@ -1568,8 +1615,21 @@ not enough elements were present." |
1568 | 1615 | :added "0.1"} |
1569 | 1616 | ([n coll] (partition n n coll)) |
1570 | 1617 | ([n step coll] |
1571 | | - (when-let [s (seq coll)] |
1572 | | - (cons (take n s) (partition n step (drop step s)))))) |
| 1618 | + (when-let [s (seq coll)] |
| 1619 | + (lazy-seq |
| 1620 | + (cons (take n s) (partition n step (drop step s))))))) |
| 1621 | + |
| 1622 | +(defn partitionf [f coll] |
| 1623 | + {:doc "A generalized version of partition. Instead of taking a constant number of elements, |
| 1624 | + this function calls f with the remaining collection to determine how many elements to |
| 1625 | + take." |
| 1626 | + :examples [["(partitionf first [1 :a, 2 :a b, 3 :a :b :c])" |
| 1627 | + nil ((1 :a) (2 :a :b) (3 :a :b :c))]]} |
| 1628 | + (when-let [s (seq coll)] |
| 1629 | + (lazy-seq |
| 1630 | + (let [n (f s)] |
| 1631 | + (cons (take n s) |
| 1632 | + (partitionf f (drop n coll))))))) |
1573 | 1633 |
|
1574 | 1634 | (defn destructure [binding expr] |
1575 | 1635 | (cond |
@@ -1942,6 +2002,9 @@ user => (refer 'pixie.string :exclude '(substring))" |
1942 | 2002 | (pred (first coll)) (recur pred (next coll)) |
1943 | 2003 | :else false)) |
1944 | 2004 |
|
| 2005 | +; If you want a fn that uses destructuring in its parameter list, place |
| 2006 | +; it after this definition. If you don't, you will get compile failures |
| 2007 | +; in unrelated files. |
1945 | 2008 | (defmacro fn |
1946 | 2009 | {:doc "Creates a function. |
1947 | 2010 |
|
@@ -2115,6 +2178,45 @@ Expands to calls to `extend-type`." |
2115 | 2178 | [~@body])))] |
2116 | 2179 | `(or (seq ~(gen-loop [] bindings)) '()))) |
2117 | 2180 |
|
| 2181 | +(defn reverse |
| 2182 | + ; TODO: We should probably have a protocol IReversible, so we can e.g. |
| 2183 | + ; reverse vectors efficiently, etc.. |
| 2184 | + [coll] |
| 2185 | + "Returns a collection that contains all the elements of the argument in reverse order." |
| 2186 | + (into () coll)) |
| 2187 | + |
| 2188 | +;; TODO: implement :>> like in Clojure? |
| 2189 | +(defmacro condp |
| 2190 | + "Takes a binary predicate, an expression and a number of two-form clauses. |
| 2191 | + Calls the predicate on the first value of each clause and the expression. |
| 2192 | + If the result is truthy returns the second value of the clause. |
| 2193 | + |
| 2194 | + If the number of arguments is odd and no clause matches, the last argument is returned. |
| 2195 | + If the number of arguments is even and no clause matches, throws an exception." |
| 2196 | + [pred-form expr & clauses] |
| 2197 | + (let [x (gensym 'expr), pred (gensym 'pred)] |
| 2198 | + `(let [~x ~expr, ~pred ~pred-form] |
| 2199 | + (cond ~@(mapcat |
| 2200 | + (fn [[a b :as clause]] |
| 2201 | + (if (> (count clause) 1) |
| 2202 | + `((~pred ~a ~x) ~b) |
| 2203 | + `(:else ~a))) |
| 2204 | + (partition 2 clauses)) |
| 2205 | + :else (throw "No matching clause!"))))) |
| 2206 | + |
| 2207 | +(defmacro case |
| 2208 | + "Takes an expression and a number of two-form clauses. |
| 2209 | + Checks for each clause if the first part is equal to the expression. |
| 2210 | + If yes, returns the value of the second part. |
| 2211 | + |
| 2212 | + The first part of each clause can also be a set. If that is the case, the clause matches when the result of the expression is in the set. |
| 2213 | + |
| 2214 | + If the number of arguments is odd and no clause matches, the last argument is returned. |
| 2215 | + If the number of arguments is even and no clause matches, throws an exception." |
| 2216 | + [expr & args] |
| 2217 | + `(condp #(if (set? %1) (%1 %2) (= %1 %2)) |
| 2218 | + ~expr ~@args)) |
| 2219 | + |
2118 | 2220 | (defmacro use |
2119 | 2221 | [ns] |
2120 | 2222 | `(do |
@@ -2176,14 +2278,47 @@ Expands to calls to `extend-type`." |
2176 | 2278 | (mapcat walk (children node))))))] |
2177 | 2279 | (walk root))) |
2178 | 2280 |
|
| 2281 | +(defn flatten [x] |
| 2282 | + ; TODO: laziness? |
| 2283 | + {:doc "Takes any nested combination of ISeqable things, and return their contents |
| 2284 | + as a single, flat sequence. |
| 2285 | + |
| 2286 | + Calling this function on something that is not ISeqable returns a seq with that |
| 2287 | + value as its only element." |
| 2288 | + :examples [["(flatten [[1 2 [3 4] [5 6]] 7])" nil [1 2 3 4 5 6 7]] |
| 2289 | + ["(flatten :this)" nil [:this]]]} |
| 2290 | + (if (not (satisfies? ISeqable x)) [x] |
| 2291 | + (transduce (comp (map flatten) cat) |
| 2292 | + conj [] |
| 2293 | + (seq x)))) |
| 2294 | + |
| 2295 | +(defn juxt [& fns] |
| 2296 | + {:doc "Returns a function that applies all fns to its arguments, |
| 2297 | + and returns a vector of the results." |
| 2298 | + :examples [["((juxt + - *) 2 3)" nil [5 -1 6]]]} |
| 2299 | + (fn [& args] |
| 2300 | + (mapv #(apply % args) fns))) |
| 2301 | + |
| 2302 | +(defn map-invert |
| 2303 | + {:doc "Returns a map where the vals are mapped to the keys." |
| 2304 | + :examples [["(map-invert {:a :b, :c :d})" nil {:b :a, :d :c}]]} |
| 2305 | + [m] |
| 2306 | + (reduce (fn [m* ent] |
| 2307 | + (assoc m* (val ent) (key ent))) |
| 2308 | + {} m)) |
| 2309 | + |
2179 | 2310 | (defn mapv |
2180 | 2311 | ([f col] |
2181 | 2312 | (transduce (map f) conj col))) |
2182 | 2313 |
|
| 2314 | +(def *1) |
| 2315 | +(def *2) |
| 2316 | +(def *3) |
2183 | 2317 | (defn -push-history [x] |
2184 | 2318 | (def *3 *2) |
2185 | 2319 | (def *2 *1) |
2186 | 2320 | (def *1 x)) |
2187 | 2321 |
|
| 2322 | +(def *e) |
2188 | 2323 | (defn -set-*e [e] |
2189 | 2324 | (def *e e)) |
0 commit comments