Skip to content

Instantly share code, notes, and snippets.

@aburjg
Last active May 28, 2024 18:56
Show Gist options
  • Save aburjg/1dffba5516095050089f6ea293cb782b to your computer and use it in GitHub Desktop.
Save aburjg/1dffba5516095050089f6ea293cb782b to your computer and use it in GitHub Desktop.
Homoiconic Python Post

Substack https://aljamal.substack.com/p/homoiconic-python

First

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']
])

Second

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]]])
@dan-s-cox
Copy link

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!

@aburjg
Copy link
Author

aburjg commented May 28, 2024

The assoc() call in the 'cond' implementation has only one argument

not in 'cond', but you're right. corrected, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment