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"))

Reply via email to