## 2014年7月16日水曜日

### Python - 足し算、クラスベースのオブジェクト指向版 (個数*単価 = 代金, 代金 = 個数*単価 @AXION_CAVOK , @dankogai )

JavaScript - 個数*単価 = 代金, 代金 = 個数*単価 ( @AXION_CAVOK , @dankogai )

クラスベースのオブジェクト指向(今回は python 3.4 )と、どちらが書きやすいか、比較のために書いてみた。(今回はかけ算じゃなくて足し算で。)

コード(BBEdit, Emacs)

constraint_system.py

```#!/usr/bin/env python3
#-*- coding: utf-8 -*-

class Constraint:
def __init__(self): pass
def process_new_value(self): pass
def process_forget_value(self): pass

class Connector:
def __init__(self):
self.value = None
self.informant = None
self.constraints = []

@staticmethod
def for_each_except(exception, bln, items):
for item in items:
if item != exception:
if bln:
item.process_new_value()
else:
item.process_forget_value()
return 'done'

@property
def has_value(self):
return self.informant != None

def set_value(self, newval, setter):
if not self.has_value:
self.value = newval
self.informant = setter
return self.for_each_except(setter, True, self.constraints)
if self.value != newval:
raise Exception('Contradiction {0}, {1}'.format(self.value, newval))
return 'ignored'

def forget_value(self, retractor):
if retractor == self.informant:
self.informant = None
return self.for_each_except(
retractor, False, self.constraints)
return 'ignored'

def connect(self, constraint):
try:
self.constraints.index(constraint)
except:
self.constraints.insert(0, constraint)
if self.has_value:
constraint.process_new_value()
return 'done'
def probe(self, name):
p = Probe(name, self)
self.connect(p)

class Probe(Constraint):
def __init__(self, name, connector):
self.name = name
self.connector = connector

def print_probe(self, value):
print('Probe: {0} = {1}'.format(self.name, value))

def process_new_value(self):
self.print_probe(self.connector.value)

def process_forget_value(self):
self.print_probe('?')

class Adder(Constraint):
def __init__(self, a1, a2, s):
self.a1 = a1
self.a2 = a2
self.s = s
self.a1.connect(self)
self.a2.connect(self)
self.s.connect(self)

def process_new_value(self):
if self.a1.has_value and self.a2.has_value:
self.s.set_value(self.a1.value + self.a2.value, self)
elif self.a1.has_value and self.s.has_value:
self.a2.set_value(self.s.value - self.a1.value, self)
elif self.a2.has_value and self.s.has_value:
self.a1.set_value(self.s.value - self.a2.value, self)

def process_forget_value(self):
self.s.forget_value(self)
self.a1.forget_value(self)
self.a2.forget_value(self)
self.process_new_value()

if __name__ == '__main__':
a1 = Connector()
a2 = Connector()
s = Connector()
adder = Adder(a1, a2, s)
i = 'kamimura'
a1.probe('a1')
a2.probe('a2')
s.probe('sum')
try:
a1.set_value(10, i)
a2.set_value(20, i)
a1.forget_value(i)
s.set_value(100, i)
s.set_value(200, i)
except Exception as err:
print(err)

```

```\$ ipython
Python 3.4.1 (default, May 21 2014, 01:39:38)
Type "copyright", "credits" or "license" for more information.

IPython 2.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: from constraint_system import *

In [2]: a1 = Connector()

In [3]: a2 = Connector()

In [4]: s = Connector()

In [5]: adder = Adder(a1, a2, s)

In [6]: i = 'kamimura'

In [7]: a1.probe('a1')

In [8]: a2.probe('a2')

In [9]: s.probe('sum')

In [10]: a1.set_value(10, i)
Probe: a1 = 10
Out[10]: 'done'

In [11]: a2.set_value(20, i)
Probe: a2 = 20
Probe: sum = 30
Out[11]: 'done'

In [12]: a1.forget_value(i)
Probe: a1 = ?
Probe: sum = ?
Out[12]: 'done'

In [13]: s.set_value(100, i)
Probe: sum = 100
Probe: a1 = 80
Out[13]: 'done'

In [14]: s.set_value(100, i)
Out[14]: 'ignored'

In [15]: quit()
\$ ./constraint_system.py
Probe: a1 = 10
Probe: a2 = 20
Probe: sum = 30
Probe: a1 = ?
Probe: sum = ?
Probe: sum = 100
Probe: a1 = 80
Contradiction 100, 200
\$
```