Preferences


The Nil-Coalescing Operator they add is actually redundant.

Instead of their new fancy syntax:

  print(message ?? "The message was nil.")
The idiomatic way would be:

  print(message or "The message was nil.")
The or operator works just fine. (Edit: Note that this works because empty strings, lists and the number 0 are all truthy in Lua)

Generally not a big fan of adding additional syntax and operators for minimal gain.

I feel like most changes are nice to have but not really worth the disadvantage of not being able to use LuaJIT.

Honestly, the most interesting goal for me is is having a beefier Python-style standard library. Now, if we had that together with LuaJIT levels of performance that would be an absolute Python killer.

The only actual problem with Lua (that can't be fixed without forking) is that new variables are global by default but you can cope with that. Just have your linter check that you are always using the "local" keyword. Couldn't find if Pluto is fixing that.

Edit: Oh they provide a "let" alias for "local", case in point, little changes with not much value.

No it's not the same; `x ?? 'foo'` evaluates to `x` when `x` is not `nil` and to `'foo'` otherwise; `x or 'foo'` evaluates to `x` when `x` is not one of `nil` or `false`, and to `'foo'` otherwise.

This idiom seems to have been made widely popular by Perl folks, and while it has always been a good trick up your sleeve when you're 16 and want to impress the other kids, it's never been a good, correct way of doing things seriously, especially not across different scripting languages when every single one has its own Byzantine rules of what counts as truthy and what as falsey (like empty strings or empty lists). It is an especially pernicious idiom because of the widespread clout with which it tends to be transmitted; turns out it's one of the Falsehoods Clever Programmers Think They Know Better About. They don't.

Empty strings, lists and the number 0 are all truthy in Lua so this isn't an issue.

Different languages have different semantics. Yes, using the or operator like that is not a good idea in many languages but in Lua it is idiomatic.

pls see my other comment(s)
i can see you are probably a polyglot, working in several languages with regularity.

it would certainly be frustrating to have to juggle these semantics as you switched back and forth.

however, languages are just that - they have their own meanings, and unfortunately they can't all be the same across languages (or they'd all be the same language).

different languages are different, and they have every right to be different, and I have every right to point out in whichever ways they differ. Personal tastes differ, too, and as far as I'm concerned I think that using 'shorthand Boolean coalescence' (I just made up that term) is a false convenience; when I write a condition that relies on a list being empty, ideally that should look like `if is_empty a then ...` according to my taste—explicit is better than implicit, and this is still concise.

Be that as it may but shrugging and sighing, like, "ah well, different languages will be different" and using that as an argument against a discussion of the merits and demerits of certain aspects of certain languages is not constructive, is it?

You want to learn the specifics of ?? means in this language, but not the boolean projections? It's one thing to be peeved that empty strings or lists are falsy when it's useful for them not to be, but this seems like barking up the wrong tree.
You almost never want to exploit, in a scripting language, the subtleties of the Boolean projections when writing the (un-) idiom `b = b or b_default`; it is more commonly a mistake made by script kiddies and hand-waving mavericks (i.e. People Who Finish First, a.k.a. People Who Never Write Proper Tests) that has become deeply ingrained due to the Look Ma How Clever effect. If `b` should be a Boolean with a default of `true` then `b = b or true` will quite obviously never allow it to be `false`. Rewrite that and put it in a row of such assignments as in `a = a or a_default; b = b or b_default`; c or c or c_default;` and it looses its fishy smell enough to pass as "OK, trivially no problem here".

I've indeed gotten tired by the entire idea of Boolean projections, yes, but that's not the point here, at least not almost always in practice.

I’m not clear on what the point of your response is, the comment you responded to is making an often overlooked point that certain subtleties in how languages implement constructs can create sharp edges, one of those being the null coalescing operator.
the point is that lua didn't make the mistake of false 'empty' values, so that particular sharp edge is absent
The edge of "false 'empty' values" is absent in Lua, indeed, but the `a = b or c`, more often used in the form `b = b or c`, has, in Lua, still the problem that it will evaluate to `c` if `b` is `nil` and when b is `false` which may or may not be what one wants—and often one wants it not. The idiom is commonly used to assign a proper value to a variable that has not been set to an explicit value, i.e. a variable that is `nil`. The assignment `b = b or true` will set `b` to `true` if it was `nil` or `false`; assuming allowable values for `b` are `true` and `false` and the default is `true`, `b` will then never keep the value of `false` and always be set to `true`.
Well the Perl people also invented the defined-or operator (//), so there is that.
I was just guessing here and didn't know about `//`; this in turn comes transparently from C as an enhancement of the C idiom `b = b || c`; it may have been a later introduction though (me learning Perl was way back in the (early?) 90s) or I missed it (not unlikely)
It’s been too long since I’ve played with Lua to recall whether this would also be the case, but in JS the nullish coalescing operator is useful over logical OR because it prevents false-y values (0, empty string, false) from being treated as nullish ones, a frequent source of bugs.
The number 0 and empty strings are considered truthy, so it isn't that bad.

  return 0 or 42

  > 0
