A
A
Anatoly Ivanov2018-06-25 12:18:24
Python
Anatoly Ivanov, 2018-06-25 12:18:24

how to override if in python?

I saw an example of introducing my own if option in Lisp Scheme

(define (new-if predicate then-clause else-clause)
    (cond (predicate then-clause)
    (else else-clause)))

how to do the same in python and is there any possibility to override the behavior of if or any other keyword?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergey Gornostaev, 2018-06-25
@apeks

First of all, I want to note that no other language provides such great opportunities for extending the language as in Lisp. But in some languages, including Python, you can do a little magic with the code at the stage of parsing it.

import ast
import sys

class DumbLisp(ast.NodeTransformer):
    def fix(self, source, result):
        ast.copy_location(result, source)
        ast.fix_missing_locations(result)
        return result

    def visit_Expr(self, node):
        if isinstance(node.value, ast.Tuple):
            t = node.value
            if isinstance(t.elts[0], ast.Name):
                if t.elts[0].id == 'newif':
                    _else = [ast.Expr(value=t.elts[3])] if len(t.elts) == 4 else []
                    _if = ast.If(test=t.elts[1],
                                body=[ast.Expr(value=t.elts[2])],
                                orelse=_else)
                    self.generic_visit(_if)
                    return self.fix(node, _if)
                elif t.elts[0].id == 'define':
                    assign = ast.Assign(targets=[ast.Name(id=t.elts[1].id, ctx=ast.Store())],
                                        value=t.elts[2])
                    return self.fix(node, assign)
                else:
                    call = ast.Expr(value=ast.Call(func=t.elts[0], args=t.elts[1:], keywords=[]))
                    return self.fix(node, call)
        return node


with open(sys.argv[1]) as fh:
    tree = ast.parse(fh.read())
    DumbLisp().visit(tree)
    code = compile(tree, filename=sys.argv[1], mode="exec")
    exec(code)

(define, a, 1)

(newif, a == 1, (print, 'Yes'), (print, 'No'))

Running
Naturally, the example is extremely simple, and therefore we have to use tuples as s-forms. But there is a full-fledged Python compiler front-end that translates a Lisp dialect close to Clojure - Hy into python bytecode .

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question