teal-language / tl

The compiler for Teal, a typed dialect of Lua
MIT License
2.03k stars 101 forks source link

Implementation of 'new' keyword #690

Closed NotSoSeriouss closed 10 months ago

NotSoSeriouss commented 10 months ago

I know that this might be not so important but it might also make some code cleaner. I already took a look at #638 and realized how important is the existance for both static functions and methods inside of records. But I think a cleaner way of working with methods will also lead to cleaner code:

Right now if I want to create a constructor I have to do it this way:

local record Point
    x: integer
    y: integer
    new: function(x: integer, y: integer) : Point -- Constructor
end

function Point.new(x: integer, y: integer) : Point -- Constructor definition
    local self: Point = setmetatable({}, {__index = Point})
    self.x = x
    self.y = y
    return self
end

And to create a new method:

local record Point
    x: integer
    y: integer
    new: function(x: integer, y: integer) : Point
    incrementX: function(self: Point, n: integer) -- Method declaration
end

And

function Point:incrementX(n: integer) -- Method definition
    self.x = self.x + n
end

But I propose a different way of building constructors and methods:

To make a constructor for an object we can simply declare a function with the same name of the record. This shouldn't cause any compatibiliy issues since Teal already doesn't allow that. But instead of giving an error, this:

local record Point
    x: integer
    y: integer
end

function Point(x: integer, y: integer)
    self.x = x
    self.y = y
end

Could get automatically compiled as if it were:

local record Point
    x: integer
    y: integer
    new: function(x: integer, y: integer) : Point
end

function Point.new(x: integer, y: integer) : Point
    local self: Point = setmetatable({}, {__index = Point})
    self.x = x
    self.y = y
    return self
end

And if there is no declaration of the constructor, then this would be the case:

local record Point
    x: integer
    y: integer
    new: function() : Point
end

This can allow for a nice improvement: the use of new

local record Point
    x: integer
    y: integer
end

local a: Point = new Point()
-- Or even
local a: Point = new() -- Since the type is already known

which is only shugar syntax for:

local a: Point = Point.new()
NotSoSeriouss commented 10 months ago

About methods: I didn't include the part about methods because this is already too munch by itself so I didn't want to overload the issue. But it would work in a similar way by using the keyword "method" instead of "function" in the declaration inside the record. Just like how #638 proposed so I didn't want to repeat that.

NotSoSeriouss commented 10 months ago

Just realized this is a kind of duplicate of #200. I will leave the issue open just in case

hishamhm commented 10 months ago

@NotSoSeriouss Yes, this is a duplicate of #200 and #97. I'm going to close this one, but these references will create backlinks at the open issues so that your comments can be found from there as well.