Skip to content

Commit

Permalink
Avoid extra calls to hy.as-model in map-model
Browse files Browse the repository at this point in the history
`hy.as-model` is already recursive.
  • Loading branch information
Kodiologist committed Oct 8, 2024
1 parent 0b0da75 commit 5968678
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 4 deletions.
8 changes: 8 additions & 0 deletions NEWS.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
.. default-role:: code

Unreleased
======================================================

Bug Fixes
------------------------------
* `map-model` now calls `as-model` only once (before its own recursion),
and it does so unconditionally.

0.7.0 (released 2024-09-22; uses Hy ≥ 1)
======================================================

Expand Down
9 changes: 5 additions & 4 deletions hyrule/macrotools.hy
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@


(defn map-model [x f]
#[[Recursively apply a callback to some code. The unary function ``f`` is called on the object ``x``, converting it to a :ref:`model <hy:models>` first if it isn't one already. If the return value isn't ``None``, it's converted to a model and used as the result. But if the return value is ``None``, and ``x`` isn't a :ref:`sequential model <hy:hysequence>`, then ``x`` is used as the result instead. ::
#[[Recursively apply a callback to some code. The unary function ``f`` is called on the object ``x``, calling :hy:func:`hy.as-model` first. If the return value isn't ``None``, it's converted to a model and used as the result. But if the return value is ``None``, and ``x`` isn't a :ref:`sequential model <hy:hysequence>`, then ``x`` is used as the result instead. ::
(defn f [x]
(when (= x 'b)
Expand All @@ -266,14 +266,15 @@
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.]]

(when (not (isinstance x hy.models.Object))
(setv x (hy.as-model x)))
(_map-model (hy.as-model x) f))

(defn _map-model [x f]
(cond
(is-not (setx value (f x)) None)
(hy.as-model value)
(isinstance x hy.models.Sequence)
((type x)
(gfor elem x (map-model elem f))
(gfor elem x (_map-model elem f))
#** (cond
(isinstance x hy.models.FString)
{"brackets" x.brackets}
Expand Down
8 changes: 8 additions & 0 deletions tests/test_macrotools.hy
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@
(= x "hello") "wrong"
(= x '"hello") "right")))
'["right"]))
; Even if the outermost layer of the input is already a model.
(setv seen [])
(map-model
(hy.models.List ["hello"])
(fn [x]
(.append seen (= x '["hello"]))
1))
(assert (= seen [True]))

; String and byte models aren't recursed into. (They're iterable,
; but not sequential models.)
Expand Down

0 comments on commit 5968678

Please sign in to comment.