Hacker News new | past | comments | ask | show | jobs | submit | opticfluorine's comments login

Having just gone through the exercise of integrating Lua with a custom game engine over the past few weeks, I have to echo how clean the integration with other languages is.

It's also worth noting that the interface is clean in such a way that it is straightforward to automatically generate bindings. In my case, I used a handful of Roslyn Incremental Source Generators to automatically generate bindings between C# and Lua that matched my overall architecture. It was not at all difficult because of the way the interface is designed. The Lua stack together with its dynamic typing and "tables" made it very easy to generate marshallers for arbitrary data classes between C# and Lua.

That said, there are plenty of valid criticisms of the language itself (sorry, not to nitpick, but I am really not a fan of one-based indexing). I'm thinking about designing an embedded scripting language that addresses some of these issues while having a similar interface for integration... Would make for a fun side project one of these days.


> sorry, not to nitpick, but I am really not a fan of one-based indexing

It is very funny how this is just the one sole criticism that always gets brought up. Not that other problems don't exist, but they're not very talked about.

Lua's strength as a language is that it does a lot quite well in ways that aren't noticeable. But when you compare things to the competition then they're quite obvious.

E.g. Type Coercion. Complete shitshow in lots of languages. Nightmare in Javascript. In Lua? It's quite elegant but most interestingly, effortlessly elegant. Very little of the rest of the language had to change to accomodate the improvement. (Excercise for the reader: Spot the one change that completely fixes string<->number conversion)

Makes Brendan Eich look like a total clown in comparison.


To be fair, having to work with 1 based indexing when you're used to 0 would be a frustrating source of off-by-one errors and extra cognitive load

As someone who's used Lua a lot as an embedded language in the VFX industry (The Games industry wasn't the only one that used it for that!), and had to deal with wrapping C++ and Python APIs with Lua (and vice-versa at times!), this is indeed very annoying, especially when tracing through callstacks to work out what's going on.

Eventually you end up in a place where it's beneficial to have converter functions that show up in the call stack frames so that you can keep track of whether the index is in the right "coordinate index system" (for lack of a better term) for the right language.


Oh that’s super interesting, where in the VFX industry is Lua common? I typically deal with Python and maybe Tcl (I do mostly Nuke and pipeline integrations), and I can’t think of a tool that is scripted in Lua. But I’ve never worked with Vega or Shake or what this is/was called

Katana uses LuaJIT quite extensively for user-side OpScripts, and previously both DNeg and MPC (they've largely moved on to newer tech now) had quite a lot of Lua code...

Oh, I had no idea! I don’t have much to do with Katana, I just assumed it was also all python

It used to in older (pre 2.0) versions, but due to Python's GIL lock (and the fact Python's quite a bit slower than lua anyway), it was pretty slow an inefficient using Python with AttributeScripts, so 2.0 moved to Lua with OpScripts...

