On Mon, 2019-11-04 at 23:45 +0000, Urs Liska wrote: Dear Urs; many thanks for your comments and hints! I admire how thoroughly you read other work and how many time you spend with helping others! > Hi Karsten, > > 4. November 2019 17:59, "Karsten Reincke" <k.rein...@fodina.de> schrieb: > [...] > > Here is a pure scheme / guile solution using lisp association lists (demoed > > by > > using the box example from the extend tutorial). > > I see one major issue with your approach: it pollutes the namespace with a > multitude of global variables. The global variables are only syntactical sugar. I've attached a version which does not use any global variable any longer
> > I don't want to push you towards using openLilyLib ;-) but oll-core includes a > macro "with-options" (created by Stéfano Troncaro) that allows the > modification > of define-music-function (I'm not sure about markup functions right now) so > that > the function accepts an optional \with { } clause, performs validation against > mandatory and optional arguments (optionally along with their types) and can > provide default values - all without necessarily using #(define XXX) and > creating global variables. > > The code starts here: > https://github.com/openlilylib/oll-core/blob/master/internal/options.ily#L245 > This is a nice example using the main feature of LISP: even code can become a parameter and vice versa. But for my purpose, it is too sophisticated. > Urs wit best regards Karsten -- Karsten Reincke /\/\ (+49|0) 170 / 927 78 57 Im Braungeröll 31 >oo< mailto:k.rein...@fodina.de 60431 Frankfurt a.M. \/ http://www.fodina.de/kr/
\version "2.18.2" % A pure scheme / guile solution to define a LilyPond markup % command with a variable list of arguments by using a % technique of lisp scheme / guile called association lists % (demoed by using the box example from the extend tutorial). % The target is, that the users of the 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 % feel free to adopt this example under the following terms: % Copyright 2019 Karsten Reincke, Frankfurt % Permission is hereby granted, free of charge, to any person % obtaining a copy of this software and associated documentation % files (the "Software"), to deal in the Software without % restriction, including without limitation the rights to use, % copy, modify, merge, publish, distribute, sublicense, and/or sell % copies of the Software, and to permit persons to whom the % Software is furnished to do so, subject to the following conditions: % The above copyright notice and this permission notice shall be % included in all copies or substantial portions of the Software. % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, % EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES % OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND % NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT % HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, % WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING % FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE % OR OTHER DEALINGS IN THE SOFTWARE. % 1) we need a function - let us name it "assign" % (you will understand in a short time, why) - which takes % a key, an association list (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) (let* ((localPair (assoc keyValue assocList))) (if localPair (cdr localPair) defaultValue) ) ) % 2.) we define a markup function using a flexible variable % parameter list: % a) At the beginning we define the local parameter variables % and let them be instantiated by our assign function. % b) Then we manipulate the given values in any way. % c) 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 "k1" AL "blank")) (lb (assign "k2" AL "")) (lc (assign "k3" AL '())) (ld (assign "k4" AL "blank")) (le (assign "k5" AL "")) (lresult "result") ) ; because we used an empty list (nil) as default value (if (eq? lc '()) (set! lc "")) ; our 'manupilation' is a concatenation ;-) (set! lresult (string-append la lb lc ld le)) (interpret-markup layout props #{ \markup \box { #lresult } #} ) ) ) \markup \mybox #'(("k5" . "V5")("k1" . "V1"))