Nim 0.17.2 and 0.18.0
These compile and work fine.
r.inc; if r == rescnt; (r = 0, modk = modpg)
r += 1; if r == rescnt; (r = 0, modk = modpg)
But these throw an error.
if r.inc == rescnt; (r = 0, modk = modpg)
if (r.inc) == rescnt; (r = 0, modk = modpg)
if (r += 1) == rescnt; (r = 0, modk = modpg)
twinprimes_test6yc2.nim(158, 17) Error: type mismatch: got <void, int>
but expected one of:
proc `==`(x, y: int8): bool
first type mismatch at position: 1
required type: int8
but expression 'r += 1' is of type: void
proc `==`(x, y: int32): bool
first type mismatch at position: 1
required type: int32
but expression 'r += 1' is of type: void
proc `==`(x, y: int): bool
first type mismatch at position: 1
required type: int
but expression 'r += 1' is of type: void
proc `==`(a, b: Time): bool
first type mismatch at position: 1
required type: Time
but expression 'r += 1' is of type: void
proc `==`[T](x, y: set[T]): bool
first type mismatch at position: 1
required type: set[T]
but expression 'r += 1' is of type: void
proc `==`(x, y: pointer): bool
first type mismatch at position: 1
required type: pointer
but expression 'r += 1' is of type: void
proc `==`(x, y: char): bool
first type mismatch at position: 1
required type: char
but expression 'r += 1' is of type: void
proc `==`[T](x, y: seq[T]): bool
first type mismatch at position: 1
required type: seq[T]
but expression 'r += 1' is of type: void
proc `==`[T: tuple |
object](x, y: T): bool
first type mismatch at position: 1
required type: T: tuple or object
but expression 'r += 1' is of type: void
proc `==`(x, y: cstring): bool
first type mismatch at position: 1
required type: cstring
but expression 'r += 1' is of type: void
proc `==`(x, y: float): bool
first type mismatch at position: 1
required type: float
but expression 'r += 1' is of type: void
proc `==`[T](x, y: ref T): bool
first type mismatch at position: 1
required type: ref T
but expression 'r += 1' is of type: void
proc `==`[T: proc](x, y: T): bool
first type mismatch at position: 1
required type: T: proc
but expression 'r += 1' is of type: void
proc `==`(x, y: float32): bool
first type mismatch at position: 1
required type: float32
but expression 'r += 1' is of type: void
proc `==`[I, T](x, y: array[I, T]): bool
first type mismatch at position: 1
required type: array[I, T]
but expression 'r += 1' is of type: void
proc `==`(x, y: int16): bool
first type mismatch at position: 1
required type: int16
but expression 'r += 1' is of type: void
proc `==`(x, y: string): bool
first type mismatch at position: 1
required type: string
but expression 'r += 1' is of type: void
proc `==`(x, y: bool): bool
first type mismatch at position: 1
required type: bool
but expression 'r += 1' is of type: void
proc `==`[T: SomeUnsignedInt](x, y: T): bool
first type mismatch at position: 1
required type: T: SomeUnsignedInt
but expression 'r += 1' is of type: void
proc `==`(x, y: int64): bool
first type mismatch at position: 1
required type: int64
but expression 'r += 1' is of type: void
proc `==`(zone1, zone2: Timezone): bool
first type mismatch at position: 1
required type: Timezone
but expression 'r += 1' is of type: void
proc `==`[Enum: enum](x, y: Enum): bool
first type mismatch at position: 1
required type: Enum: enum
but expression 'r += 1' is of type: void
proc `==`(err1, err2: OSErrorCode): bool
first type mismatch at position: 1
required type: OSErrorCode
but expression 'r += 1' is of type: void
proc `==`[T](x, y: ptr T): bool
first type mismatch at position: 1
required type: ptr T
but expression 'r += 1' is of type: void
expression: r += 1 ==
rscnt
I do this nesting in Ruby, Crystal, et al, with no problem.
Is this a bug, or something that the Nim compiler should be able to figure out?
The first line of the error message (Error: type mismatch: got <void, int>) gives you a clue.
r.inc (and r += 1 too) increments r in-place and returns void. After that, you are trying to see if that void is equal to rscnt which is int.
You have already solved this - use the first version. First increment, then compare.
I do this nesting in Ruby, Crystal, et al, with no problem.
And Swift deprecated ++ because it's bad. ;-)
These compile and work fine.
This is off-topic, but do they really? I'm surprised to see that an if statement followed by a ; compiles.
First, I made a typo in rewriting the example code, it should have been a colon : not a ; after ... == rscnt: ...
So, OK. It was nonintutive for r.inc to return a void instead of its value. However, using this information, the following code compiles, but it's oh so ugly. :-(
if (r.inc; r) == rscnt: (r = 0; modk += md; k.inc)
I think the interpreter|compiler can be made smart enough to intuite in this context that what is resired here is the value of the result of the r.inc operation. It would certainly make it compatible with other languages, and just make programmers lives happier. :-)
If you'd like it to be more pretty, just use a template! A simple one like this would do:
template incr(r: int): int =
r.inc
r
And then what you did should work if you replace r.inc with r.incr
Can we agree the operational intent of these phrases are clear?
if r.inc == rescnt: -- while index.dec > indx: -- num.inc + gcd(c,y)/par.dec
Isn't it straightforward to have the interpreter|compiler parse r.inc -> (r.inc; r), etc if that's what needed for the AST, etc?
Detailed answer
r.inc == rescnt
This is not clear because in the left side, it's mutating operation and the right-side has simple value. Of course mutating operation/function can have a return value but it's then too ambiguous to reason.
index.dec > indx
Same reason, mutating operation is just that unreasonable that Haskell have them done in Monad instead of pure function. cmiiw
Isn't it straightforward to have the interpreter|compiler parse r.inc -> (r.inc; r)
Explicit is better than implicit, on the right side it's obvious we send r after mutating it instead of the left, we just simply mutating it. If it's in concurrent world, we can have r.inc to return bool to indicate we successfully mutate the value like cas function. But returning bool different topic altogether.
It's better to differ mutating operations and pure operations.
You see a program (in whatever language) which has these snippets:
if r.inc == rescnt: -- while index.dec > indx: -- num.inc + gcd(c,y)/par.dec
What do you think the programmer wants the program to do? Write what you think the snippet wants done in English.
Ex: if num.inc == 10:
Translation 1: if the incremented value of num equals 10 then do ....
Translation 2: increment num, and if that value is equal to 10 then do ....
I have demonstrated that the phrase:
r.inc == rscnt
will compile if replaced by
(r.inc; r) == rscnt
Without regard to whether you think it should|shouldn't be done is it technically possible for to parse the phrase r.inc -> (r.inc; r), etc, when necessary so that it will compile appropriately to achieve programmatic intent?
Well you said it yourself, there is no unambiguous intent here, at least 2 different interpretations are possible.
No. the two English translations of if num.inc == 10 are equivalent phrasings and unambiguous to an English speaker. And you didn't present your English translations of any of the examples. So if you think they are ambiguous I am interested in seeing what you (anyone) thinks those programming snippets are saying.
So, the examples in 1) are clear and unambiguous as to programmatic intent.
Also Ruby, Crystal (with Nim) allow this programming style, but make it easy for programmers to do it.
Ruby: if (r += 1) == rescnt; .... end also (.....) if (r += 1) == rescnt
Crystal: if (r += 1) == rescnt; .... end also (.....) if (r += 1) == rescnt
Nim: if (r.inc; r) == rescnt: (....) also if (r += 1; r) == rescent: (....)
So, in all three of these languages (as a non exhaustive sample) this programming paradigm is allowed and possible. However, while Nim could also provide the syntactic sugar that Ruby, Crystal, et al provides, you insist to force the programmer to become a manual parser to conform to your whims, than to provide the simple means to deal with these cases, and make programmers lives easier.
Well, if you're going to force programmers to be compilers you can at least clearly document this for their benefit.
Well, if you're going to force programmers to be compilers you can at least clearly document this for their benefit.
Yes, let's document the features that Nim does not have. Brilliant idea.
And again, here is the rest of my reply which you conveniently ignored so that you can continue to rumble on:
"And if your productivity depends so much on these shortcuts, create them for yourself. Others have already shown you how to do this with today's Nim. Hint, it's possible with today's Nim, no language changes required, that implies it's "technically possible"."
No. the two English translations of if num.inc == 10 are equivalent phrasings and unambiguous to an English speaker.
The two possible interpretations are:
i.e. the 10 is compared to the value before increment and after.
In place change of data-> return void, otherwise return value. If you want it another way use a library with your style of programming. But its not good for this unambiguous functions to be in standard.
if (i.inc==10) or i.inc==23: echo "bla"
would increase the value twice for each check. Which wouldn't be as clear as separating the logic and the check.judging the outcome of the question and not the specifics technical aspects
But I answered your question in technical aspects :(
We're talking about function operation here, we know two kind of operation, one that mutate and one that return value.
In order to avoid ambiguity, we have to differ those two kind of operations. In case of inc(x: var int) here, it's mutating the x, so we can't return any value there.
Next question, why we can't? It's to avoid ambiguity. Can we do something about it? Yes, just make that inc(x: var int) violate that difference and have it defined such as inc(x: var int): var int .
Unless for reason of performance and resource constraint, it's better to have pure functions as possible. Everyone who has to read the code several months or years later will be grateful if you do it like that ;)
you insist to force the programmer to become a manual parser to conform to your whims, than to provide the simple means to deal with these cases, and make programmers lives easier.
I checked your previous posts a bit. This was your last impertinence.