Yuescript icon indicating copy to clipboard operation
Yuescript copied to clipboard

[Feature request] Computed properties

Open SkyyySi opened this issue 6 months ago • 1 comments

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

SkyyySi avatar Jun 05 '25 09:06 SkyyySi

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.

pigpigyyy avatar Jun 05 '25 10:06 pigpigyyy