Nims func keyword is defined as "shorthand for the {.noSideEffect.} pragma". No side effects is a Functional term to describe function purity:
A function is considered pure when two conditions are met:
But Nim drops the ball on condition number two: You can change state on any var or ref parameter and the compiler will sign off on that. That is not correct behavior
Why is this so?
Because it's more useful this way. Note that with the new "strict funcs" features only var T parameters continue to be allowed to be mutated and since there is no reason to use var T when a T would have sufficed this allows us to use func for a very important class of functions that are like seq's add operation:
func add[T](s: var seq[T]; arg: sink T)
This is crucial for non-human readers like Nim's optimizer. (Which could be better, as always, but the potential is there.)
I understand the theory, however I think what you said is still true of var types in funcs assuming it is a value / non-ref type. A copy would be made on any assignment or whatever down the road if there were inter-thread communication.
The ref object situation is different, both in the func behavior and the behavior once threads are in the mix. To be explicit, my point is mostly focused on the value types like seq, string, etc where var is most commonly used and seen I think.
The point is that the term no-side-effects is a de facto technical term: when you use it you better mean: no-side-effects - or you violate the principle of least astonishment.
I happen to think that Nims use of the "func" keyword is a potential stroke of genius, but it would require strict checks on pointer assignments by default to fulfill that potential. As it stands it is sort of a wasted opportunity.
proc (impure) func (pure) method (dynamic dispatch)
With correct behavior Nim would stand out in the crowd, where these things are referred to ad hoc with no proper understanding of the concepts. Most languages simply do not understand the technical distinctions. Nim is so close to doing that...
Yeah, I thought there might be some technical stuff behind that decision. But you're violating the principle of least astonishment here.
I don't, it is just that you're wrong:
func split(s: string): seq[string] =
result = @[]
for w is words(s): result.add w
In my version of Nim, this simply works, in yours it does not because func cannot call add.
"Think about it."
Araq, I already did - and you have my opinion. Make of it what you will...
^ works for Nim strict funcs. No "opinion" of yours is required, it's objective.
Well it works out since point (2) is poorly phrased. var x = noSideEffectF() is a state change outside of the scope of the function so nothing happens if we extend it to cover noSideEffectF(#[byvar]# x). (Also definitions usually don't repeat the word 'ever' three times in a row and use more formal language.)
Then you just make ""strict func" the default ...
That is planned indeed but var T parameters continue to be fine, sorry.