Re: Procedure for set-paper-size in \paper ?
Thomas Morley writes: > 2018-05-19 9:45 GMT+02:00 David Kastrup : >> Thomas Morley writes: > > Uh, oh, another typo/oversight. > Note to self: Don't post anything while being overtired... > >> >> Now if you want to execute only conditionally, you either need to wrap >> in lambdas or use a macro rather than a procedure: >> >> #(define-macro (proc bool x y) >>(if bool x y)) >> >> \paper { >> #(if #t (set-paper-size "a8" 'landscape) (set-paper-size "a8")) >> } Talk about type/oversight: I don't even use the proc macro here. You need to write it instead of "if" in the paper block, or the example does not make a whole lot of sense. >> Note that this will only work with a _literal_ #f or #t as argument: >> you'll likely want to have some actual condition evaluated at runtime, >> like some variable name. Then you'll need to write >> >> #(define-macro (proc bool x y) >> `(if ,bool ,x ,y)) > > Thanks for the insights, The last bit is a whole lot of quasiquote obviously equivalent to (list 'if bool x y) But in the context of macro expansions, using quasiquotes is sort of customary for emphasizing the structure of what gets returned rather than how it is getting built. -- David Kastrup ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: Procedure for set-paper-size in \paper ?
2018-05-19 9:45 GMT+02:00 David Kastrup : > Thomas Morley writes: > >> Hi all, >> >> (1) >> consider the following code (working as expected): >> >> \paper { >> #(if #t (set-paper-size "a8" 'landscape) #(set-paper-size "a8")) >> } >> >> \score { { R1 } \layout { ragged-right = ##f } } >> >> Switching from #t to #f results in different paper-size, as desired. > > Unlikely as you write #(set-paper-size ...) here, see below. > >> >> (2) >> But trying to put it in a procedure, it always returns the true-case: >> >> #(define (proc bool x y) >> (if bool x y)) >> >> \paper { >> #(proc #f (set-paper-size "a8" 'landscape) #(set-paper-size "a8")) >> } > > Uh, the return value is irrelevant. It always _executes_ the true case. > It also executes the false case but that is not overly interesting since > the false case is a vector consisting of the elements 'set-paper-size > and "a8" since you write #(...) while already in Scheme, the syntax for > vector literals. Uh, oh, another typo/oversight. Note to self: Don't post anything while being overtired... > > Now if you want to execute only conditionally, you either need to wrap > in lambdas or use a macro rather than a procedure: > > #(define-macro (proc bool x y) >(if bool x y)) > > \paper { > #(if #t (set-paper-size "a8" 'landscape) (set-paper-size "a8")) > } > > Note that this will only work with a _literal_ #f or #t as argument: > you'll likely want to have some actual condition evaluated at runtime, > like some variable name. Then you'll need to write > > #(define-macro (proc bool x y) > `(if ,bool ,x ,y)) > > -- > David Kastrup Thanks for the insights, Harm ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: Procedure for set-paper-size in \paper ?
Thomas Morley writes: > Hi all, > > (1) > consider the following code (working as expected): > > \paper { > #(if #t (set-paper-size "a8" 'landscape) #(set-paper-size "a8")) > } > > \score { { R1 } \layout { ragged-right = ##f } } > > Switching from #t to #f results in different paper-size, as desired. Unlikely as you write #(set-paper-size ...) here, see below. > > (2) > But trying to put it in a procedure, it always returns the true-case: > > #(define (proc bool x y) > (if bool x y)) > > \paper { > #(proc #f (set-paper-size "a8" 'landscape) #(set-paper-size "a8")) > } Uh, the return value is irrelevant. It always _executes_ the true case. It also executes the false case but that is not overly interesting since the false case is a vector consisting of the elements 'set-paper-size and "a8" since you write #(...) while already in Scheme, the syntax for vector literals. Now if you want to execute only conditionally, you either need to wrap in lambdas or use a macro rather than a procedure: #(define-macro (proc bool x y) (if bool x y)) \paper { #(if #t (set-paper-size "a8" 'landscape) (set-paper-size "a8")) } Note that this will only work with a _literal_ #f or #t as argument: you'll likely want to have some actual condition evaluated at runtime, like some variable name. Then you'll need to write #(define-macro (proc bool x y) `(if ,bool ,x ,y)) -- David Kastrup ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: Procedure for set-paper-size in \paper ?
On 2018-05-18 16:03, Thomas Morley wrote: 2018-05-19 0:36 GMT+02:00 Aaron Hill : On 2018-05-18 14:24, Thomas Morley wrote: #(define (proc bool x y) (if bool x y)) Your `proc` function does not have this behavior, as the arguments passed in will be evaluated before you get to the inner `if`. Hm, then I should reword my request. Is there a way to circumvent this behaviour? Yes, you need to use some form of lazy evaluation. Perhaps the most explicit way is to pass in lambdas: \version "2.19.81" #(define (proc bool x y) ((if bool x y))) \paper { #(proc #t (lambda () (set-paper-size "a8" 'landscape)) (lambda () (set-paper-size "a8"))) } \markup { "Are we landscape or not?" } NOTE: There is an extra set of parentheses in the `proc` body in order to evaluate the selected parameter. Another less verbose option is to simply quote the arguments and `eval` them as needed: #(define (proc bool x y) (eval (if bool x y) (interaction-environment))) \paper { #(proc #t '(set-paper-size "a8" 'landscape) '(set-paper-size "a8")) } NOTE: Unlike before, we *need* the extra quote for `landscape` in this case, so there is a potential gotcha. -- Aaron Hill ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: Procedure for set-paper-size in \paper ?
2018-05-19 0:36 GMT+02:00 Aaron Hill : > On 2018-05-18 14:24, Thomas Morley wrote: >> #(define (proc bool x y) >> (if bool x y)) > Your `proc` function does not have this behavior, as the arguments passed in > will be evaluated before you get to the inner `if`. Hm, then I should reword my request. Is there a way to circumvent this behaviour? I'm finally aiming at a function selecting from different set-whatever! > Now, `set-paper-size` > has a side-effect, so the evaluation of that function alone is enough to > have an impact. Technically, the function should be named > `set-paper-size!`, as the convention is to suffix an exclamation to indicate > such functions. > > So, calling `proc` with the two functions results in both being evaluated, > which is not what you want. Ok, then another example for this would be: #(define (proc bool x y) (if bool x y)) #(define lst #f) #(proc #f (set! lst '(1 2)) (set! lst '(3 4))) #(write lst) always returns: '(3 4) > > Your `apply` approach is closer to what you want, since you are using `proc` > as a means of selecting the arguments you want and calling `set-paper-size` > only once. This should work, except you have an extra quote. > > > #(apply set-paper-size (proc #t '("a8" landscape) '("a8"))) > > > The outer quote for invoking the list shorthand already results in > `landscape` being a symbol. The extra quote would put another layer of > indirection, which `set-paper-size` does not expect. Ok, it's an overside then. Thanks for spotting it. > > Hope this helps, > > -- Aaron Hill It helped a lot. Many thanks, Harm ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: Procedure for set-paper-size in \paper ?
On 2018-05-18 14:24, Thomas Morley wrote: Hi all, (1) consider the following code (working as expected): \paper { #(if #t (set-paper-size "a8" 'landscape) #(set-paper-size "a8")) } \score { { R1 } \layout { ragged-right = ##f } } Switching from #t to #f results in different paper-size, as desired. (2) But trying to put it in a procedure, it always returns the true-case: #(define (proc bool x y) (if bool x y)) \paper { #(proc #f (set-paper-size "a8" 'landscape) #(set-paper-size "a8")) } \score { { R1 } \layout { ragged-right = ##f } } Paper-size is always a8-landscape. (3) Trying: #(define (proc bool x y) (if bool x y)) \paper { #(apply set-paper-size (proc #t '("a8" 'landscape) '("a8"))) } \score { { R1 } \layout { ragged-right = ##f } } Paper-size is always a8 - What's happening here and why? And how to make a procedure accepting set-paper-size work, with different settings and an if-condition? My Scheme is a little rusty over the years, but I will try to explain what is going on. Firstly, `if` has a rule that it only evaluates either the true-value or false-value based on the Boolean. That means exactly one of the two expressions will evaluate. Your `proc` function does not have this behavior, as the arguments passed in will be evaluated before you get to the inner `if`. Now, `set-paper-size` has a side-effect, so the evaluation of that function alone is enough to have an impact. Technically, the function should be named `set-paper-size!`, as the convention is to suffix an exclamation to indicate such functions. So, calling `proc` with the two functions results in both being evaluated, which is not what you want. Your `apply` approach is closer to what you want, since you are using `proc` as a means of selecting the arguments you want and calling `set-paper-size` only once. This should work, except you have an extra quote. #(apply set-paper-size (proc #t '("a8" landscape) '("a8"))) The outer quote for invoking the list shorthand already results in `landscape` being a symbol. The extra quote would put another layer of indirection, which `set-paper-size` does not expect. Hope this helps, -- Aaron Hill ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Procedure for set-paper-size in \paper ?
Hi all, (1) consider the following code (working as expected): \paper { #(if #t (set-paper-size "a8" 'landscape) #(set-paper-size "a8")) } \score { { R1 } \layout { ragged-right = ##f } } Switching from #t to #f results in different paper-size, as desired. (2) But trying to put it in a procedure, it always returns the true-case: #(define (proc bool x y) (if bool x y)) \paper { #(proc #f (set-paper-size "a8" 'landscape) #(set-paper-size "a8")) } \score { { R1 } \layout { ragged-right = ##f } } Paper-size is always a8-landscape. (3) Trying: #(define (proc bool x y) (if bool x y)) \paper { #(apply set-paper-size (proc #t '("a8" 'landscape) '("a8"))) } \score { { R1 } \layout { ragged-right = ##f } } Paper-size is always a8 - What's happening here and why? And how to make a procedure accepting set-paper-size work, with different settings and an if-condition? Cheers, Harm ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user