It absolutely is. For a language whose biggest selling factor is embeddability with C/C++, that decision (and I'm being polite) is a headscratcher (along with the other similar source of errors: 0 evaluating to true).

It's the perfect distraction: once you start accepting one-based, everything else that might be not quite to your liking isn't worth talking about. I could easily imagine an alternative timeline where lua was zero-based, but never reached critical mass.

Absolutely so. It’s just one obvious thing from a large set of issues with it.

One can read through “mystdlib” part of any meaningful Lua-based project to see it. Things you’ll likely find there are: NIL, poor man’s classes, __newindex proxying wrapper, strict(), empty dict literal for json, “fixed” iteration protocols.

You don’t even have to walk too far, it’s all right there in neovim: https://neovim.io/doc/user/lua.html


Perhaps that's the secret to lua's success: they got the basics so wrong that they can't fall into the trap of chasing the dream of becoming a better language, focusing on becoming a better implementation instead. Or perhaps even more important: not changing at all when it's obviously good enough for the niche it dominates.

This is very valuable! Thank you!

That's an interesting notion but I think that Lua had no competition - it was almost unique in how easy it was to integrate vs the power it gives. Its popularity was inevitable that way.

The language actually started as a data entry notation for scientists.

I don't really blame Lua for that, though. 1-based indexing comes naturally to humans. It's the other languages which are backwards. I get why other languages are backwards from human intuition, I do. But if something has to be declared the bad guy, imo it's the paradigm which is at odds with human intuition which deserves that label, not the paradigm which fits us well.

1-based indexing is not any more natural than 0-based, it’s just that humans started indexing before the number 0 was conceptualized.

https://www.cs.utexas.edu/~EWD/transcriptions/EWD08xx/EWD831...

Why numbering should start at zero. -- Dijkstra


Argument by authority.

To me 1 based indexing is natural if you stop pretending that arrays are pointers + index arithmetics. Especially with slicing syntax.

It's one of the things that irked me when switching to Julia from Python but which became just obviously better after I made the switch.

E.g. in Julia `1:3` represents the numbers 1 to 3. `A[1]` is the first element of the array, `A[1:3]` is a slice containing the first to third element. `A[1:3]` and `A[4:end]` partitions the array. (As an aside: `For i in 1:3` gives the number 1, 2, 3.)

The same sentence in python:

`1:3` doesn't make sense on its own. `A[0]` is the first element of the array. `A[0:3]` gives the elements `A[0], A[1]` and `A[2]`. `A[0:3]` and `A[3:]` slice the array.

For Python, which follows Dijkstra for its Slice delimiters, I need to draw a picture for beginners (I feel like the numpy documentation used to have this picture, but not anymore). The Julia option requires you to sometimes type an extra +1 but it's a meaningful +1 ("start at the next element") and even beginners never get this wrong.

That said, it seems to me that for Lua, with the focus on embedding in the C world, 0 index makes more sense.


I admire Dijkstra for many things, but this has always been a weak argument to me. To quote:

"when starting with subscript 1, the subscript range 1 ≤ i < N+1; starting with 0, however, gives the nicer range 0 ≤ i < N"

So it's "nicer", ok! Lua has a numeric for..loop, which doesn't require this kind of range syntax. Looping is x,y,step where x and y are inclusive in the range, i.e. Dijkstra's option (b). Dijkstra doesn't like this because iterating the empty set is awkward. But it's far more natural (if you aren't already used to languages from the 0-indexed lineage) to simply specify the lower and upper bounds of your search.

I actually work a lot with Lua, all the time, alongside other 0-indexed languages such as C and JS. I believe 0 makes sense in C, where arrays are pointers and the subscript is actually an offset. That still doesn't make the 1st item the 0th item.

Between this, and the fact that, regardless of language, I find myself having to add or subtract 1 frequently in different scenarios, I think it's less of a deal than people make it out to be.


In any language, arrays are inherently regions of memory and indexes are -- whether they start at 0 or 1 -- offsets into that region. When you implement more complicated algorithms in any language, whether or not it has pointers or how arrays are syntactically manipulated, you start having to do mathematical operations on both indexes and on ranges of index, and it feels really important to make these situations easier.

If you then even consider the simple case of nested arrays, I think it becomes really difficult to defend 1-based indexing as being cognitively easier to manipulate, as the unit of "index" doesn't naturally map to a counting number like that... if you use 0-based indexes, all of the math is simple, whereas with 1-based you have to rebalance your 1s depending on "how many" indexes your compound unit now represents.


And the reason to dismiss c) and d) is so that the difference between the delimiters is the length. That's not exactly profound either.

If the word for word same argument was made by an anonymous blogger no one would even consider citing this as a definitive argument that ends the discussion.


