diff --git a/docs/language/api.rst b/docs/language/api.rst index 625ebc0..87e6b57 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -334,6 +334,18 @@ For example: => (counter [1 2 3 4 5 2 3] 2) 2 +They can be used to assign multiple variables at once: + +.. code-block:: hy + + => (setv a 1 b 2) + (1L, 2L) + => a + 1L + => b + 2L + => + defclass -------- diff --git a/hy/compiler.py b/hy/compiler.py index 6da7215..1fa1854 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -1903,11 +1903,29 @@ class HyASTCompiler(object): @builds("def") @builds("setv") - @checkargs(2) + @checkargs(min=2) def compile_def_expression(self, expression): - return self._compile_assign(expression[1], expression[2], - expression.start_line, - expression.start_column) + expression.pop(0) + if len(expression) == 2: + return self._compile_assign(expression[0], expression[1], + expression.start_line, + expression.start_column) + elif len(expression) % 2 != 0: + raise HyTypeError(expression, + "setv needs an even number of arguments") + else: + result = Result() + exprs = [] + for tgt, target in zip(expression[::2], expression[1::2]): + item = self._compile_assign(tgt, target, + tgt.start_line, tgt.start_column) + result += item + exprs.append(item.force_expr) + + result += ast.Tuple(elts=exprs, lineno=expression.start_line, + col_offset=expression.start_column, + ctx=ast.Load()) + return result def _compile_assign(self, name, result, start_line, start_column): diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index 580cccf..79756c9 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -58,6 +58,18 @@ (try (eval '(defn lambda [] (print "hello"))) (catch [e [TypeError]] (assert (in "Can't assign to a builtin" (str e)))))) + +(defn test-setv-pairs [] + "NATIVE: test that setv works on pairs of arguments" + (assert (= (setv a 1 b 2) (, 1 2))) + (assert (= a 1)) + (assert (= b 2)) + (setv y 0 x 1 y x) + (assert y) + (try (eval '(setv a 1 b)) + (catch [e [TypeError]] (assert (in "setv needs an even number of arguments" (str e)))))) + + (defn test-fn-corner-cases [] "NATIVE: tests that fn/defn handles corner cases gracefully" (try (eval '(fn "foo"))