LuaJIT 3.0's named varargs can skip the table allocation
LuaJIT issue #1475 is the umbrella proposal for LuaJIT 3.0's syntax extensions: bit operators, ternary, safe navigation, const, continue and more.
Issue #1475 in the LuaJIT repository is an umbrella document for every syntax extension planned for LuaJIT 3.0, and the list runs long: C-style bit operators, the customary spellings !, &&, || and !=, a ternary conditional ?:, a safe navigation operator ?., a nil-coalescing operator ??, compound assignment (+=, -=, *= and the rest), floor division //, a continue statement, a const declaration, arrow-style short functions, named vararg parameters, underscores in number literals, semicolons allowed anywhere, and a C-preprocessor-style line directive. Part of the work is consolidation, since LuaJIT’s existing extensions are documented in scattered places, and part is genuinely new surface.
The author sets a bar for what gets in: it has to improve day-to-day ergonomics, be proven in another language or Lua dialect, introduce no syntactic ambiguity, break no backwards compatibility, and not make life hard for formatters and language servers. There is an explicit line about not wanting the syntactic weight of Perl, Ruby, C++ or Rust.
The semantics are where the detail matters.
Bit operators
~ is xor, because ^ is already exponentiation in Lua. Right shift splits into >> for logical and ~>> for arithmetic; >>> was rejected because JavaScript uses it for a logical shift and the overlap would mislead. The operators work on plain Lua numbers, FFI cdata integers and integer vectors, and fall through to a metamethod on anything else. The bit.* library stays. The compatibility catch is worth flagging: these bitwise semantics differ from every Lua 5.2+ minor version, and those versions are mutually incompatible as well, so for code that has to run across Lua and LuaJIT the issue points you at the Lua BitOp module instead of the operators.
The null-safety trio
The ternary a ? b : c short-circuits and is right-associative, so nested conditions read left to right. It has one sharp edge: b cannot directly hold a method call, because obj:method() creates a parse ambiguity, so you wrap it as cond ? (obj:method()) : default. The operator earns its place by fixing the old a and b or c trap, where a truthy a still returns c when b is nil or false. true and false or 42 yields 42; true ? false : 42 yields the false you meant.
Safe navigation ?. checks the left side for nil before indexing or calling, and in LuaJIT only nil values and NULL cdata pointers compare equal to nil. When the left side is nil, the rest of the chain is suppressed: no indexing, no call, no metamethod lookup, and in an indexed assignment the right-hand expression is not evaluated either, which matters when it has side effects. A chain like a?.b?.[c]?.d?.:e?.() performs five independent checks.
nil-coalescing a ?? b returns a unless it is nil, in which case it returns b, and a is evaluated once. It replaces a or b, which also hands back b when a is false, and which treats a NULL cdata pointer as truthy.
Compound assignment
obj.ctx.arr[idx].count += 10 resolves the target path once rather than twice, so x.y.z.field += b behaves as local tmp = x.y.z; tmp.field = tmp.field + b. It invokes __index and __newindex where the long form would, and when the operation itself needs a metamethod it passes true as a third argument, as in __add(a, b, true), which lets the metamethod mutate in place and return the first operand. There is no ++ or --, since -- collides with comment syntax, and ^= was omitted on purpose because in most languages that spelling means xor-assign.
const, continue, short functions
const gives a block-scoped binding that cannot be reassigned, though the contents of a const table remain mutable. The proposal is blunt that this is about catching mistakes rather than speed: “a modern compiler can figure out ‘constness’ of a variable by itself and is helped only very little by a constant declaration.” continue is the jump-to-hidden-label at the end of a loop that people have long written by hand with goto. Both are soft keywords, so existing code that uses const or continue as a variable name still parses. Short functions give you |a, b| -> a + b and, for a single parameter, x -> x + 1; the issue cautions that Lua is imperative and LuaJIT is not tuned for heavy functional style, so leaning hard on lambdas will disappoint.
Named varargs, the one with a speed story
function f(a, b, ...va) binds va to a const table whose va.n holds the argument count. Built by hand with select("#", ...), that table is a real allocation; with the named form the VM can elide the allocation when the only uses are read-only indexing, which makes it both tidier and faster than plain .... Use va.n, not #va: the length operator reports the wrong count when nil arguments are passed, so (|...va| -> #va)(nil, nil) is 0 while va.n is 2.
What to watch
Underscores in number literals (1_234_567_890) are accepted by the source parser in any position after the first digit, across every base and suffix. tonumber() and implicit string-to-number coercion do not accept them, so a separator that is valid in a literal will fail the moment the same text reaches you as a string through config or user input. The line directive (# 123 "input.file") and semicolons-anywhere exist for code generators, so generated Lua can carry its original file and line into error messages.
Keep Reading
data breachA February 2025 migration exposed DigiCert customer records online
A February 2025 server migration exposed a DigiCert internal system, and a self-registered account read archived customer data and identity documents.
OpenSSHLong Passwords Bypass Alpine SSH Authentication
OpenSSH 10.6p2 fixes a critical password authentication bypass affecting Alpine Linux and other potentially vulnerable musl systems.
opensshLong passwords unlock disabled accounts
The "*sshole" flaw lets oversized passwords log into *-disabled accounts on musl-based OpenSSH servers like Alpine under certain configurations. Fixed in 10.6p2.
Latest on the Wire
Full wire →- Bending Spoons Destroys Harvest With 10x Price Hike and LLM SupportHacker News
- CISA Flags SonicWall MFA Bypass Amid Exploitation ReportsThe Hacker News
- Claude Opus Ports 3D Models from Three.js to Vanilla WebGLSimon Willison
- Collapsing AI PR descriptions with HTML details tagsSimon Willison
New signal daily · RSS
Stay in the loop
New writing delivered when it's ready. No schedule, no spam.