Я делаю символические вычисления для оригами, включая вычисление параметрического уравнения складки с учетом двух точек, как показано ниже.Я надеюсь превратить это в очень простой гибрид средства доказательства теорем оригами / CAS.
; number -> number -> vertex
(struct vertex (x y))
; lambda _ -> crease
(struct crease (equation))
; λ -> vertex -> vertex -> vertex
(define (vop-symbol op v1 v2)
(vertex `(,op ,(vertex-x v1) ,(vertex-x v2))
`(,op ,(vertex-y v1) ,(vertex-y v2))))
; vertex -> vertex -> vertex
(define (vadd-symbol v1 v2)
(vop-symbol + v1 v2))
; vertex -> vertex -> vertex
(define (vsub-symbol v1 v2)
(vop-symbol - v1 v2))
; number -> vertex -> vertex
(define (vsmul-symbol s v)
(vertex `(* ,s ,(vertex-x v)) `(* ,s ,(vertex-y v))))
; vertex -> vertex -> crease
(define (axiom1 v1 v2)
(crease (λ (s)(vadd-symbol v1 (vsmul-symbol s (vsub-symbol v2 v1))))))
Это очень просто, но имеет тот недостаток, что для использования конкретных чисел вместо символов требуется eval
при вводе пользователем:
> (define crease1 (axiom1 (vertex 0 0) (vertex 3 3)))
> (vertex-y ((crease-equation crease1) 1/2))
'(#<procedure:+> 0 (* 1/2 (#<procedure:-> 3 0)))
> (eval (vertex-y ((crease-equation crease1) 1/2)))
1 1/2
Таким образом, мой вопрос заключается в том, лучше ли практиковаться, например, в более легком / более удобном в обслуживании выполнении такого рода символьных манипуляций во время выполнения (как в примерах получения функций SICP) или во время компиляции? Т.е. стоит ли избегать использования макросов eval
?Или есть обходной путь с функциями?
Спасибо!