Merge pull request #1588 from Kodiologist/no-amp-key

Remove &key
This commit is contained in:
Simon Gomizelj 2018-04-27 00:21:11 -04:00 committed by GitHub
commit 032247e380
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 7 additions and 109 deletions

View File

@ -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
------------------------------ ------------------------------

View File

@ -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.

View File

@ -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):

View File

@ -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:

View File

@ -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]

View File

@ -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"

View File

@ -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))")

View File

@ -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]]

View File

@ -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])

View File

@ -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 []