Hi Jean,
Thank you very much for multiple options! I've decided to try the first
one. I still have two difficulties
- How to create alist from the components ax, ay, ... (see comment in
the code below)?
- How would I call this function? I guess c'4 \shapedSlur fu #'((bs .
3.0) (ht . 2.0)) ( d)
I managed to created the below music function following your advice for the
option 1
shapedSlur = #(define-music-function (dir prs mus) (symbol? alist?
ly:music?)
(let* ((bs (assoc-get 'bs pars 2.0))
(sh (assoc-get 'sh prs 0.5))
(wd (assoc-get 'wd prs 1.0))
(ht (assoc-get 'ht prs 1.0))
(dt (assoc-get 'dt prs 0.0))
(pts (cond
((equal? dir 'fu)
(let ((ax (+ sh (* 0.0 wd)))
(bx (+ sh (* 1.0 wd)))
(cx (+ sh (* 2.0 wd)))
(dx (+ sh (* 3.0 wd)))
(ay bs)
(by (+ bs ht))
(cy (+ bs ht))
(dy (+ bs dt)))
;; Do not know how to create alist suitable for
;; \tweak control-points
(list ax ay bx by cx cy dx dy)))
((equal? dir 'fd)
(let ((ax (+ sh (* 0.0 wd)))
(bx (+ sh (* 1.0 wd)))
(cx (+ sh (* 2.0 wd)))
(dx (+ sh (* 3.0 wd)))
(ay (* -1 bs))
(by (* -1 (+ bs ht)))
(cy (* -1 (+ bs ht)))
(dy (* -1 (+ bs dt))))
(list ax ay bx by cx cy dx dy)))
((equal? dir 'bu)
(let ((ax (- (+ sh (* 0.0 wd)) (* 3.0 wd)))
(bx (- (+ sh (* 1.0 wd)) (* 3.0 wd)))
(cx (- (+ sh (* 2.0 wd)) (* 3.0 wd)))
(dx (- (+ sh (* 3.0 wd)) (* 3.0 wd)))
(ay (+ bs dt))
(by (+ bs ht))
(cy (+ bs ht))
(dy bs))
(list ax ay bx by cx cy dx dy)))
((equal? dir 'bd)
(let ((ax (- (+ sh (* 0.0 wd)) (* 3.0 wd)))
(bx (- (+ sh (* 1.0 wd)) (* 3.0 wd)))
(cx (- (+ sh (* 2.0 wd)) (* 3.0 wd)))
(dx (- (+ sh (* 3.0 wd)) (* 3.0 wd)))
(ay (* -1 (+ bs dt)))
(by (* -1 (+ bs ht)))
(cy (* -1 (+ bs ht)))
(dy (* -1 bs)))
(list ax ay bx by cx cy dx dy)))
)))
(tweak 'control-points pts mus)))
Thank you,
Vlad
On Sun, Jul 2, 2023 at 3:05 PM Jean Abou Samra <[email protected]> wrote:
> Le dimanche 02 juillet 2023 à 14:28 +0200, Volodymyr Prokopyuk a écrit :
>
> I wonder if there is a *way to define a music function with default
> parameters* and be able to selectively specify some parameters using the
> *parameters
> names* leaving all other parameters with their default values? Probably
> it is asking too much :)
>
> It is indeed asking too much from music functions (as in many languages
> where functions are called without parentheses or some other delimiter).
> There are a couple of ways around this restriction, though. One would be to
> just specify your arguments in a Scheme alist, like
>
> shapedSlur =
> #(define-music-function (params item) (alist? ly:music?)
> (let* ((dir (assoc-get 'dir params))
> (bs (assoc-get 'bs params 2.0))
> ...)
> (tweak 'control-points `(...) item)))
>
> Another one is to define a Scheme function. If you use define instead of
> define*, it will recognize special objects in its argument list (called
> "keywords", written with "#:") which define named parameters.
>
> #(define* (shaped-slur dir #:key (bs 2.0)
> (sh 0.5)
> (wd 1.0)
> (ht 1.0)
> (dt 0.0))
> (let ((control-points ...))
> #{ \tweak control-points #control-points \etc #}))
>
> {
> c'$(shaped-slur 'your-dir #:bs 3.0 #:sh 0.1)( c')
> }
>
> Finally, you could abuse context mods a bit ("context mods" is the
> technical name for \with blocks), like this:
>
> shapedSlur =
> #(define-music-function (params item) (ly:context-mod? ly:music?)
> (let* ((properties (filter-map (match-lambda (('assign prop val) (cons
> prop val))
> (else #f))
> (ly:get-context-mods params)))
> (dir (assoc-get 'dir properties))
> (bs (assoc-get 'bs properties 2.0))
> ...
> (control-points `(...)))
> (tweak 'control-points control-points item)))
>
> {
> c'\shapedSlur \with { dir=#'foo bs=5.0 } ( c')
> }
>
> Best,
>
> Jean
>