lilypond-user
[Top][All Lists]
Advanced

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

Re: scheme-question about accumulating lists of lists


From: Thomas Morley
Subject: Re: scheme-question about accumulating lists of lists
Date: Sun, 21 Apr 2019 10:44:38 +0200

Am So., 21. Apr. 2019 um 02:34 Uhr schrieb David Pirotte <address@hidden>:
>
> Hi Thomas,
>
> > ...
> > Thanks pointing me to this possibility, in my use-case I then could do:
> > (define (p) (cons '(1 2 3) '(4 5 6)))
> > (define l1 '(a b c))
> > (define l2 '(x y z))
> > (cons* l1 l2 (car (p)) (cdr (p)) '())
> > =>
> > ((a b c) (x y z) (1 2 3) (4 5 6))
>
> Yes, if you can (you mentioned the code was not yours and couldn't be
> changed ...) that would be a lot cleaner, imo, and will let you use 'built-in'
> scheme, guile and srfi-1 procedures that work on lists, as mentioned in my 
> first
> answer.

Yep, I can't change the 'consing' built-in procedure, (I tried to
patch it but it gives an unexpected error at on first sight absolutely
unrelated location, should investigate ...).

> > > (define (blue-walk blue proc)
> > >   (let loop ((blue blue)
> > >              (result '()))
> > >     (match blue
> > >       ((a . rest)
> > >        (if (pair? a)
> > >            (loop rest
> > >                  (cons (proc a) result))
> > >            (reverse! (cons (proc (cons a rest))
> > >                            result))))
> > >       (()
> > >        (reverse! result)))))
>
> In the above code, I am performing an extra and therefore useless cons, here
> is a correction (not a bug, but one should _always_ avoid consing whenever 
> possible):
>
> (define (blue-walk blue proc)
>   (let loop ((blue blue)
>              (result '()))
>     (match blue
>       ((a . rest)
>        (if (pair? a)
>            (loop rest
>                  (cons (proc a) result))
> ->           (reverse! (cons (proc blue)
>                            result))))
>       (()
>        (reverse! result)))))

Thanks again!

> > My guile-knowledge is mostly limited to what LilyPond needs.
> > As far as I can tell (ice-9 match) isn't used in our source.
> > So I need to study your `blue-walk´ from scratch.
>
> In this particular case, match is 'convenient', but not really indispensable 
> - and I
> see now it's not in guile-1.8.

I think you're wrong.
It's not in the guile-1.8-docs, but below worked:

~$ guile
guile> (version)
"1.8.8"
guile> (use-modules (ice-9 match))
guile> (define blue
  (cons '(a b c) (cons '(1 2 3) '(x y z))))
guile> (define fox
  (cons '(a b c) (cons '(1 2 3) (cons '(x y z) '()))))
guile> (define (blue-walk blue proc)
  (let loop ((blue blue)
             (result '()))
    (match blue
      ((a . rest)
       (if (pair? a)
           (loop rest
                 (cons (proc a) result))
           (reverse! (cons (proc blue)
                           result))))
      (()
       (reverse! result)))))
guile> (blue-walk blue cdr)
((b c) (2 3) (y z))
guile> (blue-walk fox cdr)
((b c) (2 3) (y z))
guile>

> Here is a version that does not need match (though
> you might not even need it if you can (cons* a b c ... '()) as you mentioned 
> here
> above):
>
> (define (fox-walk fox proc)
>   (let loop ((fox fox)
>              (result '()))
>     (if (null? fox)
>         (reverse! result)
>         (let ((a (car fox)))
>           (if (pair? a)
>               (loop (cdr fox)
>                     (cons (proc a) result))
>               (reverse! (cons (proc fox)
>                               result)))))))
>
> Now, if/when you (lily devs I mean, not just you of course) plan to use 2.0, 
> 2.2 or
> 3.0 (2.9.1 is it is ...) [*], it is highly recommended to use match 
> 'everywhere'
> you'd use car, cdr, cadr ... but not only, look at the "7.7 Pattern Matching"
> section of a recent manual for more ...  the code is/becomes a lot more 
> readable,
> and match is not only extremely powerful, but also extremely fast (no 
> figures, but
> it's being said there is no penalty compared to using 'older' destructuring
> techniques ... (referred to, among guilers, 'the car cdr hell' :))

Other devs may drop in here, but this is my very basic understanding
about LilyPond/guile-relationship:
LilyPond uses guile as it's extending language.
Among LilyPond users there are musicians with little or even no
programming  background up to experienced programmers with interests
in type-setting music.
(Actually I was one of those musicians with no programming background.
Ok, probably one could say I had some ambitions.)

To give the former the possibility to extend LilyPond with guile we
try to keep things as simple as possible (it's sometimes scaring
enough), give the users strong tools at hand which hide complexity,
and do things in a modular way so they can be changed in detail
without affecting other stuff, if possible. David Kastrup did
wagonloads of work in this regard (and the C++ layer as well).

Among keeping things simple is the attempt to use very little
additional guile-modules.

So far my general basic understanding.

Whether 'pattern matching' will be useful to hide complexity to make
life easier for our users or whether it adds an abstraction layer,
which would make it even harder for users to write their own
guile-code, I can't judge currently.

Thanks,
  Harm

>
> David.
>
> [*]     I know why the change hasn't been made, I don't expect any answer 
> here,
>         just mentioning that if/when ... (saying this so you save your energy 
> and to
>         avoid to start yet another conversation on this already deeply 
> discussed
>         mater among you ...)



reply via email to

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