commit
032247e380
1
NEWS.rst
1
NEWS.rst
@ -8,6 +8,7 @@ Removals
|
|||||||
* Dotted lists, `HyCons`, `cons`, `cons?`, and `list*` have been removed.
|
* Dotted lists, `HyCons`, `cons`, `cons?`, and `list*` have been removed.
|
||||||
These were redundant with Python's built-in data structures and Hy's most
|
These were redundant with Python's built-in data structures and Hy's most
|
||||||
common model types (`HyExpression`, `HyList`, etc.).
|
common model types (`HyExpression`, `HyList`, etc.).
|
||||||
|
* `&key` is no longer special in lambda lists. Use `&optional` instead.
|
||||||
|
|
||||||
Other Breaking Changes
|
Other Breaking Changes
|
||||||
------------------------------
|
------------------------------
|
||||||
|
@ -493,28 +493,6 @@ Parameters may have the following keywords in front of them:
|
|||||||
=> (total-value 100 1)
|
=> (total-value 100 1)
|
||||||
101.0
|
101.0
|
||||||
|
|
||||||
&key
|
|
||||||
Parameter is a dict of keyword arguments. The keys of the dict
|
|
||||||
specify the parameter names and the values give the default values
|
|
||||||
of the parameters.
|
|
||||||
|
|
||||||
.. code-block:: clj
|
|
||||||
|
|
||||||
=> (defn key-parameters [&key {"a" 1 "b" 2}]
|
|
||||||
... (print "a is" a "and b is" b))
|
|
||||||
=> (key-parameters :a 1 :b 2)
|
|
||||||
a is 1 and b is 2
|
|
||||||
=> (key-parameters :b 1 :a 2)
|
|
||||||
a is 2 and b is 1
|
|
||||||
|
|
||||||
The following declarations are equivalent:
|
|
||||||
|
|
||||||
.. code-block:: clj
|
|
||||||
|
|
||||||
(defn key-parameters [&key {"a" 1 "b" 2}])
|
|
||||||
|
|
||||||
(defn key-parameters [&optional [a 1] [b 2]])
|
|
||||||
|
|
||||||
&kwargs
|
&kwargs
|
||||||
Parameter will contain 0 or more keyword arguments.
|
Parameter will contain 0 or more keyword arguments.
|
||||||
|
|
||||||
|
@ -443,17 +443,6 @@ similar to `*args` and `**kwargs` in Python::
|
|||||||
=> (optional-arg #* args #** kwargs)
|
=> (optional-arg #* args #** kwargs)
|
||||||
[1, 2, 4, 3]
|
[1, 2, 4, 3]
|
||||||
|
|
||||||
There's also a dictionary-style keyword arguments construction that
|
|
||||||
looks like:
|
|
||||||
|
|
||||||
.. code-block:: clj
|
|
||||||
|
|
||||||
(defn another-style [&key {"key1" "val1" "key2" "val2"}]
|
|
||||||
[key1 key2])
|
|
||||||
|
|
||||||
The difference here is that since it's a dictionary, you can't rely on
|
|
||||||
any specific ordering to the arguments.
|
|
||||||
|
|
||||||
Hy also supports ``*args`` and ``**kwargs`` in parameter lists. In Python::
|
Hy also supports ``*args`` and ``**kwargs`` in parameter lists. In Python::
|
||||||
|
|
||||||
def some_func(foo, bar, *args, **kwargs):
|
def some_func(foo, bar, *args, **kwargs):
|
||||||
|
@ -529,7 +529,7 @@ class HyASTCompiler(object):
|
|||||||
|
|
||||||
def _parse_lambda_list(self, exprs):
|
def _parse_lambda_list(self, exprs):
|
||||||
""" Return FunctionDef parameter values from lambda list."""
|
""" Return FunctionDef parameter values from lambda list."""
|
||||||
ll_keywords = ("&rest", "&optional", "&key", "&kwonly", "&kwargs")
|
ll_keywords = ("&rest", "&optional", "&kwonly", "&kwargs")
|
||||||
ret = Result()
|
ret = Result()
|
||||||
args = []
|
args = []
|
||||||
defaults = []
|
defaults = []
|
||||||
@ -542,13 +542,7 @@ class HyASTCompiler(object):
|
|||||||
for expr in exprs:
|
for expr in exprs:
|
||||||
|
|
||||||
if expr in ll_keywords:
|
if expr in ll_keywords:
|
||||||
if expr == "&optional":
|
if expr in ("&optional", "&rest", "&kwonly", "&kwargs"):
|
||||||
if len(defaults) > 0:
|
|
||||||
raise HyTypeError(expr,
|
|
||||||
"There can only be &optional "
|
|
||||||
"arguments or one &key argument")
|
|
||||||
lambda_keyword = expr
|
|
||||||
elif expr in ("&rest", "&key", "&kwonly", "&kwargs"):
|
|
||||||
lambda_keyword = expr
|
lambda_keyword = expr
|
||||||
else:
|
else:
|
||||||
raise HyTypeError(expr,
|
raise HyTypeError(expr,
|
||||||
@ -566,27 +560,6 @@ class HyASTCompiler(object):
|
|||||||
"There can only be one "
|
"There can only be one "
|
||||||
"&rest argument")
|
"&rest argument")
|
||||||
varargs = expr
|
varargs = expr
|
||||||
elif lambda_keyword == "&key":
|
|
||||||
if type(expr) != HyDict:
|
|
||||||
raise HyTypeError(expr,
|
|
||||||
"There can only be one &key "
|
|
||||||
"argument")
|
|
||||||
else:
|
|
||||||
if len(defaults) > 0:
|
|
||||||
raise HyTypeError(expr,
|
|
||||||
"There can only be &optional "
|
|
||||||
"arguments or one &key argument")
|
|
||||||
# As you can see, Python has a funny way of
|
|
||||||
# defining keyword arguments.
|
|
||||||
it = iter(expr)
|
|
||||||
for k, v in zip(it, it):
|
|
||||||
if not isinstance(k, HyString):
|
|
||||||
raise HyTypeError(expr,
|
|
||||||
"Only strings can be used "
|
|
||||||
"as parameter names")
|
|
||||||
args.append(k)
|
|
||||||
ret += self.compile(v)
|
|
||||||
defaults.append(ret.force_expr)
|
|
||||||
elif lambda_keyword == "&optional":
|
elif lambda_keyword == "&optional":
|
||||||
if isinstance(expr, HyList):
|
if isinstance(expr, HyList):
|
||||||
if not len(expr) == 2:
|
if not len(expr) == 2:
|
||||||
|
@ -84,7 +84,7 @@ splits a fn argument list into sections based on &-headers.
|
|||||||
returns an OrderedDict mapping headers to sublists.
|
returns an OrderedDict mapping headers to sublists.
|
||||||
Arguments without a header are under None.
|
Arguments without a header are under None.
|
||||||
"
|
"
|
||||||
(setv headers '[&optional &key &rest &kwonly &kwargs]
|
(setv headers '[&optional &rest &kwonly &kwargs]
|
||||||
sections (OrderedDict [(, None [])])
|
sections (OrderedDict [(, None [])])
|
||||||
header None)
|
header None)
|
||||||
(for [arg form]
|
(for [arg form]
|
||||||
@ -177,14 +177,7 @@ Arguments without a header are under None.
|
|||||||
~(self.expand-symbols (second pair))])]
|
~(self.expand-symbols (second pair))])]
|
||||||
[True
|
[True
|
||||||
(.add protected pair)
|
(.add protected pair)
|
||||||
(.append argslist pair)]))]
|
(.append argslist pair)]))]))
|
||||||
[(= header '&key)
|
|
||||||
(setv &key-dict '{})
|
|
||||||
(for [[k v] (-> section first partition)]
|
|
||||||
(.add protected k)
|
|
||||||
(.append &key-dict k)
|
|
||||||
(.append &key-dict (self.expand-symbols v)))
|
|
||||||
(.append argslist &key-dict)]))
|
|
||||||
(, protected argslist))
|
(, protected argslist))
|
||||||
|
|
||||||
(defn handle-fn [self]
|
(defn handle-fn [self]
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
(% "received a `%s' instead of a symbol for macro name"
|
(% "received a `%s' instead of a symbol for macro name"
|
||||||
(. (type name)
|
(. (type name)
|
||||||
__name__)))))
|
__name__)))))
|
||||||
(for* [kw '[&kwonly &kwargs &key]]
|
(for* [kw '[&kwonly &kwargs]]
|
||||||
(if* (in kw lambda-list)
|
(if* (in kw lambda-list)
|
||||||
(raise (hy.errors.HyTypeError macro-name
|
(raise (hy.errors.HyTypeError macro-name
|
||||||
(% "macros cannot use %s"
|
(% "macros cannot use %s"
|
||||||
|
@ -396,8 +396,6 @@ def test_ast_non_decoratable():
|
|||||||
|
|
||||||
def test_ast_lambda_lists():
|
def test_ast_lambda_lists():
|
||||||
"""Ensure the compiler chokes on invalid lambda-lists"""
|
"""Ensure the compiler chokes on invalid lambda-lists"""
|
||||||
cant_compile('(fn [&key {"a" b} &key {"foo" bar}] [a foo])')
|
|
||||||
cant_compile('(fn [&optional a &key {"foo" bar}] [a foo])')
|
|
||||||
cant_compile('(fn [&optional [a b c]] a)')
|
cant_compile('(fn [&optional [a b c]] a)')
|
||||||
cant_compile('(fn [&optional [1 2]] (list 1 2))')
|
cant_compile('(fn [&optional [1 2]] (list 1 2))')
|
||||||
|
|
||||||
@ -427,13 +425,6 @@ def test_lambda_list_keywords_rest():
|
|||||||
can_compile("(fn (&optional a &rest xs) (print xs))")
|
can_compile("(fn (&optional a &rest xs) (print xs))")
|
||||||
|
|
||||||
|
|
||||||
def test_lambda_list_keywords_key():
|
|
||||||
""" Ensure we can compile functions with &key."""
|
|
||||||
can_compile("(fn (x &key {foo True}) (list x foo))")
|
|
||||||
cant_compile("(fn (x &key {bar \"baz\"} &key {foo 42}) (list x bar foo))")
|
|
||||||
cant_compile("(fn (x &key {1 2 3 4}) (list x))")
|
|
||||||
|
|
||||||
|
|
||||||
def test_lambda_list_keywords_kwargs():
|
def test_lambda_list_keywords_kwargs():
|
||||||
""" Ensure we can compile functions with &kwargs."""
|
""" Ensure we can compile functions with &kwargs."""
|
||||||
can_compile("(fn (x &kwargs kw) (list x kw))")
|
can_compile("(fn (x &kwargs kw) (list x kw))")
|
||||||
|
@ -295,19 +295,6 @@
|
|||||||
(assert (= (foo 10 20 30)
|
(assert (= (foo 10 20 30)
|
||||||
(, 10 20 30)))))
|
(, 10 20 30)))))
|
||||||
|
|
||||||
(defn test-let-key []
|
|
||||||
(let [a 1
|
|
||||||
b 6
|
|
||||||
d 2]
|
|
||||||
(defn foo [&key {a a b None c d}]
|
|
||||||
(, a b c))
|
|
||||||
(assert (= (foo)
|
|
||||||
(, 1 None 2)))
|
|
||||||
(assert (= (foo 10 20 30)
|
|
||||||
(, 10 20 30)))
|
|
||||||
(assert (= (, a b d)
|
|
||||||
(, 1 6 2)))))
|
|
||||||
|
|
||||||
(defn test-let-closure []
|
(defn test-let-closure []
|
||||||
(let [count 0]
|
(let [count 0]
|
||||||
(defn +count [&optional [x 1]]
|
(defn +count [&optional [x 1]]
|
||||||
|
@ -1374,14 +1374,6 @@
|
|||||||
(assert (= (foo 10 20 30) [10 (, 20 30) {}])))
|
(assert (= (foo 10 20 30) [10 (, 20 30) {}])))
|
||||||
|
|
||||||
|
|
||||||
(defn test-key-arguments []
|
|
||||||
"NATIVE: test &key function arguments"
|
|
||||||
(defn foo [&key {"a" None "b" 1}] [a b])
|
|
||||||
(assert (= (foo) [None 1]))
|
|
||||||
(assert (= (foo :a 2) [2 1]))
|
|
||||||
(assert (= (foo :b 42) [None 42])))
|
|
||||||
|
|
||||||
|
|
||||||
(defn test-optional-arguments []
|
(defn test-optional-arguments []
|
||||||
"NATIVE: test &optional function arguments"
|
"NATIVE: test &optional function arguments"
|
||||||
(defn foo [a b &optional c [d 42]] [a b c d])
|
(defn foo [a b &optional c [d 42]] [a b c d])
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
(foo x y))
|
(foo x y))
|
||||||
|
|
||||||
(defn test-macro-kw []
|
(defn test-macro-kw []
|
||||||
"NATIVE: test that an error is raised when &kwonly, &kwargs, or &key is used in a macro"
|
"NATIVE: test that an error is raised when &kwonly or &kwargs is used in a macro"
|
||||||
(try
|
(try
|
||||||
(eval '(defmacro f [&kwonly a b]))
|
(eval '(defmacro f [&kwonly a b]))
|
||||||
(except [e HyTypeError]
|
(except [e HyTypeError]
|
||||||
@ -72,12 +72,6 @@
|
|||||||
(eval '(defmacro f [&kwargs kw]))
|
(eval '(defmacro f [&kwargs kw]))
|
||||||
(except [e HyTypeError]
|
(except [e HyTypeError]
|
||||||
(assert (= e.message "macros cannot use &kwargs")))
|
(assert (= e.message "macros cannot use &kwargs")))
|
||||||
(else (assert False)))
|
|
||||||
|
|
||||||
(try
|
|
||||||
(eval '(defmacro f [&key {"kw" "xyz"}]))
|
|
||||||
(except [e HyTypeError]
|
|
||||||
(assert (= e.message "macros cannot use &key")))
|
|
||||||
(else (assert False))))
|
(else (assert False))))
|
||||||
|
|
||||||
(defn test-fn-calling-macro []
|
(defn test-fn-calling-macro []
|
||||||
|
Loading…
Reference in New Issue
Block a user