IRC channel logs

2025-04-22.log

back to list of logs

<trannus_aran>How do y'all handle polymorphism in your guile? Message passing á la (card 'print) with the constructor dispatching on a value? Or with callback messages like (print card)? I'm doing SICP Exercise 2.4 pg. 92 and I've been thinking about this sort of thing a while now...
<daviid>trannus_aran: (most of) guile users who need polylorphism use goops, guile's clos/mop implementation
<daviid>sneek goops-tutorial?
<sneek>Its been said that goops-tutorial is https://www.wedesoft.de/software/2014/03/02/oop-with-goops/
<daviid>trannus_aran: ^^
<trannus_aran>Isn't there like a tradeoff in performance with goops tho?
<trannus_aran>I guess the question is rather: is there something between a full blown CLOS system with inheritance and something folks do with, idk, record types and message passing? Like let's say we don't need inheritance but we *do* want good C interop (maybe that's a false dichotomy, pls lemme know!)
<trannus_aran>also thank you very much for the guide! :D
<daviid>trannus_aran: goops is light, and quite efficent
<ArneBab>daviid: wasn’t there an experimental result here that goops starts becoming a bit slow when there’s a lot of different types to dispatch on? ⇒ don’t build a big data classification system mostly on goop?
<ArneBab>trannus_aran: it would be great if you could do a quick benchmark: create a generic function and check whether ,profile (for-each your-fun (iota 10000)) becomes slower when you add more specialized arguments to (your-fun something).
<daviid>ArneBab: no miracle, it's a runtime type dispatch system, as a user, you should only specify the strict minimum arg's type to acheive proper dispatch, generally, like most of the situation, it's on the first arg only
<daviid>then it is extremelly fast
<ArneBab>daviid: that’s what I mean. If trannus_aran wants to build something with very many types, some benchmarking could be in order. Point in case: I have not yet hit any performance problems with GOOPS.
<trannus_aran>nah, it's more the case that I'm trying to strike a balance between "not making a nightmare to refactor" and "not getting bogged down with abstraction layers"
<trannus_aran>considering that record types were themselves a "why do people use that? *shrug*" kinda thing to me not that long ago, I wanted to make sure I wasn't leaving good design practice on the table
<daviid>ArneBab: you can have many types, g-golf extensively uses it, it defines a couple of thousands of classes (as it imports the user required namespace classes), but rarely would a user pass more then a few args to its methods, and very rarely would he need to dispatch on more then the first arg - practically speaking, ime
<daviid>trannus_aran: fwiw, imo, forget about writing your own oop system, just use goops, and ask for help if necessary
<trannus_aran>sounds good, I think I'm more trying to figure out when the use case *calls* for something like goops, considering how much similarly "big" software gets made in guile without it?
<trannus_aran>the sorta..."C-style" scheme of just having different functions for every type is more what I'm used to (and composition of those functions thereof), so I'm kinda eyeing goops from over the fence
<daviid>ArneBab: g-golf is, by far, the 'most expensive' goops app 'out there', and I have zero performance problem - I need to improve the loading time, but it's not a goops the problem
<daviid>trannus_aran: as soon as you need classes and inheritance, should it be for a few classes only, use goops
<trannus_aran>ooo, I actually didn't know about g-golf at all! this is dope (I figured something along these lines existed in GNU land somewhere, but hadn't taken a look yet)
<daviid>and generic functions ofc
<trannus_aran>yeah, I think that's the thing: I almost never need inheritance, but generic functions rear their heads in terms of usefulness more often than the other OO benefits
<trannus_aran>(curious how clojure handles this...thinking of other big Lisp-1 impls 🤔)
<daviid>trannus_aran: fwiw https://www.gnu.org/software/g-golf
<daviid>clojure 'is java', exactly the opposite of what one should be doing, wrt oop I mean - but I don't have time t discuss this, get back to hack ... good luck with your project(s), ping if you need specific goops help (and read the above tutorial)
<rlb>trannus_aran: clojure has two main tracks -- it pragmatically favors "protocols" which are effectively first-argument dispatch, because the jvm's designed to make that *fast*, including wrt jit optimization at runtime, but clojure also has "multimethods", which are more or less another flavor of generic functions.
<rlb>And yes, I'd generally "just use goops" past a lowish threshold.
<rlb>fwiw, that's what lokke currently uses (heavily) to implement its clojure dialect.
<rlb>(lokke does not yet do multimethods, though -- in truth, I've personally, rarely needed them in clojure, but it's good that they're available)
<mwette>tho not scheme, julia uses generic functions, and the manual provides nice explanation of the approach: https://docs.julialang.org/en/v1/manual/methods/a
<rlb>What I've read about julia sounds generally interesting as compared to some of the other options in the domain...
<rlb>Never tried it, though.
<ieure>Julia is one I want to experiment with more. Heard some bad things about stability/bugginess, maybe that situation has improved.
<rlb>I think it may have -- fwiw, there was another lwn article in the past month(s) iirc.
<rlb>also think maybe I recalled reading they've been able to shrink the resulting binary sizes if/when you want one...
<rlb>though still not "small"
<lechner>Hi, what is this error message hinting at, please? In procedure frame-source: Wrong type argument in position 1 (expecting VM_FRAME_P): #<output: file /dev/tty9>
<ieure>lechner, Something is calling (frame-source ...) and the first argument is a value of a type the procedure doesn't expect.
<ArneBab>daviid: thank you for the info. IIRC the case where someone had performance problems was that they used types to categorize a huge onthology, so they may have had more than thousands of types — hopefully not the typical case.
<old>ArneBab: you asked about way of improving fibers performance. I wonder, is conditino variables sometime a bottle neck?
<old>In a wait/wake pattern
<ArneBab>old: I don’t know, but if you find a way to speed them up more, it would help I think.
<old>There is a pattern for wait/wake that is faster than condition variable and without mutex
<old>but I'm not sure if this is really a problem for the operations that fibers does
<old>this: https://github.com/urcu/userspace-rcu/blob/master/src/urcu-wait.h
<old>(only Linux)
<ArneBab>old: I created an issue in the hope that people better versed in the C-side of things than me can look into that: https://github.com/wingo/fibers/issues/121
<ArneBab>the cancel timer test for fibers currently fails: https://github.com/wingo/fibers/actions/runs/14170825654/job/39693995276
<ArneBab> heap grew too much: 11.27 MiB vs. 4.75 MiB
<ArneBab>FAIL: tests/cancel-timer.scm
<old>ArneBab: thanks
<ArneBab>old: glad to … forward your work to the people who I hope can build on it (it’s not that I did a lot)
<ArneBab>with luck I could contribute something by that ☺
<old>what's faster? (append lst '()) or (append '() lst) ?
<ieure>Well, they should both be noops.
<ieure>old, Try `profile' and see? I'd assume that, in general, (append short-list long-list) is going to be faster than (append long-list short-list).
<old>would be nice to have support for ffi with variadic arguments
<mwette>libffi does not really support variadic arguments. You can generate the ffi wrapper for each call. nyacc's ffi-helper does this (automatically) but user has to pass args with type).
<old>libffi seems to support variadic arguments?
<mwette> https://github.com/libffi/libffi/blob/master/doc/libffi.texi#L185
<mwette>argument passing in C ABIs is typically complicated, especially for x86
<old>Yes I suppose
<old>Just wished to use syscall(2) from Guile :(
<Arsen>ACTION raises eyebrow
<Arsen>that sounds cursed.. why not just write a few lines of C at that point ;)
<old>Because I want pure Guile for what I'm doing
<Arsen>I fear calling syscall negates all portability being pure guile might yield you (also, syscall is usually a macro, not a variadic function)
<old>syscall(2) is always a symbol on Linux ?
<old>not a macro
<old>but I managed to do what I wanted without syscall so that's fine
<old>any fibers friends here?
<old>I have multiple fibers that wants to print something on the terminal. I want exclusive access while printing the text to avoid mangling
<old>I was thinking of using a channel, but I don't know how to terminate the consummer when `run-fibers' terminates
<dthompson>you could signal a condition
<old>hmm right and drain the queue
<old>didn't see there was condition
<old>only though there was channels okay
<dthompson>and then the fiber that is in charge of printing can perform a choice operation: either read from the channel or wait on the condition
<dthompson>or set a terminate message through the channel
<dthompson>send8
<dthompson>send** ugh
<old>I would just wait on a condition and loop over a queue
<old>when run-fibers terminate, it also signal the same condition but say a flag to say to stop
<ArneBab>old: (define out '()) (define lst (iota 100000000)) ,profile (set! out (append lst '())) ⇒ 1.83 seconds.
<ArneBab>,profile (set! out (append '() lst)) => no samples recorded.
<ArneBab>old: reason: (append lst '()) is a series of cons of elements from lst to '().
<old>ArneBab: right I saw that after testing
<ArneBab>old: (append '() lst) is a noop
<ArneBab>old: thumbsup ☺
<ArneBab>old: besides: I remembered that there was a difference, but only remembered that it’s a cons after seeing the result …
<old>anyway good way to profile fibers?
<old>meh I guess it support it natively well enough
<mwette>Technically syscall should not be hard from guile. Just create a set of calls with 1,2,3,4,5 etc long (I think) args and base off that.
<old>actually the syscall I was trying to use do have a glic wrapper
<old>the man pages is just plain wrong
<old>good lord I have 87% usage of set-procedure-property!. None of my path use that procedure
<mwette>grep set-procedure-property goops.scm
<old>I use goops extensively
<old>but there are static definition, I don't understand what this has to do with what I'm doing
<old>I am indeed calling abunch of goop methods
<old>ah I assume it was becasue I was not loading a compiled version
<ArneBab>old: I’d suggest running the skynet benchmark.
<ArneBab>I think I wrote that here …