Substack https://aljamal.substack.com/p/homoiconic-python
atom=lambda x:not isinstance(x,list)
eq=lambda x,y:x == y
car=lambda x:x[0]
cdr=lambda x:x[1:]
cons=lambda x,y:[x,y] if atom(y) else [x]+y
append=lambda x,y:x+y
def eval(x):
if atom(x): return x
elif eq(car(x),'quote'): return car(cdr(x))
elif eq(car(x),'atom'): return atom(eval(car(cdr(x))))
elif eq(car(x),'eq'): return eq(eval(car(cdr(x))),
eval(car(cdr(cdr(x)))))
elif eq(car(x),'car'): return car(eval(car(cdr(x))))
elif eq(car(x),'cdr'): return cdr(eval(car(cdr(x))))
elif eq(car(x),'cons'): return cons(eval(car(cdr(x))),
eval(car(cdr(cdr(x)))))
elif eq(car(x),'cond'):
for i in cdr(x):
if eval(car(i)):
return eval(car(cdr(i)))
return []
def e(x):
try:print(eval(x))
except Exception as e:print(e)
e([atom])
e(42)
e(['quote',[10,20]])
e(['atom',1])
e(['atom',['quote',1]])
e(['atom',['quote',[1,2,3]]])
e(['eq',1,1])
e(['eq',1,2])
e(['car',['quote',[1000,20]]])
e(['cdr',['quote',[10,20,1.1]]])
e(['car',['car',['cdr',['cdr',
['cdr',['quote',[1,2,10,[50,100]]]]]]]])
e(['cons',1,['quote',[10,20]]])
e(['cons',['quote',[1,2]],['quote',[10,20]]])
e(['cond',
[['eq', 1, 1], 'true'],
[['atom', ['quote', 2]], 'false'],
['t', 'default']
])
e(['cond',
[['atom', ['quote', 2]], 'cake'],
['t', 'default']
])
e(['cond',
[['atom', ['quote',[1,2]]], 'false'],
['t', 'default']
])
atom=lambda x:not isinstance(x,list)
eq=lambda x,y:x == y
car=lambda x:x[0]
cdr=lambda x:x[1:]
cons=lambda x,y:[x,y] if atom(y) else [x]+y
append=lambda x,y:x+y
#assoc=lambda x,y:(car(y) if eq(car(car(y)),x) else assoc(x,cdr(y))) if y else []
assoc=lambda x,y:car([cdr(i) for i in y if eq(car(i),x)] or [x])
#pairlis=lambda x,y:cons(cons(car(x),car(y)),pairlis(cdr(x),cdr(y))) if x and y else []
pairlis=lambda x,y:[cons(x[i],y[i]) for i in range(len(x))]
def eval(x,y):
if atom(x):return assoc(x,y)
elif atom(car(x)):
if eq(car(x),'quote'):return car(cdr(x))
elif eq(car(x),'atom'):return atom(eval(car(cdr(x)),y))
elif eq(car(x),'eq'):return eq(eval(car(cdr(x)),y),eval(car(cdr(cdr(x))),y))
elif eq(car(x),'car'):return car(eval(car(cdr(x)),y))
elif eq(car(x),'cdr'):return cdr(eval(car(cdr(x)),y))
elif eq(car(x),'cons'):return cons(eval(car(cdr(x)),y),eval(car(cdr(cdr(x))),y))
elif eq(car(x),'cond'):
for i in cdr(x):
if eval(car(i),y):return eval(car(cdr(i)),y)
else:return eval(cons(assoc(car(x),y),[eval(i,y) for i in cdr(x)]),y)
elif eq(car(car(x)),'lambda'):return eval(car(cdr(cdr(car(x)))),
append(pairlis(car(cdr(car(x))),[eval(i,y) for i in cdr(x)]),y))
def e(x):
try:print(eval(x,[]))
except Exception as e:print(e)
e([atom]) # error
e(42)
e(['quote',[10,20]])
e(['atom',1])
e(['atom',['quote',1]])
e(['atom',['quote',[1,2,3]]])
e(['eq',1,1])
e(['eq',1,2])
e(['car',['quote',[1000,20]]])
e(['cdr',['quote',[10,20,1.1]]])
e(['car',['car',['cdr',['cdr',['cdr',['quote',[1,2,10,[50,100]]]]]]]])
e(['cons',1,['quote',[10,20]]])
e(['cons',['quote',[1,2]],['quote',[10,20]]])
e(['cond',
[['eq', 1, 1], 'true'],
[['atom', ['quote', 2]], 'false'],
['t', 'default']
])
e(['cond',
[['atom', ['quote', 2]], 'cake'],
['t', 'default']
])
e(['cond',
[['atom', ['quote',[1,2]]], 'false'],
['t', 'default']
])
e([['lambda', ['x'], ['car', 'x']], ['quote', [1, 2, 3]]])
e([['lambda', ['x'], ['cdr', 'x']], ['quote', [1, 2, 3]]])
e([['lambda', ['x','y'], ['cons', 'x','y']],5,['quote', [1, 2, 3]]])
I couldn't find an email address for Mr. Jamal, so I'm commenting here. This code has an error. The assoc() call in the 'cond' implementation has only one argument, and the function takes two. Could you please correct it? Thanks!