More Related Content Similar to Functional Pattern Matching on Python Similar to Functional Pattern Matching on Python (20) More from Daker Fernandes More from Daker Fernandes (9) Functional Pattern Matching on Python3. PROLOG
botname("Chatty").
chatterbot(['hello'], ['Hello', ',', 'my', 'name', 'is', B]) :-
botname(B).
chatterbot(['how', 'much', 'is' | Expr], ['It', 'is'], Result) :-
eval_expression(Expr, Result).
chatterbot(['my', 'name', 'is', Name], ['Nice', 'to', 'meet', 'you']) :-
assert(name(Name)).
6. HASKELL
count :: [n] -> n -> n
count (n:tail) n = 1 + count tail n;
count (k:tail) n = count tail n;
count [] _ = 0;
11. HOW IT WORKS?
@patterns
if function():
if RULE1: EXPRESSION1
if RULE2: EXPRESSION2
...
if function(*args):
if match(args, RULE1):
ASSIGNS1
return EXPRESSION1
elif match(args, RULE2):
ASSIGNS2
return EXPRESSION2
else:
raise Mismatch()
14. CHATTERBOT
botname = "Chatty"
@patterns
def answer():
if ['hello']:
"Hello, my name is %s" % botname
if ['hello', 'my', 'name', 'is', name]:
"Hello, %s!" % name.capitalize()
if ['how', 'much', 'is'] + expr:
"It is %d" % eval(' '.join(expr))
if ['bye']:
"Good bye!"
15. CHATTERBOT
botname = "Chatty"
def answer(message):
if message == ['hello']:
return "Hello, my name is %s" % botname
elif message[:-1] == ['hello', 'my', 'name', 'is']:
return "Hello, %s" % message[-1].capitalize()
elif message[:3] == ['how', 'much', 'is']:
return "It is %d" % eval(' '.join(expr))
elif message == ['bye']:
return "Good bye!"
else:
raise Mismatch()
17. PATTERNS
import sys, inspect, ast, re
from ast import *
def patterns(func):
empty_argspec = inspect.ArgSpec(args=[], varargs=None,
keywords=None, defaults=None)
assert inspect.getargspec(func) == empty_argspec
# TODO: make it not as weird and dirty
func.__globals__['Mismatch'] = Mismatch
tree = get_ast(func)
transform_function(tree.body[0])
return compile_func(func, tree)
18. GET_AST
def get_ast(func):
# Get function source
source = inspect.getsource(func)
# Fix extra indent if present
spaces = re_find(r'^s+', source)
if spaces:
source = re.sub(r'(^|n)' + spaces, 'n', source)
return ast.parse(source, func_file(func), 'single')
21. TRANSFORM_FUNCTION
...
if isinstance(cond, (Num, Str, List, Tuple)) and not has_vars(cond):
test.test = make_eq(N('value'), cond)
if isinstance(cond, (Num, Str, Name, Compare, List,
Tuple, Dict, BinOp)):
tests, assigns = destruct_to_tests_and_assigns(N('value'), cond)
test.test = BoolOp(op=And(), values=tests) if tests else V(1)
test.body = assigns + test.body
else:
raise TypeError("Don't know how to match %s" % ...)
...
22. TRANSFORM_FUNCTION
...
if isinstance(cond, (Num, Str, List, Tuple)) and not has_vars(cond):
test.test = make_eq(N('value'), cond)
if isinstance(cond, (Num, Str, Name, Compare, List,
Tuple, Dict, BinOp)):
tests, assigns = destruct_to_tests_and_assigns(N('value'), cond)
test.test = BoolOp(op=And(), values=tests) if tests else V(1)
test.body = assigns + test.body
else:
raise TypeError("Don't know how to match %s" % ...)
...
24. TESTS_AND_ASSIGNS
def destruct_to_tests_and_assigns(topic, pattern):
if isinstance(pattern, (Num, Str)):
return [make_eq(topic, pattern)], []
elif isinstance(pattern, Name):
return [], [make_assign(pattern.id, topic)]
elif isinstance(pattern, Compare) and
len(pattern.ops) == 1 and isinstance(pattern.ops[0], Is):
return [make_call('isinstance', topic, pattern.comparators[0])],
[make_assign(pattern.left.id, topic)]
...
26. Q & A
DAKER FERNANDES PINHEIRO
HTTP://CODECEREAL.BLOGSPOT.COM