diff --git a/hy/compiler.py b/hy/compiler.py index e82758a..0b85ed3 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -1934,6 +1934,19 @@ class HyASTCompiler(object): raise HyTypeError(expression, "First argument to (fn) must be a list") ret, args, defaults, stararg, kwargs = self._parse_lambda_list(arglist) + for i, arg in enumerate(args): + if isinstance(arg, HyList): + # Destructuring argument + if not arg: + raise HyTypeError(arglist, + "Cannot destruct empty list") + args[i] = var = HySymbol(self.get_anon_var()) + expression = HyExpression([ + HyExpression([ + HyString("setv"), arg, var + ])] + ) + expression + expression = expression.replace(arg[0]) if PY34: # Python 3.4+ requires that args are an ast.arg object, rather diff --git a/tests/compilers/test_ast.py b/tests/compilers/test_ast.py index 4a63b6b..01d6269 100644 --- a/tests/compilers/test_ast.py +++ b/tests/compilers/test_ast.py @@ -404,6 +404,12 @@ def test_ast_tuple(): assert type(code) == ast.Tuple +def test_argument_destructuring(): + """ Ensure argument destructuring compilers. """ + can_compile("(fn [[a b]] (print a b))") + cant_compile("(fn [[]] 0)") + + def test_lambda_list_keywords_rest(): """ Ensure we can compile functions with lambda list keywords.""" can_compile("(fn (x &rest xs) (print xs))") diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index d75e267..d8a712c 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -1153,3 +1153,8 @@ (assert (= (identify-keywords 1 "bloo" :foo) ["other" "other" "keyword"]))) + +(defn test-argument-destr [] + "Make sure argument destructuring works" + (defn f [[a b] [c]] (, a b c)) + (assert (= (f [1 2] [3]) (, 1 2 3))))