On Sat, May 27, 2023 at 1:38 AM Andrey <andreyorst@gmail.com> wrote: > >Oh yeah! (I was the one who wrote it! Ahah) > > Oh, haha, you're right! > > >I remember seeing these limitations the last time I referenced the > >library to talk about this in #fennel~ > > > >I wonder if there's a better way to implement it? (Or maybe even a > >better place?) > >(Actually, where would I even need to look if there was?) > > Well, IIRC I was sitting and thinking of a different way, and the only one that > comes to mind is literally using GOTO labels. This will turn named let into a > simple jump + rebind, and it will probably be possible to support > multiple-value binding. Probably. (Un)fortunately, lua escape hatch doesn't > allow defining goto labels. I figured out a way to bypass these limitations in a way that doesn't involve introducing GOTO, doesn't break with the caveats that the cljlib implementation has (afaict), and changes no existing syntax at all (and validates in the same way as existing let!) Archenoth (1): add named let! src/fennel/specials.fnl | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) -- 2.38.4
fennel/patches/.build.yml: FAILED in 55s [Re: Clojure-like loop/recur or Scheme named-let in Fennel?][0] from [~archenoth][1] [0]: https://lists.sr.ht/~technomancy/fennel/patches/41463 [1]: mailto:archenoth@gmail.com ✗ #997582 FAILED fennel/patches/.build.yml https://builds.sr.ht/~technomancy/job/997582
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~technomancy/fennel/patches/41463/mbox | git am -3Learn more about email & git
From: Archenoth <archenoth@gmail.com> This commit will allow for `let` bindings to optionally specify a name in the same way that `fn` can in order to restart its body with new bindings (Like how Scheme does it!) --- src/fennel/specials.fnl | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/fennel/specials.fnl b/src/fennel/specials.fnl index 503ddd9..339dbb5 100644 --- a/src/fennel/specials.fnl +++ b/src/fennel/specials.fnl @@ -451,8 +451,18 @@ and lacking args will be nil, use lambda for arity-checked functions." true) (fn kv? [t] (. (icollect [k (pairs t)] (if (not= :number (type k)) k)) 1)) +(fn compile-named-let-fn [ast scope parent opts name bindings] + (let [args (icollect [i v (ipairs bindings)] + (when (= 1 (% i 2)) v)) + body (icollect [i l (ipairs ast)] + (when (> i 2) l)) + declaration [:fn name args (table.unpack body)]] + (SPECIALS.fn (utils.list (table.unpack declaration)) scope parent))) + (fn SPECIALS.let [ast scope parent opts] - (let [bindings (. ast 2) + (let [name (when (and (utils.sym? (. ast 2)) (utils.table? (. ast 3))) + (table.remove ast 2)) + bindings (. ast 2) pre-syms []] (compiler.assert (and (utils.table? bindings) (not (kv? bindings))) "expected binding sequence" bindings) @@ -469,11 +479,13 @@ and lacking args will be nil, use lambda for arity-checked functions." true) (compiler.destructure (. bindings i) (. bindings (+ i 1)) ast sub-scope sub-chunk {:declaration true :nomulti true :symtype :let})) + (when name + (table.insert ast 3 (compile-named-let-fn ast scope parent opts name bindings))) (SPECIALS.do ast scope parent opts 3 sub-chunk sub-scope pre-syms)))) -(doc-special :let ["[name1 val1 ... nameN valN]" "..."] - "Introduces a new scope in which a given set of local bindings are used." - true) +(doc-special :let [:name? "[name1 val1 ... nameN valN]" "..."] + "Introduces a new scope in which a given set of local bindings are used. +Optionally allowing for a name to restart the body with new bindings" true) (fn get-prev-line [parent] (if (= :table (type parent)) -- 2.38.4
builds.sr.ht <builds@sr.ht>fennel/patches/.build.yml: FAILED in 55s [Re: Clojure-like loop/recur or Scheme named-let in Fennel?][0] from [~archenoth][1] [0]: https://lists.sr.ht/~technomancy/fennel/patches/41463 [1]: mailto:archenoth@gmail.com ✗ #997582 FAILED fennel/patches/.build.yml https://builds.sr.ht/~technomancy/job/997582