aboutsummaryrefslogtreecommitdiff
path: root/patter.rb
diff options
context:
space:
mode:
authorNat Lasseter <Nat Lasseter user@4574.co.uk>2018-02-15 14:50:59 +0000
committerNat Lasseter <Nat Lasseter user@4574.co.uk>2018-02-15 14:50:59 +0000
commitbfed3dfba46a3f39389bdb529e021e266128df67 (patch)
treee624950a22a25c66b3ef83c9f2af99d6aac3e616 /patter.rb
Initial Commit
Diffstat (limited to 'patter.rb')
-rw-r--r--patter.rb43
1 files changed, 43 insertions, 0 deletions
diff --git a/patter.rb b/patter.rb
new file mode 100644
index 0000000..348cbdf
--- /dev/null
+++ b/patter.rb
@@ -0,0 +1,43 @@
+module Patter
+ class Var; end
+
+ class Fun
+ def initialize
+ @patterns = {}
+ end
+
+ def when(*args, &block)
+ raise "Block arity does not match number of free variables" if args.count(Var) != block.arity
+ @patterns[args] = block
+ end
+
+ def call(*args)
+ free_vars, block = match(args)
+ block.call(*free_vars)
+ end
+
+ alias_method :[], :call
+
+ private
+
+ def match(args)
+ @patterns.each do |pattern, block|
+ next if pattern.length != args.length
+ free_variables = []
+ matched = true
+ pattern.zip(args).each do |pair|
+ if pair.first == Var then
+ free_variables << pair.last
+ next
+ end
+ if pair.first != pair.last then
+ matched = false
+ break
+ end
+ end
+ return [free_variables, block] if matched
+ end
+ raise "Inexhaustive patterns"
+ end
+ end
+end