[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
signature.asc
Description: This is a digitally signed message part.