tran li <litra...@hotmail.com> writes: > Recently I found that it is possible to use OOP in LilyPond Scheme by > using the `oop goops` module so I would like to reconstruct some of my > code in my `lily-score` project.
With all due respect: I would recommend more focus on using Scheme in LilyPond Scheme first. You don't seem to have a good grasp of its idioms, and the Goops module's way of providing OOP features is so generic that it doesn't even proscribe a certain programming style. That makes it very likely that your code will evolve to be unreadable to Scheme programmers. Here is an example: > And the Bezier-related code: > > ```ly > #(define (binom n k) > ;; binomial coefficient $\binom{n}{k} = \frac{n!}{k!(n - k)!}$ > (if (> k (/ n 2)) (set! k (- n k))) > (let* > ((result 1)) > (for-each > (lambda (i) > (let* ((p (- n i)) > (q (- k i))) > (set! result (* result (/ p q))))) > (iota k)) > result)) > ``` Scheme idioms are inherently recursive, math definitions are inherently recursive. Yet you use a loop with variables and assignments here, and with arithmetic involving i. More Schemish would be #(define (binom n k) (let loop ((n n) (k (min k (- n k))) (q 1)) (if (positive? k) (/ (* n (loop (1- n) (1- k) (1+ q))) q) 1))) It doesn't build a whole unnecessary list with (iota k). It doesn't reassign variables but recurses. It doesn't unnecessarily trigger rational math (hint: (/ p q) rarely is an integer). Note that it still relies on n being an integer and at least k, but you can fix this with the initial condition, like #(define (binom n k) (let loop ((n n) (k (if (and (integer? n) (>= n k)) (min k (- n k)) k)) (q 1)) (if (positive? k) (/ (* n (loop (1- n) (1- k) (1+ q))) q) 1))) Whether or not the use case warrants looking at those exceptions (it probably doesn't), the idiom is more Schemish. However, one also might want to check that the _use_ of binom is not better replaced by recursive evaluation: > #(define ((bernstein-poly n k) t) > (* (binom n k) (expt (- 1 t) (- n k)) (expt t k))) > > #(define ((bezier cpts) t) > ;; parameterization for bezier curves > (let* ((x 0) (y 0) > (n (- (length cpts) 1))(k 0)) > (for-each (lambda (cpt) > (let* ((x_k (car cpt)) > (y_k (cdr cpt)) > (coef ((bernstein-poly n k) t))) > (set! x (+ x (* x_k coef))) > (set! y (+ y (* y_k coef)))) > (set! k (+ k 1))) > cpts) > (cons x y))) > ``` Here you calculate succesive values of (binom n k) in a loop, each time going from scratch rather than using the last value. Wrapping that kind of complexity problem in OOP boxes will make it harder to fix it. -- David Kastrup