From mboxrd@z Thu Jan 1 00:00:00 1970 From: swedebugia Subject: Re: Learning the match-syntax... Date: Tue, 8 Jan 2019 09:25:34 +0100 Message-ID: <9bf31a36-3774-5dc2-8fe7-acc34e3d6a7f@riseup.net> References: <87pntxwqx0.fsf@gnu.org> <08635A1A-EDA5-44B0-8C8A-532F16683154@flashner.co.il> <20181219192926.GB2581@macbook41> <87imzmmwno.fsf@gnu.org> <20181225143202.GO2581@macbook41> <87zhsf2ec6.fsf@gnu.org> <878szx1nah.fsf@gmail.com> <9ee2cc12-7394-6256-7268-adc43c1a56c9@riseup.net> <87bm4s862z.fsf@elephly.net> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable Return-path: Received: from eggs.gnu.org ([209.51.188.92]:53610) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggmb7-0005qS-5N for guix-devel@gnu.org; Tue, 08 Jan 2019 03:18:54 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggmb4-0007kp-8c for guix-devel@gnu.org; Tue, 08 Jan 2019 03:18:52 -0500 Received: from mx1.riseup.net ([198.252.153.129]:35118) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggmb3-0007gf-Qj for guix-devel@gnu.org; Tue, 08 Jan 2019 03:18:50 -0500 In-Reply-To: <87bm4s862z.fsf@elephly.net> Content-Language: en-US List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: "Guix-devel" To: Ricardo Wurmus Cc: "guix-devel@gnu.org" On 2019-01-07 23:18, Ricardo Wurmus wrote: >=20 > Hej swedebugia, >=20 >> e.g. >> (match '(1 2 "y" "x") >> (1 >> 'one) >> (number >> 'number)) >> >> Will match any number for the first clause and any string for the >> second. It ONLY checks if it is a number. >=20 > This is not correct. The first clause does not match because the numbe= r > 1 is not equal to the list '(1 2 "y" "x"). So we fall through to the > next pattern. That pattern is just the variable name =E2=80=9Cnumber=E2= =80=9D, which > will match absolutely anything. =E2=80=9Cnumber=E2=80=9D will be bound= to '(1 2 "y" > "x") and the return value of the clause is the symbol 'number. >=20 >> To actually match something e.g. the "x" literally we need to nest the >> match like this: >> >> (match '(1 2 y x) >> (string >> (match string >> ("x" >> 'x!))) >> (number >> 'number)) >=20 > No. Here the first pattern matches absolutely anything. The name > =E2=80=9Cstring=E2=80=9D could be anything at all. It=E2=80=99s just t= he name of a variable > that should be bound. So here you first bind '(1 2 y x) to the variabl= e > =E2=80=9Cstring=E2=80=9D, and then you try match the value of that very= same variable to > the string "x", which fails. Hence we fall through to the next clause, > where the pattern is just the variable =E2=80=9Cnumber=E2=80=9D, which = will bind to > absolutely anything. So that=E2=80=99s what happens and the symbol 'nu= mber is > returned. >=20 >> Positional arguments work like this: >> >> (match '(1 2 y x) >> ;match the third item >> (_ _ string >> ;check if it is the literal "x" >> (match string >> ("x" >> 'x!))) >> (number >> 'number)) >> >> Correct? >=20 > No. If you run this in the REPL you=E2=80=99ll see an error. You have > misunderstood how match works. Here=E2=80=99s another example: >=20 > (match '(1 2 x y) > ((one two three four) > (format #f > "the first value is ~a, the second is ~a, the third is ~a a= nd the fourth is ~a\n" > one two three four)) > ((this will never match) > #f)) >=20 > Here we have two clauses: the first clause has the pattern >=20 > (one two three four) >=20 > i.e. a list of four variables. This matches the value exactly. Each > variable is bound to one of the values of the list. >=20 > The second clause has also four variables and would match just as well, > but it will not be considered as the first pattern has already matched. >=20 > Does this make things clearer? >=20 >=20 > To match by *type* (as you tried above) you need to use predicates. > Here=E2=80=99s an example: >=20 > (match '(1 2 x y) > (((? string? one) two three four) > 'will-not-match) > ((this (? number? will) totally match) > will)) >=20 > The first pattern would only match if the first value were a string > (which would be bound to the variable =E2=80=9Cone=E2=80=9D). But it i= s not, so the > next pattern is tried. There we want to match against four variables o= f > which the second needs to be a number. This matches, so =E2=80=9Cwill=E2= =80=9D is bound > to the number 2, which is what we return. This was exactly what I needed to understand! <3 I went ahead and coded all morning and now I ported one of the=20 medium-level procedures in guile-wikidata to use match: (define* (get-label qid #:key (language 'en)) "Return STRING with label in the target language. Supports only one language. Defaults to \"en\"." (and-let* ((l "labels") (result (wdquery-alist (getentities-uri qid l #:languages language)= ))) (match result ((_ (entities (q id type (labels (result (value . val) lang) _=20 ...) _ ...))) val)))) scheme@(wikidata apis) [39]> (load "../guile-wikidata/wikidata/apis.scm") scheme@(wikidata apis) [39]> (get-label "Q1111") $25 =3D "electric charge" scheme@(wikidata apis) [39]> (get-label "Q1111" #:language 'sv) $26 =3D "elektrisk laddning" --=20 Cheers Swedebugia