1 Python & Pattern Matching with Regular Expressions (REs) OPIM 101 File:PythonREs.ppt.
Functional Pattern Matching on Python
-
Upload
daker-fernandes -
Category
Technology
-
view
1.991 -
download
1
Transcript of Functional Pattern Matching on Python
DAKER FERNANDESPINHEIRO
UFPE
INDT RECIFE
WEBKIT (NIX)
QT, KDE, ...
C++, C, PYTHON, JAVASCRIPT, PROLOG, ...
PYTHON SINCE 2009
PROLOGbotname("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)).
PATTERNMATCHING
HASKELLfib :: Int -> Intfib 1 = 1;fib n = n * fib n - 1;
HASKELLcount :: [n] -> n -> ncount (n:tail) n = 1 + count tail n;count (k:tail) n = count tail n;count [] _ = 0;
ERLANGgreet(male, Name) -> io:format("Hello, Mr. ~s!", [Name]);greet(female, Name) -> io:format("Hello, Mrs. ~s!", [Name]);greet(_, Name) -> io:format("Hello, ~s!", [Name]).
PYTHON!!@patternsdef fib(): if 1: 1 if n: n * fib(n - 1)
DISCLAIMER
PIP INSTALL PATTERNS... OR CLONE IT.
HOW IT WORKS?@patternsif 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()
PYTHON@patternsdef fib(): if 1: 1 if n: n * fib(n - 1)
def fib(n): if n == 1: return 1 else: return n * fib(n - 1)
TREE@patternsdef depth(): if ('Tree', _, left, right): 1 + max(depth(left), depth(right)) if None: 0
def depth(tree): if tree: return max(depth(tree[2]), depth(tree[3])) else: return 0
CHATTERBOTbotname = "Chatty"
@patternsdef 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!"
CHATTERBOTbotname = "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()
BREATH DEEP,SEEK PEACE
PATTERNSimport sys, inspect, ast, refrom 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)
GET_ASTdef 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')
TRANSFORM_FUNCTIONdef transform_function(func_tree): assert all(isinstance(t, If) for t in func_tree.body), \ 'Patterns function should only have if statements'
# Adjust arglist and decorators func_tree.args.args.append(Name(ctx=Param(), id='value')) func_tree.decorator_list = []
...
TRANSFORM_FUNCTION... for test in func_tree.body: cond = test.test...
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" % ...)
...
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" % ...)
...
TRANSFORM_FUNCTION ... func_tree.body = map(wrap_tail_expr, func_tree.body) func_tree.body.append( Raise(type=N('Mismatch'), inst=None, tback=None))
TESTS_AND_ASSIGNSdef 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)] ...
A NEW PEP? :-)