generalize #% to arbitrary expressions
This commit is contained in:
parent
b5f1136ba5
commit
497e929913
2
NEWS
2
NEWS
@ -23,7 +23,7 @@ Changes from 0.13.0
|
|||||||
* `return` has been implemented as a special form
|
* `return` has been implemented as a special form
|
||||||
* `while` loops may now contain an `else` clause, like `for` loops
|
* `while` loops may now contain an `else` clause, like `for` loops
|
||||||
* `xi` from `hy.extra.anaphoric` is now the `#%` tag macro
|
* `xi` from `hy.extra.anaphoric` is now the `#%` tag macro
|
||||||
* `#%` also has a new `&kwargs` parameter `%**`.
|
* `#%` works on any expression and has a new `&kwargs` parameter `%**`
|
||||||
|
|
||||||
[ Bug Fixes ]
|
[ Bug Fixes ]
|
||||||
* Numeric literals are no longer parsed as symbols when followed by a dot
|
* Numeric literals are no longer parsed as symbols when followed by a dot
|
||||||
|
@ -234,20 +234,32 @@ Returns a function which applies several forms in series from left to right. The
|
|||||||
#%
|
#%
|
||||||
==
|
==
|
||||||
|
|
||||||
Usage ``#%(body ...)``
|
Usage ``#% expr``
|
||||||
|
|
||||||
Makes a function with an implicit parameter list from ``%`` parameters.
|
Makes an expression into a function with an implicit ``%`` parameter list.
|
||||||
|
|
||||||
A ``%i`` symbol designates the `i` th parameter (1-based, e.g. ``%1 %2 %3`` etc.).
|
A ``%i`` symbol designates the (1-based) *i* th parameter (such as ``%3``).
|
||||||
|
Only the maximum ``%i`` determines the number of ``%i`` parameters--the
|
||||||
|
others need not appear in the expression.
|
||||||
``%*`` and ``%**`` name the ``&rest`` and ``&kwargs`` parameters, respectively.
|
``%*`` and ``%**`` name the ``&rest`` and ``&kwargs`` parameters, respectively.
|
||||||
Nesting of ``#%()`` forms is not recommended.
|
|
||||||
|
|
||||||
This is similar to Clojure's anonymous function literals (``#()``).
|
|
||||||
|
|
||||||
.. code-block:: hy
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (#%(identity [%1 %5 [%2 %3] %* %4]) 1 2 3 4 5 6 7 8)
|
=> (#%[%1 %6 42 [%2 %3] %* %4] 1 2 3 4 555 6 7 8)
|
||||||
[1, 5, [2, 3,] (6, 7, 8), 4]
|
[1, 6, 42, [2, 3], (7, 8), 4]
|
||||||
=> (def add-10 #%(+ 10 %1))
|
=> (#% %** :foo 2)
|
||||||
=> (add-10 6)
|
{"foo": 2}
|
||||||
16
|
|
||||||
|
When used on an s-expression,
|
||||||
|
``#%`` is similar to Clojure's anonymous function literals--``#()``.
|
||||||
|
|
||||||
|
.. code-block:: hy
|
||||||
|
|
||||||
|
=> (setv add-10 #%(+ 10 %1))
|
||||||
|
=> (add-10 6)
|
||||||
|
16
|
||||||
|
|
||||||
|
``#%`` determines the parameter list by the presence of a ``%*`` or ``%**``
|
||||||
|
symbol and by the maximum ``%i`` symbol found *anywhere* in the expression,
|
||||||
|
so nesting of ``#%`` forms is not recommended.
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
;;; These macros make writing functional programs more concise
|
;;; These macros make writing functional programs more concise
|
||||||
|
|
||||||
|
|
||||||
(defmacro ap-if [test-form then-form &optional else-form]
|
(defmacro ap-if [test-form then-form &optional else-form]
|
||||||
`(do
|
`(do
|
||||||
(setv it ~test-form)
|
(setv it ~test-form)
|
||||||
@ -112,29 +111,32 @@
|
|||||||
"Returns a function which is the composition of several forms."
|
"Returns a function which is the composition of several forms."
|
||||||
`(fn [var] (ap-pipe var ~@forms)))
|
`(fn [var] (ap-pipe var ~@forms)))
|
||||||
|
|
||||||
(deftag % [body]
|
(deftag % [expr]
|
||||||
"makes a function with an implicit parameter list from `%` parameters.
|
"Makes an expression into a function with an implicit `%` parameter list.
|
||||||
|
|
||||||
A %i symbol designates the ith parameter (1-based, e.g. `%1 %2 %3` etc.).
|
A `%i` symbol designates the (1-based) ith parameter (such as `%3`).
|
||||||
|
Only the maximum `%i` determines the number of `%i` parameters--the
|
||||||
|
others need not appear in the expression.
|
||||||
`%*` and `%**` name the `&rest` and `&kwargs` parameters, respectively.
|
`%*` and `%**` name the `&rest` and `&kwargs` parameters, respectively.
|
||||||
Nesting of `#%()` forms is not recommended."
|
|
||||||
(setv flatbody (flatten body))
|
Nesting of `#%` forms is not recommended."
|
||||||
`(fn [;; generate all %i symbols up to the maximum found in body
|
(setv %symbols (set-comp a
|
||||||
~@(genexpr (HySymbol (+ "%"
|
[a (flatten [expr])]
|
||||||
(str i)))
|
(and (symbol? a)
|
||||||
[i (range 1
|
(.startswith a '%))))
|
||||||
;; find the maximum %i
|
`(fn [;; generate all %i symbols up to the maximum found in expr
|
||||||
(-> (list-comp (int (cut a 1))
|
~@(genexpr (HySymbol (+ "%" (str i)))
|
||||||
[a flatbody]
|
[i (range 1 (-> (list-comp (int (cut a 1))
|
||||||
(and (symbol? a)
|
[a %symbols]
|
||||||
(.startswith a '%)
|
(.isdigit (cut a 1)))
|
||||||
(.isdigit (cut a 1))))
|
(or (, 0))
|
||||||
(+ [0])
|
max
|
||||||
max
|
inc))])
|
||||||
inc))])
|
;; generate the &rest parameter only if '%* is present in expr
|
||||||
;; generate the &rest parameter only if '%* is present in body
|
~@(if (in '%* %symbols)
|
||||||
~@(if (in '%* flatbody)
|
|
||||||
'(&rest %*))
|
'(&rest %*))
|
||||||
~@(if (in '%** flatbody)
|
;; similarly for &kwargs and %**
|
||||||
|
~@(if (in '%** %symbols)
|
||||||
'(&kwargs %**))]
|
'(&kwargs %**))]
|
||||||
(~@body)))
|
~expr))
|
||||||
|
|
||||||
|
@ -127,4 +127,18 @@
|
|||||||
;; test &rest &kwargs
|
;; test &rest &kwargs
|
||||||
(assert-equal (#%(, %* %**) 1 2 :a 'b)
|
(assert-equal (#%(, %* %**) 1 2 :a 'b)
|
||||||
(, (, 1 2)
|
(, (, 1 2)
|
||||||
(dict :a 'b))))
|
(dict :a 'b)))
|
||||||
|
;; test other expression types
|
||||||
|
(assert-equal (#% %* 1 2 3)
|
||||||
|
(, 1 2 3))
|
||||||
|
(assert-equal (#% %** :foo 2)
|
||||||
|
(dict :foo 2))
|
||||||
|
(assert-equal (#%[%3 %2 %1] 1 2 3)
|
||||||
|
[3 2 1])
|
||||||
|
(assert-equal (#%{%1 %2} 10 100)
|
||||||
|
{10 100})
|
||||||
|
(assert-equal (#% #{%3 %2 %1} 1 3 2)
|
||||||
|
#{3 1 2}) ; sets are not ordered.
|
||||||
|
(assert-equal (#% "%1")
|
||||||
|
"%1"))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user