change xi macro to #% tag macro

This commit is contained in:
gilch 2017-10-22 19:53:05 -06:00
parent 2319adcc7f
commit f81fb771eb
4 changed files with 39 additions and 35 deletions

1
NEWS
View File

@ -22,6 +22,7 @@ Changes from 0.13.0
* support EDN `#_` syntax to discard the next term
* `return` has been implemented as a special form
* `while` loops may now contain an `else` clause, like `for` loops
* `xi` from `hy.extra.anaphoric` is now the `#%` tag macro.
[ Bug Fixes ]
* Numeric literals are no longer parsed as symbols when followed by a dot

View File

@ -229,21 +229,24 @@ Returns a function which applies several forms in series from left to right. The
=> (op 2)
9
.. _xi
.. _#%
xi
#%
==
Usage ``(xi body ...)``
Usage ``#%(body ...)``
Returns a function with parameters implicitly determined by the presence in the body of xi parameters. An xi symbol designates the ith parameter (1-based, e.g. x1, x2, x3, etc.), or all remaining parameters for xi itself. This is not a replacement for fn. The xi forms cannot be nested.
Returns a function with parameters implicitly determined by the presence in
the body of %i parameters. A %i symbol designates the ith parameter
(1-based, e.g. ``%1 %2 %3`` etc.), or all remaining parameters for ``%&``.
Nesting of ``#%()`` forms is not recommended.
This is similar to Clojure's anonymous function literals (``#()``).
.. code-block:: hy
=> ((xi identity [x1 x5 [x2 x3] xi x4]) 1 2 3 4 5 6 7 8)
=> (#%(identity [%1 %5 [%2 %3] %& %4]) 1 2 3 4 5 6 7 8)
[1, 5, [2, 3,] (6, 7, 8), 4]
=> (def add-10 (xi + 10 x1))
=> (def add-10 #%(+ 10 %1))
=> (add-10 6)
16

View File

@ -112,25 +112,25 @@
"Returns a function which is the composition of several forms."
`(fn [var] (ap-pipe var ~@forms)))
(defmacro xi [&rest body]
(deftag % [body]
"Returns a function with parameters implicitly determined by the presence in
the body of xi parameters. An xi symbol designates the ith parameter
(1-based, e.g. x1, x2, x3, etc.), or all remaining parameters for xi itself.
This is not a replacement for fn. The xi forms cannot be nested. "
the body of %i parameters. A %i symbol designates the ith parameter
(1-based, e.g. %1, %2, %3, etc.), or all remaining parameters for %&.
Nesting of #%() forms is not recommended."
(setv flatbody (flatten body))
`(fn [;; generate all xi symbols up to the maximum found in body
~@(genexpr (HySymbol (+ "x"
`(fn [;; generate all %i symbols up to the maximum found in body
~@(genexpr (HySymbol (+ "%"
(str i)))
[i (range 1
;; find the maximum xi
;; find the maximum %i
(inc (max (+ (list-comp (int (cut a 1))
[a flatbody]
(and (symbol? a)
(.startswith a 'x)
(.startswith a '%)
(.isdigit (cut a 1))))
[0]))))])
;; generate the &rest parameter only if 'xi is present in body
~@(if (in 'xi flatbody)
'(&rest xi)
;; generate the &rest parameter only if '%& is present in body
~@(if (in '%& flatbody)
'(&rest %&)
'())]
(~@body)))

View File

@ -99,28 +99,28 @@
(assert-equal ((ap-compose (+ it 1) (* it 3)) 2) 9)
(assert-equal ((ap-compose (list (rest it)) (len it)) [4 5 6 7]) 3))
(defn test-xi []
"NATIVE: testing xi forms"
(defn test-tag-fn []
"NATIVE: testing #%() forms"
;; test ordering
(assert-equal ((xi / x1 x2) 2 4) 0.5)
(assert-equal ((xi / x2 x1) 2 4) 2)
(assert-equal ((xi identity (, x5 x4 x3 x2 x1)) 1 2 3 4 5) (, 5 4 3 2 1))
(assert-equal ((xi identity (, x1 x2 x3 x4 x5)) 1 2 3 4 5) (, 1 2 3 4 5))
(assert-equal ((xi identity (, x1 x5 x2 x3 x4)) 1 2 3 4 5) (, 1 5 2 3 4))
(assert-equal (#%(/ %1 %2) 2 4) 0.5)
(assert-equal (#%(/ %2 %1) 2 4) 2)
(assert-equal (#%(identity (, %5 %4 %3 %2 %1)) 1 2 3 4 5) (, 5 4 3 2 1))
(assert-equal (#%(identity (, %1 %2 %3 %4 %5)) 1 2 3 4 5) (, 1 2 3 4 5))
(assert-equal (#%(identity (, %1 %5 %2 %3 %4)) 1 2 3 4 5) (, 1 5 2 3 4))
;; test &rest
(assert-equal ((xi sum xi) 1 2 3) 6)
(assert-equal ((xi identity (, x1 xi)) 10 1 2 3) (, 10 (, 1 2 3)))
(assert-equal (#%(sum %&) 1 2 3) 6)
(assert-equal (#%(identity (, %1 %&)) 10 1 2 3) (, 10 (, 1 2 3)))
;; no parameters
(assert-equal ((xi list)) [])
(assert-equal ((xi identity "Hy!")) "Hy!")
(assert-equal ((xi identity "xi")) "xi")
(assert-equal ((xi + "Hy " "world!")) "Hy world!")
(assert-equal (#%(list)) [])
(assert-equal (#%(identity "Hy!")) "Hy!")
(assert-equal (#%(identity "%&")) "%&")
(assert-equal (#%(+ "Hy " "world!")) "Hy world!")
;; test skipped parameters
(assert-equal ((xi identity [x3 x1]) 1 2 3) [3 1])
(assert-equal (#%(identity [%3 %1]) 1 2 3) [3 1])
;; test nesting
(assert-equal ((xi identity [x1 (, x2 [x3] "Hy" [xi])]) 1 2 3 4 5)
(assert-equal (#%(identity [%1 (, %2 [%3] "Hy" [%&])]) 1 2 3 4 5)
[1 (, 2 [3] "Hy" [(, 4 5)])])
;; test arg as function
(assert-equal ((xi x1 2 4) +) 6)
(assert-equal ((xi x1 2 4) -) -2)
(assert-equal ((xi x1 2 4) /) 0.5))
(assert-equal (#%(%1 2 4) +) 6)
(assert-equal (#%(%1 2 4) -) -2)
(assert-equal (#%(%1 2 4) /) 0.5))