logoalt Hacker News

nagaiaida01/22/20250 repliesview on HN

raku's take on gradual typing may be to your taste; i likewise prefer to leave irrelevant types out and use maximally-expressive types where it makes sense¹. i feel this is helped by the insistence on sigils because you then know the rough shape of things (and thus a minimal interface they implement: $scalar, @positional, %associative, &callable) even when you lack their specific types. in the same vein, dynamically scoped variables are indicated with the asterisk as a twigil (second level sigil).

  @foo
is a list (well, it does Positional anyway), while

  @*foo
is a different variable that is additionally dynamically scoped.

it's idiomatic to see

  $*db
as a database handle to save passing it around explicitly, env vars are in

  %*ENV
things like that. it's nice to have the additional explicit reminder whenever you're dealing with a dynamic variable in a way the language checks for you and yells at you for forgetting.

i would prefer to kick more of the complex things i do with types back to compile time, but a lot of static checks are there. more to the point, raku's type system is quite expressive at runtime (that's what you get when you copy common lisp's homework, after all) and helpful to move orthogonal concerns out into discrete manageable things that feel like types to use even if what they're doing is just a runtime branch that lives in the function signature. doing stuff via subset types or roles or coercion types means whatever you do plays nicely with polymorphic dispatch, method resolution order, pattern matching, what have you.

in fact, i just wrote a little entirely type level... thing? to clean up the body of an http handler that lifts everything into a role mix-in pipeline that runs from the database straight on through to live reloading of client-side elements. processing sensor readings for textual display, generating html, customizing where and when the client fetches the next live update, it's all just the same pipeline applying roles to the raw values from the db with the same infix operator (which just wraps a builtin non-associative operator to be left associative to free myself from all the parentheses).

not getting bogged down in managing types all the time frees you up to do things like this when it's most impactful, or at least that's what i tell myself whenever i step on a rake i should have remembered was there.

¹ or times where raku bubbles types up to the end-user, like the autogenerated help messages generated from the type signature of MAIN. i often write "useless" type declarations such as subset Domain-or-IP; which match anything² so that the help message says --host[=Domain-or-IP] instead of --host[=Str] or whatever

² well, except junctions, which i consider the current implementation of to be somewhat of a misstep since they're not fundamentally also a list plus a context. it's a whole thing. in any case, this acts at the level of the type hierarchy that you want anyway.