lua-users home
lua-l archive

Lua pattern matching for the poor

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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.

AltStyle によって変換されたページ (->オリジナル) /