IRC channel logs

2026-03-19.log

back to list of logs

<jab>evening everybody.
<jab>I was considering closures...can one think of closures as object oriented programming ? Or is it more broad than that ?
<jcowan>jab: Yes. "Closures are poor man's objects, but then again objects are poor man's closures."
<jab>jcowan: I guess I was interested in learning about pure functional programming.
<jab>it seems streams are an important concept in purely functional programming, at least according to SICP. I'm learning that now.
<jcowan>Classic objects don't really fit with FP; the rough equivalent is sum types.
<jab>yeah, SICP talks about making a bank account with closures. I'm still trying to figure out how to make a "bank account" program without using set! .
<jab>I'll figure it out eventually.
<jcowan>Basically thread the account object through your program, but you can't actually hide the fields in it.
<jcowan>But doing set! on a local variable is not a Bad Thing
<jcowan>local variables are truly hidden
<jab>hmmm, I guess I have the notion of wouldn't it be cool to write programs without using any "!".
<jab>so no set!, etc.
<jcowan>If you make them parameters, you can tail recurse giving the new values, and using a shim procedure that supplies the original values. That is what (let loop ...) is rewritten to.
<jab>ok, infinite streams are super cool! with a few lines of code you can define integers.
<jab>that's wild!
<identity>jab: wait until you see (and understand) McIlroy's Power Serious
<jab>looking it up now.
<jab>is this it? https://www.cs.dartmouth.edu/~doug/powser.html
<identity>yeah
<jab>you're right. I didn't understand it. :)
<identity>jab: you would need to learn Haskell first, or at least an ML-like language
<jab>is ML worth learning ?
<identity>a programming language that does not change how you think about programming is not worth learning. ML is worth learning
<apteryx>is the author of the current srfi-64 implementation in guile around?
<identity>in fact, there is a book by the author of The Little Schemer called The Little MLer
<jab>gotcha.
<jab>so, SICP just defined the stream of primes with something essentially this: https://paste.rs/ecqD5 is this efficient ?
<jab>also I'm actually shocked.
<jab>(stream-car (stream-drop 8 primes)) -> 23
<jab>then when you evaluate primes -> #stream(? ? ? ? ? ? ? 23 ...)
<jab>the only value of primes that is known is currently the 8th value. I'm surprised that the earlier values have not been known yet...
<identity>jab: it is not the most efficient way, but it should pretty fast unless you do, like, (stream-ref primes 1e9)
<jab>that is probably the coolest way to define the prime numbers that I've ever seen.
<jab>well actually I didn't know that it was possible to define an infinite series of numbers in code before. That is super cool!
<identity>stream/lazy evaluation gives way for some concise definitions, like the Power Serious's definition of the sine and cosine series
<jab>well, at the moment I'm still trying to understand how the sieve function filters out the composite numbers, but then I'm still trying to figure out how it's efficient too.
<jab>SICP said that recursion is super cool, but the "naive" way to recursively define a function is normally not the most efficient.
<jab>for example, here's the naive way to define a factorial function: https://paste.rs/D7zLQ it's not very efficient.
<jab>the more efficient way to define factorial is: https://paste.rs/9TlNT
<jab>the second function defines factorial with 2 functions: factorial and fact-iter.
<identity>jab: it is not efficient because it is not tail-recursive. in practice, any decent compiler is going to transform the first version into the second
<jab>identity are you saying that the guile compiler is soo smart that the naive version of factorial and the more efficient version...run the same speed on guile ?
<identity>jab: well, in the same space
<jab>that's kind of awesome.
<apteryx>should GNU MP be added to the guile package in the guix.scm file at the root of the repo? configure fails without it, unless specified --enable-mini-gmp
<apteryx>it's an annoyance
<identity>jab: assuming a compiler does not make such an optimization, the change in speed for the inefficient version because of the space requirement is likely negligible, but not non-existent
<jab>well I guess my un-enlightened brain just sees the prime sieve function as looking like that naive factorial function. and thus slow.
<jab>I'll probably end up blogging about this. maybe trying to teach it will make it make more sense for me.
<identity>jab: this optimization is called ‹tail-recursion modulo cons›, because it is applicable to tail calls of the form (define (func …) … (cons … (func …)) …)
<identity>but you can replace cons with almost any function
<jab>yeah...maybe me writing a scheme compiler would help me understand this a bit too.
<identity>jab: here is an interesting way to define factorial: (define (interval-list k l) (if (> k l) '() (cons k (interval-list (+ 1 k) l)))) (define (factorial n) (apply * (interval-list 1 n)))
<jab>I'm going to have to take some time to digest that...
<jab>actually I think guile has a interval-list function...
<jab>something like return me a list of numbers 1 - n ...
<jab>ah, it's "iota"
<identity>jab: (define (interval-list k l) (iota l k))
<identity>so that factorial definition is really just (define (factorial k) (iota k 1))
<identity>err
<identity>(apply * (iota k 1))
<jab>isn't that cool!
<identity>very much so
<jab>I actually found out about the iota function, because I started to write APL in guile.
<jab>I haven't gotten very far.
<jab>but I think there should be a SRFI for APL.
<jab>maybe it would be hard to write that in portable scheme.
<identity>jab: the interesting part about that factorial definition is that it runs in more-or-less the same time as (define (factorial k) (if (zero? k) k (* k (factorial (- k 1))))), despite the fact that it allocates memory for the whole list
<identity>at least, on my laptop running guile
<jab>what are you using the test the speed comparison ?
<jab>also, I probably need to go to sleep soon, but this guile chat has been super fun, btw.
<identity>in the REPL, ‹,pr <expression>›
<identity>pr is short for profile
<jab>hmmm... ",pr (factorial 4)" --> no samples recorded.
<identity>it runs too fast, try a bigger number
<jab>interesting. I'll have to play with that.
<apteryx>hm, how is the srfi-64-test plugged into the test suite? it looks like it isn't
<apteryx>I'd expect something like make check TESTS=tests/srfi-64-test.scm to work
<rlb>apteryx: perhaps see the top of ./check-guile if you haven't wrt the last bit.
<rlb>...and while I wasn't involved in creating the current srfi-64, I did wire it in to the parallel test harness in main. See c85825328826e2078fe0177e43185e4550d14282.
<rlb>And the patches around df04f5357a0c7146d7ec1c4fcd8c11a42feb5e01 show how we switched to the parallel test harness a bit back.
<apteryx>so all files ending by .scm .sr64 or .test are ran a Scheme tests (using the scheme test driver) ?
<rlb>To run during make check, they also have to be listed in TESTS in the relevant Makefile.am.
<rlb>see info autoconf for a lot more about that.
<apteryx>should srfi-64-test.scm be added to SCM_TESTS ?
<rlb>(the patches also show how some of that is done)
<rlb>Sorry, guile-suite tests end in .test, not .scm.
<apteryx>in Guix we have TESTS = $(SCM_TESTS) $(SH_TESTS)
<rlb>While I don't know I assume that srfi-64-test.scm is "something else".
<apteryx>that makes it possible to run a single scheme test via its file name like 'make check TESTS=tests/some-test.scm'
<rlb>Oh, right, it's just included by srfi-64.test.
<apteryx>I see; so it's already "registered" or at least part of the normal test suite
<rlb>guile's test suite was originally completely custom (check-guile, test-suite/test-suite/, etc.), now that custom harness can also be driven by automake's parallel harness.
<rlb>(and can handle srfi-64 too)
<apteryx>good, I see that 'make check' alone picks tests/srfi-64.test. It's a bit odd that a failure (caused by a local change) is then reported as FAIL: tests/srfi-64-test.scm
<rlb>(you can also run the tests from test-suite via "make tests/something.log" if the log doesn't exist)
<apteryx>or can I select it via the TESTS environment variable?
<apteryx>s/or/how/
<apteryx>I can use 'make recheck' for now, but I'm still curious to know how to use TESTS with the Guile test suite.
<rlb>The supported way is just ./check-guile ...
<apteryx>won't that run every tests?
<rlb>Read the top of ./check gule
<rlb>./check-guile
<apteryx>I see: Usage: check-guile [-i GUILE] [--] [TEST...]
<rlb>Oh, sorry, I thought you were looking at main.
<rlb>It's better documented now I think.
<rlb>fsvo "better documented"
<apteryx>I was reading ./check-guile --help from main yes
<rlb>No, the comments at the top of the file.
<rlb>less ./check-guile
<apteryx>OK, so './check-guile srfi-64.test' should do it
<rlb>yep
<rlb>(I don't recall offhand if there's an easy way to use TESTS to do the same thing with our arrangement.)
<apteryx>thanks. Would be nice to have this plugged these tests in TESTS as standard in Automake as well (info "(automake) Overview of Custom Test Drivers Support")
<apteryx>would be nice to have these tests registered in TESTS*
<rlb>I suspect our recursive make arrangement might make it harder.
<rlb>They are all in TESTS already.
<rlb>See test-suite/Makefile.am, depending on what you mean.
<apteryx>oh, right. So it should be possible to use TESTS; I think there must be a way to list tests as well but I don't know how.
<rlb>Looks like this will do it
<rlb>make -C test-suite check SUBDIRS= TESTS=tests/srfi-9.test
<rlb>But ./check-guile srfi-9.test is a lot simpler, and likely to keep working as-is indefinitely.
<rlb>i.e. it's the "supported way" atm
<apteryx>Interesting; it's not too far from being usable, but I wonder why we havve to override SUBDIRS this way
<apteryx>I'll use check-guile for now, thank you.
<rlb>Try removing it
<apteryx>yeah, it doesn't work without it
<rlb>It'll run the standalone tests too.
<rlb>Because we have more than one "test suite"
<rlb>They're handled via the "SUBDIRS = standalone" in test-suite/Makefile.am, so you have to "turn that off", but that's also likely fragile.
<apteryx>I see; it'd be nice that over time the test suites coalesce into a single one
<rlb>The standalone tests also use TESTS, but in the subdir --- I don't know that the automake test harness has a way to use TESTS for selectivity across recursive make directories...
<apteryx>I don't think so, but the relative file name can be used in these cases
<apteryx>e.g. make check TESTS=tests/some-level-down/my-test.scm
<apteryx>not very elegant but easy to reason with
<rlb>Oh, the automake docs even talk about overriding SUBDIRS, so maybe that's "fine".
<rlb>(or rather, expected)
<apteryx>and in Guix we have a "fancy" test driver for Scheme that can select/deselect tests based on regexps, e.g.: make check TESTS=tests/packages.scm SCM_LOG_DRIVER_FLAGS='--select=^fold-packages'
<apteryx>this selects tests whose names start with 'fold-packages' in a given SRFI 64 test file, in this case tests/packages.scm
<rlb>I'm just glad we got the parallel harness working --- much faster testing (if you have multiple cores).
<apteryx>yes, that's great improvement, thanks for working on it!
<rlb>got tired of waiting :)
<apteryx>./check-guile says srfi-207 is failing on main; is it just for me? https://paste.guixotic.coop/_shell_2_-616026-616865.html
<apteryx>In procedure simple-format: FORMAT: Unsupported format option ~x - use (ice-9 format) instead
<apteryx>seems reproducible
<apteryx>./check-guile srfi-207.test passes though, so that's odd
<apteryx>rlb: simple review, somewhat related to this discussion :-) https://codeberg.org/guile/guile/pulls/135#issuecomment-11809701
<apteryx>I've tested it fixes the test-driver.scm in guix when using --select=something
<apteryx>ACTION afk
<rogerfarrell>Is it possible to pattern match against a bound value?
<identity>rogerfarrell: wdym? just do (match variable …) ?
<rogerfarrell>Yes. I was going off the docs. I actually want to match anything but a variable.
<old>rogerfarrell: I guess you are talking about syntax-case here and not match ?
<old>not sure what you actually want here wrt to bound value
<rogerfarrell>Supposing I have variable lst. How could I define a pattern that matches anything but the contents of another variable, say smbl = "word"?
<rogerfarrell>(match lst (((not smbl) _ ...) #t))
<rogerfarrell>This is what I tried.
<identity>so you want the pattern to match if (not (equal? (car lst) smbl))?
<rogerfarrell>Yes.
<old>I don't think you can with current match AFAIK
<rogerfarrell>Good. That makes me feel slightly more literate. The manual section on pattern matching is a little dense for a beginner.
<identity>(and (? symbol?) (? (lambda (x) (not (symbol=? x symbol))))) is definitely one way
<rogerfarrell>Oof.
<rogerfarrell>I think I will just stick with a nested if.
<identity>or i guess (not (? (lambda (x) (eq? x symbol))))
<rogerfarrell>Is that intuitive to you? I am still getting comfortable with the language, so I sometimes have trouble knowing what is ledgible syntax for more experienced eyes. (Think Haskell.)
<identity>or, if it the first element of a list, (not `(,symbol . _)) should work
<identity>rogerfarrell: sure, just knowing that you can use the usual logical operators in patterns and inject your own predicates takes you a long way, even if it is not the “best” way to construct the patterns
<identity>or did you mean if the specification for the matcher in the manual is intuitive?
<rogerfarrell>The former.
<rogerfarrell>Your last suggestion is nice! I am mentally expanding it against the manual.
<identity>it might take some time to get used to, but the DSL is pretty simple, all things considered
<rogerfarrell>Thanks for the recommendations! I am playing with it now.
<rlb>apteryx: wrt that change, and only from a cursory glance, I don't know enough about what srfi-64 requires to know if that'd be OK, i.e. whether it's OK depends on whether the skip count should only count intentionally skipped tests. The srfi-64.scm author might know (Tomas Volf).
<rlb>apteryx: and right, the ./check-guile crash looks like a bug to me.
<rlb>(I might poke at it later.)
<rlb>apteryx: was just a missing use (ice-9 format). I'll fix it, and thanks for reporting it.
<old>rlb: from my reading of the spec, SRFI-64 is not clear on wether skip should count or not. I think it should
<old>I had to fix this in BLUE for 3.0.11: https://codeberg.org/lapislazuli/blue/src/commit/ab79d7634b327ee3199ea4e0e6b2a59139ba0486/blue/stencils/guile/test-driver.scm#L146
<rlb>I don't have an opinion either way atm --- haven't read srfi-64 closely enough on that front.
<mwette>(define-syntax match-no-word (syntax-rules (word) ((_ any) any)))