Associative arrays are also "nicer" with 1 based indexing

  t={}
  t[#t+1] --> t[1] DONE!
  t[#t==0 and 0 or #t+1]
Now, in order to fix this (or achieve the same behavior as #t+1), the length operator must return -1, which would be ridiculous. its empty, and we have a perfect representation of emptiness in math "0".

This is also true in awk as well, nobody ever whines about awk "arrays" being 0


Especially when one of the language's main purposes is to be embedded in applications written in other languages (which are predominantly zero based) - and so you tend to have a lot of back-and-forth integration between these two styles that can get confusing. Even from the C API side, for example, the Lua stack is one-based but addressed exclusively from the host language which is likely zero-based.

Don't forget that not equals is ~=, the horror.

The real gripes should be globals by default and ... nothing. Lua is wonderful.


"Don't forget that not equals is ~=, the horror."

I get you are taking the piss but ~= is just as logical as != being the symbols for: "not equals", if you've been exposed to some math(s) as well as ... well, ! means factorial, doesn't it?

Syntax is syntax and so is vocabulary! In the end you copy and paste off of Stack Exchange and all is golden 8)


! is commonly used as the unary not operator, so "a != b" makes sense as a shortcut for "!(a == b)". a not equals b.

But in Lua, the unary not is written as “not”.

For a language apparently inspired from Wirth, one would have expected <> (greater-or-lesser-than). But the real horror, to me, is Windows not letting one disable the so~called "dead keys" easily.

I'm more familiar with CSS than I am with Lua. The syntax for the former has a very different meaning[1].

  [attr~=value]
  Represents elements with an attribute name of attr whose value is a whitespace-separated list of words, one of which is exactly value.

[1] https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_s...

It's _ENV by default, it just defaults to _G.

Yeah, 36 years of Unicode and it's still not ‘≠’.

In unicode != on a keyboard

It is funny, isn't it? I always wonder how the language would be perceived had they gone with zero based indexing from the start.

I'm a big fan of Lua, including for the reasons you mention. I suspect the reason this one thing is always brought up is twofold: it's easy to notice, and it's very rare these days outside of Lua (if you consider VB.NET to be a legacy language, anyway). Other criticisms take more effort to communicate, and you can throw a rock and hit ten other languages with the same or similar issues.


Honestly, it might almost act as a "honeypot" to give people a convenient target to complain about, which makes it easier for the rest of the language to get viewed as a whole rather than nitpicked. Sometimes I think people like to have at least one negative thing to say about something new they learn, whether it's to show that they understand enough to be able to find something or it's to be "cool" enough not to just like everything.

that would be a galaxy brain move on the part of lua.

To be clear, I'm not claiming that I think this was the original intent for implementing array indexes like this; I'm just theorizing that this might explain why this ends up being such a fixation when it comes to discusses downsides of Lua.

>Makes Brendan Eich look like a total clown in comparison.

To be fair, Brendan Eich was making a scripting language for the 90's web. It isn't his fault Silicon Valley decided that language needed to become the Ur-language to replace all application development in the future.


Most of the blame should go to Netscape management. They didn't give Eich much time, then burst in before he was done and made him copy a bunch of things from Java. (The new language, codenamed "Mocha" internally, was first publicly announced as "LiveScript", and then Sun threw a bunch of money at Netscape.)

IIRC, Eich was quite influenced by Python's design. I wish he'd just used Lua - would likely have saved a lot of pain. (Although, all that said, I have no idea what Lua looked like in 1994, and how much of its design has changed since then.)


https://news.ycombinator.com/item?id=1905155

If you don't know what Lua was like then, don't wish that I'd "just used Lua".

Other issues include Netscape target system support, "make it look like Java" orders from above, without which it wouldn't have happened, and more.


Oh hi Yoz! LTNS! Hi Brendan!

It sounds like you're saying Yoz got the sequence of events wrong, and that MILLJ was a necessary part of getting scripting in the browser? I sort of had the impression that the reason they hired you in the first place was that they wanted scripting in the browser, but I wasn't there.

I don't think Lua was designed to enforce a security boundary between the user and the programmer, which was a pretty unusual requirement, and very tricky to retrofit. However, contrary to what you say in that comment, I don't think Lua's target system support or evolutionary path would have been a problem. The Lua runtime wasn't (and isn't) OS-dependent, and it didn't evolve rapidly.

But finding that out would have taken time, and time was extremely precious right then. Also, Lua wasn't open-source yet. (See https://compilers.iecc.com/comparch/article/94-07-051.) And it didn't look like Java. So Lua had two fatal flaws, even apart from the opportunity cost of digging into it to see if it was suitable. Three if you count the security role thing.


> It isn't his fault Silicon Valley decided that language needed to become the Ur-language to replace all application development in the future.

Which remains one of the most baffling decisions of all time, even to this day. Javascript is unpleasant to work with in the browser, the place it was designed for. It is utterly beyond me why anyone would go out of their way to use it in contexts where there are countless better languages available for the job. At least in the browser you pretty much have to use JS, so there's a good reason to tolerate it. Not so outside of the browser.


> To be fair, Brendan Eich was making a scripting language for the 90's web.

He was, and he doesn't deserve the full blame for being bad at designing a language when that wasn't his prior job or field of specialization.

But Lua is older so there's this element of "it didn't need to be this bad, he just fucked up" (And Eich being a jerk makes it amusing to pour some salt on that wound. Everyone understands it's not entirely serious.)


"Silicon Valley" is not an actor (human or organization of humans) that decided any such thing. This is like saying a virus decides to infect a host. JS got on first, and that meant it stuck. After getting on first, switching costs and sunk costs (fallacy or not) kept it going.

The pressure to evolve JS in a more fair-play standards setting rose and fell as browser competition rose and fell, because browser vendors compete for developers as lead users and promoters. Before competition came back, a leading or upstart browser could and did innovate ahead of the last JS standard. IE did this with DHTML mostly outside the core language, which MS helped standardize at the same time. I did it in Mozilla's engine in the late '90s, implementing things that made it into ES3, ES5, and ES6 (Array extras, getters and setters, more).

But the evolutionary regime everyone operated in didn't "decide" anything. There was and is no "Silicon Valley" entity calling such shots.


> "Silicon Valley" is not an actor (human or organization of humans) that decided any such thing.

Oh come on, you understand full well that they're referring to the wider SV business/software development "ecosystem".

Which is absolutely to blame for javascript becoming the default language for full-stack development, and the resulting JS-ecosystem being a dysfunctional shitshow.

Most of this new JS-ecosystem was built by venture capital startups & tech giants obsessed with deploying quickly, with near-total disregard for actually building something robustly functional and sustainable.

e.g. React as a framework does not make sense in the real world. It is simply too slow on the median device.

It does, however, make sense in the world of the Venture Capital startup. Where you don't need users to be able to actually use your app/website well. You only need that app/website to exist ASAP so you can collect the next round of investment.


Oh come on yourself.

Companies including Bloomberg and Microsoft (neither in or a part of Silicon Valley), also big to small companies all over the world, built on JS once Moore’s Law and browser tech combined to make Oddpost, and then gmail, feasible.

While the Web 2.0 foundations were being laid by indie devs, Yahoo!, Google, others in and out of the valley, most valley bigcos were building “RIAs” on Java, then Flash. JS did not get some valley-wide endorsement early or all at once.

While there was no command economy leader or bureaucracy to dictate “JS got on first but it is better to replace it with [VBScript, likeliest candidate]”, Microsoft did try a two-step approach after reacting to and the reverse-engineering JS as “JScript”.

They also created VBS alongside JS, worked to promote it too (its most used sites were MS sites), but JS got on first, so MS was too late even by IE3 era, and IE3 was not competitive vs. Netscape or tied to Windows. IE4 was better than Netscape 3 or tardy, buggy 4 on Windows; and most important, it was tied. For this tying, MS was convicted in _U.S. v. Microsoft_ of abusing its OS monopoly.

Think of JS as evolution in action. A 2024-era fable about the Silly Valley cartel picking JS early or coherently may make you feel good, but it’s false.


Wasn't the language he was making for the web Scheme?

No, Scheme was defined in 1975.

So? That doesn't stop Brendan Eich from putting it in a web browser 20 years later.

No, it does not. I see I misunderstood your q.

I don't think JavaScript will replace all application development in the future. WebAssembly will displace JavaScript. With WebAssembly you can use whatever language you like and achieve higher performance than JavaScript.

if you fix the one based indexing you should call yours KT@ or Kt`

> I'm thinking about designing an embedded scripting language that addresses some of these issues...

https://xkcd.com/927/

;)


To add to this, there are also official Microsoft extensions to VSCode which add absurdly useful capabilities behind subtle paywalls. For example, the C# extension is actually governed by the Visual Studio license terms and requires a paid VS subscription if your organization does not qualify for Visual Studio Community Edition.

I'm not totally sold on embrace-extemd-extinguish here, but learning about this case was eyebrow raising for me.


C# extension is MIT, even though vsdbg it ships with is closed-source. There's a fork that replaces it with netcoredbg which is open.

C# DevKit is however based on VS license. It builds on top of base C# extension, the core features like debugger, language server, auto-complete and auto-fixers integration, etc. are in the base extension.


When I used to work in defense contracting, this is precisely what we (the contractor) did. We would buy up all available stock of any difficult-to-replace parts (often specific SBCs) when the manufacturer announced end of life.


There's a market in conforming interface and ABI spec meeting hardware to emulate the boot and upgrade devices for German tanks, or some other hardware. Sd card or USB behind, giant milspec plug to the fore.


Doesn’t it rot?


Given that it's definitionally military-grade hardware, and very high value-density and therefore easy to store very securely, I doubt it.


I've ruled out several properties in my current homebuying search for this exact reason. Having lived next to the neighborhood collection pond once before (a rental thankfully), I'm extra paranoid about stormwater and drainage now.

I've seen a number of homes in my area where the builder received special permission to build right where the drainage needs to go. Some were beautiful and I was tempted to give it a shot, but your story reminds me that I need to trust my gut on this issue and head for high ground.


My organic chemistry professor always liked to point out that while CO2 is a gas that is easily dealt with following metabolism, SiO2 - silica/quartz - is most decidedly not a gas. Add that to the list of challenges for silicon-based lifeforms. Not to say that it isn't possible, but it does constrain the solution space somewhat.


> The random number returned is OR-ed with 0b1000000000000001 to set its first and last bit to 1. The last bit set to 1 makes it an odd number and the first bit set to 1 ensures that it is a sufficiently large number which covers the entire range of bits I need.

I can understand setting the low bit to 1 since an even number will never be a prime (edit: obviously except 2). But why set the high bit to 1 as well? Admittedly I don't know much about prime numbers or crypto, but it seems to me like this is just giving up a bit of entropy unnecessarily. What am I missing here?


Another factor is if your high bit is always set, and you encode the prime with that bit, your prime always takes the same number of byte to encode.

Variable byte encoding can lead to problems, if you need to exchange the data between different software, unless the specifications are very clear, and well tested. (See problems with RSA based DHE if the server public key has leading zeros)


Same as generating a 2 digit number. If the first digit is a zero, it is not a 2 digit number.


For the purposes of key generation, however, wouldn't you want the full n bits of entropy? Otherwise the search space for a brute force factorization (haha right) is 2^(n-1) instead of 2^n, or half as many possibilities. The domain of the product is still [0..2^(2n)] so the resulting key is the desired 2^(2n) bits.

I guess another way to pose my question would be: is there an issue with sampling the entire 2^n space that makes us only take the highest 2^(n-1) subset of integers instead when selecting factors for a key?


you want the nth bit to be set because otherwise there is a small but noticable chance that you generate a surprisingly weak prime.


Out of curiosity, if it is known that the nth bit is set, don't I also have the same risk but in (n-1) bits? Genuinely curious here.

Edit: Ah, nevermind, I see now why I don't have that issue. It's because I can't easily iterate the primes in that domain even though I can iterate the reduced number of bits. Thanks!


As the other comments have mentioned, by setting the first bit to one it looses a bit of entropy but ensures that the prime is large enough. Another thing to add is that in RSA two primes are multiplied together. If one of them is 1024 bits the other can be ~200 bits (if i remember correctly) and still reach the required number of entropy bits for the key. So, having both primes be 1024-bit adds a bit of wiggle room too.


You are giving up a bit of entropy, yeah, but you still have 1022, it's probably safer than wondering if a 1020 bit prime is fine even if they asked for a 1024 bit one. Eg we usually don't consider 00042 a 5-digit number.

Technically probably depends on exactly what you're using it for which choice is optimal, but I'd think the one in the article is the safer default.


Losing one bit of entropy to generate a prime that's definitely not only 50 bits long seems like a worthy tradeoff.


Not disagreeing with your point, but it couldn't be a compiler optimization, could it? The compiler isn't able to infer that the class will not be inherited anywhere else, since another compilation unit unknown to the class could inherit.


Possibly not in the default c++ language mode, but check out -fwhole-program-vtables. It can be a useful option in cases where all relevant inheritance relationships are known at compile time.

https://reviews.llvm.org/D16821


Which is good, but may not apply. I have an application where I can't do that because we support plugins and so a couple classes will get overridden outside of the compilation (this was in hindsight a bad decision, but too late to change now). Meanwhile most classes will never be overriden and so I use final to saw that. We are also a multi-repo project (which despite the hype I think is better for us than mono-repo), another reason why -f-whole-program-vtables would be difficult to use - but we could make it work with effort if it wasn't for the plugins.


I assume it could be or is part of link time optimization when compiling an application rather than a library?


Very similar experience here, and I ended up going directly into industry instead of a postdoc because I had the same realization. I'm glad I did it that way, though, because I'm very proud of my research and I think we did something very interesting and novel.


Welp, glad I didn't go through with trying to contribute to TMW. That's disappointing to hear. I've had a much better experience trying to build my own MMO engine instead.


In 200 years this is going to be like when we discover yet another proof of Euler or Gauss, 20 years after a current mathematician arrived at the same result.


Or it could be like multipoint touch screens, early version of which were a solved problem in 1980s or earlier, and just needed compute power to catch up, which it did over subsequent decades.

Or it could be like code=data and homoiconity and other CS fundamentals that were figured out 40+ years ago, but are still mostly ignored by software industry/culture.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: