guix-devel
[Top][All Lists]
Advanced

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

Learning the match-syntax...


From: swedebugia
Subject: Learning the match-syntax...
Date: Sat, 05 Jan 2019 13:25:40 -0800

Saluton Ludo' :)

I write this to you for no other reason than I like the code your write
and would love to learn more.

If you don't have time/energy just let me know and I will ask Pierre or
somebody else. :)

On 2019-01-05 18:39, Ludovic Courtès wrote:
> One last thing:
> 
>> +(define (check-source-unstable-tarball package)
>> +  "Emit a warning if PACKAGE's source is an autogenerated tarball."
>> +  (define (check-source-uri uri)
>> +    (when (and (string=? (uri-host (string->uri uri)) "github.com")
>> +               (string=? (third (split-and-decode-uri-path
>> +                                   (uri-path (string->uri uri))))
>> +                     "archive"))
> 
> ‘third’ could fail badly if the list has fewer elements, so I’d suggest
> writing it something like:
> 
>   (when (and …
>              (match (split-and-decode-uri-path …)
>                ((_ _ "archive" _ ...) #t)
>                (_ #f)))
>      …)

This is an elegant rewrite to return a boolean #f in case the URL is bad
in some way.

I'm trying very hard to learn the guile match-syntax.

To make sure I understand the above I would like to explain it and you
can verify that I got it right. Ok?

>              (match (split-and-decode-uri-path …) <- this is the input
>                ((_ _ "archive" _ ...) #t)
                   ^ ^ ^ =third  ^       ^return true if the clause
match
                                 ^fourth & more
                   ^ ^ = anything twice 
>                (_ #f)))
                  ^ =the general case =else return #f.

Correct?

This is a more complicated (nested) match example from Juliens opam
importer which I find is an elegant functional way to find what we need:

(define (metadata-ref file lookup)
  (fold (lambda (record acc)
          (match record
            ((record key val)
             (if (equal? key lookup)
               (match val
                 (('list-pat . stuff) stuff)
                 (('string-pat stuff) stuff)
                 (('multiline-string stuff) stuff)
                 (('dict records ...) records))
               acc))))
        #f file))

(define (metadata-ref file lookup)
                      ^ 2 arguments
  (fold (lambda (record acc)
                  ^2 formals, why the acc?
          (match record
                 ^input
            ((record key val)
               ^match "record" "key" "val" in a list?
             (if (equal? key lookup)
                          ^ we continue if the key is right
               (match val
                       ^input
                 (('list-pat . stuff) stuff)
                     ^ if 'list-pat return stuff
                 (('string-pat stuff) stuff)
                     ^ if 'string-pat return stuff
                 (('multiline-string stuff) stuff)
                 (('dict records ...) records))
                    ^if 'dict return first record
               acc))))
                ^ this is the else (what is this good for?)
        #f file))
             ^ input to fold
         ^ no initial in the fold

If I understood this correctly I hope I will be able to get something
like this to work in the quicklisp importer :)

-- 
Cheers 
Swedebugia



reply via email to

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