hylang / hy

A dialect of Lisp that's embedded in Python
http://hylang.org
Other
5.12k stars 373 forks source link

Tag #** not working in the keyword type argument #1351

Closed philoskim closed 7 years ago

philoskim commented 7 years ago

I got an error like this in 'hy 0.13.0+50.gd9a5acb using CPython(default) 3.5.3 on Linux'.

(defn total-purchase [price amount &optional [fees 1.05] [vat 1.1]]
  (* price amount fees vat))

(total-purchase #* [10 15] #** {"vat" 1.05})
; => 165.375

(total-purchase #* [10 15] #** {:vat 1.05})
; => Traceback (most recent call last):
;    File "/home/philos/.local/hy3/lib/python3.5/site-packages/hy/importer.py", line 201, in hy_eval
;      return eval(ast_compile(expr, "<eval>", "eval"), namespace)
;    File "<eval>", line 1, in <module>
; TypeError: total_purchase() got an unexpected keyword argument '﷐:vat'
refi64 commented 7 years ago
{:vat 1.05}

This doesn't do what you think it does!! Try running Hy with --spy and you'll see what I mean.

(But the short version is that :val in any context other than keyword arguments is compiled to \UNICODECHARCTERval, including here.)

gilch commented 7 years ago

Interestingly, this does work with symbols:

=> (total-purchase #* [10 15] #** {'vat 1.05})
165.375

If you were splicing into a function call in a quasiquote (like for a macro), then you do have to use keywords:

=> (eval `(total-purchase ~@[10 15 ':vat 1.05]))
165.375
Kodiologist commented 7 years ago

To be precise, both symbols and keywords are subclasses of str (or unicode) and hence can be used as keyword arguments, but the keyword :foo has the string value "\ufdd0:foo", not "foo". The reason that (total-purchase 10 15 :vat 1.05) works is that a literal keyword in a function call is magical: it compiles to a keyword argument (in the Python sense of the word "keyword"), and the leading "\ufdd0:" is stripped.