Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions changelog.d/20260713_144500_fromstring_fn4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
### Fixed

- `fromStringImpl` matches its `Fn4` declaration: the Lua entry is a single
4-ary function (previously it was a chain of nested single-argument
closures, so `Data.Number.fromString` returned a function instead of a
`Maybe Number` — Lua silently drops the surplus arguments of the n-ary
`runFn4` call).
25 changes: 10 additions & 15 deletions src/Data/Number.lua
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,15 @@ return {
sqrt = (math.sqrt),
tan = (math.tan),
trunc = (function(x) return x < 0 and math.ceil(x) or math.floor(x) end),
fromStringImpl = (function(str)
return function(isFinite)
return function(just)
return function(nothing)
-- Mirror JS parseFloat: a leading-numeric prefix is parsed and
-- trailing junk (and a whitespace prefix) is tolerated. Guard against
-- a failed parse — the old code wrapped tonumber's nil in Just — and
-- use the supplied isFinite predicate so non-finite results are Nothing.
local prefix = str:match("^%s*([%-+]?%d*%.?%d+[eE]?[%-+]?%d*)")
local x = prefix and tonumber(prefix) or nil
if x ~= nil and isFinite(x) then return just(x) end
return nothing
end
end
end
fromStringImpl = (function(str, isFinite, just, nothing)
-- Declared Fn4, so the entry is a single 4-ary function.
-- Mirror JS parseFloat: a leading-numeric prefix is parsed and
-- trailing junk (and a whitespace prefix) is tolerated. Guard against
-- a failed parse — the old code wrapped tonumber's nil in Just — and
-- use the supplied isFinite predicate so non-finite results are Nothing.
local prefix = str:match("^%s*([%-+]?%d*%.?%d+[eE]?[%-+]?%d*)")
local x = prefix and tonumber(prefix) or nil
if x ~= nil and isFinite(x) then return just(x) end
return nothing
end)
}
6 changes: 4 additions & 2 deletions test/regression/number.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@ check("min 1 NaN is NaN", isNaN(M.min(1)(nan)), tostring(M.min(1)(nan)))
check("min NaN 1 is NaN", isNaN(M.min(nan)(1)), tostring(M.min(nan)(1)))
check("min 3 7 == 3", M.min(3)(7) == 3, tostring(M.min(3)(7)))

-- #93 fromString (via the Fn4-style curried FFI)
-- #93 fromString. fromStringImpl is declared `Fn4`, so the Lua entry is a
-- 4-ary function called with all arguments at once (`runFn4` and the
-- compiler's uncurried lift both call it that way).
local function just(x) return {tag = "just", value = x} end
local nothing = {tag = "nothing"}
local function fromString(s) return M.fromStringImpl(s)(M.isFinite)(just)(nothing) end
local function fromString(s) return M.fromStringImpl(s, M.isFinite, just, nothing) end
local function isJust(m, v) return type(m) == "table" and m.tag == "just" and m.value == v end
local function isNothing(m) return type(m) == "table" and m.tag == "nothing" end

Expand Down