janet-lang / janet

A dynamic language and bytecode vm
https://janet-lang.org
MIT License
3.43k stars 221 forks source link

Add `:unless` loop modifier #1286

Closed primo-ppcg closed 11 months ago

primo-ppcg commented 11 months ago

I recently attempted to write something like this:

(seq [i :in vals :unless (f i)] ...)

and was surprised that isn't supported. Of course, this can be written as :when (not (f i)), but given the presence of both :while and :until, it seems like an omission.

It's also trivial to add:

@@ /src/boot/boot.janet -467,10 +467,11 @@
         (case binding
           :until ~(do (if ,verb (break) nil) ,rest)
           :while ~(do (if ,verb nil (break)) ,rest)
           :let ~(let ,verb (do ,rest))
           :after ~(do ,rest ,verb nil)
           :before ~(do ,verb ,rest nil)
           :repeat (with-syms [iter]
                     ~(do (var ,iter ,verb) (while (> ,iter 0) ,rest (-- ,iter))))
           :when ~(when ,verb ,rest)
+          :unless ~(unless ,verb ,rest)
           (error (string "unexpected loop modifier " binding))))))
sogaiu commented 11 months ago

I usually find code that uses (unless ... over (when (not ... harder to understand when I'm reading someone else's code.

I've used such code myself, but when returning to it, it hasn't been unusual to find it on the opaque side and I sometimes resort to rewriting using (when (not ... (sometimes just temporarily).

That said, it seems easy to add (and maintain?) and unless is part of Janet, so it seems like a sensible change to me.