Yuescript
Yuescript copied to clipboard
[Feature request] Computed properties
Some languages allow defining methods that can be used like object attributes. For example, in JavaScript:
class Foo {
get x() {
console.log("Getting x");
// In JS, member names starting wtih `#` are private and cannot
// be accessed from the outside by any means.
return this.#x;
}
set x(value) {
console.log("Setting x to", value);
this.#x = value;
}
}
I would appreciate it if YueScript could do something similar. It could look something like this:
import "yue"
class Foo
get x: () =>
print("Getting x")
@_x
set x: (value) =>
io.write("Setting x to ")
yue.p(value)
@_x = value
The output could then be something like this:
local yue = require("yue")
local Foo
local _class_0
local _base_0 = {}
local _index_0 = rawget(_base_0, "__index")
if _index_0 == nil then
_index_0 = _base_0
end
if type(_index_0) == "table" then
local _index_1 = _index_0
_index_0 = function(_, key)
return _index_1[key]
end
end
local _newindex_0 = rawget(_base_0, "__newindex")
if _newindex_0 == nil then
_newindex_0 = rawset
end
rawset(_base_0, "__index", function(self, key)
local properties = rawget(_class_0, "__properties")
local property = rawget(properties, key)
if property ~= nil then
local getter = rawget(property, "get")
if getter ~= nil then
return getter(self)
end
end
return _index_0(self, key)
end)
rawset(_base_0, "__newindex", function(self, key, value)
local properties = rawget(_class_0, "__properties")
local property = rawget(properties, key)
if property ~= nil then
local setter = rawget(property, "set")
if setter ~= nil then
return setter(self, value)
end
end
return _newindex_0(self, key, value)
end)
_class_0 = setmetatable({
__init = function() end,
__base = _base_0,
__name = "Foo",
__properties = {
x = {
get = function(self)
print("Getting x")
return self._x
end,
set = function(self, value)
io.write("Setting x to ")
yue.p(value)
self._x = value
return value
end
}
}
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
Foo = _class_0
return _class_0
And to test it:
print(Foo, Foo.x)
local instance = Foo()
print(instance, instance.x)
instance.x = "Test"
print(instance.x)
Its output:
table: 0x12341234 nil
Getting x
table: 0xdeadbeef nil
Setting x to "Test"
Getting x
Test
I had a little lib for property simulation and for speeding up inheritance member field accessing.
https://github.com/IppClub/YueScript/blob/main/spec/inputs/props.yue
Maybe this feature can be better left for users to implement, due to it introduces more cost (at least one extra table indexing) for property field accessing.