SICPの2.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)))) (define (add-complex z1 z2) (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 def add_complex(z1, z2): 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 print add_complex(ri, ma)
結果
['rectangular', [1, 2]] ['polar', [3, 4]] ['rectangular', [-0.96093086259083593, -0.27040748592378483]]