Obviously the pattern doesn't work for checking for the existence of booleans as both nil and false are falsy but you are less likely to confuse that. So yes, the ?? would help a little bit but then again, you could just explicitly check for nil.
> the ?? would help a little bit

that's the only point of the operator.

given: a = 0; b = 42;

then `a or b` and `a ?? b` give two different answers, but take the same number of characters to write.

> just explicitly check for nil

1. I am lazy and 2. I am explicitly checking, that's why I picked `??` not `or`

false-y values in dynamically typed languages is a mistake
Coming from Python, I find empty collections being falsey very convenient.
I feel like typing len(...) is not that bad, compared to how verbose "default if var_to_test is None else var_to_test" is (compared to "var_to_test or default"). But I agree it is nice -- I wish Python had the ?? operator.
len() may be either expensive or not possible to calculate for some collections where an emptiness check is trivial. For example a proxy for results from some paged API where you hold the first page initially. Empty check is immediate, len() may take hours.
(implicitly converting strings to numbers is pretty convenient too but that doesn't mean php made the right call)
Even though it would make the language a little more verbose, I would love if Lua had a 'global' keyword and declaring global/local was required. With that one change, I think Lua would have the best implementation of scope out of any language I've used.
Yes. My solution though is to just pretend that naked assignment isn't supported and don't use global variables.
It is actually not redundant. I have run into this problem at least once in real Lua code.

    local x = false
    print(x ?? "message was nil")
    print(x or "message was nil")
which results in

>false

>message was nil

Penlight[1] was supposed to offer python like batteries. It's kind of been abandoned by now, as has most of lua IMV. To me you still need luastd and a couple of other things (posix, lfs, socket, luasec) you can just fetch with luarocks and you're semi set.

[1]: https://lunarmodules.github.io/Penlight/

Ideally a new Lua dialect would be capable of compiling to both Lua and LuaJIT. The language is effectively forked, with the fastest implementation (LuaJIT) and the official implementation (Lua) living in seemingly irreconcilable worlds.
Eh it's not just luajit and luajit didn't create that problem either. It's a symptom of lua actually succeeding at its design goal of being easily embedded as an extension language. A handful of incompatible runtimes are more popular than the most recent puc lua, including I believe the older official lua 5.2 released in 2011.

I've done a fair bit of professional lua development and I don't think I've ever written standalone up-to-date puc lua except maybe for some tooling & scripts. It's such a small language and used in such a way that the runtime, distribution method, and available APIs have much more impact on your use (and compatibility) than the version.

Virtually everyone shipping a lua environment is also shipping changes to it that make it a unique target, if only extensions to the standard library. This is why I think syntax layer-only approach like fennel's is the correct choice for improving on lua. It mirrors lua's runtime semantics exactly, and allows you to access the implementation peculiars on their own terms and so can just be run on top of any lua system.

https://fennel-lang.org

Alternatively, Luau is a well-supported Lua variant with type checking and performance improvements, aimed more towards being a sandboxed embedded scripting environment.

https://luau-lang.org/

Plus, it's widely used, thanks to Roblox!
i haven't tried it, but here's my possibly erroneous impression from looking at the web pages

the good:

- string interpolation

- a continue statement

- conditional expressions

- augmented assignment

- frozen tables

- some kind of static typing?

the bad:

- much worse documentation

- no luajit

- you can't compile without c++‽ that's the opposite extreme from 'retains the easy embeddability of Lua'

- and wtf, a build system in php? the nope level is rising rapidly

- you still index from 1

- variables are still global by default

- misspelling a variable or property still gives you nil instead of throwing an exception

- aping c++/java syntax and semantics for classes and class instantiation

- redundant aliases for operators

- a redundant mechanism for private fields

- dwim for for-in on a table

it seems like a c++ or perl programmer didn't understand what was good about lua and decided to make it look like perl

> - misspelling a variable or property still gives you nil instead of throwing an exception

Isn't that the whole point of "frozen tables", which you listed as "good"? For globals, freeze `_G` and/or `_ENV`.

https://pluto-lang.org/docs/New%20Features/Table%20Freezing

That sounds more like a setmetatable(tbl,{__index = function () error"got nil" end}) variables are harder but you can make a wrapper function that errors whenever you get nil.

I cannot even imagine how pattern matching will work when it always returns nil, not to mention tables are full of nil sometimes, it would be an incredible waste to have a table full of false instead of nil.

agreed about the property thing, though it sort of makes nil even less of a first-class value than it already is

what do you mean about pattern matching

Whenever a pattern match fails, be it string.match or string.find, it returns nil. Could it return false instead?
At least for continues and frozen tables, lua already semi offered them via goto and setting __newindex in a metatable.

Conditional expression which I imagine is ternaries can be done with a constructor and the condition in the field a la {nil,"b"}[cond and 1 or 2]

oh thanks! i generally use lua 5.1, because that's what minetest and luajit use, and lua 5.1 doesn't have goto. though i see luajit has added it!
The landing page ought to show some examples of the differences between Lua and Pluto.
Agreed, and even browsing the docs, it's hard for someone not intimately familiar with Lua to discern the differences.
This should have been the idea of the landing page: https://pluto-lang.org/docs/category/new-features
PLUTO is already a reference language for test and operations procedures for satellites and spacecrafts.

https://ecss.nl/standard/ecss-e-st-70-32c-test-and-operation...

Perhaps even more relevant, it's already the name of a persistence library for Lua. Probably unmaintained at this point, but it's been around for decades (version 1.2 was released in 2004). Unless names are invented words, collisions are inevitable at this point.

http://lua-users.org/wiki/PlutoLibrary

https://github.com/hoelzro/pluto

i don't think this maintains the simplicity that lua offers.
One thing i like about lua, is that it is a very intentionally designed language with what it does or does not support. Many of the things pluto adss seem to be things that lua intentionally omitted as a design choice.
Odd syntax choices. The ones that stand out for me are "enum class" for scoped enums, and ":" as the delimiter in switch statements. It doesn't seem really well thought out.
I frankly find the whole idea of the switch statement unfortunate. The switch statement in C has a really understandable compiled representation: linear code where you can jump into in the middle. It was fine in 1970. But in 2023 I'd expect introduction of pattern matching instead, which generalizes the idea much better. Python pulled this off successfully. Java pulled it off successfully. Lua could, too.
I looked into the jump table optimization. The normal Lua version is here[1] and it uses the opcode as a index into a static array to jump to the label. The “faster” Pluto version is here[2] and it just uses a switch statement on the labels. I would naively assume that these would compile to the same code because the lua version is just manually creating the jump table and the pluto version is leaving it to the compiler. How could the compiler optimize the switch so that would outperform the manual jump table (by a decent margin)?

[1] https://github.com/PlutoLang/Pluto/blob/main/src/ljumptabgcc...

[2] https://github.com/PlutoLang/Pluto/blob/main/src/ljumptab.h

What is lacking is any space for community. No mailing-list or other place to discuss the direction of the project. No documentation expressing what is the overall reason or rationale behind the project, or who are the main contributors, how decisions are made, no roadmap.

There seems to be zero braking force on adding new features to the syntax and libraries. While I agree with 90% of them, I can find no discussion of why they were added, what arguments against adding were considered, how the decision was made, and by whom.

I have created my own (as yet unreleased) fork of Lua, adding some of these same features. I could abandon it and instead use (and contribute to) Pluto, but I am frightened by the mystery surrounding its origins, governance, and seeming lack of community input into the future direction.

The compound operators[1] are also in Playdate's variant of Lua[2].

The "continue" statement[3] is the one I really wish was available everywhere.

[1] https://pluto-lang.org/docs/New%20Operators#compound-operato...

[2] https://sdk.play.date/2.1.1/Inside%20Playdate.html#_lua_enha...

[3] https://pluto-lang.org/docs/New%20Features/Continue%20Statem...

Interesting that it contains a PHP-based build system https://pluto-lang.org/docs/Getting%20Started#php-scripts
"Interesting" is not the word I would use for that

Where does `$file` come from in `for_each_obj` <https://github.com/PlutoLang/Pluto/blob/0.8.0/scripts/compil...> ... from `scandir` of "src" of course: https://github.com/PlutoLang/Pluto/blob/0.8.0/scripts/common...

Here's hoping you didn't want to alter the intermediate output directory away from "int" or change the CPPFLAGS for your own setup

I'm certainly no php ninja, but I'd put good money that a similarly homegrown bash build system would be about an equal number of lines of code but 1/10000th the WTF and not require an apt-get install before trying to contribute to the project

As a PHP dev, even I am perplexed by this. I normally just use Bash.

Then again, writing maintainable Bash is a pain so I don't totally hate it. Definitely have wrestled with a fair share of write-only Bash scripts where I was tempted to rewrite them in PHP.

Good Python or even PHP is eons better to work with than Bash.
Needs compiled binary size comparison somewhere on the website
This is interesting, but lua needs a refresh.

I think berrylang shows a lot of promise now https://berry-lang.github.io/. The documentation has improved a lot and while it doesn't have a 'luajit' yet it has a lot of really interesting optimisation/reduction techniques.

Just tried it online¹ to see how it deals with a long standing problem² I have with Lua and I'm pleased to see actual improvement in the form of a warning:

    script.pluto:1: warning: function was hinted to return string
    but actually returns nil [type-mismatch]
        1 | function foo(x: number): string 
          | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ here
Unfortunately the underlying table was corrupted when the code ran and only

    1 foo
was generated in the output. I would have preferred it to have refused to run at all (will need to look in the docs to see if there's a way to get that behavior with configuration). The purist in me wants more but the practical side of me appreciates that this is definitely an improvement over current Lua.

¹: https://pluto-lang.org/web/#code=function%20foo(x%3A%20numbe...

²: https://www.hackerneue.com/item?id=38030778

It looks like you can set any warning to cause an error with a pragma:

https://pluto-lang.org/docs/New%20Features/Compiler%20Warnin...

It's not "corruption" when you don't understand the semantics of the functions you're calling—ipairs stops at the smallest integer index that doesn't have a value. You can still find that the key 3 exists with pairs; you can't find the key 2, because it's not in the table.

The language just doesn't distinguish "key present with no value" in a table, which is frankly a bizarre thing to want with typechecking in the same breath.

You make a good point: since "pairs" returns all the values as it should, calling the table "corrupted" may be too harsh. It's been so long now I can't recall why the original code I found this problem in used "ipairs" instead of "pairs". It's simply not safe to use "ipairs" on a table containing a nil and the code that did that was wrong.

I think working with newer languages like Typescript have made me unsatisfied with languages like Lua which provide no clear way to prevent this sort of mistake, so I like that dialects like Pluto are showing ways Lua could be improved.

Requiring c++17 seems like a big change from standard lua.
Why perpetrating the mistakes of our venerable predecessors, in the form of automatic fallthrough for switch statements?
Testes? Do you mean tests?
It’s Portuguese. It’s the same in the Lua codebase [1].

[1]: https://github.com/lua/lua

Thank you for informing me. I feel dumb for having chuckled.
don't feel dumb, your chuckle made me chuckle...
I genuinely think adding "classes, class inheritance" to Lua is a downgrade. There are many different systems, which you'll still encounter when using other Lua libraries anyway. Why add another?

Requiring C++17 to build is also a downgrade.

The lambda shorthand looks fine. Typing might be useful. But it says that's WIP so I'll have to try it out more than the examples. Default arguments, named arguments, the added general operators and safe navigation operators are generally useful and positive changes.

I would say that nearly every Pluto feature not marked as special on the https://pluto-lang.org/docs/Compatibility page would be a fine addition to mainline Lua. These are small quality-of-life improvements, battle-tested in other languages, with nearly zero new conceptual load.

Compiler message improvements would be great to port, too.

I see Pluto as a research project of sorts, trying new things. Trying incompatible and controversial things in such a project is the point.

Not a planet!

This item has no comments currently.

Keyboard Shortcuts

Story Lists

j
Next story
k
Previous story
Shift+j
Last story
Shift+k
First story
o Enter
Go to story URL
c
Go to comments
u
Go to author

Navigation

Shift+t
Go to top stories
Shift+n
Go to new stories
Shift+b
Go to best stories
Shift+a
Go to Ask HN
Shift+s
Go to Show HN

Miscellaneous

?
Show this modal