Teach apply about symbol mangling
apply now mangles strings and keywords according to the Hy mangling rules (by using the same function, now imported from hy.lex.parser). With this change, if the dict passed to apply has keywords, strings or quoted symbols, they'll get mangled, to turn them into proper keys. This only works for the cases where the keys are directly in the apply params. A previously deffed dict, or key through a variable will not be mangled. This closes #219. Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
This commit is contained in:
parent
b1f497ae72
commit
26f342d580
@ -115,8 +115,10 @@ it appends it as the last argument. The following code demonstrates this:
|
|||||||
apply
|
apply
|
||||||
-----
|
-----
|
||||||
|
|
||||||
``apply`` is used to apply an optional list of arguments and an optional
|
``apply`` is used to apply an optional list of arguments and an
|
||||||
dictionary of kwargs to a function.
|
optional dictionary of kwargs to a function. The symbol mangling
|
||||||
|
transformations will be applied to all keys in the dictionary of
|
||||||
|
kwargs, provided the dictionary and its keys are defined in-place.
|
||||||
|
|
||||||
Usage: ``(apply fn-name [args] [kwargs])``
|
Usage: ``(apply fn-name [args] [kwargs])``
|
||||||
|
|
||||||
@ -142,6 +144,8 @@ Examples:
|
|||||||
(apply total-purchase [] {"price" 10 "amount" 15 "vat" 1.05})
|
(apply total-purchase [] {"price" 10 "amount" 15 "vat" 1.05})
|
||||||
;=> 165.375
|
;=> 165.375
|
||||||
|
|
||||||
|
(apply total-purchase [] {:price 10 :amount 15 :vat 1.05})
|
||||||
|
;=> 165.375
|
||||||
|
|
||||||
and
|
and
|
||||||
---
|
---
|
||||||
|
@ -38,6 +38,8 @@ from hy.models.cons import HyCons
|
|||||||
|
|
||||||
from hy.errors import HyCompileError, HyTypeError
|
from hy.errors import HyCompileError, HyTypeError
|
||||||
|
|
||||||
|
from hy.lex.parser import hy_symbol_mangle
|
||||||
|
|
||||||
import hy.macros
|
import hy.macros
|
||||||
from hy._compat import (
|
from hy._compat import (
|
||||||
str_type, long_type, PY27, PY33, PY3, PY34, PY35, raise_empty)
|
str_type, long_type, PY27, PY33, PY3, PY34, PY35, raise_empty)
|
||||||
@ -1640,7 +1642,21 @@ class HyASTCompiler(object):
|
|||||||
ret = stargs + ret
|
ret = stargs + ret
|
||||||
|
|
||||||
if expr:
|
if expr:
|
||||||
kwargs = self.compile(expr.pop(0))
|
kwargs = expr.pop(0)
|
||||||
|
if isinstance(kwargs, HyDict):
|
||||||
|
new_kwargs = []
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
if isinstance(k, HySymbol):
|
||||||
|
pass
|
||||||
|
elif isinstance(k, HyString):
|
||||||
|
k = HyString(hy_symbol_mangle(str_type(k))).replace(k)
|
||||||
|
elif isinstance(k, HyKeyword):
|
||||||
|
sym = hy_symbol_mangle(str_type(k)[2:])
|
||||||
|
k = HyString(sym).replace(k)
|
||||||
|
new_kwargs += [k, v]
|
||||||
|
kwargs = HyDict(new_kwargs).replace(kwargs)
|
||||||
|
|
||||||
|
kwargs = self.compile(kwargs)
|
||||||
if PY35:
|
if PY35:
|
||||||
kwargs_expr = kwargs.force_expr
|
kwargs_expr = kwargs.force_expr
|
||||||
ret.expr.keywords.append(
|
ret.expr.keywords.append(
|
||||||
|
@ -45,6 +45,22 @@ pg = ParserGenerator(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def hy_symbol_mangle(p):
|
||||||
|
if p.startswith("*") and p.endswith("*") and p not in ("*", "**"):
|
||||||
|
p = p[1:-1].upper()
|
||||||
|
|
||||||
|
if "-" in p and p != "-":
|
||||||
|
p = p.replace("-", "_")
|
||||||
|
|
||||||
|
if p.endswith("?") and p != "?":
|
||||||
|
p = "is_%s" % (p[:-1])
|
||||||
|
|
||||||
|
if p.endswith("!") and p != "!":
|
||||||
|
p = "%s_bang" % (p[:-1])
|
||||||
|
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
def set_boundaries(fun):
|
def set_boundaries(fun):
|
||||||
@wraps(fun)
|
@wraps(fun)
|
||||||
def wrapped(p):
|
def wrapped(p):
|
||||||
@ -297,22 +313,7 @@ def t_identifier(p):
|
|||||||
if obj.startswith(":"):
|
if obj.startswith(":"):
|
||||||
return HyKeyword(obj)
|
return HyKeyword(obj)
|
||||||
|
|
||||||
def mangle(p):
|
obj = ".".join([hy_symbol_mangle(part) for part in obj.split(".")])
|
||||||
if p.startswith("*") and p.endswith("*") and p not in ("*", "**"):
|
|
||||||
p = p[1:-1].upper()
|
|
||||||
|
|
||||||
if "-" in p and p != "-":
|
|
||||||
p = p.replace("-", "_")
|
|
||||||
|
|
||||||
if p.endswith("?") and p != "?":
|
|
||||||
p = "is_%s" % (p[:-1])
|
|
||||||
|
|
||||||
if p.endswith("!") and p != "!":
|
|
||||||
p = "%s_bang" % (p[:-1])
|
|
||||||
|
|
||||||
return p
|
|
||||||
|
|
||||||
obj = ".".join([mangle(part) for part in obj.split(".")])
|
|
||||||
|
|
||||||
return HySymbol(obj)
|
return HySymbol(obj)
|
||||||
|
|
||||||
|
@ -309,7 +309,10 @@
|
|||||||
(assert (= (apply sumit [] {"a" 1 "b" 1 "c" 2}) 4))
|
(assert (= (apply sumit [] {"a" 1 "b" 1 "c" 2}) 4))
|
||||||
(assert (= (apply sumit ((fn [] [1 1])) {"c" 1}) 3))
|
(assert (= (apply sumit ((fn [] [1 1])) {"c" 1}) 3))
|
||||||
(defn noargs [] [1 2 3])
|
(defn noargs [] [1 2 3])
|
||||||
(assert (= (apply noargs) [1 2 3])))
|
(assert (= (apply noargs) [1 2 3]))
|
||||||
|
(defn sumit-mangle [an-a a-b a-c a-d] (+ an-a a-b a-c a-d))
|
||||||
|
(def Z "a_d")
|
||||||
|
(assert (= (apply sumit-mangle [] {"an-a" 1 :a-b 2 'a-c 3 Z 4}) 10)))
|
||||||
|
|
||||||
|
|
||||||
(defn test-apply-with-methods []
|
(defn test-apply-with-methods []
|
||||||
|
Loading…
x
Reference in New Issue
Block a user