[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Lua pattern matching for the poor
- From: "Alexander Gladysh" <agladysh@...>
- Date: Mon, 20 Mar 2006 16:40:02 +0300
Hi all!
While playing with language, I've came to following implementation of
pattern-matching-for-the-poor in Lua. Any comments?
Example:
match {
{
function() return true_if_matched end;
function(optional_match_results) do_something() end
};
{
function() return true_if_matched_2 end;
function(optional_match_results) do_something_else() end
};
{
function() return true end;
function(optional_match_results) default_case() end
};
}
To get rid of limitation for unified predicate interface, match
construction assumes predicates work with some upvalues.
While this approach brings considerable syntax and (possibly)
performance overhead, I think it still can be useful in some cases...
With best regards,
Alexander.
-- TODO: This whole thing looks quite performance-hungry.
-- T is table filled with pairs of nullary match-predicates and
result generators,
-- accepting table of return values from match-predicates:
-- t = { {function() ... end, function() ... end} }
-- Matches first valid pattern.
match = function(t)
local res;
for _, v in t do
res = { v[1]() }
if res[1] then return v[2](res) end
end
return assert(false, "No match")()
end
-- Some utility functions
inv = function(v) -- invariant
return function() return v end
end
default = inv(true);
append_to_iter = function(val, iter)
local iter_fn
iter_fn = function() iter_fn = iter; return val end
return function()
return iter_fn();
end
end
-- Silly example:
my_gfind = function(s, pat)
local m = string.gfind(s, pat)
return m(), m
end
-- Some macroses would help greatly to reduce syntax overhead.
classificate = function(str)
-- Not using inv() for first two cases to delay potentially
performance-hungry evaluation.
return match {
{
function() return my_gfind(str, "%d+") end;
function(m) return "numbers", append_to_iter(m[1], m[2]) end
};
{
function() return my_gfind(str, "%a+") end;
function(m) return "letters", append_to_iter(m[1], m[2]) end
};
{ default; inv(nil) };
}
end
print_classification = function(str)
local r = { classificate(str) }
-- Conventional if would do here :)
match {
{
inv(r[1] ~= nil);
function()
print("type: ", r[1], "\nvalues:");
for val in r[2] do
print(val);
end
end
};
{ default; function() print("type:", "unclassified") end };
}
end
print_classification("this matches numbers 1 and 2");
print_classification("this matches words");
print_classification(")($&*#@($*&#$"); -- No match.