Hello,
since we are discussing possible variants on SRFI-26, I thought I would
write a bit about the one I am using.
Yuval Langer <xxxxxx@gmail.com> writes:
> for a while now I wanted to write two macros, `cuter` and `cutr`, that
> would work similarily to `cute` and `cut`, but instead of using the
> positional `<>` holes syntax, would use numbered holes in the form of
> `<i>`, where `i` goes from `0` up to and including `n-1`.
>
> [..]
>
> I think it's best when all holes `0` up to and including `N-1` must be
> present at least once when invoking the macro, i.e. after the `cutr`
> or `cuter` keyword. If not all numbers between `0` and `N-1` are
> used, the arguments at those hole positions would be dropped each time
> the specialised procedure is used, and I can think of no reason to
> have that behaviour.
This is sometimes useful when you need to adhere to some expected
prototype, but a specific argument is of no use to you. Not common, but
sometimes useful.
>
> Additionally, the names of these two macros are very similar to
> SRFI-26's names, and as much as I love wordplay, it may result in
> confusion, so new names are needed.
>
> Also additionally, this might be a bit of a spam SRFI. I don't think
> it is very important, but I had to write it down publicly for you to
> judge and maybe tell me what to do to get it SRFI-ed if you deem it
> worthy.
>
> Anyway, I have a repository up on Codeberg[1]. Its README.md file is
> not up-to-date, but I've committed today an almost complete `cuter`
> macro, lacking only the `<...>` keyword you can find in SRFI-26. It
> is also not good code and it is almost completely not tested.
>
> [1]: https://codeberg.org/kakafarm/srfi-26-cuter
I went in a bit different direction, with cut*. It is strongly inspired
by llama library for Emacs. Quoting myself from my manual:
> For expressing short lambdas — when argument names are not important —
> Guile provides ‘cut’ and ‘cute’ procedures (*note (guile)SRFI-26::).
> They often work well, but have two fundamental limitations.
>
> • You cannot use the same argument multiple times. Since slots are
> all marked with the same symbol (‘<>’), using it twice just means
> two arguments. That limits what you can express.
>
> • And, more annoyingly, they do not recurse deeper into the
> expression, they consider just ‘<>’s on the top-level. Any ‘<>’ on
> deeper level will just be taken as a variable, usually leading to
> ‘Unbound variable: <>’ error.
>
> These two together mean that for example the following ‘cut’ intended
> for getting the file’s base name does not work. Two ‘<>’ cannot refer
> to the same parameter (the original file name) and the inner ‘<>’ is not
> bound.
>
> (cut substring <> 0 (string-rindex <> #\.))
>
And example:
> Now, time for the ‘cut*’. You can specify mandatory arguments using
> ‘%’ prefix and a number, optional arguments using ‘&’ prefix and a
> number and ‘&*’ for the rest arguments. As a special case, ‘%’ and ‘&’
> translate to ‘%1’ and ‘&1’, respectively. Both ‘%’ and ‘%1’ cannot be
> used in the same expression (same for ‘&’).
>
> You can have gaps in the number sequence, and they are filled with
> unused bindings. Probably best illustrated with a couple of examples.
>
> (cut* list % & &*)
> ↦ (lambda* (% #:optional & #:rest &*)
> ↦ (list % & &*))
>
> (cut* list %1 %3) ; %2 is unused
> ↦ (lambda* (%1 _ %3)
> ↦ (list %1 %3))
>
> With this, we are finally able to make our example from the very
> beginning work: ‘(cut* substring % 0 (string-rindex % #\.))’.
>
> -- Special Form: cut* expr expr* ...
> Return a new procedure which will make a call (expr expr* ...) but
> with selected parameters specialized to given expressions.
>
> Numeric bindings prefixed with either ‘%’ or ‘&’ will be bound to
> respective arguments to the procedure.
>
For those interested, implementation (for GNU Guile) can be found here:
https://git.wolfsden.cz/guile-wolfsden/tree/wolfsden/control.scm#n227
Have a nice day,
Tomas
--
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.