Skip to content
Merged
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
12 changes: 12 additions & 0 deletions NEWS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ Removals
------------------------------
* `defn/a+` has been removed. Use `(defn+ :async …)` instead.
* `fn/a+` has been removed. Use `(fn+ :async …)` instead.
* `profile/calls` has been removed. Use `pycallgraph2` or
`python-call-graph`, which are available on PyPI, instead.
* `profile/cpu` has been removed. Use `(with [pr (cProfile.Profile)]
…)` instead.

Other Breaking Changes
------------------------------
* `(with-gensyms [a b c] …)` is now written `(def-gensyms a b c) …`.
* The names of gensyms produced by `import-path` have changed. (This
shouldn't break your code unless you're doing something
exceptionally weird, but the argument to `hy.gensym` was documented,
so this is technically a breaking change.)

Bug Fixes
------------------------------
Expand Down
4 changes: 1 addition & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,13 @@ API
.. hy:automodule:: hyrule.macrotools

.. hy:autotag:: /
.. hy:automacro:: def-gensyms
.. hy:automacro:: defmacro-kwargs
.. hy:automacro:: defmacro!
.. hy:autofunction:: macroexpand-all
.. hy:autofunction:: map-hyseq
.. hy:autofunction:: map-model
.. hy:autofunction:: match-fn-params
.. hy:automacro:: with-gensyms

``oop`` — Tools for object-oriented programming
----------------------------------------------------------------------
Expand Down Expand Up @@ -144,8 +144,6 @@ API
.. hy:autofunction:: import-path
.. hy:automacro:: of
.. hy:autofunction:: parse-args
.. hy:automacro:: profile/calls
.. hy:automacro:: profile/cpu
.. hy:automacro:: pun
.. hy:autofunction:: sign
.. hy:automacro:: smacrolet
Expand Down
4 changes: 2 additions & 2 deletions hyrule/anaphoric.hy
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ easier to read. An anaphoric macro assigns values to designated symbols


(require
hyrule.macrotools [defmacro!]
hyrule.macrotools [defmacro! def-gensyms]
hyrule.argmove [->])


Expand Down Expand Up @@ -100,7 +100,7 @@ easier to read. An anaphoric macro assigns values to designated symbols
there is no such element. ::

