Closed metagn closed 3 years ago
There was actually a somewhat similar feature in the language called "Automatic self insertions" https://nim-lang.org/0.19.0/manual.html#overloading-resolution-automatic-self-insertions - it got removed.
with
does this https://nim-lang.github.io/Nim/with.html#with.m%2Ctyped%2Cvarargs%5Buntyped%5D
with window:
setDrawColor(0, 255, 0)
A couple more downvotes and closing
We had that feature, one problem:
echo "a"
# rewritten to:
echo this, "a"
Now what are the rules? Why is echo
special? I never found a good rule.
Is that a response to the RFC or a tangent on {.this.}
? The RFC is that it would only replace parameters with a specific name.
It would equally apply to your variant of the feature:
let window = newWindow("Window Title", 800, 600)
let renderer = window.createRenderer()
using
window = window
renderer = renderer
# render logic
setDrawColor(0, 255, 0)
drawText("Hello world", rect(10, 10, 80, 20))
echo "hello"
If not, why not? Because echo
doesn't have a parameter named window
nor renderer
?
Yes
Outside of just looking ugly or being confusing, this could be very hard or cumbersome or problematic to technically pull off, and it could have some fundamental flaws interacting with the rest of the language that I am missing, but maybe indulge it for a little bit.
Proposal: An expansion on the
using
statement that allows syntax likeusing a = b
, where if any routines called in the following code have a named argument nameda
, it will be set tob
for each call by default (I believe this is slightly similar to implicit parameters in Scala). Example:A possible further expansion is specifying a type to work with routines that take arguments of the same name but need a completely different value.
This has a fair bit of nuance to deal with.
Too implicit
You could think this is way too much hidden control flow, but what is a clear alternative? Just putting
context
in the proc arguments to meancontext = context
would make no sense. If you wanted to restrict it inside a block which is specifically annotated with a{.cast().}
-like construct though prettier like Rustunsafe
, you could almost do it with a macro.Maybe you could force annotating specific proc parameters that this would replace with
{.implicitable.}
or something at the proc definition somewhat like in Scala (Scala goes by type, not by name). I don't think restricting this feature in whatever way would be a hard task, so I'm not going to focus on it very much.Confusion with default argument values in procs
Someone might think these are the same:
This is not allowed in current Nim (you have to do
using a: int; proc foo(a = 5) = discard
), and I can't think of many cases where it would be needed either. If this wasn't supported but the proposal was, I don't think the confusion here would be too much of a problem if someone were to fall for it. The compiler wouldn't give an error that's too cryptic, it would just be a little unexpected.Small sidenote:
using a {.pragma.}: int
is allowed though I think it's ignored.If this syntax were to be supported for proc default arguments in definitions, it wouldn't necessarily have to clash with proc passing, it could do both, though doing 2 different things at once could be undesirable. Maybe a pragma could be used to only apply it to 1 kind of either default argument definitions or default argument passes, maybe this would be ugly.
Beyond that, there is another problem with supporting default arguments in definitions, proc argument default values can depend on other arguments, like so (not sure if this is documented):
using
wouldn't have to support this, but it's not exactly clear what it should be doing instead. Should it store an untyped expression or type the expression once and pass it around or evaluate it as a constant? Should the programmer be able to choose for themselves?Typed or untyped
In the example I gave above with
window
andrenderer
andcontext
, they all depend on a strictly runtime value that might be used in a lot of code but can only be created under strict conditions (well,window
at least). It would obviously be asking for trouble to do something likeusing window = newWindow()
, but one might still want to be careful. In this example:It would make sense that
b
is type checked at theusing
statement first and then again every time it's injected. But you would have to ensure that you can use theb
that was typed in the using statement can be used at the injection site (not that this would be too much of a problem, asusing
statements are local to a module. exported templates would break with it but those should not be supported at all).You could want
b
to be re-typed at every callsite (it's important to not emulatelet
orconst
behavior here), or you might want to support this syntax for templates (no matter how broken that would be). If you set this to be the default behavior, you lose some safety that you might want otherwise. Perhaps type it by default, and allow leaving it untyped as an option:This notation could be a problem as
untyped
andauto
are the same type in Nim internals IIRC and we wantusing a = b
to be typed but by inferring the type ofb
, whichauto
is meant for. So maybe yet another pragma likeusing a {.untyped.} = b
or something weird likeusing a = untyped(b)
.We're still not done with this kind of "type safety".
using
is top level onlyWhat if we wanted "type safety", but didn't want to deal with expressions that can only be typed at top level (e.g. global variables)? Then we can change:
To:
There are obviously more use cases for scope-local variants of these but I just wanted to get that one out of the way to keep up with the topic of type safety. The point is Nim does not currently support local
using
at all, though it would greatly be benefited from here. If you think it's too cumbersome you can doYes, this means macros and templates could take advantage of this feature for DSLs, though currently you can just fill in overloads for routines like I'm sure many people do already.
I think that's enough points in the main post for now, I don't expect this issue to be necessarily supported very much as there was an RFC to remove the existing
using
statement, the most support I've seen for something like it is stuff like https://github.com/nim-lang/Nim/issues/12873 which would be very nice and I would 100% use but seems a little disconnected from the normalusing
statement IMO.