[HN Gopher] Pluto is a unique dialect of Lua with a focus on gen...
       ___________________________________________________________________
        
       Pluto is a unique dialect of Lua with a focus on general-purpose
       programming
        
       Author : 90s_dev
       Score  : 71 points
       Date   : 2025-07-01 00:58 UTC (22 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | 90s_dev wrote:
       | Basically a more convenient/intuitive Lua for JS/C/Java/C++
       | users, plus optional static typing. May in fact use this instead
       | of Lua.
        
         | Imustaskforhelp wrote:
         | Yea. I am definitely trying this out too. It really has some
         | new features changes that I wished lua had.
        
         | JdeBP wrote:
         | There's almost nothing in there that's like C or C++. But
         | there's a definite influence of .NET and C# with things like
         | null-coalescing, null-conditionals, and interpolated strings.
        
       | wavemode wrote:
       | Curious how this compares with Luau: https://luau.org
        
         | Rochus wrote:
         | Or Luon: https://github.com/rochus-keller/Luon
        
       | tzury wrote:
       | Well, this is a very poor design, one which makes me think what
       | is the purpose of this project in the first place?
       | for i = 1, 10 do -- Loop 1.             for ii = 1, 5 do -- Loop
       | 2.                 break 1 -- This will break from Loop 2.
       | break 2 -- This will break from Loop 1.             end
       | end
       | 
       | https://pluto-lang.org/docs/New%20Features/Break%20Statement
        
         | sweetgiorni wrote:
         | That's... interesting.
        
           | tzot wrote:
           | If the numeric argument to break is what you find
           | interesting, then this is exactly the same construct as the
           | shell's break argument:
           | 
           | https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V.
           | ..
        
         | ModernMech wrote:
         | "Pluto aspires to be a version of Lua with a larger feature-
         | set, that is all. Pluto is not a Lua-killer, an attempted
         | successor, or any of that. Many people (rightly so) love Lua
         | precisely because of the design philosophy. And fundamentally,
         | Pluto is a major deviation from Lua's design philosophy. Some
         | may prefer this, some may not."
        
         | chirsz wrote:
         | I guess it is inspired by De Bruijn index[1].
         | 
         | [^1]: https://en.wikipedia.org/wiki/De_Bruijn_index
        
         | philsnow wrote:
         | What's poor about it, the numbers in the example? Think of them
         | as inner/outer instead of "1" and "2". Without this kind of
         | break statement, what do you do when you want to exit the outer
         | loop, something like this probably:                 local stop
         | = false       for i = 1, 10 do         -- outer loop         if
         | stop then break end         for j = 1, 5 do        -- inner
         | loop           break                -- to break from inner loop
         | stop = true; break   -- to break from outer loop         end
         | end
         | 
         | So this new feature fits with the general theme of pluto being
         | a very-sugared lua.
        
           | aa-jv wrote:
           | This is just poor language design.
           | 
           | The reason one might find this cumbersome or problematic, is
           | in the case of very large numbers of lines of code - sure,
           | your example is visible and somewhat readable (arguable) in
           | its current form - but tell me you won't have issues when the
           | loop is 80 or 100 lines of code, and you need to add another
           | inner loop as part of the development process.
           | 
           | Are you now going to go through and be sure all your breaks
           | are numbered properly? Are you really, though?
           | 
           | Better, imho, would have been to introduce labels and "break
           | <label>", but even that is going to cause more headaches than
           | its worth.
           | 
           | Ultimately, one shouldn't write such horrid code anyway.
        
             | philsnow wrote:
             | Ah, well said on all points and i couldn't agree more.
        
         | gitaarik wrote:
         | Seems logical to me. 1 = break the current level, 2 = break 1
         | level up, 3 = break 2 levels up, etc.
         | 
         | If you would do it the other way around, and then if you would
         | add another for loop around the others, the breaks will break.
         | You wouldn't expect that if you're modifying this code without
         | looking at the current breaks or knowing about the break
         | behavior.
         | 
         | If you however move the break statements inside a new for loop,
         | at the most inner level, it would seem obvious that you have to
         | update the break numbers.
        
           | nextaccountic wrote:
           | Adding a label to each loop and breaking by label (like in
           | Rust) feels better and more resistant to code changes
        
         | lifthrasiir wrote:
         | I don't particularly dislike that design, but Lua already
         | supports a goto target label `::label::` so I think the
         | following syntax would work better:                   ::outer::
         | for i = 1, 10 do             ::inner:: for ii = 1, 5 do
         | break inner                 break outer             end
         | end
        
         | raincole wrote:
         | That's a Lua dialect so I don't know what you expect ;)
        
         | quietbritishjim wrote:
         | I often wished for a multi-level break statement when I started
         | programming. But it turns out that, most of the time, you're
         | best served by moving that whole chunk into its own function
         | and using "return" instead of "break outer". That amount of
         | control flow complexity usually justifies moving into a
         | separate function anyway.
        
       | Rochus wrote:
       | Interesting, apparently the source also includes a (modified)
       | version of the PUC Lua VM. Why don't they just generate bytecode
       | for the existing VM and leave it as is (unless the modified
       | version somehow would significantly increase performance)? What
       | changes were necessary to the original VM to implement the
       | language?
        
         | 90s_dev wrote:
         | Some features like break N and default function args seem to be
         | incompatible with the vanilla lua vm.
        
           | Rochus wrote:
           | I think that would be achievable with plain PUC Lua bytecode;
           | it's actually just a jump. The same for default function
           | arguments; the VM doesn't actually care how many arguments
           | the caller pushes on stack, and providing default values is
           | easy to implement for the caller.
        
       | yannis wrote:
       | Well written and well documented. I will be trying it out. One
       | drawback that I see is the use of packages from LuaRocks might be
       | an issue and one does not really want to cope with compilation
       | issues. But Lua is a beautiful language in any form.
        
       | matusnovak wrote:
       | Is it possible to use Pluto alongside with a binding library such
       | as Sol2[0]? I don't mind not being able to set type hints in the
       | bindings to use in some IDE, I can create stubs for it manually.
       | 
       | [0]: https://github.com/ThePhD/sol2
        
       | WillAdams wrote:
       | Would general-purpose programming include making a Graphical User
       | Interface?
       | 
       | A simple and small language with GUI bindings and a graphical
       | tool for laying out a design in a flexible manner with a
       | responsive result is something a lot of folks would find useful.
        
       | nathan_compton wrote:
       | This appears to be a pile of syntactic sugar on top of Lua, which
       | is an idea which would have appealed to me a lot as a younger
       | developer. But the older I get the more I realize that its almost
       | never actually syntax or brevity that gets in the way in a
       | software project and that this sort of thing often introduces a
       | lot of cognitive overhead. It isn't that these extra doodads are
       | hard to wrap your head around, but the fact that we have two very
       | similar languages (Pluto, Lua) that we are interactive with on a
       | regular basis (because Pluto works within the Lua ecosystem) and
       | now we have to think about that a lot.
       | 
       | I think a lot of programmers when they first learn Lisp go crazy
       | with macros, adding all sorts of flimflam to their programs
       | because they can, but then eventually you realize that just makes
       | life harder, or at least marginally more complicated, and you
       | gradually give it up. Feels like a similar calculation could
       | apply here.
        
         | ryandvm wrote:
         | Absolutely agree. In my experience, languages that have
         | multiple forms of syntax for doing the same thing are just
         | laborious to read.
         | 
         | Kotlin has some great ideas, but it's kind of frustrating to
         | have half my code yellow-highlighted because the IDE has
         | detected that there's a short-hand version of everything.
        
         | Lerc wrote:
         | I feel like good syntactic sugar should reduce cognitive load.
         | 
         | for example in JavaScript                   let fish = 5
         | let cheese = 27         let nop = 0x4e71
         | 
         | being able to do                   result = {fish,cheese,nop}
         | 
         | Is 'only' syntatic sugar but significantly reduces the
         | cognitive load over                   result =
         | {fish:fish,cheese:cheese,nope:nop}
         | 
         | looking at the latter it is harder to take in the options at a
         | glance, when reviewing you have to check if the names match. If
         | they don't match was it intentional or accidental. Whereas if
         | you encountered                   result =
         | {fish,cheese,nope:nop}
         | 
         | You are left with no doubt that the nope is not a typo but a
         | explicit name specifier.
        
           | nathan_compton wrote:
           | I don't know, from my point of view having both syntaxes is
           | clearly more to think about, and all you get from the shorter
           | one is typing a few fewer keystrokes.
           | 
           | Philosophically, I feel a little ambivalent about the briefer
           | syntax because it mixes two sorts of denotations. Variables
           | refer to scoped objects for which, from the point of view of
           | what the program means, vanish (in compiled languages they
           | literally can totally vanish - variable references are just
           | resolved into the appropriate reference to memory). The keys
           | of a hash table are totally different sorts of things and
           | persist at runtime. I'd prefer that these two very distinct
           | conceptual spaces remain separate, even if in a certain sense
           | they overlap in a specific case.
           | 
           | Doesn't really matter, though.
        
             | Lerc wrote:
             | >I don't know, from my point of view having both syntaxes
             | is clearly more to think about
             | 
             | That's storage, not load. You need you know more, but you
             | don't have to think about as much at any one time.
             | 
             | BrainFuck has extremely simple operations. You don't have
             | to think about very many different things at all, but you
             | need to think about them a lot.
             | 
             | >and all you get from the shorter one is typing a few fewer
             | keystrokes.
             | 
             | I'm not particularly concerned about keystrokes (unless I'm
             | golfing). I'm happy to increase the size of the content to
             | reduce how much I think about it. Reducing the number of
             | elements I have to look at to grasp the same concept is
             | distinct from keystrokes.
             | 
             | Sometimes                  ArbitraryLongVariableName = 43
             | 
             | is better than                  a = 43
             | 
             | one the other hand I'd take
             | ArbitraryLongVariableName += 1
             | 
             | over                  ArbitraryLongVariableName =
             | ArbitrarilyLongVariableName + 1
        
             | hmmokidk wrote:
             | Low key this is so interesting because in Elixir there was
             | this specific example with a library that extended the lang
             | to do this.
             | 
             | The concise syntax was tossed out, but I have a soft spot
             | for it.
        
       | spacechild1 wrote:
       | Lot's of good stuff in there. My personal highlights:
       | 
       | 1. classes
       | 
       | 2. named parameters with default values
       | 
       | 3. string interpolation
       | 
       | I love Lua, but it's a bit sad that everyone ends up hacking
       | together their own OOP system (including myself). I would really
       | prefer a standardized solution.
       | 
       | Named parameters are such an underrated feature IMO. It makes
       | function calls so much easier to read, in particular if the
       | arguments all have the same type. I know, we can "fake" named
       | arguments by passing a single table argument, but this has some
       | overhead and default values are still rather awkward to
       | implement. The one big downside of named parameters is that the
       | parameter names are now part of the public API.
        
         | jay_kyburz wrote:
         | In my next lua project I'm going to try and avoid oop and stick
         | with functions and data.
         | 
         | I don't know why, but 100 times a day I have to go back and
         | replace a dot with a colon and it drives me nuts.
        
       | actinium226 wrote:
       | I've heard that Lua can be configured to avoid dynamic memory
       | allocation, potentially allowing it to be used in real-time
       | safety critical contexts. I'm not sure if anyone has used it that
       | way, but I wonder if Pluto retains this?
        
         | HexDecOctBin wrote:
         | More specifically, Lua allows you to inject your own memory
         | allocator function, so one can get Lua to use a real-time
         | allocator like TLSF operating out of a fixed memory block in
         | such contexts.
        
       | TeddyDD wrote:
       | I like the idea of bundling Lua with bunch of batteries but the
       | syntactic changes go too far. They seem to be lousily designed
       | attempt at turning Lua into Typescript.
       | 
       | For example coalescing operator. You can do the same in standard
       | Lua with or. Pipe operator might seem like cool idea, but the
       | language needs to be designed around it (Elixir) or you need
       | multiple variants (threading macros in Lisps).
        
         | Lerc wrote:
         | I'm not a Lua user but is this a falsiness issue?
         | 
         | local function report(result) print(result ?? "The value was
         | nil.") end
         | 
         | report(filesize("/path/to/file/of/length/zero"))
         | 
         | If filesize returns nil for file-not-found and the length
         | otherwise. Wouldn't coalescing work and or would not be able to
         | identify existing but empty files.
        
         | 90s_dev wrote:
         | As a TypeScript fan, I was really happy to read pretty much
         | every one of these changes. This is a language I wouldn't
         | personally use unless it gains massive traction, but one that I
         | hope it gains massive traction so that I can justify spending
         | the time memorizing and learning _all_ these new language
         | additions.
         | 
         | It's particularly exciting that they constantly rebase upstream
         | Lua, and plan to update it to be compatible with Lua 5.5.
         | Especially because Lua 5.5 finally has the ability to turn off
         | globals!
        
         | shayway wrote:
         | Yeah, there are a lot of odd inclusions like that; things that
         | overlap or replace standard lua flow for no reason (see ternary
         | expressions[0]). I would love an expanded lua, with built-in
         | classes and a more robust standard library, but this feels more
         | like a rewrite into a new langauge with two vastly different
         | design philosophies layered awkwardly on top of each other.
         | Which it is I guess.
         | 
         | I don't mean to discount the work that has gone into it, and
         | there are a lot of really neat features here. But honestly I
         | think it would be stronger as a standalone thing, without all
         | the lua baggage, given how far idiomatic pluto diverges from
         | idiomatic lua.
         | 
         | [0]https://pluto-
         | lang.org/docs/New%20Features/Ternary%20Express...
        
       | yungporko wrote:
       | i was expecting something dumb if i'm honest but it looks really
       | nice, i would probably use this. it seems like the perfect
       | extension of the "code vomit" speed of writing lua and moves it
       | further in that direction imo.
       | 
       | the thing i like lua for is easily getting into that "flow state"
       | of just writing code without having to think about "how should i
       | approach this" but sometimes the lack of things which pluto
       | addresses forces a level of verbosity that snaps me out of it. i
       | often find myself hitting a mental roadblock where i think "like
       | fuck am i gonna write that much code to do X, i'll just go work
       | on a more fun part of the program and come back later".
        
       ___________________________________________________________________
       (page generated 2025-07-01 23:02 UTC)