(ap-last (> it 5) (range 10)) ; => 9"
(setv x (hy.gensym))
(def-gensyms x)
`(let [it None]
(setv ~x None)
(for [it ~xs :if ~form]
Expand Down
6 changes: 4 additions & 2 deletions hyrule/argmove.hy
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
also known as arrow macros."


(require
hyrule.macrotools [def-gensyms])
(import
hyrule.iterables [rest]
itertools [chain])
Expand Down Expand Up @@ -116,7 +118,7 @@ also known as arrow macros."
(.get {"a" 1 "b" 2} char))
(some-> "q" lookup (print "is the value"))
; Prints nothing, since `(lookup "q")` returns `None`.]]
(setv val (hy.gensym))
(def-gensyms val)
`(cond (is (setx ~val ~head) None) None
~@(chain.from_iterable (gfor node args
[`(is (setx ~val (hy.R.hyrule.-> ~val ~node)) None) None]))
Expand Down Expand Up @@ -144,7 +146,7 @@ also known as arrow macros."

(doto [] (.append 1) (.append 2) (.reverse)) ; => [2 1]"

(setv f (hy.gensym))
(def-gensyms f)
(defn build-form [expression]
(setv expression (_dotted expression))
(if (isinstance expression hy.models.Expression)
Expand Down
28 changes: 15 additions & 13 deletions hyrule/control.hy
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(require
hyrule.macrotools [defmacro!])
hyrule.macrotools [defmacro! def-gensyms])
(import
hyrule.collections [by2s]
hyrule.iterables [coll?]
Expand Down Expand Up @@ -123,7 +123,7 @@
; the key exactly once.
(when (% (len rest) 2)
(raise (TypeError "each test-form needs a result-form")))
(setv x (hy.gensym "case-key"))
(def-gensyms x)
`(do
(setv ~x ~key)
(cond ~@(sum
Expand All @@ -147,7 +147,7 @@


(defn _do-n [count-form body]
(setv count (hy.gensym))
(def-gensyms count)
`(do
(setv ~count ~count-form)
(for [~(hy.gensym)
Expand Down Expand Up @@ -179,21 +179,20 @@
``sys.argv`` is always the name of the script being invoked, whereas the rest
are command-line arguments. If ``args`` is ``[]``, this will be treated like
``[#* _]``, so any command-line arguments (and the script name) will be
allowed, but ignored.
allowed, but ignored. ::

(defmain [program-name argument]
(print "Welcome to" program-name)
(print "The answer is" (* (float argument) 2)))

If the defined function returns an :class:`int`, :func:`sys.exit` is called
with that integer as the return code.

If you want fancy command-line arguments, you can use the standard Python
module :mod:`argparse` in the usual way, because ``defmain`` doesn't change
``sys.argv``. See also :hy:func:`parse-args`. ::
``sys.argv``. See also :hy:func:`parse-args`.]]

(defmain [program-name argument]
(print "Welcome to" program-name)
(print "The answer is" (* (float argument) 2)))]]

(setv retval (hy.gensym)
restval (hy.gensym))
(def-gensyms retval restval)
`(when (= __name__ "__main__")
(import sys)
(setv ~retval ((fn [~@(or args `[#* ~restval])] ~@body) #* sys.argv))
Expand Down Expand Up @@ -247,7 +246,7 @@

(setv counter 0)
(list-n 5 (+= counter 1) counter) ; => [1 2 3 4 5]"
(setv l (hy.gensym))
(def-gensyms l)
`(do
(setv ~l [])
~(_do-n count-form [`(.append ~l (do ~@body))])
Expand All @@ -264,13 +263,16 @@

With ``loop``, this would be written as::

(require hyrule [loop])
(import hyrule [recur])

(defn factorial [n]
(loop [[n n] [acc 1]]
(if n
(recur (- n 1) (* acc n))
acc)))

Don't forget to ``(import hyrule [recur])``. The :hy:class:`recur` object holds the arguments for the next call. When the function returns a :hy:class:`recur`, ``loop`` calls it again with the new arguments. Otherwise, ``loop`` ends and the final value is returned. Thus, what would be a nested set of recursive calls becomes a series of calls that are resolved entirely in sequence.
The :hy:class:`recur` object holds the arguments for the next call. When the function returns a :hy:class:`recur`, ``loop`` calls it again with the new arguments. Otherwise, ``loop`` ends and the final value is returned. Thus, what would be a nested set of recursive calls becomes a series of calls that are resolved entirely in sequence.

Note that while ``loop`` uses the same syntax as ordinary function definitions for its lambda list, all parameters other than ``#* args`` and ``#** kwargs`` must have a default value, because the function will first be called with no arguments."

Expand Down
19 changes: 9 additions & 10 deletions hyrule/destructure.hy
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Iterator patterns are specified with a :class:`hy.models.Expression`. They work
(require
hyrule.argmove [->>]
hyrule.control [unless branch]
hyrule.macrotools [defmacro!])
hyrule.macrotools [defmacro! def-gensyms])
(import
itertools [starmap chain count]
functools [reduce]
Expand Down Expand Up @@ -158,8 +158,8 @@ Take pairs of destructuring patterns and input data structures, and return a dic
{"apple" 1 "banana" 2})
; => {'a 1 'b 2}]]

(setv gsyms []
result (hy.gensym 'dict=:))
(setv gsyms [])
(def-gensyms result)
`(do
(setv ~result {}
~@(gfor [binds expr] (by2s pairs)
Expand All @@ -184,8 +184,8 @@ Take pairs of destructuring patterns and input data structures, and return a dic
and :as must be last, if present.
"
(defn dispatch [f]
(setv dcoll (hy.gensym f.__name__)
result [dcoll expr]
(def-gensyms dcoll)
(setv result [dcoll expr]
seen #{})
(defn found [magic target]
(when (= magic target)
Expand Down Expand Up @@ -320,9 +320,8 @@ Take pairs of destructuring patterns and input data structures, and return a dic
``itertools.tee`` to ``foo``.
For example, try ``(destructure '(a b c :& more :as it) (count))``.
"
(setv [bs magics] (find-magics binds)
copy-iter (hy.gensym)
tee (hy.gensym))
(setv [bs magics] (find-magics binds))
(def-gensyms copy-iter tee)
(if (in ':as (sfor [x #* _] magics x))
(.extend result [diter `(do
(import itertools [tee :as ~tee])
Expand All @@ -345,7 +344,7 @@ Take pairs of destructuring patterns and input data structures, and return a dic
s)))))

(defmacro defn+ [#* args]
"As :hy:func:`defn`, but the lambda list is destructured as a list pattern. The usual special parameter names in lambda lists, such as `#*`, aren't special here. No type annotations are allowed are in the lambda list, but a return-value annotation for the whole function is allowed."
"As :hy:func:`defn`, but the lambda list is destructured as a list pattern. The usual special parameter names in lambda lists, such as ``#*``, aren't special here. No type annotations are allowed are in the lambda list, but a return-value annotation for the whole function is allowed."
(destructuring-fn 'defn args))

(defmacro fn+ [#* args]
Expand All @@ -354,7 +353,7 @@ Take pairs of destructuring patterns and input data structures, and return a dic

(defn destructuring-fn [like args]
(setv [headers params doc body] (parse-defn-like like args))
(setv args (hy.gensym) kwargs (hy.gensym))
(def-gensyms args kwargs)
`(~@headers [#* ~args #** ~kwargs]
~doc
~(_expanded-setv params args kwargs)
Expand Down
10 changes: 5 additions & 5 deletions hyrule/iterables.hy
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

(defn coll? [x]
#[[Return ``True`` if ``x`` inherits from :class:`collections.abc.Iterable`
but not ``str`` or ``bytes``. ::
but not :class:`str` or :class:`bytes`. ::

(coll? ["abc"]) ; True
(coll? {"a" 1 "b" 2}) ; True
Expand All @@ -29,7 +29,7 @@
(defn distinct [coll]
"Return an iterator from the original iterable ``coll`` with no
duplicates. Duplicates are detected by calling :hy:func:`in
<hy.pyops.in>` on a :class:`set`. Elements will be produced in order
<hy.pyops.in>` on a :class:`set`. Elements are produced in order
of their first appearance in ``coll``. ::

(list (distinct [1 2 3 4 3 5 0 2])) ; => [1 2 3 4 5 0]"
Expand Down Expand Up @@ -95,11 +95,11 @@
arguments as ``range``, but includes the endpoint (given a
compatible start point and step size). ::

(thru 3)
(list (thru 3))
; => [0 1 2 3]
(thru 0 10 2)
(list (thru 0 10 2))
; => [0 2 4 6 8 10]
(thru 0 9 2)
(list (thru 0 9 2))
; => [0 2 4 6 8]"

(when (is b None)
Expand Down
60 changes: 28 additions & 32 deletions hyrule/macrotools.hy
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@
hyrule.iterables [coll? flatten])


(defmacro def-gensyms [#* symbols]

#[[Define a number of gensyms, binding each symbol to a call to
:hy:func:`hy.gensym`. The syntax ::

(def-gensyms a b c)

is equivalent to ::

(setv
a (hy.gensym 'a)
b (hy.gensym 'b)
c (hy.gensym 'c))]]

`(setv ~@(gfor
sym symbols
x [sym `(hy.gensym '~sym)]
x)))


(defmacro defmacro-kwargs [name params #* body]

#[=[Define a macro that can take keyword arguments. When the macro
Expand All @@ -12,7 +32,7 @@
local variables that can be used in the macro body. ::

(defmacro-kwargs do10times [form [print-iteration 'False]]
(setv i (hy.gensym))
(def-gensyms i)
`(for [~i (range 10)]
(when ~print-iteration
(print "Now on iteration:" ~i))
Expand All @@ -31,7 +51,7 @@
(setv docstring None)
(when (and body (isinstance (get body 0) hy.models.String))
(setv [docstring #* body] body))
(setv g (hy.gensym))
(def-gensyms g)
`(defmacro ~name [#* ~g]
~@(if docstring [docstring] [])
(setv ~g (hy.I.hyrule.match-fn-params ~g '~params))
Expand All @@ -45,11 +65,11 @@

(defn match-fn-params [args params]
#[[Match an iterable of arguments against a parameter list in the
style of a :hy:func:`defn` lambda list. The parameter-list syntax
here is somewhat restricted: annotations are forbiddden, ``/`` and
``*`` aren't recognized, and nothing is allowed after ``#* args``
other than ``#** kwargs``. Return a dictionary of the parameters and
their values. ::
style of a :hy:func:`defn` lambda list. Return a dictionary of the
parameters and their values. The parameter-list syntax here is
somewhat restricted: annotations are forbiddden, ``/`` and ``*``
aren't recognized, and nothing is allowed after ``#* args`` other
than ``#** kwargs``. ::

(match-fn-params
[1 :foo "x"]
Expand Down Expand Up @@ -298,7 +318,7 @@
(+= FOO (ABS -5)))
(print foo) ; => 20

That's why the parameters of ``map-model`` are backwards compared to ``map``: in user code, ``x`` is typically a symbol or other simple form whereas ``f`` is a multi-line anonymous function.]]
That's why the parameters of ``map-model`` are backwards compared to :func:`map`: in user code, ``x`` is typically a symbol or other simple form whereas ``f`` is a multi-line anonymous function.]]

(_map-model (hy.as-model x) f))

Expand Down Expand Up @@ -333,30 +353,6 @@
x))


(defmacro with-gensyms [args #* body]

#[[Evaluate ``body`` with each name in ``args`` (a list of symbols) bound to
a gensym. The syntax ::

(with-gensyms [a b c]
…)

is equivalent to ::

(do
(setv a (hy.gensym 'a))
(setv b (hy.gensym 'b))
(setv c (hy.gensym 'c))
…)]]

(setv syms [])
(for [arg args]
(.extend syms [arg `(hy.gensym '~arg)]))
`(do
(setv ~@syms)
~@body))


(defreader /

#[[Read one identifier and interpret it as a one-shot import in the same
Expand Down
Loading