Yuescript icon indicating copy to clipboard operation
Yuescript copied to clipboard

Fill operator

Open K4rakara opened this issue 4 years ago • 5 comments

In JavaScript, the fill operator is a very handy thing:

const template = {
  foo: "Hello",
  bar: "World",
  baz: "!",
};

const specialized = {
  ...template,
  bar: "Bob"
};

Since ... in lua is used for unpacking variable arguments and therefore can't be used here, I'd like to suggest that .. be used as the fill operator only when it comes before an identifier in a table:

str1 = "Hello"
str2 = "world"
str3 = str1.." "..str2.."!" -- Concat operator is used here

template = {
  foo: "Hello",
  bar: "World",
  baz: "!",
}

specialized = {
  ..template, -- Fill operator is used here
  foo: "Goodbye",
  ..template, -- Fill operator is used here
  bar: "Bob",
  baz: template.baz.."?", -- Concat operator is used here
}

-- specialized = { foo: "Hello", bar: "Bob", baz: "" }

Compilation for this might require a utility function to be baked in:

_G["月"] = {
  fill = function(from, to)
    local mt = getmetatable(from)
    if mt ~= nil then
      -- Checks for a __fill metamethod, in case classes or other special tables should be handled differently.
      if type(mt.__fill) == "function" then
        mt.__fill(from, to)
        return
      end
    end
    for key, value in next, from do to[key] = value end
  end,
}

local template = {
  foo = "Hello",
  bar = "World",
  baz = "!",
}

local specialized
do
  local o = { }
  _G["月"].fill(template, o)
  o.foo = "Goodbye"
  _G["月"].fill(template, o)
  o.bar = "Bob"
  o.baz = template.baz.."?"
  specialized = o
end

Of course, the utility function could be inlined, but I feel like thats probably a waste.

K4rakara avatar Feb 24 '21 19:02 K4rakara

Yuescript is more like a macro system for Lua to introduce more syntax sugar and compiles to Lua. Since the table filling function is not implemented in Lua compiler itself, the Yuescript compiler has to add some inlined Lua codes to finish the job. In this way, for different code files in the same project, the utility function will be duplicated.

pigpigyyy avatar Feb 25 '21 01:02 pigpigyyy

There is a Coffeescript dialect named Livescript which adds many similar features for new syntax by inlining many Javascript codes or functions, but Livescript provides function to merge multiple source files into one source file so that the duplicated inline codes could be eliminated. So I think it is currently not a good idea for Yuescript to implement features like this.

pigpigyyy avatar Feb 25 '21 03:02 pigpigyyy

I think thats true-- this would be better to implement if (when?) YueScript can compile several files together

K4rakara avatar Feb 25 '21 03:02 K4rakara

latest yuescript version workaround (only index)

template = {
  foo: "Hello",
  bar: "World",
  "!"
}

specialized = {
  index#: template, -- "fill" operator workaround (uses metatable __index)
  bar: "Bob"
}

print specialized.foo .. " " .. specialized.bar .. specialized[1] --> "Hello Bob!"

aergo20 avatar Mar 06 '21 03:03 aergo20

Add an implementation for the Fill operator, works on both array table and hash table.

template = {
  foo: "Hello"
  bar: "World"
  "!"
}

specialized = {
  "a", "b", "c"
  ...template
  bar: "Bob"
}

Compile to:

local template = {
  foo = "Hello",
  bar = "World",
  "!"
}
local specialized
do
  local _tab_0 = {
    "a",
    "b",
    "c"
  }
  local _idx_0 = 1
  for _key_0, _value_0 in pairs(template) do
    if _idx_0 == _key_0 then
      _tab_0[#_tab_0 + 1] = _value_0
      _idx_0 = _idx_0 + 1
    else
      _tab_0[_key_0] = _value_0
    end
  end
  _tab_0.bar = "Bob"
  specialized = _tab_0
end

Get result:

specialized = {
  [1] = "a"
  [2] = "b"
  [3] = "c"
  [4] = "!"
  [foo] = "Hello"
  [bar] = "Bob"
}

pigpigyyy avatar Apr 24 '22 07:04 pigpigyyy