***karlosz_ is now known as karlosz
<lloda>there's a repl shortcut ,re (module) <ekaitz>oh! I just found the ,profile command <ekaitz>lloda: yeah! I just found that through the ,profile command, thanks a lot! <tohoyn>IMHO the cumulative time measurement in the current Guile is broken ***X-Scale` is now known as X-Scale
<tribals>Hello! I have a question about pattern matching and srfi-9 records <tribals>(= field pat) a ``field'' of an object <tribals>Here the $ pattern is used to match a SRFI-9 record of type person containing two or more slots. The value of the first slot is bound to name. The = pattern is used to apply force on the second slot, and then checking that the result matches the given pattern. <tribals>Yes, it's funny - recursive friends, lol. <tribals>But what the hell, on the haven and in the earth, this `(= field pat)` is? <tribals>According to docs, I'm supposed to guess what "field" is? <lilyp>"field" here means a procedure to extract a value from pat <tribals>Hello, lilyp! Thanks for answering me! ^_^ <tribals>In there, I'm trying to use `(country-name ...)` "to extract a value from pat". What is this "pat" supposed to be, indeed? <tribals>Could I be given a simple example instead, please? <lilyp>(match australia ((= country-name "Australia") "Yay, kangaroos!") ((= country-name "Austria") "No kangaroos for you")) <tribals>Okay. How to bind it? I want the body to be `(string-append "Yay, kangaroos in " name "!")` <lilyp>(match australia ((= country-name (and "Australia" name)) (string-append "Yay, kangaroos in " name "!")) ((= country-name "Austria") "No kangaroos for you")) <lilyp>$2 = "Yay, kangaroos in Australia!" <tribals>How to write a pattern that matches "country with name Australia, but only <country>!" Assuming I've `(define-record-type <country-music-land> (make-country-music-land name) country-music-land? (name country-name))` ? <lilyp>(and (? country?) (= country-name "Australia")) ? <tribals>`(and "New-Zealand" name)` - that's strange... <tribals>why not `(match c (($ <country> a-pattern-i'm-not-aware-of-to-match-a-field) 'Yay!))` ? <tribals>I mean, that `($ <record-type ...)` already mathches records, not? <lilyp>so ($ <country> "Australia") matches australia if name is the first field <lilyp>alternatively if you don't know the ABI, you could still (and ($ <country>) (= country-name "Australia")) <tribals>Lord, what's that thing ABI? why I'm ever need to know that? <lilyp>"ABI" or "application binary interface" is here meant as a shorthand for the order in which record fields have been declared <lilyp>if you know C, you might be familiar with structs and how they are packed <tribals>I *know* what ABI is. I don't know why pattern matching of record types depend on it <lilyp>well, you could read the description for $ or you could just trust me to know that it does :) <tribals>I'm sure I dont' need to ask random habitue of an IRC channel in order to figure it out. <lilyp>"Here the ‘$’ pattern is used to match a SRFI-9 record of type PERSON <lilyp>containing two or more slots. The value of the first slot is bound to <lilyp>So yeah, slot order matching *is* documented by example <tribals>There is no example. I'm not tend to count Alice-and-Bob as example. <lilyp>Here is a more complex example: <tribals><lilyp> containing two or more slots <tribals>Where is the slots in SRFI-9 records? <civodul>i think i wrote the Alice-and-Bob example and i like it :-) <tribals>civodul: I disagree. It illustrates nothing. <civodul>surely we can do better and add more examples, but is this one particularly bad? <civodul>tribals: could you elaborate though? <civodul>i trust it didn't work for you, but how could it be improved? <tribals> (($ person name (= force (($ person "Bob")))) <tribals>($ person name (= force (($ person "Bob"))) <tribals>It uses two patterns at once, so it is not clear what get's bound to what? <civodul>there's a paragraph below explaining taht <civodul>but yes, it's a more complex example, as the manual says <civodul>maybe we need more simpler examples? <lilyp>I mean you do see the records yourself <lilyp>the record is literally (make-person "Alice" (delay (list bob))) <tribals>At first glance, it is not even clear that force is a procedure (should be procedure? again, docs has nothing to say). Only if reader is aware that it is builtin, he can spot it. <tribals>(= field pat) a ``field'' of an object <lilyp>force is a documented procedure <civodul>does the fact that the example uses a promise make it harder to grasp? <lilyp>I think the confusion is with fields vs. slots in SRFI records <lilyp>slots are a low-level implementation detail, whereas fields are what they are called on the high level <lilyp>thus "field" of object invites confusion <civodul>this part uses the word "slot", but today i'd rather use "field" because we're talking about plain records, not GOOPS objects <lilyp>because the first field (slot) of a country is not a country <civodul>so you're applying 'country-name' on a string <civodul>you can either write: ($ <country> "Australia") <civodul>the latter would throw an exception if the thing being matched is not a <country> though, so the former is preferable <tribals>first depends on fields order, which depends on ABI (now I know that); second match anything with `(country-name`), not just countries <tribals>>the latter would throw an exception if the thing being matched is not a <country> thoug <lilyp>country-name checks that its argument is a country and throws an exception if not, just so you know <tribals>($ person name (= force (($ person "Bob")))) <tribals> | | `- another "field" pattern, or binding? <tribals> So, I read 1 as "call force on field, then match its value with whatever pattern is supplied" <tribals>($ <country> (= country-name "Australia")) <tribals>So, I read 2 as "call country-name on record, then match with literal value" <tribals>This is because I read "(= field pat)" (and corresponding "a ``field'' of an object") as is. A field of an object is, eg. `(country-name ...)` <lilyp>civodul: I think renaming ``field'' to ``accessor'' is the right choice here <tribals>I mean, patter matching is hard topic at its own. Why to mix another hard topic (force/delay)? <tribals>Then I need to "decipher" example instead of just reading it. <tribals>In this is only one example of "feild" matching. <lilyp>force and delay are not that hard tho? <tribals>Is *is* hard when there is two, instead of one. <lilyp>I mean it is literally said to be a complex example and then explained exactly what it does ._. <tribals>The whole Scheme is about simplifying things down to simplest possible form. <tribals>I mean, why it needs "to be a complex example". Why simple example doesn't qualifies here? <lilyp>complex example shows more features with less space <lilyp>the Guile manual is already considered TL;DR by many, so that's something to consider <tribals>That's what makes me sad. Then becomes a "cypher". <tribals>> complex example shows more features with less space <tribals>Clean means simple. Simple as Scheme. <lilyp>Well, IMHO most of the patterns are self-explanatory and those that aren't can be found in code bases in a manner that makes you learn by reading. <lilyp>both $ and = find application in Guix, for example <lilyp>Plus you literally have an interpreter for experiments, so you could weasel your way out by trial and error. <lilyp>That does require some skill w.r.t. interpreting error messages though. <tribals>They would be self-explanatory, but only if there is "self" - example. <tribals>cd projects/guix; rg -t lisp -A 10 -B 5 '\(\(\$ .* \(=' -p | less <tribals>774-(test-assert "build-expression->derivation and derivation-prerequisites" <tribals>775- (let ((drv (build-expression->derivation %store "fail" #f))) <tribals>777: (($ <derivation-input> (= derivation-file-name path)) <tribals>778- (string=? path (derivation-file-name (%guile-for-build))))) <tribals>($ <derivation-input> (= derivation-file-name path) <lilyp>Also = has uses outside of $ so your grep fails you. <lilyp>See the gnome updater for a simpler one <lilyp>and again, if you see $ in the wild without =, you probably wouldn't be confused either <tribals>That's the point. After reading docs, I has been sure it must be used in place of field pattern. Isn't that true? <lilyp>particularly not in the guix code base where the coding style suggests using the slot name and not somehting random <lilyp>(match "42" ((= string->number 42) #t)) <lilyp>(= procedure pat) matches object if (procedure object) matches pat <lilyp>where (procedure object) is a literal function call <lilyp>the ``field'' comes from the fact that this is how fields are written in scheme – as simple procedure calls <lilyp>there is nothing that distinguishes (car list) syntactically from (person-age alice) <tribals>`((procedure object) "Australia")` => `((country-name country) "Australia"))` <lilyp>your confusion stems from the belief that ``field'' here implies something special when it in fact does not ***Guest3516 is now known as chrislck
<lilyp>yeah, so going back to my earlier example (match australia ((= country-name "Australia") #t)) <tribals>But instead `(country-name "Australia")` which is obviously wrong <lilyp>(match (country-name australia) ((= country-name "Australia") "WTF are you doing here???")) <lilyp>does it cause the same error as your example? why yes it does <tribals>My confusion originates from belief that `(= ...)` extracts a field from record, but, only if it is passed a record, and not "slot" of that record <lilyp>you are already deconstructing your record with $ though <lilyp>($ <country> this-is-not-a-country this-is-not-a-country-either country-does-not-have-three-fields ...) <tribals>and only way to match a record non-positionally is use `(= ...)` <lilyp>yes, and you can use the (and ) pattern to apply guards <lilyp>(and (? country?) (= country-name "Australia")) <lilyp>is semantically equivalent though less efficient to ($ <country> "Australia") with your ABI <tribals>And naming bindings in a `($ ...)` pattern doesn't magically make them extract record fields from corresponding "slots". Indeed, they can be named any way: `(match a-country-at-this-time (($ country fluf pluf) (list fluf pluf)))` <tribals>Now, would not it be useful for future readers to net be confused same way? <lilyp>I already wrote this ages ago, by calling it (= accessor pat) and saying that it matches if (accessor exp) matches pat <tribals>I mean, this example makes me believe field names *does* matter: `($ <country> name code)` It's obvious to think than "names comes from, well, name". But this is a lie. It even *depends* on ABI. Docs say nothing about it. <tribals>lilyp: Hope this ever will be written in docs. <tribals>Thank you all who participated in this little discussion ^_^ It is too late. I'm leaving... zZZ <dsmith-work>(Tom Lord did the initial Guile as a port of SCM as a library)