Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a macro for punning keyword arguments #1686

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ New Features
* Keyword objects (not just literal keywords) can be called, as
shorthand for `(get obj :key)`, and they accept a default value
as a second argument.
* Added a new core macro `pun`.

Bug Fixes
------------------------------
Expand Down
14 changes: 14 additions & 0 deletions docs/language/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,20 @@ print
.. note:: ``print`` always returns ``None``.


pun
---

The ``pun`` macro provides a shorthand for setting a keyword argument equal to
a variable of the same name. Any argument that's a literal keyword beginning
with a caret (``^``) is replaced, such that ``:^foo`` becomes ``:foo foo``, and
the result is an expression of all the arguments. For example, the following::

(pun dict :^monitor :^verbose :^cv-folds)

expands to::

(dict :monitor monitor :verbose verbose :cv-folds cv-folds)

quasiquote
----------

Expand Down
9 changes: 8 additions & 1 deletion hy/core/macros.hy
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
;;; These macros form the hy language
;;; They are automatically required in every module, except inside hy.core

(import [hy.models [HyList HySymbol]])
(import [hy.models [HyList HySymbol HyKeyword HyExpression]])

(defmacro as-> [head name &rest rest]
"Beginning with `head`, expand a sequence of assignments `rest` to `name`.
Expand Down Expand Up @@ -276,3 +276,10 @@ Such 'o!' params are available within `body` as the equivalent 'g!' symbol."
_hy_tag
[None]
['~symbol])))))


(defmacro pun [&rest body]
(HyExpression (reduce + (gfor x body
(if (and (keyword? x) (.startswith x.name "^"))
[(HyKeyword (cut x.name 1)) (HySymbol (cut x.name 1))]
[x])))))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This definition isn't indented properly. Make sure it passes parlinter.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I asked you to stop this. Twice. Then you insulted me about it. Please don't comment on my indentation again.

9 changes: 8 additions & 1 deletion tests/native_tests/native_macros.hy
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
;; This file is part of Hy, which is free software licensed under the Expat
;; license. See the LICENSE.

(import [hy.errors [HyTypeError]])
(import [tests.resources [kwtest]]
[hy.errors [HyTypeError]])

(defmacro rev [&rest body]
"Execute the `body` statements in reverse"
Expand Down Expand Up @@ -329,3 +330,9 @@
(except [e SystemExit]
(assert (= (str e) "42"))))
(setv --name-- oldname))

(defn test-pun []
(setv foo 15)
(assert (= (pun kwtest :^foo) {"foo" 15}))
(setv ^⁂ 16)
(assert (= (pun kwtest :^^⁂) {"hyx_Xcircumflex_accentXXasterismX" 16})))