Closed timotheecour closed 3 years ago
this parser change should be backported to 1.0 branch so that libraries involving dot like operators can work there too
Maybe but we know from the survey results that most people are on version 1.4 and happy to upgrade. Maybe it's time to make the next Nim release version 2.0, keeping semver. Or dropping semver altogether as it's just terrible, see also https://news.ycombinator.com/item?id=19137896
There should be a stability focused 1.x version where everything that was or will be introduced in 1.x works decently (views, arc/orc, IC,...). People need to be able to rollback without losing too much.
Now regarding, Nim 2.0, I don't see the value of the "2", unless there is a new strategy to decouple the standard library from the compiler, because there is nothing 2.0 in the standard library: views are not used, threadpools need revamp, concepts/interfaces should be used as well, strutils and sequtils need to embrace dup and maybe have an alternative view/stream/iterator API as well.
There should be a stability focused 1.x version where everything that was or will be introduced in 1.x works decently (views, arc/orc, IC,...).
Yes and we are working on that. But should the community be hold back until we have this version? Maybe some people prefer to work on 2.0-worthy things.
Relevant line for first proposal:
Change could be done today, seems pretty uncontroversial. Should be done IMO.
Second proposal is interesting, but =
must be the most edge cased expression in the language lol. I mean, .=
is a ternary operator, if we extend it to specifically other dot operators, then why stop there? Why use operators when you can use names?
proc `.?=`(x, y, z: int) = echo x * y * z
1 .? 2 = 3
# becomes
proc `foo=`(x, y, z: int) = echo x * y * z
1.foo(2) = 3
I don't know if it's worth making these kinds of changes unless =
is generalized for custom implementations, which is another topic whether or not it should be.
Change could be done today, seems pretty uncontroversial. Should be done IMO.
yes, PR welcome for proposal 1!
if we extend it to specifically other dot operators, then why stop there?
you're right, and maybe dotOperators
is an un-necessay hack:
a.?foo = bar
1.foo(2) = 3
a.foo += bar # this will be parsed as `+=`(a.foo, bar) and `.=` can't help here [1]
In fact, dotOperators
is a poor-man's attempt at TRW (term rewriting macros, https://nim-lang.github.io/Nim/manual_experimental.html#term-rewriting-macros).
What if we instead do this:
template ex1{a.foo = c}(a: JsonNode, foo: untyped, c: JsonNode) = a[astToStr(foo)] = c
x.bar = y # rewritten as a["bar"] = y
and these would also work:
# this replaces a setter, like `foo=`:
template ex1{a.foo = c}(a: Foo, c: int) =
echo "setting real field fooImpl"
a.fooImpl = c
except it's more general than a setter as, unlike setters, it can be made to work for module scope variables as shown in https://github.com/nim-lang/Nim/issues/14674#issuecomment-778570371
furthermore, unlike setters, it can be used for more general assignments, eg +=
(we don't have foo+=
setters):
template ex1{a.foo += c}(a: Foo, c: int) = ...
or for dynamic fields:
template ex2{a.foo += c}(a: Foo, foo: untyped, c: int) = ...
Note that TRW currently can't allow some of the things mentioned here (but https://github.com/nim-lang/Nim/issues/14674#issuecomment-778570371 works), but it's close; maybe it could be a different syntax than the current TRW though.
Although TRW adds another level of complexity and magic, I'd argue the magic is already present in dotOperators
except it's worse as the rewrite rule is written in the compiler instead of in library code via the declaration in the TRW eg template ex1{a.foo += c}(a: Foo, c: int) = ...
; by making it more general, it can be made in fact less buggy. Similarly, using TRW could make the []=
array indexing operators less magic/buggy (see https://github.com/nim-lang/Nim/issues/15911). And since you have symbol names for each rewrite rules, you can import/export them individually, unlike []=
+ similar.
[1] eg, suppose you have a proxy DSL for some operations that happen in a remote server (eg mongodb/sql), you'll want a.foo += bar
to happen entirely on the remote, you can't have it parsed as: a.foo = a.foo + bar
(eg you can't get a var reference to a.foo
which is an abstract remote operation)
TRWs are not well designed either: They slow down compilations significantly (I have ideas how to fix that) and have been designed for custom optimizations. For your purpose it's not a good fit.
What do you guys think of this forum post about dotOperators
?
Like @hlaaftana said, the case of .?=
is essentially a ternary operator, and from my newbie perspective modifying Nim's binary operators to act like ternary ones for special cases seems like a work-around. @timotheecour's TRW macro idea seems like it can model the ternary case well, but like @Araq said it's designed for other things. The idea in the forum post might be an alternative, as it can also cover .?=
in a way similar to a TRW macro:
type Obj = object
macro `=call`(o: Obj, field: untyped, args: varargs[untyped]) =
echo $field
let obj = Obj()
obj.?test = 1 # prints '?test='
# same as
`?test=`(obj, 1)
I don't know if the above is even possible, but I just feel like extending dot operators like in this RFC would more fit languages that have the "methods go inside class definitions" concept, and Nim doesn't do this. I think maybe leveraging Nim's UFCS capabilities would fit Nim more, instead of modelling after Dlang's opDispatch
. You're the experts, but just wanted to voice this idea.
This has been implemented.
Is it ok to add `.[]`
and `.[]=`
to the list? This way you can wrap object fields that are arrays. Edit dont really need it.
originally proposed in https://github.com/nim-lang/Nim/pull/16924#issuecomment-776542934
proposal 1
we defined dot like operators as operators starting with
.
, but excluding operators starting with..
like..<
,..^
etc.Dot like operators shall have same precedence as
.
example
current output:
under this RFC,
a.?b.c
would instead parse as:(a.?b).c
, and.?
would then be a valid replacement for user-defined.
, in particular for jsffi or nimpy, without having to mess around with builtin.
:note
this reduces the need for
dotOperators
(see also https://github.com/nim-lang/Nim/pull/16996 which removed dotOperators instd/wrapnils
) but this RFC isn't about deprecatingdotOperators
(this can be discussed elsewhere); in particular, there may be valid remaining use cases for type punning.After this RFC, jsffi/nimpy + any other library/API that was using dotOperators as a means to provide dynamic field access would then be encouraged to use
.?
(or similar) instead of.
.This would sidestep issues like https://github.com/nim-lang/Nim/issues/7777, https://github.com/nim-lang/Nim/issues/15607, https://github.com/nim-lang/Nim/issues/13063 for those use cases.
proposal 2 (on top of proposal 1)
all of https://nim-lang.github.io/Nim/manual_experimental.html#special-operators would apply to dot-like operators, except that the flag
{.experimental: "dotOperators".}
would not be needed for those (except for.
itself).in particular, these can be defined:
(ditto with replacing .? by another dot like operator, eg
.!
,.$$
etc)breaking change discussion
links
opDispatch
https://tour.dlang.org/tour/en/gems/opdispatch-opapply