I struggle to understand a point in the code by Peter Norvig, 'Even better Python Lisp interpreter', here.
In eval function, aimed at parsing, he is doing the test isanstance(x,Symbol). Class Symbol is defined before, but it has no method, since it is declared with pass:
class Symbol(str): pass
These lines build a symbol_table.
def Sym(s, symbol_table={}):
"Find or create unique Symbol entry for str s in symbol table."
if s not in symbol_table: symbol_table[s] = Symbol(s)
return symbol_table[s]
_quote, _if, _set, _define, _lambda, _begin, _definemacro, = map(Sym,
"quote if set! define lambda begin define-macro".split())
_quasiquote, _unquote, _unquotesplicing = map(Sym,
"quasiquote unquote unquote-splicing".split())
I don't understand why Symbol(s)
is working, since no constructor for Symbol class has been defined. Afterwards, eval
method checks whether the token is a Symbol the following way:
def eval(x, env=global_env):
"Evaluate an expression in an environment."
while True:
if isa(x, Symbol): # variable reference
return env.find(x)[x]
else: #other stuff
isa(x,Symbol)
is a mystery. Here in code, should check whether token is a variable reference (that is x, with x that have been defined before). In my opinion, Symbol(s) here are a decoration for strings, in the initialization list built with
_quote, _if, _set, _define, _lambda, _begin, _definemacro, = map(Sym,
"quote if set! define lambda begin define-macro".split())
Could you please explain based on your knowledge or reading of this code by P. Norvig or experience of Python? Thanks
Like all other methods, __init__
is inherited. Symbol
inherits str
's __init__
.
Update: Note further that __init__
performs initialisation, not construction, and that initialisation code (with a slightly different effect) can also exist inside the class definition. This means that a valid object can exist without __init__
even needing to be called.