I just saved myself a ton of heartache by doing something a lot easier instead.
I think. Either that, or I introduced a weird brittle workaround ...
For further actions, you may consider blocking this person and/or reporting abuse
It's not an elegant or full solution, so yes, it's a "hack." In other words, we could likely find a much better and more performative solution, even without knowing exactly how to achieve it.
However, does it matter in this context? You mentioned that it sacrifices speed, but your use-case isn't defined as needing to scale. This is where the engineering part collides with software development. If you're limited on time, you can call it complete. You've implemented a solution that solves the problem while acknowledging the shortfalls, and the solution only falls apart while scaling beyond your intended purpose. In a large org or project, you would document the shortfalls of this solution and make sure your team (or maintainers) are aware of the downsides to this solution. Otherwise, pat yourself on the back for solving a weird problem in an ill-suited environment.
This is a really great answer, thank you! Of course, it's not quite so simple as "bad" or "good". For now it's allowing me to move on with the program, and if it ends up being a bottleneck, I'll revisit.
Ahhhh - this looks fun! I hope you're enjoying doing this as much as I did reading it.
So, I have a question: what made you decide to support partial application of functions? It looks like you're going down the 'everything is curried' route, like in Haskell. Is this coming from the book?
I've not seen a Lisp with that language feature before, and I'm wondering what the downsides of supporting it are... what are the tradeoffs?
(Reading this post gave me Rust flashbacks - those types! 😮)
It IS fun! It's been my favorite Rust project to date. I highly recommend both the book as-is and the exercise of translating it.
You're correct, this is coming from the book. My end goal is an equivalent interpreter to that found in the book, and the Lisp the author describes is indeed idiosyncratic.
As it turns out, variadic functions are the very next thing on the list, but employing a syntax like
{x & xs}
, usingxs
to collect any trailing arguments. Then we can define curry:fun {unpack f xs} {eval (join (list f) xs)}
and uncurry:fun {pack f & xs} {f xs}
.Just remembered one tradeoff - variadic functions!