Skip to content

Commit

Permalink
Merge pull request #2533 from Kodiologist/docs
Browse files Browse the repository at this point in the history
Documentation improvements
  • Loading branch information
Kodiologist committed Nov 28, 2023
2 parents 408cc75 + 8a45c6a commit 1e5d503
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 15 deletions.
30 changes: 20 additions & 10 deletions docs/macros.rst
Expand Up @@ -156,22 +156,32 @@ Ultimately it's wisest to use only four kinds of names in macro expansions: gens
Reader macros
-------------

Reader macros allow you to hook directly into Hy's parser to customize how text is parsed into models. They're defined with :hy:func:`defreader`, or, like regular macros, brought in from other modules with :hy:func:`require`. Rather than receiving function arguments, a reader macro has access to a :py:class:`HyReader <hy.reader.hy_reader.HyReader>` object named ``&reader``, which provides all the text-parsing logic that Hy uses to parse itself (see :py:class:`HyReader <hy.reader.hy_reader.HyReader>` and its base class :py:class:`Reader <hy.reader.reader.Reader>` for the available methods). A reader macro is called with the hash sign ``#``, and like a regular macro, it should return a model or something convertible to a model. ::
Reader macros allow you to hook directly into Hy's parser to customize how text is parsed into models. They're defined with :hy:func:`defreader`, or, like regular macros, brought in from other modules with :hy:func:`require`. Rather than receiving function arguments, a reader macro has access to a :py:class:`HyReader <hy.reader.hy_reader.HyReader>` object named ``&reader``, which provides all the text-parsing logic that Hy uses to parse itself (see :py:class:`HyReader <hy.reader.hy_reader.HyReader>` and its base class :py:class:`Reader <hy.reader.reader.Reader>` for the available methods). A reader macro is called with the hash sign ``#``, and like a regular macro, it should return a model or something convertible to a model.

Here's a moderately complex example of a reader macro that couldn't be implemented as a regular macro. It reads in a list of lists in which the inner lists are newline-separated, but newlines are allowed inside elements. ::

(defreader matrix
(.slurp-space &reader)
(setv start (.getc &reader))
(assert (= start "["))
(.slurp-space &reader)
(setv out [[]])
(while (not (do (.slurp-space &reader) (.peek-and-getc &reader "]")))
(setv x (.parse-one-form &reader))
(if (= x '|)
(.append out [])
(.append (get out -1) x)))
(if (= out [[]]) [] out))

(print (hy.repr #matrix [1 2 3 | 4 5 6 | 7 8 9]))
; => [[1 2 3] [4 5 6] [7 8 9]]
(while (not (.peek-and-getc &reader "]"))
(cond
(any (gfor c " \t" (.peek-and-getc &reader c)))
None
(.peek-and-getc &reader "\n")
(.append out [])
True
(.append (get out -1) (.parse-one-form &reader))))
(lfor line out :if line line))

(print (hy.repr #matrix [
1 (+ 1 1) 3
4 ["element" "containing"
"a" "newline"] 6
7 8 9]))
; => [[1 2 3] [4 ["element" "containing" "a" "newline"] 6] [7 8 9]]

Note that because reader macros are evaluated at parse-time, and top-level forms are completely parsed before any further compile-time execution occurs, you can't use a reader macro in the same top-level form that defines it::

Expand Down
22 changes: 17 additions & 5 deletions docs/whyhy.rst
Expand Up @@ -150,8 +150,20 @@ aforementioned mixing of statements and expressions, :ref:`name mangling
Python-legal identifiers, and a :hy:func:`let` macro to provide block-level scoping
in place of Python's usual function-level scoping.

Overall, Hy, like Common Lisp, is intended to be an unopinionated big-tent
language that lets you do what you want. If you're interested in a more
small-and-beautiful approach to Lisp, in the style of Scheme, check out
`Hissp <https://github.com/gilch/hissp>`_, another Lisp embedded in Python
that was created by a Hy developer.

What Hy is not
--------------

Hy isn't minimal or elegant. Hy is big and ugly and proud of it; it's an
unopinionated big-tent language that lets you do what you want. It has all
of Python's least-motivated semantic features, plus more features, plus
various kinds of syntactic sugar. (The syntax isn't as complex as
Python's, but there are a lot of details beyond plain old S-expressions.)
If you're interested in a more small-and-beautiful approach to Lisp, in
the style of Scheme, check out `Hissp <https://github.com/gilch/hissp>`_,
another Lisp embedded in Python that was created by a Hy developer.

Also, Hy isn't a reimplementation of an older Lisp. It is its own
language. It looks kind of like Clojure and kind of like Common Lisp, but
nontrivial programs that run in one of these langauges can't be expected
to run on another unaltered.

0 comments on commit 1e5d503

Please sign in to comment.