I've just watched "Why is heskell so hard to learn and how to deal with it" youtube video. On minute 33 have a quote that "Functional purity is the most important thing that sets Heskell apart".
As soon as I see this slide, my first though is "wait... I remember that nim also have this feature. It's {. noSideEffect .} pragma, or just use "func" instead of "proc" and problem solved.
Here's what I've try
# experiment no side effect
# could nim enforce pure function like Heskell?
import md5
# This is ok, no side effect
func nse1(s:int): string = $s
# This is not ok, echo have side effect
func nse2(s:string): string =
echo s
return s
# This is not ok, read from file have side effect
func nse3(s:string): string = readFile("secret") & s
# This is ok, use var but not modify var
func nse4(s: var string): string = return s & " no side effect"
# This is not ok, use var and modify var
func nse5(s: var string): string =
s = s & "hi"
return s & " no side effect"
# This should ok, why not?
func nse6(s:string): string = $s.toMD5
when(isMainModule):
echo 123.nse1
var s = "hello"
echo s.nse2
echo s.nse3
echo s.nse4
echo s.nse5
echo s #s was modified
echo s.nse6
my question is why nse5 not fail to compile? it's modify input --> s before call = "hello" while s after call = "hellohi" why nse6 fail to compile? it's just call md5.toMD5 and not modify anythingwhy nse5 not fail to compile? it's modify input --> s before call = "hello" while s after call = "hellohi"
It is explained here: https://nim-lang.org/docs/manual.html#pragmas-nosideeffect-pragma
why nse6 fail to compile? it's just call md5.toMD5 and not modify anything
Low level memory operations like copyMem, or zeroMem are used inside toMD5 proc. I think that is why Nim say "'nse6' can have side effects". https://github.com/nim-lang/Nim/blob/version-1-0/lib/pure/md5.nim#L180
Thanks for clarify, so from my understand
nse5 --> Can compile because proc only changes locations that are reachable from its parameters (var s). OK
nse6 --> Cannot compile because use zeroMem, copyMem which modify memory. But this mean all MD5 function will never pure? (no side effect)
I'm not to sure why MD5 use copyMem and zeroMem and also conversion to cstring.
Note that the module was written mostly in 2010: https://github.com/nim-lang/Nim/commits/version-1-0/lib/pure/md5.nim
It wouldn't look the same now and we can certainly modify it to be nosideeffect.
I want to help to submit the nosideeffect version to you but I'm afraid that my knowledge is not up to that level yet. If you can point me to nosideeffect of python version I'll try to convert it to nim and do pull request
You can just modify the current code. I think it's either one of the copyMem, zeroMem functions or the cstring function that triggers this.
Normally the error message when you tag function should give you a hint. Otherwise you can use this:
{.noSideEffect.}:
mySuspectedSideEffectStatement()
Just bisect the code with the {.noSideEffect.} block until the function compiles. And then it will be easier to discuss the appropriate step. maybe it's just doing a for loop or doing reset(foo)