| 1 | #!/usr/bin/env python2
 | 
| 2 | from __future__ import print_function
 | 
| 3 | """
 | 
| 4 | class_vs_closure.py
 | 
| 5 | 
 | 
| 6 | TODO: These should be implemented the same way in the interpreter loop?
 | 
| 7 | 
 | 
| 8 | Closure is implemented with:
 | 
| 9 | 
 | 
| 10 | - pyobj.Function.func_closure
 | 
| 11 | 
 | 
| 12 | Class is implemented with type(), and then the constructor creates a namespace
 | 
| 13 | with __dict__ and so forth.  Access through 'self'.  LOAD_FAST self, where self
 | 
| 14 | is a local variable.
 | 
| 15 | 
 | 
| 16 | There was one language that made it explicit.  Skew language?
 | 
| 17 | 
 | 
| 18 | 
 | 
| 19 | # {} is for static language of types/data.  : is for language of
 | 
| 20 | # code/algorithms.
 | 
| 21 | 
 | 
| 22 | class Adder1 {
 | 
| 23 |   init(self.amount):  # auto-init
 | 
| 24 |     pass
 | 
| 25 | 
 | 
| 26 |   call(x):
 | 
| 27 |     return x + self.amount
 | 
| 28 | }
 | 
| 29 | 
 | 
| 30 | func Adder2(amount) {
 | 
| 31 |   return func(x) {   # function literal
 | 
| 32 |     # outer means that the variable is captured lexically?
 | 
| 33 |     return x + outer::amount
 | 
| 34 |   }
 | 
| 35 | }
 | 
| 36 | 
 | 
| 37 | # Shortcut
 | 
| 38 | class Adder1 is Object (self.amount Int) {
 | 
| 39 |   call(x Int):
 | 
| 40 |     return x + self.amount
 | 
| 41 | }
 | 
| 42 | 
 | 
| 43 | """
 | 
| 44 | 
 | 
| 45 | import sys
 | 
| 46 | 
 | 
| 47 | 
 | 
| 48 | class Adder1(object):
 | 
| 49 |   def __init__(self, amount):
 | 
| 50 |     self.amount = amount
 | 
| 51 | 
 | 
| 52 |   def __call__(self, x):
 | 
| 53 |     return x + self.amount
 | 
| 54 | 
 | 
| 55 | 
 | 
| 56 | # This one uses a LOAD_CLOSURE bytecode; the other one doesn't.
 | 
| 57 | def Adder2(amount):
 | 
| 58 |   def anon(x):
 | 
| 59 |     return x + amount
 | 
| 60 |   return anon
 | 
| 61 | 
 | 
| 62 | 
 | 
| 63 | def main(argv):
 | 
| 64 |   a1 = Adder1(1)
 | 
| 65 |   a2 = Adder2(1)
 | 
| 66 | 
 | 
| 67 |   print(a1(42))
 | 
| 68 |   print(a2(42))
 | 
| 69 | 
 | 
| 70 | 
 | 
| 71 | if __name__ == '__main__':
 | 
| 72 |   try:
 | 
| 73 |     main(sys.argv)
 | 
| 74 |   except RuntimeError as e:
 | 
| 75 |     print('FATAL: %s' % e, file=sys.stderr)
 | 
| 76 |     sys.exit(1)
 |