-
Notifications
You must be signed in to change notification settings - Fork 191
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}"] = true
example usage:
class MyClass
const self, 'foo'
new: (@foo)=>
lock_const self, 'foo'
untrusted_function self
This 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.