Properly add yield-from, using python's real "yield from".
The yield-from that existed previously wasn't actually implementing the full complexity of "yield from": http://legacy.python.org/dev/peps/pep-0380/#formal-semantics ... this includes passing along errors, and many other things. Also removes the yield-from backport macro, since it does not seem possible at present to conditionally build macros. Thus, there is no longer yield-from on pre-python-3.3 systems. Includes updated docs and tests to reflect all this.
This commit is contained in:
parent
5de39a4e1d
commit
d5194f23fa
@ -1227,6 +1227,20 @@ infinite series without consuming infinite amount of memory.
|
||||
=> (list-comp x [x (take 15 (random-numbers 1 50))])])
|
||||
[7, 41, 6, 22, 32, 17, 5, 38, 18, 38, 17, 14, 23, 23, 19]
|
||||
|
||||
|
||||
yield-from
|
||||
----------
|
||||
|
||||
.. versionadded:: 0.9.13
|
||||
|
||||
**PYTHON 3.3 AND UP ONLY!**
|
||||
|
||||
`yield-from` is used to call a subgenerator. This is useful if you
|
||||
want your coroutine to be able to delegate its processes to another
|
||||
coroutine, say if using something fancy like
|
||||
`asyncio <http://docs.python.org/3.4/library/asyncio.html>`_.
|
||||
|
||||
|
||||
.. _zipwith:
|
||||
|
||||
zipwith
|
||||
|
@ -1017,6 +1017,28 @@ class HyASTCompiler(object):
|
||||
|
||||
return ret
|
||||
|
||||
@builds("yield_from")
|
||||
@checkargs(max=1)
|
||||
def compile_yield_from_expression(self, expr):
|
||||
if not PY33:
|
||||
raise HyCompileError(
|
||||
"yield-from only supported in python 3.3+!")
|
||||
|
||||
expr.pop(0)
|
||||
ret = Result(contains_yield=True)
|
||||
|
||||
value = None
|
||||
if expr != []:
|
||||
ret += self.compile(expr.pop(0))
|
||||
value = ret.force_expr
|
||||
|
||||
ret += ast.YieldFrom(
|
||||
value=value,
|
||||
lineno=expr.start_line,
|
||||
col_offset=expr.start_column)
|
||||
|
||||
return ret
|
||||
|
||||
@builds("import")
|
||||
def compile_import_expression(self, expr):
|
||||
def _compile_import(expr, module, names=None, importer=ast.Import):
|
||||
|
@ -27,8 +27,8 @@
|
||||
|
||||
|
||||
(import [hy.models.list [HyList]]
|
||||
[hy.models.symbol [HySymbol]])
|
||||
|
||||
[hy.models.symbol [HySymbol]]
|
||||
[hy._compat [PY33 PY34]])
|
||||
|
||||
|
||||
(defmacro for [args &rest body]
|
||||
@ -155,12 +155,6 @@
|
||||
`(if-not ~test (do ~@body)))
|
||||
|
||||
|
||||
(defmacro yield-from [iterable]
|
||||
"Yield all the items from iterable"
|
||||
(let [[x (gensym)]]
|
||||
`(for* [~x ~iterable]
|
||||
(yield ~x))))
|
||||
|
||||
(defmacro with-gensyms [args &rest body]
|
||||
`(let ~(HyList (map (fn [x] `[~x (gensym '~x)]) args))
|
||||
~@body))
|
||||
|
@ -1,3 +1,6 @@
|
||||
(import [hy._compat [PY33]])
|
||||
(import [hy.errors [HyCompileError]])
|
||||
|
||||
(defmacro rev [&rest body]
|
||||
"Execute the `body` statements in reverse"
|
||||
(quasiquote (do (unquote-splice (list (reversed body))))))
|
||||
@ -99,11 +102,18 @@
|
||||
|
||||
(defn test-yield-from []
|
||||
"NATIVE: testing yield from"
|
||||
(defn yield-from-test []
|
||||
(for* [i (range 3)]
|
||||
(yield i))
|
||||
(yield-from [1 2 3]))
|
||||
(assert (= (list (yield-from-test)) [0 1 2 1 2 3])))
|
||||
|
||||
(try
|
||||
(eval
|
||||
'(do (defn yield-from-test []
|
||||
(for* [i (range 3)]
|
||||
(yield i))
|
||||
(yield-from [1 2 3]))
|
||||
(assert (= (list (yield-from-test)) [0 1 2 1 2 3]))))
|
||||
(catch [e HyCompileError]
|
||||
;; Yup, this should happen on non-Python3.3 thingies
|
||||
(assert (not PY33)))
|
||||
(else (assert PY33))))
|
||||
|
||||
(defn test-if-python2 []
|
||||
(import sys)
|
||||
|
Loading…
x
Reference in New Issue
Block a user