Change the signature of (for) and (with).
(for) is restored to clojure-like flatness. (with) can be used without the nested list if you don't care about the name. Tests and examples updated.
This commit is contained in:
parent
8cabf22749
commit
eeef65b505
2
NEWS
2
NEWS
@ -55,8 +55,6 @@ Changes from Hy 0.9.11
|
||||
|
||||
|
||||
[ Syntax Fixes ]
|
||||
* for changed syntax from (for [] ...) -> (for [[]] ...)
|
||||
* with changed syntax from (with [] ...) -> (with [[]] ...)
|
||||
* get allows multiple arguments
|
||||
|
||||
|
||||
|
@ -205,11 +205,12 @@ however is called only for every other value in the list.
|
||||
;; assuming that (side-effect1) and (side-effect2) are functions and
|
||||
;; collection is a list of numerical values
|
||||
|
||||
(for (x collection) (do
|
||||
(side-effect1 x)
|
||||
(if (% x 2)
|
||||
(continue))
|
||||
(side-effect2 x)))
|
||||
(for [x collection]
|
||||
(do
|
||||
(side-effect1 x)
|
||||
(if (% x 2)
|
||||
(continue))
|
||||
(side-effect2 x)))
|
||||
|
||||
|
||||
do / progn
|
||||
@ -489,10 +490,10 @@ collection and calls side-effect to each element in the collection:
|
||||
.. code-block:: clj
|
||||
|
||||
;; assuming that (side-effect) is a function that takes a single parameter
|
||||
(for [[element collection]] (side-effect element))
|
||||
(for [element collection] (side-effect element))
|
||||
|
||||
;; for can have an optional else block
|
||||
(for [[element collection]] (side-effect element)
|
||||
(for [element collection] (side-effect element)
|
||||
(else (side-effect-2)))
|
||||
|
||||
The optional `else` block is executed only if the `for` loop terminates
|
||||
@ -500,14 +501,14 @@ normally. If the execution is halted with `break`, the `else` does not execute.
|
||||
|
||||
.. code-block:: clj
|
||||
|
||||
=> (for [[element [1 2 3]]] (if (< element 3)
|
||||
=> (for [element [1 2 3]] (if (< element 3)
|
||||
... (print element)
|
||||
... (break))
|
||||
... (else (print "loop finished")))
|
||||
1
|
||||
2
|
||||
|
||||
=> (for [[element [1 2 3]]] (if (< element 4)
|
||||
=> (for [element [1 2 3]] (if (< element 4)
|
||||
... (print element)
|
||||
... (break))
|
||||
... (else (print "loop finished")))
|
||||
@ -680,7 +681,7 @@ function is defined and passed to another function for filtering output.
|
||||
... {:name "Dave" :age 5}])
|
||||
|
||||
=> (defn display-people [people filter]
|
||||
... (for [[person people]] (if (filter person) (print (:name person)))))
|
||||
... (for [person people] (if (filter person) (print (:name person)))))
|
||||
|
||||
=> (display-people people (fn [person] (< (:age person) 25)))
|
||||
Alice
|
||||
|
@ -7,5 +7,5 @@
|
||||
|
||||
(with-as (ThreadPoolExecutor 10) executor
|
||||
(setv jobs (list-comp (.submit executor task-to-do) (x (range 0 10))))
|
||||
(for (future (as-completed jobs))
|
||||
(for [future (as-completed jobs)]
|
||||
(.result future)))
|
||||
|
@ -31,14 +31,14 @@
|
||||
|
||||
(defmacro ap-each [lst &rest body]
|
||||
"Evaluate the body form for each element in the list."
|
||||
`(for [[it ~lst]] ~@body))
|
||||
`(for [it ~lst] ~@body))
|
||||
|
||||
|
||||
(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)]]
|
||||
(for [[it ~lst]]
|
||||
(for [it ~lst]
|
||||
(if (p it)
|
||||
~@body
|
||||
(break)))))
|
||||
@ -47,7 +47,7 @@
|
||||
(defmacro ap-map [form lst]
|
||||
"Yield elements evaluated in the form for each element in the list."
|
||||
`(let [[f (lambda [it] ~form)]]
|
||||
(for [[v ~lst]]
|
||||
(for [v ~lst]
|
||||
(yield (f v)))))
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@
|
||||
"Yield elements evaluated for each element in the list when the
|
||||
predicate function returns True."
|
||||
`(let [[f (lambda [it] ~rep)]]
|
||||
(for [[it ~lst]]
|
||||
(for [it ~lst]
|
||||
(if (~predfn it)
|
||||
(yield (f it))
|
||||
(yield it)))))
|
||||
@ -64,7 +64,7 @@
|
||||
(defmacro ap-filter [form lst]
|
||||
"Yield elements returned when the predicate form evaluates to True."
|
||||
`(let [[pred (lambda [it] ~form)]]
|
||||
(for [[val ~lst]]
|
||||
(for [val ~lst]
|
||||
(if (pred val)
|
||||
(yield val)))))
|
||||
|
||||
|
@ -25,16 +25,29 @@
|
||||
;;; These macros form the hy language
|
||||
;;; They are automatically required in every module, except inside hy.core
|
||||
|
||||
|
||||
(import [hy.models.list [HyList]]
|
||||
[hy.models.symbol [HySymbol]])
|
||||
|
||||
|
||||
|
||||
(defmacro for [args &rest body]
|
||||
"shorthand for nested for loops:
|
||||
(for [[x foo] [y bar]] baz) ->
|
||||
(for [x foo
|
||||
y bar]
|
||||
baz) ->
|
||||
(for* [x foo]
|
||||
(for* [y bar]
|
||||
baz))"
|
||||
|
||||
(if (odd? (len args))
|
||||
(macro-error args "`for' requires an even number of args."))
|
||||
|
||||
(if (empty? body)
|
||||
(macro-error None "`for' requires a body to evaluate"))
|
||||
(if args
|
||||
`(for* ~(.pop args 0) (for ~args ~@body))
|
||||
`(for* [~(.pop args 0) ~(.pop args 0)]
|
||||
(for ~args ~@body))
|
||||
`(do ~@body)))
|
||||
|
||||
|
||||
@ -44,9 +57,17 @@
|
||||
(with* [x foo]
|
||||
(with* [y bar]
|
||||
baz))"
|
||||
(if args
|
||||
`(with* ~(.pop args 0) (with ~args ~@body))
|
||||
`(do ~@body)))
|
||||
|
||||
(if (not (empty? args))
|
||||
(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.
|
||||
`(with* [~@primary] (with ~args ~@body))
|
||||
;;; OK, let's just give it away. This may not be something we
|
||||
;;; can do, but that's really the programmer's problem.
|
||||
`(with* [~primary] (with ~args ~@body))))
|
||||
`(do ~@body)))
|
||||
|
||||
|
||||
(defmacro-alias [car first] [thing]
|
||||
|
@ -313,7 +313,7 @@ def test_ast_valid_while():
|
||||
|
||||
def test_ast_valid_for():
|
||||
"Make sure AST can compile valid for"
|
||||
can_compile("(for [[a 2]] (print a))")
|
||||
can_compile("(for [a 2] (print a))")
|
||||
|
||||
|
||||
def test_ast_invalid_for():
|
||||
@ -452,14 +452,14 @@ def test_for_compile_error():
|
||||
assert(False)
|
||||
|
||||
try:
|
||||
can_compile("(fn [] (for [[x]]))")
|
||||
can_compile("(fn [] (for [x]))")
|
||||
except HyTypeError as e:
|
||||
assert(e.message == "`for' requires a body to evaluate")
|
||||
assert(e.message == "`for' requires an even number of args.")
|
||||
else:
|
||||
assert(False)
|
||||
|
||||
try:
|
||||
can_compile("(fn [] (for [[x xx]]))")
|
||||
can_compile("(fn [] (for [x xx]))")
|
||||
except HyTypeError as e:
|
||||
assert(e.message == "`for' requires a body to evaluate")
|
||||
else:
|
||||
|
@ -31,12 +31,12 @@
|
||||
(defn test-for-loop []
|
||||
"NATIVE: test for loops?"
|
||||
(setv count 0)
|
||||
(for [[x [1 2 3 4 5]]]
|
||||
(for [x [1 2 3 4 5]]
|
||||
(setv count (+ count x)))
|
||||
(assert (= count 15))
|
||||
(setv count 0)
|
||||
(for [[x [1 2 3 4 5]]
|
||||
[y [1 2 3 4 5]]]
|
||||
(for [x [1 2 3 4 5]
|
||||
y [1 2 3 4 5]]
|
||||
(setv count (+ count x y)))
|
||||
(assert (= count 150)))
|
||||
|
||||
@ -404,9 +404,9 @@
|
||||
|
||||
(defn test-yield []
|
||||
"NATIVE: test yielding"
|
||||
(defn gen [] (for [[x [1 2 3 4]]] (yield x)))
|
||||
(defn gen [] (for [x [1 2 3 4]] (yield x)))
|
||||
(setv ret 0)
|
||||
(for [[y (gen)]] (setv ret (+ ret y)))
|
||||
(for [y (gen)] (setv ret (+ ret y)))
|
||||
(assert (= ret 10)))
|
||||
|
||||
|
||||
@ -463,7 +463,7 @@
|
||||
(defn test-for-doodle []
|
||||
"NATIVE: test for-do"
|
||||
(do (do (do (do (do (do (do (do (do (setv (, x y) (, 0 0)))))))))))
|
||||
(for [[- [1 2]]]
|
||||
(for [- [1 2]]
|
||||
(do
|
||||
(setv x (+ x 1))
|
||||
(setv y (+ y 1))))
|
||||
@ -646,7 +646,7 @@
|
||||
|
||||
(defn test-nested-if []
|
||||
"NATIVE: test nested if"
|
||||
(for [[x (range 10)]]
|
||||
(for [x (range 10)]
|
||||
(if (in "foo" "foobar")
|
||||
(do
|
||||
(if true true true))
|
||||
@ -810,14 +810,14 @@
|
||||
|
||||
(defn test-break-breaking []
|
||||
"NATIVE: test checking if break actually breaks"
|
||||
(defn holy-grail [] (for [[x (range 10)]] (if (= x 5) (break))) x)
|
||||
(defn holy-grail [] (for [x (range 10)] (if (= x 5) (break))) x)
|
||||
(assert (= (holy-grail) 5)))
|
||||
|
||||
|
||||
(defn test-continue-continuation []
|
||||
"NATIVE: test checking if continue actually continues"
|
||||
(setv y [])
|
||||
(for [[x (range 10)]]
|
||||
(for [x (range 10)]
|
||||
(if (!= x 5)
|
||||
(continue))
|
||||
(.append y x))
|
||||
|
Loading…
Reference in New Issue
Block a user