2.4.2 Tagged dataをPythonでやってみた

SICP2.4.2 Tagged dataあたりをPythonでやってみた

scheme(original code)

```;2.4.2  Tagged data
(define (attach-tag type-tag contents)
(cons type-tag contents))
(define (type-tag datum)
(if (pair? datum)
(car datum)
(error "Bad tagged datum -- TYPE-TAG" datum)))
(define (contents datum)
(if (pair? datum)
(cdr datum)
(error "Bad tagged datum -- CONTENTS" datum)))

(define (rectangular? z)
(eq? (type-tag z) 'rectangular))
(define (polar? z)
(eq? (type-tag z) 'polar))

(define (real-part-rectangular z) (car z))
(define (imag-part-rectangular z) (cdr z))
(define (magnitude-rectangular z)
(sqrt (+ (square (real-part-rectangular z))
(square (imag-part-rectangular z)))))
(define (angle-rectangular z)
(atan (imag-part-rectangular z)
(real-part-rectangular z)))
(define (make-from-real-imag-rectangular x y)
(attach-tag 'rectangular (cons x y)))
(define (make-from-mag-ang-rectangular r a)
(attach-tag 'rectangular
(cons (* r (cos a)) (* r (sin a)))))

(define (real-part-polar z)
(* (magnitude-polar z) (cos (angle-polar z))))
(define (imag-part-polar z)
(* (magnitude-polar z) (sin (angle-polar z))))
(define (magnitude-polar z) (car z))
(define (angle-polar z) (cdr z))
(define (make-from-real-imag-polar x y)
(attach-tag 'polar
(cons (sqrt (+ (square x) (square y)))
(atan y x))))
(define (make-from-mag-ang-polar r a)
(attach-tag 'polar (cons r a)))

(define (real-part z)
(cond ((rectangular? z)
(real-part-rectangular (contents z)))
((polar? z)
(real-part-polar (contents z)))
(else (error "Unknown type -- REAL-PART" z))))
(define (imag-part z)
(cond ((rectangular? z)
(imag-part-rectangular (contents z)))
((polar? z)
(imag-part-polar (contents z)))
(else (error "Unknown type -- IMAG-PART" z))))
(define (magnitude z)
(cond ((rectangular? z)
(magnitude-rectangular (contents z)))
((polar? z)
(magnitude-polar (contents z)))
(else (error "Unknown type -- MAGNITUDE" z))))
(define (angle z)
(cond ((rectangular? z)
(angle-rectangular (contents z)))
((polar? z)
(angle-polar (contents z)))
(else (error "Unknown type -- ANGLE" z))))

(make-from-real-imag (+ (real-part z1) (real-part z2))
(+ (imag-part z1) (imag-part z2))))

(define (make-from-real-imag x y)
(make-from-real-imag-rectangular x y))
(define (make-from-mag-ang r a)
(make-from-mag-ang-polar r a))

;test
(make-from-real-imag 1 2)
(make-from-mag-ang 3 4)
(add-complex (make-from-real-imag 1 2) (make-from-mag-ang 3 4))
```

```(rectangular 1 . 2)
(polar 3 . 4)
(rectangular -0.9609308625908359 . -0.27040748592378483)
```
python
```#2.4.2  Tagged data
from __future__ import division
import math

def attach_tag(type_tag, contents):
return [type_tag, contents]
def type_tag(datum):
if len(datum) >= 2:
return datum[0]
print "error: Bad tagged datum -- TYPE-TAG", datum
def contents(datum):
if len(datum) >= 2:
return datum[1]
print "error: Bad tagged datum -- CONTENTS", datum

def rectangular_q(z):
return type_tag(z) == 'rectangular'
def polar_q(z):
return type_tag(z) == 'polar'

def real_part_rectangular(z):
return z[0]
def imag_part_rectangular(z):
return z[1]
def magnitude_rectangular(z):
return math.sqrt(real_part_rectangular(z) **2 + \
imag_part_rectangular(z) ** 2)
def angle_rectangular(z):
return math.atan2(imag_part_rectangular(z), real_part_rectangular(z))
def make_from_real_imag_rectangular(x, y):
return attach_tag('rectangular', [x, y])
def make_from_mag_ang_rectangular(r, a):
return attach_tag('rectangular', [r * math.cons(a),
r * math.sin(a)])
def real_part_polar(z):
return magnitude_polar(z) * math.cos(angle_polar(z))
def imag_part_polar(z):
return magnitude_polar(z) * math.sin(angle_polar(z))
def magnitude_polar(z):
return z[0]
def angle_polar(z):
return z[1]
def make_from_real_imag_polar(x, y):
return attach_tag('polar', [math.sqrt(x **2 + y **2), math.atan2(y,x)])
def make_from_mag_ang_polar(r,a):
return attach_tag('polar', [r, a])

def real_part(z):
if rectangular_q(z):
return real_part_rectangular(contents(z))
if polar_q(z):
return real_part_polar(contents(z))
else:
print "error: Unknown type -- REAL-PART", z
def imag_part(z):
if rectangular_q(z):
return imag_part_rectangular(contents(z))
if polar_q(z):
return imag_part_polar(contents(z))
else:
print "error: Unknown type -- IMAG-PART", z
def magnitude(z):
if rectangular_q(z):
return magnitude_rectangular(contents(z))
if polar_q(z):
return magnitude_polar(contents(z))
else:
print "error: Unknown type -- MAGNITUDE", z
def angle(z):
if rectangular_q(z):
return angle_rectangular(contents(z))
if polar_q(z):
return angle_polar(contents(z))
else:
print "error: Unknown type -- ANGLE", z

return make_from_real_imag(real_part(z1) + real_part(z2), \
imag_part(z1) + imag_part(z2))

def make_from_real_imag(x, y):
return make_from_real_imag_rectangular(x, y)
def make_from_mag_ang(r, a):
return make_from_mag_ang_polar(r, a)

#test
ri = make_from_real_imag(1,2)
ma =  make_from_mag_ang(3,4)
print ri
print ma
```['rectangular', [1, 2]]