Skip to content

Conversation

@Kode-Red
Copy link

@Kode-Red Kode-Red commented Aug 25, 2025

Description

This PR introduces a new lib.switch utility function for Lua that provides a flexible, readable alternative to long if/elseif chains. The implementation supports value-based matching, lists of possible values, predicate functions, and a "default" fallback, with optional JavaScript-style fallthrough behavior.

Changes Made

  • Added lib.switch(valueOrList, fallthrough, cases, ...) API:
    • Value-first signature for natural usage.
    • First parameter can be a single value or a list of values to test.
    • Arguments are always provided as variadic parameters (4th, 5th, 6th… positions).
  • Implemented compile step with weak-key caching to minimize recomputation.
  • Supported match types:
    • Single values (number, string, etc.).
    • Multi-value case matches ({2,4,6}).
    • Predicate functions (function(v) return v < 0 end).
    • "default" (fallback if no match found).
  • Supported behaviors:
    • fallthrough = true: executes multiple cases sequentially until breakFn() is called.
    • fallthrough = false (default): executes only the first matching case.
    • Explicit breakFn() can halt fallthrough early.
  • Returned the result of the executed action (last case result in fallthrough mode).

Testing

  • Verified exact matches return correct result.
  • Verified lists of possible values ({'foo','bar'}) resolve to the earliest matching case.
  • Verified multi-value case matches ({2,4,6}) trigger correctly.
  • Verified predicate functions work as expected.
  • Verified "default" triggers when no matches exist.
  • Verified fallthrough behavior matches JavaScript semantics.
  • Verified variadic arguments (4th, 5th, etc.) are passed through correctly.
  • Verified breakFn() stops fallthrough early.

Performance Impact

  • Uses O(1) map lookups for single values and list entries.
  • Predicate checks only run when no value/list match exists.
  • Weak-key cache ensures compilation overhead happens once per cases table.
  • Efficient loop structure with minimal allocations.

Example Usages

Example 1 – Basic Value Match

local cases = {
  { match = 2, action = function(_, n) return n .. " is two" end },
  { match = function(v) return v > 5 end, action = function(_, n) return n .. " is greater than 5" end },
  { match = "default", action = function(_, n) return n .. " didn't match anything else" end },
}
local result = lib.switch(2, false, cases, 2)
print(result) -- "2 is two"

Example 2 – Fallthrough with List of Values

local cases = {
  { match = "concat",    action = function(_, a, b) print(a .. b) end },
  { match = "nonconcat", action = function(_, a, b) print(a) end },
  { match = "default",   action = function() print("no match") end },
}

lib.switch({"concat", "nonconcat"}, true, cases, "Hello ", "World")
-- Output:
-- Hello World
-- Hello
-- no match

Additional Notes

  • Initial implementation request for a structured switch-case utility in ox_lib.
  • Recommended to use the variadic form (lib.switch(value, false, cases, ...)) in hot code paths.
  • "default" case should be placed last for clarity.

EDIT: Updated to reflect recent changes. The first argument, if a table, is now treated as a list of values to match.
Arguments are no longer accepted inside that table and must always be passed as variadic parameters (4th, 5th, 6th…).

Introduces lib.switch, a compact utility function that provides a structured
alternative to long if/elseif chains.

Features:
- Supports value, multi-value list, predicate, and "default" matches.
- Optional fallthrough behavior (true = JS-style, false = stop after first).
- Explicit breakFn to halt fallthrough early.
- Variadic arguments or table-form ({ value, ... }) supported.
- Weak-key cache for compiled dispatchers to minimize overhead.

This implementation preserves performance with O(1) lookups for values and
lists, only falling back to predicate checks when necessary.
@Kode-Red
Copy link
Author

Should also note, I have documentation ready if this is approved.

- Changed `lib.switch` so the first argument, when a table, is interpreted strictly
  as a list of possible values to match against.
- Removed prior behavior of mixing case value and arguments in the same table.
- Arguments are now always passed starting from the 4th parameter onward.
- Supports both single values and lists of values, with earliest match resolution.
- Fallthrough (`true`) continues from the first matched case; without fallthrough,
  only the first match executes.
@Kr3mu
Copy link

Kr3mu commented Aug 26, 2025

That's a cool concept

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants