lilypond-user
[Top][All Lists]
Advanced

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

How to use optional arguments / parameters in a define-markup-command


From: Karsten Reincke
Subject: How to use optional arguments / parameters in a define-markup-command
Date: Mon, 04 Nov 2019 17:59:32 +0100
User-agent: Evolution 3.34.1-2

Dear friends

A few days ago, I asked whether anyone knows how one can use variable parameter
lists = optional arguments = flexible argumentlists in a markup function. I was
told that such an opportunity does not exist (Thomas Morley) resp. must be
simulated by some embedded property features (Urs Liska). Many thanks for these
quick answers. They preserved me from doing unnecessary work.

Here is a pure scheme / guile solution using lisp association lists (demoed by
using the box example from the extend tutorial). The target is, that the users 
of
our function may insert the arguments they really need (without having to deal
with those, they do not need) and that they may insert the arguments they want 
to
use in the order they prefer [The running version is attached as a file. Each
substantial portions of the code is distributed under the terms of the MIT
license. I assume that the function shall be interpreted on the lilypond 
level]: 

First, we should define the keys, we want to use (they must be communicated to 
the
users of our function)

#(define ka "k1")
#(define kb "k2")
#(define kc "k3")
#(define kd "k4")
#(define ke "k5")

Second, we should define the respective default values

#(define dva "blank") ; a filled string
#(define dvb "") ; an empty string
#(define dvc '()) ; a null value
#(define dvd "blank") ; 
#(define dve "") ; 

Third, we need a function - let us name it "assign" (you will understand in a
short time, why) - which takes a key, an associationlist (alist) and a default
value. If the alist contains any pair with the same key, then function shall
return the corresponding value, otherwise the given default value

#(define (assign keyValue assocList defaultValue)
  (string? list?)
  (let* ((localPair (assoc keyValue assocList)))
    (if localPair (cdr localPair) defaultValue)
  )
)

Based on this pre-work, we can now define a markup function. In the beginning we
define the local parameter variables and let them be instantiated by our assign
function. Then we manipulate the given values in any way. And finally we return 
-
as a markup 'object' - a box containing the result of our manipulation:

#(define-markup-command (mybox layout props AL)
  (list?)
  (let*
    ( (la (assign ka AL dva))
      (lb (assign kb AL dvb))
      (lc (assign kc AL dvc))
      (ld (assign kd AL dvd))
      (le (assign ke AL dve))
      (lresult "result")
    )
    ;  because we used an empty list (nil) as default value
    (if (eq? lc '()) (set! lc ""))
    ; our 'manupilation' is norhing else but a concatenation ;-)
    (set! lresult (string-append la lb lc ld le))

    (interpret-markup layout props
      #{
        \markup \box { #lresult }
      #}
    )
   )
 )  

This function can be called in any markup context like

\markup \mybox #'(("k5" . "V5")("k1" . "V1"))

The result is a box containing the text "V1blankV5": V1 is given by the second
(sic!) argument - the values of the possible keys k2 and k3 are ignored, because
their default values are "" and an empty list = null - the blank is default 
value
of the unused key k4, and V5 is given by the first (sic!) argument.


best regards Karsten


-- 
  Karsten Reincke    /\/\   (+49|0) 170 / 927 78 57
 Im Braungeröll 31   >oo<  mailto:address@hidden
60431 Frankfurt a.M.  \/    http://www.fodina.de/kr/

Attachment: varpar.ly
Description: Text Data


reply via email to

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