Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Format Specification for String Interpolation #20

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

menarulalam
Copy link
Contributor

@menarulalam menarulalam commented Jan 10, 2024

We are adding string interpolation format specification to Luau with this change. It supports the same formats as string.format and is delimited by a ,.

Rendered view

EDIT: Update, this is on hold unless we can find a good delimiter. The problem with , and : (e.g. print({x:.2f}) is they are both used in other contexts.


## Alternatives

We have also considered allowing arbitrary format specifiers and not just ones supported by `string.format`. We would allow `__tostring` to take a second format argument, and that specifier get passed into it. We determined that we won't do this for now because it could mess up backwards compatibility on existing `__tostring` calls and a performance regression since we can't assume `tostring` will only have one argument anymore. Also for specifiers that work with `string.format` will be slower than just using `string.format`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no backward compatibility concerns I'm aware of? Can you provide an example where such code would break?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Theoretically if a 2nd argument is supplied to tostring, it will be used in this case?

Copy link
Contributor

@Kampfkarren Kampfkarren Jan 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local function getString(thing: T, padding: number?)
    local text = thing.name
    if padding ~= nil then
         text = string.rep(' ', padding) .. text
    end
    return text
end

setmetatable(Thing, {
    __tostring = getString,
})

-- Other calls
print(getString(thing, 4))

...would error with {thing,f}, though this isn't really backwards incompatible as it still requires you actually use the new specification.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess technically you could write tostring(x, y) and it'd work just fine and discards y and indeed, adding this feature would turn a dormant bug into a breaking bug. I still consider that an extremely unlikely event except in the case of variadics which makes it look inconspicuous at first. Something as weird as this most certainly would change behavior.

local t = setmetatable({ 1, 2, 3, 5 }, {
  __tostring = table.concat
})

-- before this RFC:
print(tostring(t)) -- 1235
print(tostring(t, ",")) -- 1235
print(`{t,,}`) -- illegal

-- after this RFC:
print(tostring(t)) -- 1235
print(tostring(t, ",")) -- 1,2,3,5 (behavior changed)
print(`{t,,}`) -- 1,2,3,5

But it's not backward incompatible via format specifiers in string interpolation syntax because it's syntactically invalid to even write one right now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants