lilypond-user
[Top][All Lists]
Advanced

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

Re: help with Wrong type of argument


From: Valentin Petzel
Subject: Re: help with Wrong type of argument
Date: Wed, 03 May 2023 22:09:00 +0200

Hi Jeff, hi Michael,

though a bit late want to throw in some bits. First of all I’d advice you to 
check out the relevant part in Jean’s scheme tutorial:

https://extending-lilypond.gitlab.io/de/scheme/quoting.html

This should probably clean up lots of uncertainties. Then I’d like to give a 
few remarks:

A common paradigm in LISP is that almost everything is either a list or a 
primitive data type. This does then include function calls. A function call of 
the type (function arg1 arg2 ...) can be seen as a list where the first 
argument evaluates to a function reference. This means that inherently there 
is no difference between data and language.

Using this we can do a lot of dynamic programming, using lazy evaluation and 
such. Compared to other languages where eval evaluates a string the scheme 
eval evaluates a list, so essentially a data structure. This has has the nice 
advantage that we can separate parsing and evaluation, and it makes 
constructing function calls programmatically quite easy.

Some example:
#(use-modules (ice-9 local-eval))
#(define (test a expr)
   (local-eval expr (the-environment)))
#(display (test 1 '(+ a 1)))
#(newline)
#(display (test 2 '(+ a 1)))

Now, for this we get a cool concept which is quoting. Starting a scheme 
expression with a quote or calling it withing (quote expression) will tell the 
parser to parse the expression, but not evaluate it. As in scheme language is 
either a list, a literal or a symbol we then get thus a list, a primitive data 
type or a symbol.

So inputting '(...) will result in a list of of everything that is given in 
... in exactly the form it is given.

We often abuse this to get a shorthand for defining lists, e.g. instead of 
doing

(list 1 2 3)

we do

'(1 2 3)

But we need to keep in mind that this is not the same thing, as the first 
expression is evaluated, the second isn’t. This we can see if we add some 
language:

(list (+ 1 1) 2 3) → 2, 2, 3
'((+ 1 1) 2 3) → (+ 1 1), 2, 3

Now we also have the concept of quasi-quoting, which is like quoting, but with 
certain parts being evaluated. This is done using backticks (to quasiquote) 
and commas (to unquote) or using the functions quasiquote and unquote. So 
starting an expression with a backtick will only evaluate those parts that are 
started with a comma. Example:

#(use-modules (ice-9 local-eval))
#(define (test a expr)
   (local-eval expr (the-environment)))
#(define a 1)
#(display (test 2 `(cons ,a a)))

Now, Lilypond path commands are designed to look like language, but they are 
not handled like language (so they are never evaluated). This means that when 
you do '(lineto 0 hgt) the procedure handling the drawing will find the symbol 
hgt in second position and not know what to do. If this was actually evaluated 
we’d get a different error, as we won’t be able to resolve the symbol hgt.

In any case, we see that this symbol hgt needs to be resolved before it is 
passed to the path procedure. Thus we’ll need to use

`(lineto 0 ,hgt)

or explicitely construct the list

(list 'lineto 0 hgt)

Cheers,
Valentin

Am Montag, 1. Mai 2023, 08:20:13 CEST schrieb Michael Werner:
> Hi Jeff,
> 
> To say I'm no expert in Scheme is a vast understatement. However, I think I
> found the answer to this one. Or, at least, something that seems to make
> this code work for me here.
> 
> On Mon, May 1, 2023 at 1:00 AM Jeff Olson <jjocanoe@gmail.com> wrote:
> %< snip >%
> 
> > Here's my code (small if not minimal):
> > 
> > \version "2.24.0"
> > 
> > #(define-markup-command (dopath layout props xtip ytip hgt wid txt rot)
> > 
> >    (number? number? number? number? string? number?)
> >    (let (
> >    
> >           (a (* wid 0.4))
> >           )
> >    
> >    (interpret-markup layout props
> >    
> >      #{\markup \translate #(cons xtip ytip) \rotate #rot \path #0.25
> 
>  Basically, as I understand things, this bit:
> >        #'((lineto 0 hgt)
> 
> Accosrding to my rather vague understanding of Scheme syntax the ' between
> the # and the 1st ( is saying don't interpret anything in that expression,
> just pass it as is. Which means that your variable hgt isn't getting passed
> as a variable but is getting passed as simply a series of three characters.
> What seems to be needed (and what made this appear to work here) is to use
> what's called quasiquoting. Basically, it lets you designate certain bits
> within an expression as "this part should be interpreted before getting
> passed on". This entails changing the above line to:
> 
> #`((lineto 0 ,hgt)
> 
> By changing the ' into a ` (BTW, that's the one that on my keyboard is up
> near the top left, just under the Escape key) you say that there's
> something in the following expression that will need interpreted. Then the
> comma before the variable name points out which item to interpret. There's
> a great deal more to all this, but this is the bare basics as I sorta kinda
> vaguely understand them. All the gory details can be found at:
> 
> https://extending-lilypond.gitlab.io/en/scheme/quoting.html
> 
> >           (closepath))
> >        
> >        #})))
> > 
> > \markup \dopath #10 #0 #2 #1 "D" #-5
> 
> Hope this helped at least a little. Or at least didn't confuse things worse.
> 
> Michael

Attachment: signature.asc
Description: This is a digitally signed message part.


reply via email to

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