lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: scheme set list function


From: Aaron Hill
Subject: Re: scheme set list function
Date: Mon, 08 Apr 2019 04:15:56 -0700
User-agent: Roundcube Webmail/1.3.8

On 2019-04-08 2:48 am, Thomas Morley wrote:
foo =
#(let ((x (cons 1 0)))
  (define-scheme-function (arg)(symbol?)
    (case arg
      ((indent) (set! x (cons (car x) (1+ (cdr x)))))
      ((increase) (set! x (cons (1+ (car x)) 0)))
      ((reset) (set! x (cons 1 0))))
    (if (zero? (cdr x))
        (format #f "~a" (car x))
        (format #f "~a.~a" (car x) (cdr x)))))

[ . . . ]

I'm still not happy with those set-whatever!-thingies. I was beaten
too often. Maybe someone comes up with a better approach.

Using set! is perfectly fine as long as you encapsulate things well. Your use of let to define a local variable minimizes the chance that folks would be able to interfere with or even care about such modification. However, your usage means there is still a "global" x that is shared amongst all of the usage of foo.

Guile's manual talks about object orientation and uses a pattern not at all dissimilar to what you provided above. Consider the following:

%%%%
\version "2.19.82"

#(define (make-section-numberer)
  ;; Note that numbers are being stored little-endian.
  (let ((numbers '(1)))
    (define (get-section) (format #f "~{~d~^.~}" (reverse numbers)))
    (define (next-section)
      (set! numbers (cons (1+ (car numbers)) (cdr numbers)))
      (get-section))
    (define (indent)
      (set! numbers (cons 1 numbers))
      (get-section))
    (define (unindent)
      (if (null? (cdr numbers))
        (error "Unable to unindent at top-level."))
      (set! numbers (cdr numbers))
      (get-section))

    (lambda args
      (apply
        (case (car args)
          ((get-section) get-section)
          ((next-section) next-section)
          ((indent) indent)
          ((unindent) unindent)
          (else (error "Unknown method.")))
        (cdr args)))))

my-section-numberer = #(make-section-numberer)
my-section-numberer-two = #(make-section-numberer)

\markup \column {
  #(my-section-numberer 'get-section)
  #(my-section-numberer 'next-section)
  #(my-section-numberer 'indent)
  \italic #(my-section-numberer-two 'get-section)
  #(my-section-numberer 'indent)
  #(my-section-numberer 'next-section)
  \italic #(my-section-numberer-two 'next-section)
  #(my-section-numberer 'unindent)
  #(my-section-numberer 'next-section)
  \italic #(my-section-numberer-two 'next-section)
  #(my-section-numberer 'unindent)
}
%%%%

The principle difference here is that there is make-section-numberer is essentially now a constructor. That means each instance has its own "numbers" variable. The example above uses two instances to demonstrate this, with the second italicized for clarity.


-- Aaron Hill



reply via email to

[Prev in Thread] Current Thread [Next in Thread]