Drop a set of brackets from let.

This changes let to use a flat list of symbol-value pairs instead of a
vector of vectors. One side effect is that (let [[a 1] z]) is not
expressible now, and one will explicitly need to set a nil value for z,
such as: (let [a 1 z nil]).

Closes #713.

Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
This commit is contained in:
Gergely Nagy 2015-08-17 09:07:32 +02:00
parent 9569537f8c
commit 9f88e07e1d
27 changed files with 254 additions and 256 deletions

View File

@ -213,17 +213,17 @@ Examples of usage:
.. code-block:: clj
=>(let [[collection {}]]
=>(let [collection {}]
... (assoc collection "Dog" "Bark")
... (print collection))
{u'Dog': u'Bark'}
=>(let [[collection {}]]
=>(let [collection {}]
... (assoc collection "Dog" "Bark" "Cat" "Meow")
... (print collection))
{u'Cat': u'Meow', u'Dog': u'Bark'}
=>(let [[collection [1 2 3 4]]]
=>(let [collection [1 2 3 4]]
... (assoc collection 2 None)
... (print collection))
[1, 2, None, 4]
@ -463,8 +463,8 @@ Parameters may have the following keywords in front of them:
.. code-block:: clj
=> (defn zig-zag-sum [&rest numbers]
(let [[odd-numbers (list-comp x [x numbers] (odd? x))]
[even-numbers (list-comp x [x numbers] (even? x))]]
(let [odd-numbers (list-comp x [x numbers] (odd? x))
even-numbers (list-comp x [x numbers] (even? x))]
(- (sum odd-numbers) (sum even-numbers))))
=> (zig-zag-sum)
@ -486,7 +486,7 @@ Parameters may have the following keywords in front of them:
.. code-block:: clj
=> (defn compare [a b &kwonly keyfn [reverse false]]
... (let [[result (keyfn a b)]]
... (let [result (keyfn a b)]
... (if (not reverse)
... result
... (- result))))
@ -786,8 +786,8 @@ list. Example usage:
.. code-block:: clj
=> (let [[animals {"dog" "bark" "cat" "meow"}]
... [numbers ["zero" "one" "two" "three"]]]
=> (let [animals {"dog" "bark" "cat" "meow"}
... numbers ["zero" "one" "two" "three"]]
... (print (get animals "dog"))
... (print (get numbers 2)))
bark
@ -988,30 +988,24 @@ example showcases this behaviour:
.. code-block:: clj
=> (let [[x 5]] (print x)
... (let [[x 6]] (print x))
=> (let [x 5] (print x)
... (let [x 6] (print x))
... (print x))
5
6
5
The ``let`` macro takes two parameters: a vector defining *variables* and the
*body* which gets executed. *variables* is a vector where each element is either
a single variable or a vector defining a variable value pair. In the case of a
single variable, it is assigned value ``None``; otherwise, the supplied value is
used.
.. code-block:: clj
=> (let [x [y 5]] (print x y))
None 5
The ``let`` macro takes two parameters: a vector defining *variables*
and the *body* which gets executed. *variables* is a vector of
variable and value pairs.
Note that the variable assignments are executed one by one, from left to right.
The following example takes advantage of this:
.. code-block:: clj
=> (let [[x 5] [y (+ x 1)]] (print x y))
=> (let [x 5
y (+ x 1)] (print x y))
5 6
@ -1050,15 +1044,15 @@ to modify variables through nested ``let`` or ``fn`` scopes:
.. code-block:: clj
(let [[x 0]]
(let [x 0]
(for [y (range 10)]
(let [[z (inc y)]]
(let [z (inc y)]
(nonlocal x) ; allow the setv to "jump scope" to resolve x
(setv x (+ x y))))
x)
(defn some-function []
(let [[x 0]]
(let [x 0]
(register-some-callback
(fn [stuff]
(nonlocal x)
@ -1467,9 +1461,9 @@ expands to:
.. code-block:: hy
(let [[a (gensym)
[b (gensym)
[c (gensym)]]
(let [a (gensym)
b (gensym)
c (gensym)]
...)
.. seealso::

View File

@ -1103,7 +1103,7 @@ if *from-file* ends before a complete expression can be parsed.
=> (with [[f (open "example.hy")]]
... (try
... (while true
... (let [[exp (read f)]]
... (let [exp (read f)]
... (do
... (print "OHY" exp)
... (eval exp))))

View File

@ -381,7 +381,7 @@ A first pass might be something like:
.. code-block:: hy
(defmacro nif [expr pos-form zero-form neg-form]
`(let [[obscure-name ~expr]]
`(let [obscure-name ~expr]
(cond [(pos? obscure-name) ~pos-form]
[(zero? obscure-name) ~zero-form]
[(neg? obscure-name) ~neg-form])))
@ -396,8 +396,8 @@ such an occasion. A much better version of ``nif`` would be:
.. code-block:: hy
(defmacro nif [expr pos-form zero-form neg-form]
(let [[g (gensym)]]
`(let [[~g ~expr]]
(let [g (gensym)]
`(let [~g ~expr]
(cond [(pos? ~g) ~pos-form]
[(zero? ~g) ~zero-form]
[(neg? ~g) ~neg-form]))))
@ -415,9 +415,9 @@ expands to:
.. code-block:: hy
(let [[a (gensym)
[b (gensym)
[c (gensym)]]
(let [a (gensym)
b (gensym)
c (gensym)]
...)
so our re-written ``nif`` would look like:
@ -426,7 +426,7 @@ so our re-written ``nif`` would look like:
(defmacro nif [expr pos-form zero-form neg-form]
(with-gensyms [g]
`(let [[~g ~expr]]
`(let [~g ~expr]
(cond [(pos? ~g) ~pos-form]
[(zero? ~g) ~zero-form]
[(neg? ~g) ~neg-form]))))
@ -440,7 +440,7 @@ Our final version of ``nif``, built with ``defmacro/g!`` becomes:
.. code-block:: hy
(defmacro/g! nif [expr pos-form zero-form neg-form]
`(let [[~g!res ~expr]]
`(let [~g!res ~expr]
(cond [(pos? ~g!res) ~pos-form]
[(zero? ~g!res) ~zero-form]
[(neg? ~g!res) ~neg-form]))))

View File

@ -105,8 +105,8 @@ Layout & Indentation
.. code-block:: clj
(let [[foo (bar)]
[qux (baz)]]
(let [foo (bar)]
qux (baz)]
(foo qux))

View File

@ -27,7 +27,7 @@
(reactor.stop))
(defn get-page [url]
(let [[d (getPage url)]]
(let [d (getPage url)]
(d.addCallback get-page-size)
(d.addErrback log-error)
(d.addCallback finish)))

View File

@ -30,8 +30,8 @@
(defmacro defn-alias [names lambda-list &rest body]
"define one function with several names"
(let [[main (first names)]
[aliases (rest names)]]
(let [main (first names)
aliases (rest names)]
(setv ret `(do (defn ~main ~lambda-list ~@body)))
(for* [name aliases]
(.append ret

View File

@ -26,7 +26,7 @@
(defmacro ap-if (test-form &rest args)
`(let [[it ~test-form]] (if it ~@args)))
`(let [it ~test-form] (if it ~@args)))
(defmacro ap-each [lst &rest body]
@ -37,7 +37,7 @@
(defmacro ap-each-while [lst form &rest body]
"Evalutate the body form for each element in the list while the
predicate form evaluates to True."
`(let [[p (lambda [it] ~form)]]
`(let [p (lambda [it] ~form)]
(for [it ~lst]
(if (p it)
~@body
@ -46,8 +46,9 @@
(defmacro ap-map [form lst]
"Yield elements evaluated in the form for each element in the list."
(let [[v (gensym 'v)] [f (gensym 'f)]]
`(let [[~f (lambda [it] ~form)]]
(let [v (gensym 'v)
f (gensym 'f)]
`(let [~f (lambda [it] ~form)]
(for [~v ~lst]
(yield (~f ~v))))))
@ -55,7 +56,7 @@
(defmacro ap-map-when [predfn rep lst]
"Yield elements evaluated for each element in the list when the
predicate function returns True."
`(let [[f (lambda [it] ~rep)]]
`(let [f (lambda [it] ~rep)]
(for [it ~lst]
(if (~predfn it)
(yield (f it))
@ -64,7 +65,7 @@
(defmacro ap-filter [form lst]
"Yield elements returned when the predicate form evaluates to True."
`(let [[pred (lambda [it] ~form)]]
`(let [pred (lambda [it] ~form)]
(for [val ~lst]
(if (pred val)
(yield val)))))
@ -85,7 +86,7 @@
(defmacro ap-first [predfn lst]
"Yield the first element that passes `predfn`"
(with-gensyms [n]
`(let [[~n None]]
`(let [~n None]
(ap-each ~lst (when ~predfn (setv ~n it) (break)))
~n)))
@ -93,7 +94,7 @@
(defmacro ap-last [predfn lst]
"Yield the last element that passes `predfn`"
(with-gensyms [n]
`(let [[~n None]]
`(let [~n None]
(ap-each ~lst (none? ~n)
(when ~predfn
(setv ~n it)))
@ -103,10 +104,10 @@
(defmacro ap-reduce [form lst &optional [initial-value None]]
"Anaphoric form of reduce, `acc' and `it' can be used for a form"
(if (none? initial-value)
`(let [[acc (car ~lst)]]
`(let [acc (car ~lst)]
(ap-each (cdr ~lst) (setv acc ~form))
acc)
`(let [[acc ~initial-value]]
`(let [acc ~initial-value]
(ap-each ~lst (setv acc ~form))
acc)))
@ -115,7 +116,7 @@
"Pushes a value through several forms.
(Anaphoric version of -> and ->>)"
(if (empty? forms) var
`(ap-pipe (let [[it ~var]] ~(first forms)) ~@(rest forms))))
`(ap-pipe (let [it ~var] ~(first forms)) ~@(rest forms))))
(defmacro ap-compose [&rest forms]

View File

@ -26,8 +26,8 @@
(do
(import [requests])
(let [[r (requests.get
"https://raw.githubusercontent.com/hylang/hy/master/AUTHORS")]]
(let [r (requests.get
"https://raw.githubusercontent.com/hylang/hy/master/AUTHORS")]
(repeat r.text)))
(except [e ImportError]
(repeat "Botsbuildbots requires `requests' to function."))))

View File

@ -2,8 +2,8 @@
(defn curry [func]
(let [[sig (.getargspec inspect func)]
[count (len sig.args)]]
(let [sig (.getargspec inspect func)
count (len sig.args)]
(fn [&rest args]
(if (< (len args) count)

View File

@ -58,7 +58,7 @@
(defmacro/g! fnr [signature &rest body]
(let [[new-body (recursive-replace 'recur g!recur-fn body)]]
(let [new-body (recursive-replace 'recur g!recur-fn body)]
`(do
(import [hy.contrib.loop [--trampoline--]])
(with-decorator
@ -85,7 +85,7 @@
;; If recur is used in a non-tail-call position, None is returned, which
;; causes chaos. Fixing this to detect if recur is in a tail-call position
;; and erroring if not is a giant TODO.
(let [[fnargs (map (fn [x] (first x)) bindings)]
[initargs (map second bindings)]]
(let [fnargs (map (fn [x] (first x)) bindings)
initargs (map second bindings)]
`(do (defnr ~g!recur-fn [~@fnargs] ~@body)
(~g!recur-fn ~@initargs))))

View File

@ -3,8 +3,8 @@
(defmacro route-with-methods [name path methods params &rest code]
"Same as route but with an extra methods array to specify HTTP methods"
`(let [[deco (apply app.route [~path]
{"methods" ~methods})]]
`(let [deco (apply app.route [~path]
{"methods" ~methods})]
(with-decorator deco
(defn ~name ~params
(do ~@code)))))

View File

@ -42,22 +42,14 @@
(defmacro let [variables &rest body]
"Execute `body` in the lexical context of `variables`"
(setv macroed_variables [])
(if (not (isinstance variables HyList))
(macro-error variables "let lexical context must be a list"))
(for* [variable variables]
(if (isinstance variable HyList)
(do
(if (!= (len variable) 2)
(macro-error variable "let variable assignments must contain two items"))
(.append macroed-variables `(setv ~(get variable 0) ~(get variable 1))))
(if (isinstance variable HySymbol)
(.append macroed-variables `(setv ~variable None))
(macro-error variable "let lexical context element must be a list or symbol"))))
(if (= (len variables) 0)
`((fn []
~@macroed-variables
~@body)))
~@body))
`((fn []
(setv ~@variables)
~@body))))
(defmacro if-python2 [python2-form python3-form]
"If running on python2, execute python2-form, else, execute python3-form"

View File

@ -84,7 +84,8 @@
(defn distinct [coll]
"Return a generator from the original collection with duplicates
removed"
(let [[seen (set)] [citer (iter coll)]]
(let [seen (set)
citer (iter coll)]
(for* [val citer]
(if (not_in val seen)
(do
@ -158,7 +159,7 @@
(defn drop-last [n coll]
"Return a sequence of all but the last n elements in coll."
(let [[iters (tee coll)]]
(let [iters (tee coll)]
(map first (apply zip [(get iters 0)
(drop n (get iters 1))]))))
@ -210,7 +211,7 @@
(setv _gensym_lock (Lock))
(defn gensym [&optional [g "G"]]
(let [[new_symbol None]]
(let [new_symbol None]
(global _gensym_counter)
(global _gensym_lock)
(.acquire _gensym_lock)
@ -310,14 +311,15 @@
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)
(let [[merge-entry (fn [m e]
(let [[k (get e 0)] [v (get e 1)]]
(let [merge-entry (fn [m e]
(let [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)]
[merge2 (fn [m1 m2]
(reduce merge-entry (.items m2) (or m1 {})))]]
m)
merge2 (fn [m1 m2]
(reduce merge-entry (.items m2) (or m1 {})))]
(reduce merge2 maps))))
(defn neg? [n]
@ -402,7 +404,8 @@
"Return every nth member of coll
raises ValueError for (not (pos? n))"
(if (pos? n)
(let [[citer (iter coll)] [skip (dec n)]]
(let [citer (iter coll)
skip (dec n)]
(for* [val citer]
(yield val)
(for* [_ (range skip)]

View File

@ -39,7 +39,7 @@
baz))"
(if (not (empty? args))
(let [[primary (.pop args 0)]]
(let [primary (.pop args 0)]
(if (isinstance primary HyList)
;;; OK. if we have a list, we can go ahead and unpack that
;;; as the argument to with.
@ -115,7 +115,7 @@
[(empty? args) `(do ~@body ~@belse)]
[(= (len args) 2) `(for* [~@args] (do ~@body) ~@belse)]
[true
(let [[alist (cut args 0 nil 2)]]
(let [alist (cut args 0 nil 2)]
`(for* [(, ~@alist) (genexpr (, ~@alist) [~@args])] (do ~@body) ~@belse))]))
@ -138,7 +138,7 @@
(if (isinstance expression HyExpression)
`(~(first expression) ~f ~@(rest expression))
`(~expression ~f)))
`(let [[~f ~form]]
`(let [~f ~form]
~@(map build-form expressions)
~f))
@ -180,13 +180,24 @@
(defmacro with-gensyms [args &rest body]
`(let ~(HyList (map (fn [x] `[~x (gensym '~x)]) args))
(setv syms [])
(for* [arg args]
(.extend syms `[~arg (gensym '~arg)]))
`(let ~syms
~@body))
(defmacro defmacro/g! [name args &rest body]
(let [[syms (list (distinct (filter (fn [x] (and (hasattr x "startswith") (.startswith x "g!"))) (flatten body))))]]
(let [syms (list
(distinct
(filter (fn [x]
(and (hasattr x "startswith")
(.startswith x "g!")))
(flatten body))))
gensyms []]
(for* [sym syms]
(.extend gensyms `[~sym (gensym (cut '~sym 2))]))
`(defmacro ~name [~@args]
(let ~(HyList (map (fn [x] `[~x (gensym (cut '~x 2))]) syms))
(let ~gensyms
~@body))))
@ -211,9 +222,9 @@
(defmacro defmain [args &rest body]
"Write a function named \"main\" and do the if __main__ dance"
(let [[retval (gensym)]
[mainfn `(fn [~@args]
~@body)]]
(let [retval (gensym)
mainfn `(fn [~@args]
~@body)]
`(when (= --name-- "__main__")
(import sys)
(setv ~retval (apply ~mainfn sys.argv))
@ -222,6 +233,6 @@
(defreader @ [expr]
(let [[decorators (cut expr nil -1)]
[fndef (get expr -1)]]
(let [decorators (cut expr nil -1)
fndef (get expr -1)]
`(with-decorator ~@decorators ~fndef)))

View File

@ -26,7 +26,7 @@
(defn + [&rest args]
"Shadow + operator for when we need to import / map it against something"
(let [[count (len args)]]
(let [count (len args)]
(if (zero? count)
(raise (TypeError "Need at least 1 argument to add/concatenate"))
(if (= count 1)
@ -36,7 +36,7 @@
(defn - [&rest args]
"Shadow - operator for when we need to import / map it against something"
(let [[count (len args)]]
(let [count (len args)]
(if (= count 0)
(raise (TypeError "Need at least 1 argument to subtract"))
(if (= count 1)
@ -53,7 +53,7 @@
(defn / [&rest args]
"Shadow / operator for when we need to import / map it against something"
(let [[count (len args)]]
(let [count (len args)]
(if (= count 0)
(raise (TypeError "Need at least 1 argument to divide"))
(if (= count 1)

View File

@ -8,18 +8,18 @@
" -- Alexander Artemenko <svetlyak.40wt@gmail.com> Thu, 30 Sep 2014 13:06:09 +0400")
(defn read-lines-from-file [filename]
(let [[f (codecs.open filename "r" "utf-8")]]
(fn [] (let [[line (.readline f) ]]
(let [f (codecs.open filename "r" "utf-8")]
(fn [] (let [line (.readline f) ]
line))))
(defn get-version-number [line]
(let [[match (re.search r"Changes from.*(\d+\.\d+\.\d+)$" line)]]
(let [match (re.search r"Changes from.*(\d+\.\d+\.\d+)$" line)]
(if match
(let [[version (.group match (int 1))]
[numbered (list (map int (.split version "."))) ]
[explicit-mapping {"0.9.12" "0.10.0"
"0.8.2" "0.9.0"}]]
(let [version (.group match (int 1))
numbered (list (map int (.split version ".")))
explicit-mapping {"0.9.12" "0.10.0"
"0.8.2" "0.9.0"}]
(assoc numbered 2 (+ (get numbered 2) 1))
(.get explicit-mapping
version
@ -36,14 +36,14 @@
(defn read-versions-from-file [filename]
(let [[reader (read-lines-from-file filename)]]
(let [reader (read-lines-from-file filename)]
(read-versions-rec (reader)
reader)))
(defn read-versions-rec [line reader]
(if line
(let [[version (get-version-number line)]
[[content next-line] (read-version-content reader)]]
(let [version (get-version-number line)
[content next-line] (read-version-content reader)]
(+ [{"from" version
"content" content}]
@ -61,6 +61,6 @@
(defmain [&rest args]
(let ((versions (read-versions-from-file "NEWS")))
(let [versions (read-versions-from-file "NEWS")]
(for [version versions]
(print (.encode (format-deb-version version) "utf-8")))))

View File

@ -321,20 +321,18 @@ def test_ast_invalid_for():
def test_ast_valid_let():
"Make sure AST can compile valid let"
can_compile("(let [])")
can_compile("(let [a b])")
can_compile("(let [[a 1]])")
can_compile("(let [[a 1] b])")
can_compile("(let [a 1])")
can_compile("(let [a 1 b nil])")
def test_ast_invalid_let():
"Make sure AST can't compile invalid let"
cant_compile("(let 1)")
cant_compile("(let [1])")
cant_compile("(let [[a 1 2]])")
cant_compile("(let [[]])")
cant_compile("(let [[a]])")
cant_compile("(let [[1]])")
cant_compile("(let [a 1 2])")
cant_compile("(let [a])")
cant_compile("(let [1])")
def test_ast_expression_basics():

View File

@ -55,7 +55,7 @@
[3 6 9])
(assert-equal (list (ap-map (* it 3) []))
[])
(assert-equal (let [[v 1] [f 1]] (list (ap-map (it v f) [(fn [a b] (+ a b))])))
(assert-equal (let [v 1 f 1] (list (ap-map (it v f) [(fn [a b] (+ a b))])))
[2]))
(defn test-ap-map-when []
@ -79,9 +79,9 @@
(defn test-ap-dotimes []
"NATIVE: testing anaphoric dotimes"
(assert-equal (let [[n []]] (ap-dotimes 3 (.append n 3)) n)
(assert-equal (let [n []] (ap-dotimes 3 (.append n 3)) n)
[3 3 3])
(assert-equal (let [[n []]] (ap-dotimes 3 (.append n it)) n)
(assert-equal (let [n []] (ap-dotimes 3 (.append n it)) n)
[0 1 2]))
(defn test-ap-first []

View File

@ -9,44 +9,44 @@
f)))
(defn test_route []
(let [[app (FakeMeth)]]
(let [app (FakeMeth)]
(route get-index "/" [] (str "Hy world!"))
(setv app-rules (getattr app "rules"))
(assert (in "/" app-rules))
(let [[(, rule-fun rule-opt) (get app-rules "/")]]
(let [(, rule-fun rule-opt) (get app-rules "/")]
(assert (not (empty? rule-opt)))
(assert (in "GET" (get rule-opt "methods")))
(assert (= (getattr rule-fun "__name__") "get_index"))
(assert (= "Hy world!" (rule-fun))))))
(defn test_post_route []
(let [[app (FakeMeth)]]
(let [app (FakeMeth)]
(post-route get-index "/" [] (str "Hy world!"))
(setv app-rules (getattr app "rules"))
(assert (in "/" app-rules))
(let [[(, rule-fun rule-opt) (get app-rules "/")]]
(let [(, rule-fun rule-opt) (get app-rules "/")]
(assert (not (empty? rule-opt)))
(assert (in "POST" (get rule-opt "methods")))
(assert (= (getattr rule-fun "__name__") "get_index"))
(assert (= "Hy world!" (rule-fun))))))
(defn test_put_route []
(let [[app (FakeMeth)]]
(let [app (FakeMeth)]
(put-route get-index "/" [] (str "Hy world!"))
(setv app-rules (getattr app "rules"))
(assert (in "/" app-rules))
(let [[(, rule-fun rule-opt) (get app-rules "/")]]
(let [(, rule-fun rule-opt) (get app-rules "/")]
(assert (not (empty? rule-opt)))
(assert (in "PUT" (get rule-opt "methods")))
(assert (= (getattr rule-fun "__name__") "get_index"))
(assert (= "Hy world!" (rule-fun))))))
(defn test_delete_route []
(let [[app (FakeMeth)]]
(let [app (FakeMeth)]
(delete-route get-index "/" [] (str "Hy world!"))
(setv app-rules (getattr app "rules"))
(assert (in "/" app-rules))
(let [[(, rule-fun rule-opt) (get app-rules "/")]]
(let [(, rule-fun rule-opt) (get app-rules "/")]
(assert (not (empty? rule-opt)))
(assert (in "DELETE" (get rule-opt "methods")))
(assert (= (getattr rule-fun "__name__") "get_index"))

View File

@ -15,17 +15,17 @@
walk-form)))
(defn test-walk []
(let [[acc '()]]
(let [acc '()]
(assert (= (walk (partial collector acc) identity walk-form)
[nil nil]))
(assert (= acc walk-form)))
(let [[acc []]]
(let [acc []]
(assert (= (walk identity (partial collector acc) walk-form)
nil))
(assert (= acc [walk-form]))))
(defn test-walk-iterators []
(let [[acc []]]
(let [acc []]
(assert (= (walk (fn [x] (* 2 x)) (fn [x] x)
(drop 1 [1 [2 [3 [4]]]]))
[[2 [3 [4]] 2 [3 [4]]]]))))

View File

@ -592,7 +592,7 @@
(setv res (list (take-nth 3 [1 2 3 None 5 6])))
(assert-equal res [1 None])
;; using 0 should raise ValueError
(let [[passed false]]
(let [passed false]
(try
(setv res (list (take-nth 0 [1 2 3 4 5 6 7])))
(except [ValueError] (setv passed true)))

View File

@ -36,7 +36,7 @@
(+ self.x value))])
(assert (= B.x 42))
(assert (= (.y (B) 5) 47))
(let [[b (B)]]
(let [b (B)]
(setv B.x 0)
(assert (= (.y b 1) 1))))

View File

@ -355,7 +355,7 @@
(try (do) (except [IOError]) (except))
;; Test correct (raise)
(let [[passed false]]
(let [passed false]
(try
(try
(raise IndexError)
@ -365,7 +365,7 @@
(assert passed))
;; Test incorrect (raise)
(let [[passed false]]
(let [passed false]
(try
(raise)
;; Python 2 raises TypeError
@ -374,16 +374,15 @@
(setv passed true)))
(assert passed))
;; Test (finally)
(let [[passed false]]
(let [passed false]
(try
(do)
(finally (setv passed true)))
(assert passed))
;; Test (finally) + (raise)
(let [[passed false]]
(let [passed false]
(try
(raise Exception)
(except)
@ -392,8 +391,8 @@
;; Test (finally) + (raise) + (else)
(let [[passed false]
[not-elsed true]]
(let [passed false
not-elsed true]
(try
(raise Exception)
(except)
@ -460,13 +459,13 @@
(setv foobar42ofthebaz 42)
(assert (= foobar42ofthebaz 42))))
(let [[passed false]]
(let [passed false]
(try
(try (do) (except) (else (bla)))
(except [NameError] (setv passed true)))
(assert passed))
(let [[x 0]]
(let [x 0]
(try
(raise IOError)
(except [IOError]
@ -474,7 +473,7 @@
(else (setv x 44)))
(assert (= x 45)))
(let [[x 0]]
(let [x 0]
(try
(raise KeyError)
(except []
@ -482,7 +481,7 @@
(else (setv x 44)))
(assert (= x 45)))
(let [[x 0]]
(let [x 0]
(try
(try
(raise KeyError)
@ -561,7 +560,7 @@
(defn test-yield-in-try []
"NATIVE: test yield in try"
(defn gen []
(let [[x 1]]
(let [x 1]
(try (yield x)
(finally (print x)))))
(setv output (list (gen)))
@ -631,13 +630,13 @@
(defn test-for-else []
"NATIVE: test for else"
(let [[x 0]]
(let [x 0]
(for* [a [1 2]]
(setv x (+ x a))
(else (setv x (+ x 50))))
(assert (= x 53)))
(let [[x 0]]
(let [x 0]
(for* [a [1 2]]
(setv x (+ x a))
(else))
@ -751,28 +750,28 @@
(defn test-let []
"NATIVE: test let works rightish"
;; TODO: test sad paths for let
(assert (= (let [[x 1] [y 2] [z 3]] (+ x y z)) 6))
(assert (= (let [[x 1] a [y 2] b] (if a 1 2)) 2))
(assert (= (let [x] x) nil))
(assert (= (let [[x "x not bound"]] (setv x "x bound by setv") x)
(assert (= (let [x 1 y 2 z 3] (+ x y z)) 6))
(assert (= (let [x 1 a nil y 2 b nil] (if a 1 2)) 2))
(assert (= (let [x nil] x) nil))
(assert (= (let [x "x not bound"] (setv x "x bound by setv") x)
"x bound by setv"))
(assert (= (let [[x "let nests scope correctly"]]
(let [y] x))
(assert (= (let [x "let nests scope correctly"]
(let [y nil] x))
"let nests scope correctly"))
(assert (= (let [[x 999999]]
(let [[x "x being rebound"]] x))
(assert (= (let [x 999999]
(let [x "x being rebound"] x))
"x being rebound"))
(assert (= (let [[x "x not being rebound"]]
(let [[x 2]] nil)
(assert (= (let [x "x not being rebound"]
(let [x 2] nil)
x)
"x not being rebound"))
(assert (= (let [[x (set [3 2 1 3 2])] [y x] [z y]] z) (set [1 2 3])))
(assert (= (let [x (set [3 2 1 3 2]) y x z y] z) (set [1 2 3])))
(import math)
(let [[cos math.cos]
[foo-cos (fn [x] (cos x))]]
(let [cos math.cos
foo-cos (fn [x] (cos x))]
(assert (= (cos math.pi) -1.0))
(assert (= (foo-cos (- math.pi)) -1.0))
(let [[cos (fn [_] "cos has been locally rebound")]]
(let [cos (fn [_] "cos has been locally rebound")]
(assert (= (cos cos) "cos has been locally rebound"))
(assert (= (-> math.pi (/ 3) foo-cos (round 2)) 0.5)))
(setv cos (fn [_] "cos has been rebound by setv"))
@ -792,9 +791,9 @@
(defn test-let-scope []
"NATIVE: test let works rightish"
(setv y 123)
(assert (= (let [[x 1]
[y 2]
[z 3]]
(assert (= (let [x 1
y 2
z 3]
(+ x y z))
6))
(try
@ -805,31 +804,31 @@
(defn test-symbol-utf-8 []
"NATIVE: test symbol encoded"
(let [[ "love"]
[ "flower"]]
(let [ "love"
"flower"]
(assert (= (+ ) "flowerlove"))))
(defn test-symbol-dash []
"NATIVE: test symbol encoded"
(let [[- "doublelove"]
[-_- "what?"]]
(let [- "doublelove"
-_- "what?"]
(assert (= - "doublelove"))
(assert (= -_- "what?"))))
(defn test-symbol-question-mark []
"NATIVE: test foo? -> is_foo behavior"
(let [[foo? "nachos"]]
(let [foo? "nachos"]
(assert (= is_foo "nachos"))))
(defn test-and []
"NATIVE: test the and function"
(let [[and123 (and 1 2 3)]
[and-false (and 1 False 3)]
[and-true (and)]
[and-single (and 1)]]
(let [and123 (and 1 2 3)
and-false (and 1 False 3)
and-true (and)
and-single (and 1)]
(assert (= and123 3))
(assert (= and-false False))
(assert (= and-true True))
@ -842,11 +841,11 @@
(defn test-or []
"NATIVE: test the or function"
(let [[or-all-true (or 1 2 3 True "string")]
[or-some-true (or False "hello")]
[or-none-true (or False False)]
[or-false (or)]
[or-single (or 1)]]
(let [or-all-true (or 1 2 3 True "string")
or-some-true (or False "hello")
or-none-true (or False False)
or-false (or)
or-single (or 1)]
(assert (= or-all-true 1))
(assert (= or-some-true "hello"))
(assert (= or-none-true False))
@ -861,12 +860,12 @@
(defn test-if-return-branching []
"NATIVE: test the if return branching"
; thanks, algernon
(assert (= 1 (let [[x 1]
[y 2]]
(assert (= 1 (let [x 1
y 2]
(if true
2)
1)))
(assert (= 1 (let [[x 1] [y 2]]
(assert (= 1 (let [x 1 y 2]
(do)
(do)
((fn [] 1))))))
@ -915,9 +914,9 @@
(defn test-eval-globals []
"NATIVE: test eval with explicit global dict"
(assert (= 'bar (eval (quote foo) {'foo 'bar})))
(assert (= 1 (let [[d {}]] (eval '(setv x 1) d) (eval (quote x) d))))
(let [[d1 {}]
[d2 {}]]
(assert (= 1 (let [d {}] (eval '(setv x 1) d) (eval (quote x) d))))
(let [d1 {}
d2 {}]
(eval '(setv x 1) d1)
(try
(do
@ -998,7 +997,7 @@
(defn test-if-let-mixing []
"NATIVE: test that we can now mix if and let"
(assert (= 0 (if true (let [[x 0]] x) 42))))
(assert (= 0 (if true (let [x 0] x) 42))))
(defn test-if-in-if []
"NATIVE: test that we can use if in if"

View File

@ -69,73 +69,73 @@
(defn test-augassign-add []
"NATIVE: test augassign add"
(let [[x 1]]
(let [x 1]
(+= x 41)
(assert (= x 42))))
(defn test-augassign-sub []
"NATIVE: test augassign sub"
(let [[x 1]]
(let [x 1]
(-= x 41)
(assert (= x -40))))
(defn test-augassign-mult []
"NATIVE: test augassign mult"
(let [[x 1]]
(let [x 1]
(*= x 41)
(assert (= x 41))))
(defn test-augassign-div []
"NATIVE: test augassign div"
(let [[x 42]]
(let [x 42]
(/= x 2)
(assert (= x 21))))
(defn test-augassign-floordiv []
"NATIVE: test augassign floordiv"
(let [[x 42]]
(let [x 42]
(//= x 2)
(assert (= x 21))))
(defn test-augassign-mod []
"NATIVE: test augassign mod"
(let [[x 42]]
(let [x 42]
(%= x 2)
(assert (= x 0))))
(defn test-augassign-pow []
"NATIVE: test augassign pow"
(let [[x 2]]
(let [x 2]
(**= x 3)
(assert (= x 8))))
(defn test-augassign-lshift []
"NATIVE: test augassign lshift"
(let [[x 2]]
(let [x 2]
(<<= x 2)
(assert (= x 8))))
(defn test-augassign-rshift []
"NATIVE: test augassign rshift"
(let [[x 8]]
(let [x 8]
(>>= x 1)
(assert (= x 4))))
(defn test-augassign-bitand []
"NATIVE: test augassign bitand"
(let [[x 8]]
(let [x 8]
(&= x 1)
(assert (= x 0))))
(defn test-augassign-bitor []
"NATIVE: test augassign bitand"
(let [[x 0]]
(let [x 0]
(|= x 2)
(assert (= x 2))))
(defn test-augassign-bitxor []
"NATIVE: test augassign bitand"
(let [[x 1]]
(let [x 1]
(^= x 1)
(assert (= x 0))))
@ -147,13 +147,13 @@
(defclass HyTestMatrix [list]
[--matmul--
(fn [self other]
(let [[n (len self)]
[m (len (. other [0]))]
[result []]]
(let [n (len self)
m (len (. other [0]))
result []]
(for [i (range m)]
(let [[result-row []]]
(let [result-row []]
(for [j (range n)]
(let [[dot-product 0]]
(let [dot-product 0]
(for [k (range (len (. self [0])))]
(+= dot-product (* (. self [i] [k])
(. other [k] [j]))))
@ -179,15 +179,15 @@
(assert (= (@ first-test-matrix second-test-matrix)
product-of-test-matrices))
;; Python <= 3.4
(let [[matmul-attempt (try (@ first-test-matrix second-test-matrix)
(except [e [Exception]] e))]]
(let [matmul-attempt (try (@ first-test-matrix second-test-matrix)
(except [e [Exception]] e))]
(assert (isinstance matmul-attempt NameError)))))
(defn test-augassign-matmul []
"NATIVE: test augmented-assignment matrix multiplication"
(let [[matrix first-test-matrix]
[matmul-attempt (try (@= matrix second-test-matrix)
(except [e [Exception]] e))]]
(let [matrix first-test-matrix
matmul-attempt (try (@= matrix second-test-matrix)
(except [e [Exception]] e))]
(if PY35
(assert (= product-of-test-matrices matrix))
(assert (isinstance matmul-attempt NameError)))))

View File

@ -107,8 +107,8 @@
(import [astor.codegen [to_source]])
(import [hy.importer [import_buffer_to_ast]])
(setv macro1 "(defmacro nif [expr pos zero neg]
(let [[g (gensym)]]
`(let [[~g ~expr]]
(let [g (gensym)]
`(let [~g ~expr]
(cond [(pos? ~g) ~pos]
[(zero? ~g) ~zero]
[(neg? ~g) ~neg]))))
@ -133,7 +133,7 @@
(import [hy.importer [import_buffer_to_ast]])
(setv macro1 "(defmacro nif [expr pos zero neg]
(with-gensyms [a]
`(let [[~a ~expr]]
`(let [~a ~expr]
(cond [(pos? ~a) ~pos]
[(zero? ~a) ~zero]
[(neg? ~a) ~neg]))))
@ -155,7 +155,7 @@
(import [astor.codegen [to_source]])
(import [hy.importer [import_buffer_to_ast]])
(setv macro1 "(defmacro/g! nif [expr pos zero neg]
`(let [[~g!res ~expr]]
`(let [~g!res ~expr]
(cond [(pos? ~g!res) ~pos]
[(zero? ~g!res) ~zero]
[(neg? ~g!res) ~neg])))

View File

@ -15,14 +15,14 @@
(defn test-kwonly []
"NATIVE: test keyword-only arguments"
;; keyword-only with default works
(let [[kwonly-foo-default-false (fn [&kwonly [foo false]] foo)]]
(let [kwonly-foo-default-false (fn [&kwonly [foo false]] foo)]
(assert (= (apply kwonly-foo-default-false) false))
(assert (= (apply kwonly-foo-default-false [] {"foo" true}) true)))
;; keyword-only without default ...
(let [[kwonly-foo-no-default (fn [&kwonly foo] foo)]
[attempt-to-omit-default (try
(let [kwonly-foo-no-default (fn [&kwonly foo] foo)
attempt-to-omit-default (try
(kwonly-foo-no-default)
(except [e [Exception]] e))]]
(except [e [Exception]] e))]
;; works
(assert (= (apply kwonly-foo-no-default [] {"foo" "quux"}) "quux"))
;; raises TypeError with appropriate message if not supplied
@ -30,9 +30,9 @@
(assert (in "missing 1 required keyword-only argument: 'foo'"
(. attempt-to-omit-default args [0]))))
;; keyword-only with other arg types works
(let [[function-of-various-args
(let [function-of-various-args
(fn [a b &rest args &kwonly foo &kwargs kwargs]
(, a b args foo kwargs))]]
(, a b args foo kwargs))]
(assert (= (apply function-of-various-args
[1 2 3 4] {"foo" 5 "bar" 6 "quux" 7})
(, 1 2 (, 3 4) 5 {"bar" 6 "quux" 7})))))

View File

@ -1,6 +1,6 @@
(defn test-shadow-addition []
"NATIVE: test shadow addition"
(let [[x +]]
(let [x +]
(assert (try
(x)
(except [TypeError] True)
@ -21,7 +21,7 @@
(defn test-shadow-subtraction []
"NATIVE: test shadow subtraction"
(let [[x -]]
(let [x -]
(assert (try
(x)
(except [TypeError] True)
@ -33,7 +33,7 @@
(defn test-shadow-multiplication []
"NATIVE: test shadow multiplication"
(let [[x *]]
(let [x *]
(assert (= (x) 1))
(assert (= (x 3) 3))
(assert (= (x 3 3) 9))))
@ -41,7 +41,7 @@
(defn test-shadow-division []
"NATIVE: test shadow division"
(let [[x /]]
(let [x /]
(assert (try
(x)
(except [TypeError] True)
@ -71,12 +71,12 @@
[1 1]
[2 2]]]
(assert (= (apply x args) (not (apply y args))))))
(let [[s-lt <]
[s-gt >]
[s-le <=]
[s-ge >=]
[s-eq =]
[s-ne !=]]
(let [s-lt <
s-gt >
s-le <=
s-ge >=
s-eq =
s-ne !=]
(assert (apply s-lt [1 2 3]))
(assert (not (apply s-lt [3 2 1])))
(assert (apply s-gt [3 2 1]))