-
Notifications
You must be signed in to change notification settings - Fork 196
Immutable object fields
This module provides a function which makes a given field of a class immutable. This is especially useful for numeric classes, like complex numbers or vectors.
The function takes a class and a field name as parameters.
export const = (fieldname)=>
rawnewindex = @__base.__newindex or rawset
@__base.__newindex = (k, v)=>
if @["_const_initialized_#{fieldname}"] and (k == fieldname or k == "_const_initialized_#{fieldname}")
error "Attempt to modify immutable field '#{fieldname}' of #{@@__name}."
rawnewindex self, k, v
rawinit = @__init
@__init = (...)=>
rawinit self, ...
@["_const_initialized_#{fieldname}"] = true if not @["_const_initialized_#{fieldname}"]example usage:
class MyClass
const self, 'foo'
new: (@foo)=>
bar: =>
print "foo is #{@foo}"
with MyClass 'baz'
\bar! --> foo is baz
.foo = "biz" --> error: attempt to modify immutable field 'foo' of MyClass.Note that the immutable property can be modified in the constructor. Until new exits, the fields are mutable. This means you should be careful when passing self as an argument to other functions in the constructor of a class with immutable fields, because if the code cannot be trusted then it is not guaranteed the fields will stay immutable.
In these situations, use the following function to "lock" a field before the constructor exits:
export lock_const = (fieldname)=> @["_const_field_initialized_#{fieldname}"] = trueexample usage:
class MyClass
const self, 'foo'
new: (@foo)=>
lock_const self, 'foo'
untrusted_function selfThis function only works for lua 5.1. In lua 5.2, the __newindex metamethod has been (irritatingly) changed so that it is only called when an empty field is assigned to, whereas in 5.1 it is called when any field is modified.