-
-
Notifications
You must be signed in to change notification settings - Fork 38
Description
Or: "what I myself don't really like about Arturo" (IMHO)
All of the points below are mainly things that I - personally - consider suboptimal and wouldn't mind seeing "fixed" - which is why I think it wouldn't be bad to have them all in one place (as a reminder at least). None of these "break" the language, but they represent areas where Arturo could be significantly more elegant, intuitive, and performant.
Conditional Control Flow
The current trio of switch, case, and when feels unintuitive and overlapping:
switch: The name itself doesn't feel Arturo-ish. I personally try to avoid writing it (using?) - and when I finally do I'm like... yuck!. Yep, that's a shameless confession. I was thinking that something shorter and more intuitive would be better - and then I think of Nim's use ofwhenas an alternativeif- they use it for compilation-timeifs, we could be using it for runtimeif-elses! But wait:whenis already in use!casevswhen: These two are confusingly similar in purpose. Do we really need both? In the end, this two things are so similar (and different at the same time), that I don't really remember how to use either of them.
My whole point is: while the transition from if?-else works absolutely fine, the overall conditional story - naming-wise at least - could be more streamlined and elegant.
Error/Exception Handling
The error handling story is currently a confusing mess:
try,try?,throws?– honestly, I don't even fully understand what each does or when to use which- The semantics aren't clear or intuitive
- Documentation doesn't make the distinctions obvious
This needs a complete rethink to make error handling predictable and easy to reason about.
Suggestion: Clear documentation at minimum, but ideally a simpler, more unified approach to error handling. Fewer commands that behave in a coherent, Arturo-like way.
Function (Scope) Performance
Function calls have horrible performance compared to inline code:
- Regular functions suffer from significant overhead
.inlinefunctions perform much better by comparison
Note: There is a plan to fix this via delta-tracking optimization to replace expensive symbol table copying while preserving pure lexical scoping semantics. But until then, this remains a major pain point, so... here we go.
(Ridiculously-)overloaded stdlib functions
Some stdlib functions handle multiple unrelated domains, making them hard to discover and reason about. The worst offender is extract, which combines:
- Path components (directory, filename, extension)
- URL parsing (scheme, host, port, query, anchor)
- Color manipulation (RGB, HSL, hue, saturation)
Why would someone parsing a URL think to use a function that also extracts RGB values?! (I mean, I seriously don't!) These should be conceptually separate: extract.path, extract.url, extract.color - or distinct functions entirely, or whatever. Certainly, not as they are right now!
to could be another example: it's not totally horrible, but something inside me breaks when I see this .hsv for converting a color. I mean... sure, yes, why not. But what is it doing there?! (Plus, I've never ever ever used such thing, aside from a Rosetta Code solution, I guess...). Also, the most obvious one: to.format: well... this should probably become a format function in its own right.
Counter-example: read/write with format attributes (.json, .csv, .xml) work well because they're still fundamentally about reading/writing - just with different parsers. The domain stays consistent.
(Somewhere here we could obviously mentioned the now-removed as & from which were probably the prime example of a mess...)
Wobbly (or uncertain) scoping
Without inheriting either one of them directly, Arturo unfortunately does inherit REBOL/Red's approach where the lines between "local"/"global" symbols are ... blurred. Obviously, it comes with perks, but it also has disadvantages:
Weak lexical scoping: Functions have proper scope, but call another function from another function and... we'll start having more than a couple of "a ha" moments! lol Also: blocks don't. And iterators inject variables that disappear after execution. I'm not saying this is "correct" or that isn't. I'm just saying it feels inconsistent... and makes it hard - at times - to reason about symbol lifetime and visibility.
Namespace collisions: With a growing package ecosystem, import "packageA" followed by import "packageB" can silently overwrite symbols. No warning, no error - just mysterious bugs.
Workarounds exist but feel bolted-on: The recently-introduced module (and all OOP-related capabilities) helps with isolation, and .lean imports return dictionaries instead of polluting globals. These are steps in the right direction, but they feel like patches rather than elegant solutions.
What would be more Arturo-like: Optional, explicit scoping controls. Something like do.scoped [...]. Or, perhaps even better, do scoped []? In a few words: short, intuitive, on-demand strictness when you need it; default to the current simple behavior, but provide clean ways to enforce boundaries when building larger systems or packages.
Clunky Template Interpolation Syntax
The <|| ... ||> and <||= ... ||> syntax for template interpolation is... let's be honest: visually jarring and verbose.
Compare:
<||= W\version ||>
{{ version }}
<%= @version %> I confess part of why I decided to go for this weirdness is some - visual - similarity with the existing |inter|polation pattern in Arturo + the fact that it can be made look rather passable using Fira Code. But forget this, and it becomes horrible.
Problems:
- Six characters of delimiters (
<||=+||>) for a simple interpolation - Looks like mismatched operators or broken syntax at first glance
- The asymmetry (
<||vs||>) makes it harder to scan - Different from Arturo's own string interpolation:
~"|variable|"which is clean and elegant
Why it hurts more: Arturo's own string interpolation syntax is, imho, elegant - ~"|x|" is short, symmetric, and obvious. Having a completely different, much uglier syntax for templates breaks consistency.
What would be better: Something that mirrors Arturo's existing interpolation style, or at minimum: shorter delimiters like <| ... |> or even just {{ ... }} (boring but universal). I mean, at this point, I'd gladly copy any design that doesn't look awful. Really! lol