2013-07-29 18:40:48 +02:00
|
|
|
;; Copyright (c) 2013 Paul Tagliamonte <paultag@debian.org>
|
|
|
|
;; Copyright (c) 2013 Bob Tolbert <bob@tolbert.org>
|
|
|
|
|
|
|
|
;; Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
;; copy of this software and associated documentation files (the "Software"),
|
|
|
|
;; to deal in the Software without restriction, including without limitation
|
|
|
|
;; the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
;; and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
;; Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
;; The above copyright notice and this permission notice shall be included in
|
|
|
|
;; all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
;; DEALINGS IN THE SOFTWARE.
|
|
|
|
|
2013-06-29 17:50:31 +02:00
|
|
|
;;;; This contains some of the core Hy functions used
|
|
|
|
;;;; to make functional programming slightly easier.
|
|
|
|
;;;;
|
|
|
|
|
2014-04-29 16:01:14 +02:00
|
|
|
(import itertools)
|
|
|
|
(import functools)
|
|
|
|
(import collections)
|
2015-06-26 23:10:22 +02:00
|
|
|
(import [fractions [Fraction :as fraction]])
|
2015-09-03 19:45:55 +02:00
|
|
|
(import operator) ; shadow not available yet
|
2014-09-04 11:29:38 +02:00
|
|
|
(import sys)
|
2015-07-28 16:51:35 +02:00
|
|
|
(if-python2
|
|
|
|
(import [StringIO [StringIO]])
|
|
|
|
(import [io [StringIO]]))
|
2013-10-11 08:35:32 +02:00
|
|
|
(import [hy._compat [long-type]]) ; long for python2, int for python3
|
2014-03-01 00:23:49 +01:00
|
|
|
(import [hy.models.cons [HyCons]]
|
2015-01-29 16:17:52 +01:00
|
|
|
[hy.models.symbol [HySymbol]]
|
2014-03-01 00:23:49 +01:00
|
|
|
[hy.models.keyword [HyKeyword *keyword-prefix*]])
|
2014-07-24 20:44:55 +02:00
|
|
|
(import [hy.lex [LexException PrematureEndOfInput tokenize]])
|
2015-12-23 21:13:18 +01:00
|
|
|
(import [hy.compiler [HyASTCompiler]])
|
2013-05-16 18:59:20 +02:00
|
|
|
|
2014-02-24 23:08:40 +01:00
|
|
|
(defn butlast [coll]
|
|
|
|
"Returns coll except of last element."
|
2014-08-22 11:51:12 +02:00
|
|
|
(drop-last 1 coll))
|
2014-02-24 23:08:40 +01:00
|
|
|
|
2014-01-12 11:19:09 +01:00
|
|
|
(defn coll? [coll]
|
|
|
|
"Checks whether item is a collection"
|
|
|
|
(and (iterable? coll) (not (string? coll))))
|
|
|
|
|
2016-12-25 21:11:25 +01:00
|
|
|
(defn comp [&rest fs]
|
|
|
|
"Function composition"
|
|
|
|
(if (not fs) identity
|
|
|
|
(= 1 (len fs)) (first fs)
|
|
|
|
(do (setv rfs (reversed fs)
|
|
|
|
first-f (next rfs)
|
|
|
|
fs (tuple rfs))
|
|
|
|
(fn [&rest args &kwargs kwargs]
|
|
|
|
(setv res (apply first-f args kwargs))
|
|
|
|
(for* [f fs]
|
|
|
|
(setv res (f res)))
|
|
|
|
res))))
|
|
|
|
|
|
|
|
(defn complement [f]
|
|
|
|
"Create a function that reverses truth value of another function"
|
|
|
|
(fn [&rest args &kwargs kwargs]
|
|
|
|
(not (apply f args kwargs))))
|
|
|
|
|
2013-05-16 18:59:20 +02:00
|
|
|
(defn cons [a b]
|
|
|
|
"Return a fresh cons cell with car = a and cdr = b"
|
|
|
|
(HyCons a b))
|
|
|
|
|
|
|
|
(defn cons? [c]
|
|
|
|
"Check whether c can be used as a cons object"
|
|
|
|
(instance? HyCons c))
|
|
|
|
|
2016-12-25 21:11:25 +01:00
|
|
|
(defn constantly [value]
|
|
|
|
"Create a function that always returns the same value"
|
|
|
|
(fn [&rest args &kwargs kwargs]
|
|
|
|
value))
|
|
|
|
|
2014-04-02 05:23:53 +02:00
|
|
|
(defn keyword? [k]
|
|
|
|
"Check whether k is a keyword"
|
|
|
|
(and (instance? (type :foo) k)
|
|
|
|
(.startswith k (get :foo 0))))
|
|
|
|
|
2013-07-08 04:36:26 +02:00
|
|
|
(defn dec [n]
|
|
|
|
"Decrement n by 1"
|
|
|
|
(- n 1))
|
|
|
|
|
2016-11-24 03:35:17 +01:00
|
|
|
(defn disassemble [tree &optional [codegen False]]
|
2014-02-24 23:08:40 +01:00
|
|
|
"Return the python AST for a quoted Hy tree as a string.
|
2014-01-04 01:47:49 +01:00
|
|
|
If the second argument is true, generate python code instead."
|
|
|
|
(import astor)
|
|
|
|
(import hy.compiler)
|
|
|
|
|
|
|
|
(fake-source-positions tree)
|
|
|
|
(setv compiled (hy.compiler.hy_compile tree (calling-module-name)))
|
2014-02-24 23:08:40 +01:00
|
|
|
((if codegen
|
2014-01-04 01:47:49 +01:00
|
|
|
astor.codegen.to_source
|
|
|
|
astor.dump)
|
2014-02-24 23:08:40 +01:00
|
|
|
compiled))
|
|
|
|
|
2013-07-08 04:36:26 +02:00
|
|
|
(defn distinct [coll]
|
|
|
|
"Return a generator from the original collection with duplicates
|
|
|
|
removed"
|
2017-02-04 02:03:06 +01:00
|
|
|
(setv seen (set) citer (iter coll))
|
2015-08-17 09:07:32 +02:00
|
|
|
(for* [val citer]
|
|
|
|
(if (not_in val seen)
|
|
|
|
(do
|
|
|
|
(yield val)
|
2017-02-04 02:03:06 +01:00
|
|
|
(.add seen val)))))
|
2013-07-08 04:36:26 +02:00
|
|
|
|
2014-04-29 16:01:14 +02:00
|
|
|
(if-python2
|
2015-09-03 19:45:55 +02:00
|
|
|
(def
|
2015-09-03 19:56:17 +02:00
|
|
|
remove itertools.ifilterfalse
|
2015-09-03 19:45:55 +02:00
|
|
|
zip-longest itertools.izip_longest
|
|
|
|
;; not builtin in Python3
|
|
|
|
reduce reduce
|
|
|
|
;; hy is more like Python3
|
|
|
|
filter itertools.ifilter
|
|
|
|
input raw_input
|
|
|
|
map itertools.imap
|
|
|
|
range xrange
|
|
|
|
zip itertools.izip)
|
|
|
|
(def
|
2015-09-03 19:56:17 +02:00
|
|
|
remove itertools.filterfalse
|
2015-09-03 19:45:55 +02:00
|
|
|
zip-longest itertools.zip_longest
|
|
|
|
;; was builtin in Python2
|
|
|
|
reduce functools.reduce
|
|
|
|
;; Someone can import these directly from `hy.core.language`;
|
|
|
|
;; we'll make some duplicates.
|
|
|
|
filter filter
|
|
|
|
input input
|
|
|
|
map map
|
|
|
|
range range
|
|
|
|
zip zip))
|
|
|
|
|
|
|
|
;; infinite iterators
|
|
|
|
(def
|
|
|
|
count itertools.count
|
|
|
|
cycle itertools.cycle
|
|
|
|
repeat itertools.repeat)
|
|
|
|
|
|
|
|
;; shortest-terminating iterators
|
|
|
|
(def
|
|
|
|
*map itertools.starmap
|
|
|
|
chain itertools.chain
|
|
|
|
compress itertools.compress
|
|
|
|
drop-while itertools.dropwhile
|
|
|
|
group-by itertools.groupby
|
|
|
|
islice itertools.islice
|
|
|
|
take-while itertools.takewhile
|
|
|
|
tee itertools.tee)
|
|
|
|
|
|
|
|
;; combinatoric iterators
|
|
|
|
(def
|
|
|
|
combinations itertools.combinations
|
|
|
|
multicombinations itertools.combinations_with_replacement
|
|
|
|
permutations itertools.permutations
|
|
|
|
product itertools.product)
|
|
|
|
|
|
|
|
;; also from itertools, but not in Python2, and without func option until 3.3
|
|
|
|
(defn accumulate [iterable &optional [func operator.add]]
|
|
|
|
"accumulate(iterable[, func]) --> accumulate object
|
|
|
|
|
|
|
|
Return series of accumulated sums (or other binary function results)."
|
|
|
|
(setv it (iter iterable)
|
|
|
|
total (next it))
|
|
|
|
(yield total)
|
|
|
|
(for* [element it]
|
|
|
|
(setv total (func total element))
|
|
|
|
(yield total)))
|
2014-04-29 16:01:14 +02:00
|
|
|
|
2013-07-08 04:36:26 +02:00
|
|
|
(defn drop [count coll]
|
|
|
|
"Drop `count` elements from `coll` and yield back the rest"
|
2016-11-24 03:35:17 +01:00
|
|
|
(islice coll count None))
|
2013-07-29 18:40:48 +02:00
|
|
|
|
2014-08-22 11:09:59 +02:00
|
|
|
(defn drop-last [n coll]
|
|
|
|
"Return a sequence of all but the last n elements in coll."
|
2017-02-04 02:03:06 +01:00
|
|
|
(setv iters (tee coll))
|
|
|
|
(map first (apply zip [(get iters 0)
|
|
|
|
(drop n (get iters 1))])))
|
2014-08-22 11:09:59 +02:00
|
|
|
|
2013-07-29 18:40:48 +02:00
|
|
|
(defn empty? [coll]
|
|
|
|
"Return True if `coll` is empty"
|
|
|
|
(= 0 (len coll)))
|
|
|
|
|
2013-07-08 04:36:26 +02:00
|
|
|
(defn even? [n]
|
|
|
|
"Return true if n is an even number"
|
|
|
|
(= (% n 2) 0))
|
|
|
|
|
2014-02-11 09:42:56 +01:00
|
|
|
(defn every? [pred coll]
|
|
|
|
"Return true if (pred x) is logical true for every x in coll, else false"
|
|
|
|
(all (map pred coll)))
|
|
|
|
|
2014-01-04 01:47:49 +01:00
|
|
|
(defn fake-source-positions [tree]
|
|
|
|
"Fake the source positions for a given tree"
|
2014-02-03 17:18:30 +01:00
|
|
|
(if (coll? tree)
|
2014-01-04 01:47:49 +01:00
|
|
|
(for* [subtree tree]
|
|
|
|
(fake-source-positions subtree)))
|
|
|
|
(for* [attr '[start-line end-line start-column end-column]]
|
|
|
|
(if (not (hasattr tree attr))
|
|
|
|
(setattr tree attr 1))))
|
|
|
|
|
2013-12-16 02:47:46 +01:00
|
|
|
(defn flatten [coll]
|
|
|
|
"Return a single flat list expanding all members of coll"
|
2014-01-12 11:19:09 +01:00
|
|
|
(if (coll? coll)
|
2013-12-16 02:47:46 +01:00
|
|
|
(_flatten coll [])
|
|
|
|
(raise (TypeError (.format "{0!r} is not a collection" coll)))))
|
|
|
|
|
|
|
|
(defn _flatten [coll result]
|
2014-02-03 17:18:30 +01:00
|
|
|
(if (coll? coll)
|
2013-11-10 19:00:01 +01:00
|
|
|
(do (for* [b coll]
|
2013-12-16 02:47:46 +01:00
|
|
|
(_flatten b result)))
|
|
|
|
(.append result coll))
|
|
|
|
result)
|
|
|
|
|
2013-07-29 18:40:48 +02:00
|
|
|
(defn float? [x]
|
|
|
|
"Return True if x is float"
|
|
|
|
(isinstance x float))
|
|
|
|
|
2015-01-29 16:17:52 +01:00
|
|
|
(defn symbol? [s]
|
|
|
|
"Check whether s is a symbol"
|
|
|
|
(instance? HySymbol s))
|
|
|
|
|
2013-12-15 01:33:56 +01:00
|
|
|
(import [threading [Lock]])
|
|
|
|
(setv _gensym_counter 1234)
|
|
|
|
(setv _gensym_lock (Lock))
|
|
|
|
|
|
|
|
(defn gensym [&optional [g "G"]]
|
2017-02-04 02:03:06 +01:00
|
|
|
(setv new_symbol None)
|
|
|
|
(global _gensym_counter)
|
|
|
|
(global _gensym_lock)
|
|
|
|
(.acquire _gensym_lock)
|
|
|
|
(try (do (setv _gensym_counter (inc _gensym_counter))
|
|
|
|
(setv new_symbol (HySymbol (.format ":{0}_{1}" g _gensym_counter))))
|
|
|
|
(finally (.release _gensym_lock)))
|
|
|
|
new_symbol)
|
2013-12-15 01:33:56 +01:00
|
|
|
|
2014-01-03 21:41:14 +01:00
|
|
|
(defn calling-module-name [&optional [n 1]]
|
|
|
|
"Get the name of the module calling `n` levels up the stack from the
|
|
|
|
`calling-module-name` function call (by default, one level up)"
|
|
|
|
(import inspect)
|
|
|
|
|
|
|
|
(setv f (get (.stack inspect) (+ n 1) 0))
|
|
|
|
(get f.f_globals "__name__"))
|
|
|
|
|
2014-01-10 19:35:21 +01:00
|
|
|
(defn first [coll]
|
|
|
|
"Return first item from `coll`"
|
2016-11-24 03:35:17 +01:00
|
|
|
(next (iter coll) None))
|
2014-01-10 19:35:21 +01:00
|
|
|
|
2014-01-21 20:19:49 +01:00
|
|
|
(defn identity [x]
|
|
|
|
"Returns the argument unchanged"
|
|
|
|
x)
|
|
|
|
|
2013-07-08 04:36:26 +02:00
|
|
|
(defn inc [n]
|
|
|
|
"Increment n by 1"
|
|
|
|
(+ n 1))
|
|
|
|
|
|
|
|
(defn instance? [klass x]
|
|
|
|
(isinstance x klass))
|
|
|
|
|
2013-10-11 08:35:32 +02:00
|
|
|
(defn integer [x]
|
|
|
|
"Return Hy kind of integer"
|
|
|
|
(long-type x))
|
|
|
|
|
2013-07-29 18:40:48 +02:00
|
|
|
(defn integer? [x]
|
2016-12-27 08:41:16 +01:00
|
|
|
"Return True if x is an integer"
|
2013-10-11 08:35:32 +02:00
|
|
|
(isinstance x (, int long-type)))
|
2013-07-29 18:40:48 +02:00
|
|
|
|
2014-01-28 23:28:41 +01:00
|
|
|
(defn integer-char? [x]
|
|
|
|
"Return True if char `x` parses as an integer"
|
|
|
|
(try
|
2014-04-29 16:01:14 +02:00
|
|
|
(integer? (int x))
|
2016-11-24 03:35:17 +01:00
|
|
|
(except [ValueError] False)
|
|
|
|
(except [TypeError] False)))
|
2014-01-28 23:28:41 +01:00
|
|
|
|
2014-08-17 04:53:57 +02:00
|
|
|
(defn interleave [&rest seqs]
|
|
|
|
"Return an iterable of the first item in each of seqs, then the second etc."
|
2015-09-03 19:45:55 +02:00
|
|
|
(chain.from-iterable (apply zip seqs)))
|
2014-08-17 04:53:57 +02:00
|
|
|
|
|
|
|
(defn interpose [item seq]
|
|
|
|
"Return an iterable of the elements of seq separated by item"
|
2015-09-03 19:45:55 +02:00
|
|
|
(drop 1 (interleave (repeat item) seq)))
|
2014-08-17 04:53:57 +02:00
|
|
|
|
2013-07-08 04:36:26 +02:00
|
|
|
(defn iterable? [x]
|
|
|
|
"Return true if x is iterable"
|
2014-04-29 16:01:14 +02:00
|
|
|
(isinstance x collections.Iterable))
|
2013-07-08 04:36:26 +02:00
|
|
|
|
|
|
|
(defn iterate [f x]
|
|
|
|
(setv val x)
|
2016-11-24 03:35:17 +01:00
|
|
|
(while True
|
2013-07-08 04:36:26 +02:00
|
|
|
(yield val)
|
|
|
|
(setv val (f val))))
|
|
|
|
|
|
|
|
(defn iterator? [x]
|
|
|
|
"Return true if x is an iterator"
|
2014-04-29 16:01:14 +02:00
|
|
|
(isinstance x collections.Iterator))
|
2013-07-08 04:36:26 +02:00
|
|
|
|
2016-12-25 22:54:53 +01:00
|
|
|
(defn juxt [f &rest fs]
|
2016-12-27 08:45:09 +01:00
|
|
|
"Return a function that applies each of the supplied functions to a single
|
|
|
|
set of arguments and collects the results into a list."
|
2016-12-25 22:54:53 +01:00
|
|
|
(setv fs (cons f fs))
|
|
|
|
(fn [&rest args &kwargs kwargs]
|
|
|
|
(list-comp (apply f args kwargs) [f fs])))
|
|
|
|
|
2015-03-18 16:23:43 +01:00
|
|
|
(defn last [coll]
|
|
|
|
"Return last item from `coll`"
|
2015-09-03 19:45:55 +02:00
|
|
|
(get (tuple coll) -1))
|
2015-03-18 16:23:43 +01:00
|
|
|
|
2013-05-16 18:59:20 +02:00
|
|
|
(defn list* [hd &rest tl]
|
|
|
|
"Return a dotted list construed from the elements of the argument"
|
|
|
|
(if (not tl)
|
|
|
|
hd
|
|
|
|
(cons hd (apply list* tl))))
|
|
|
|
|
2013-10-11 12:55:14 +02:00
|
|
|
(defn macroexpand [form]
|
2013-10-11 14:50:10 +02:00
|
|
|
"Return the full macro expansion of form"
|
2013-10-11 12:55:14 +02:00
|
|
|
(import hy.macros)
|
2013-10-11 15:30:55 +02:00
|
|
|
|
2014-01-03 21:41:14 +01:00
|
|
|
(setv name (calling-module-name))
|
2015-12-23 21:13:18 +01:00
|
|
|
(hy.macros.macroexpand form (HyASTCompiler name)))
|
2013-10-11 12:55:14 +02:00
|
|
|
|
2013-10-11 14:50:10 +02:00
|
|
|
(defn macroexpand-1 [form]
|
|
|
|
"Return the single step macro expansion of form"
|
|
|
|
(import hy.macros)
|
2013-10-11 15:30:55 +02:00
|
|
|
|
2014-01-03 21:41:14 +01:00
|
|
|
(setv name (calling-module-name))
|
2015-12-23 21:13:18 +01:00
|
|
|
(hy.macros.macroexpand-1 form (HyASTCompiler name)))
|
2013-10-11 14:50:10 +02:00
|
|
|
|
2014-01-14 08:30:36 +01:00
|
|
|
(defn merge-with [f &rest maps]
|
|
|
|
"Returns a map that consists of the rest of the maps joined onto
|
|
|
|
the first. If a key occurs in more than one map, the mapping(s)
|
|
|
|
from the latter (left-to-right) will be combined with the mapping in
|
|
|
|
the result by calling (f val-in-result val-in-latter)."
|
|
|
|
(if (any maps)
|
2017-02-04 02:03:06 +01:00
|
|
|
(do
|
|
|
|
(defn merge-entry [m e]
|
|
|
|
(setv k (get e 0) v (get e 1))
|
|
|
|
(if (in k m)
|
|
|
|
(assoc m k (f (get m k) v))
|
|
|
|
(assoc m k v))
|
|
|
|
m)
|
|
|
|
(defn merge2 [m1 m2]
|
|
|
|
(reduce merge-entry (.items m2) (or m1 {})))
|
|
|
|
(reduce merge2 maps))))
|
2014-01-14 08:30:36 +01:00
|
|
|
|
2013-07-08 04:36:26 +02:00
|
|
|
(defn neg? [n]
|
|
|
|
"Return true if n is < 0"
|
|
|
|
(< n 0))
|
|
|
|
|
|
|
|
(defn none? [x]
|
|
|
|
"Return true if x is None"
|
|
|
|
(is x None))
|
|
|
|
|
2013-07-08 04:36:26 +02:00
|
|
|
(defn numeric? [x]
|
|
|
|
(import numbers)
|
|
|
|
(instance? numbers.Number x))
|
|
|
|
|
2016-11-24 03:35:17 +01:00
|
|
|
(defn nth [coll n &optional [default None]]
|
2014-08-23 13:35:31 +02:00
|
|
|
"Return nth item in collection or sequence, counting from 0.
|
2016-11-24 03:35:17 +01:00
|
|
|
Return None if out of bounds unless specified otherwise."
|
2014-08-23 13:35:31 +02:00
|
|
|
(next (drop n coll) default))
|
2013-07-08 04:36:26 +02:00
|
|
|
|
|
|
|
(defn odd? [n]
|
|
|
|
"Return true if n is an odd number"
|
|
|
|
(= (% n 2) 1))
|
|
|
|
|
2015-09-03 06:54:24 +02:00
|
|
|
(def -sentinel (object))
|
|
|
|
(defn partition [coll &optional [n 2] step [fillvalue -sentinel]]
|
|
|
|
"Chunks coll into n-tuples (pairs by default). The remainder, if any, is not
|
|
|
|
included unless a fillvalue is specified. The step defaults to n, but can be
|
|
|
|
more to skip elements, or less for a sliding window with overlap."
|
|
|
|
(setv
|
|
|
|
step (or step n)
|
2016-11-24 03:35:17 +01:00
|
|
|
slices (genexpr (itertools.islice coll start None step) [start (range n)]))
|
2015-09-03 06:54:24 +02:00
|
|
|
(if (is fillvalue -sentinel)
|
|
|
|
(apply zip slices)
|
|
|
|
(apply zip-longest slices {"fillvalue" fillvalue})))
|
2015-08-05 22:59:05 +02:00
|
|
|
|
2013-07-08 04:36:26 +02:00
|
|
|
(defn pos? [n]
|
|
|
|
"Return true if n is > 0"
|
|
|
|
(> n 0))
|
|
|
|
|
2014-01-10 19:35:21 +01:00
|
|
|
(defn rest [coll]
|
|
|
|
"Get all the elements of a coll, except the first."
|
2014-04-29 16:01:14 +02:00
|
|
|
(drop 1 coll))
|
2013-07-08 04:36:26 +02:00
|
|
|
|
|
|
|
(defn repeatedly [func]
|
|
|
|
"Yield result of running func repeatedly"
|
2016-11-24 03:35:17 +01:00
|
|
|
(while True
|
2013-07-08 04:36:26 +02:00
|
|
|
(yield (func))))
|
|
|
|
|
2013-07-29 18:40:48 +02:00
|
|
|
(defn second [coll]
|
|
|
|
"Return second item from `coll`"
|
2014-04-29 16:01:14 +02:00
|
|
|
(nth coll 1))
|
2013-07-29 18:40:48 +02:00
|
|
|
|
2014-02-11 09:42:56 +01:00
|
|
|
(defn some [pred coll]
|
2016-11-24 03:35:17 +01:00
|
|
|
"Return the first logical true value of (pred x) for any x in coll, else None"
|
|
|
|
(first (filter None (map pred coll))))
|
2014-02-11 09:42:56 +01:00
|
|
|
|
2013-10-03 23:38:30 +02:00
|
|
|
(defn string [x]
|
|
|
|
"Cast x as current string implementation"
|
|
|
|
(if-python2
|
|
|
|
(unicode x)
|
|
|
|
(str x)))
|
|
|
|
|
2013-07-29 18:40:48 +02:00
|
|
|
(defn string? [x]
|
|
|
|
"Return True if x is a string"
|
2013-09-14 20:17:06 +02:00
|
|
|
(if-python2
|
2013-07-29 18:40:48 +02:00
|
|
|
(isinstance x (, str unicode))
|
|
|
|
(isinstance x str)))
|
|
|
|
|
2013-07-08 04:36:26 +02:00
|
|
|
(defn take [count coll]
|
|
|
|
"Take `count` elements from `coll`, or the whole set if the total
|
|
|
|
number of entries in `coll` is less than `count`."
|
2016-11-24 03:35:17 +01:00
|
|
|
(islice coll None count))
|
2013-06-29 17:50:31 +02:00
|
|
|
|
2013-07-08 04:36:26 +02:00
|
|
|
(defn take-nth [n coll]
|
|
|
|
"Return every nth member of coll
|
|
|
|
raises ValueError for (not (pos? n))"
|
|
|
|
(if (pos? n)
|
2017-02-04 02:03:06 +01:00
|
|
|
(do
|
|
|
|
(setv citer (iter coll) skip (dec n))
|
|
|
|
(for* [val citer]
|
|
|
|
(yield val)
|
|
|
|
(for* [_ (range skip)]
|
|
|
|
(next citer))))
|
|
|
|
(raise (ValueError "n must be positive"))))
|
2013-06-29 17:50:31 +02:00
|
|
|
|
2013-09-02 11:28:21 +02:00
|
|
|
(defn zero? [n]
|
|
|
|
"Return true if n is 0"
|
|
|
|
(= n 0))
|
|
|
|
|
2014-08-14 18:18:05 +02:00
|
|
|
(defn read [&optional [from-file sys.stdin]
|
2014-07-24 20:44:55 +02:00
|
|
|
[eof ""]]
|
|
|
|
"Read from input and returns a tokenized string.
|
|
|
|
Can take a given input buffer to read from"
|
|
|
|
(def buff "")
|
2016-11-24 03:35:17 +01:00
|
|
|
(while True
|
2015-07-28 16:57:50 +02:00
|
|
|
(def inn (str (.readline from-file)))
|
2014-07-24 20:44:55 +02:00
|
|
|
(if (= inn eof)
|
2015-08-09 06:04:02 +02:00
|
|
|
(raise (EOFError "Reached end of file" )))
|
2014-07-24 20:44:55 +02:00
|
|
|
(setv buff (+ buff inn))
|
|
|
|
(try
|
|
|
|
(def parsed (first (tokenize buff)))
|
2015-07-28 16:57:50 +02:00
|
|
|
(except [e [PrematureEndOfInput IndexError]])
|
2014-07-24 20:44:55 +02:00
|
|
|
(else (if parsed (break)))))
|
|
|
|
parsed)
|
|
|
|
|
2015-07-28 16:51:35 +02:00
|
|
|
(defn read-str [input]
|
|
|
|
"Reads and tokenizes first line of input"
|
|
|
|
(read :from-file (StringIO input)))
|
2014-02-20 03:27:49 +01:00
|
|
|
|
2014-03-01 00:23:49 +01:00
|
|
|
(defn hyify [text]
|
|
|
|
"Convert text to match hy identifier"
|
|
|
|
(.replace (string text) "_" "-"))
|
|
|
|
|
|
|
|
(defn keyword [value]
|
|
|
|
"Create a keyword from the given value. Strings numbers and even objects
|
|
|
|
with the __name__ magic will work"
|
2014-03-01 00:23:49 +01:00
|
|
|
(if (and (string? value) (value.startswith *keyword-prefix*))
|
2014-03-01 00:23:49 +01:00
|
|
|
(hyify value)
|
|
|
|
(if (string? value)
|
|
|
|
(HyKeyword (+ ":" (hyify value)))
|
|
|
|
(try
|
|
|
|
(hyify (.__name__ value))
|
2015-08-09 08:41:11 +02:00
|
|
|
(except [] (HyKeyword (+ ":" (string value))))))))
|
2014-03-01 00:23:49 +01:00
|
|
|
|
|
|
|
(defn name [value]
|
|
|
|
"Convert the given value to a string. Keyword special character will be stripped.
|
|
|
|
String will be used as is. Even objects with the __name__ magic will work"
|
2014-03-01 00:23:49 +01:00
|
|
|
(if (and (string? value) (value.startswith *keyword-prefix*))
|
2015-08-05 13:29:13 +02:00
|
|
|
(hyify (cut value 2))
|
2014-03-01 00:23:49 +01:00
|
|
|
(if (string? value)
|
|
|
|
(hyify value)
|
|
|
|
(try
|
|
|
|
(hyify (. value __name__))
|
2015-08-09 08:41:11 +02:00
|
|
|
(except [] (string value))))))
|
2014-03-01 00:23:49 +01:00
|
|
|
|
2015-08-03 04:37:39 +02:00
|
|
|
(defn xor [a b]
|
|
|
|
"Perform exclusive or between two parameters"
|
2017-01-31 23:31:27 +01:00
|
|
|
(if (and a b)
|
|
|
|
False
|
|
|
|
(or a b)))
|
2015-08-03 04:37:39 +02:00
|
|
|
|
2015-08-05 22:59:05 +02:00
|
|
|
(def *exports*
|
2015-09-03 19:45:55 +02:00
|
|
|
'[*map accumulate butlast calling-module-name chain coll? combinations
|
2016-12-25 21:11:25 +01:00
|
|
|
comp complement compress cons cons? constantly count cycle dec distinct
|
|
|
|
disassemble drop drop-last drop-while empty? even? every? first filter
|
|
|
|
flatten float? fraction gensym group-by identity inc input instance?
|
2016-12-25 22:54:53 +01:00
|
|
|
integer integer? integer-char? interleave interpose islice iterable?
|
|
|
|
iterate iterator? juxt keyword keyword? last list* macroexpand
|
|
|
|
macroexpand-1 map merge-with multicombinations name neg? none? nth
|
|
|
|
numeric? odd? partition permutations pos? product range read read-str
|
|
|
|
remove repeat repeatedly rest reduce second some string string? symbol?
|
|
|
|
take take-nth take-while xor tee zero? zip zip-longest])
|