My update example was meant to be pass by value (for simplicity); thanks to @Benny for pointing out - it would have to be like this (unless in some lang global a
could mean to only apply to the var instance next to it… but let’s keep it familiar):
function update(anew, increment)
global a = anew+increment # could be `outer a` in a local scope, depending on need
end
# call:
update(a, 17) # or maybe `update(global a, 17)`
In such a lang, classical OOP could still be done without breaking the main idea, because
obj.method()
can be interpreted as obj
being an implicit first argument passed to method()
to bind some self
parameter to represent the object at call time. Thus, even though such a method could have different effects at different calls, those can still be considered to be transparently depending on obj
.
Yet, depending on what data structures are available, it would still be possible to hack similar OOP constructions to the one shown by @bertschi above:
obj = (let A = [1]
inc() = obj.A[1]+=1
dec() = obj.A[1]-=1
get() = obj.A[1]
(; inc, dec, get, A)
end)
obj.get() # 1
obj.inc(); obj.inc(); obj.dec(); obj.inc();
obj.get() # 3
The way this would work is by having the following rule: if, at the time of function definition, the free variable that needs to be accessed is itself under construction/definition (like what happens to obj
above), then the resolution of that free variable if left to the call time.
EDIT: (after reading @bertschi reply below … )
Don’t take the last rule seriously (just in case you take seriously anything in this topic ). I made it up just to make that hack work. But neither the hack or this rule is important.
Here’s another hack that doesn’t depend on it and should force the evaluation of state to be done at call time:
obj = (let A = [1]
inc(dummy=1) = A[dummy]+=1
dec(dummy=1) = A[dummy]-=1
get(dummy=1) = A[dummy]
(; inc, dec, get)
end)
obj.get() # 1
obj.inc(); obj.inc(); obj.dec(); obj.inc();
obj.get() # 3