IRC channel logs

2024-03-06.log

back to list of logs

<fps>dsmith: ah, that was probably it
<fps>ok, starting with the example haunt configuration from this page: https://dthompson.us/projects/haunt.html
<fps>i wonder how to go about changing the default template to add some simple styling to all generated html
<fps>i found a function ugly-default-layout here: https://git.dthompson.us/haunt/tree/haunt/builder/blog.scm
<fps>and i wonder how i could "smuggle in" a changed version. i'm still a scheme noob, so any pointers would be welcome..
<fps>in the example haunt configuration there's a (use-modules ... (haunt builder blog) ...) so i guess the .scm file i linked to (blog.scm) defines that module..
<fps>oh, and that module exports the blog identifyer which is this? https://git.dthompson.us/haunt/tree/haunt/builder/blog.scm#n133
<graywolf>Hello,Is the define-meta-command documented somewhere?
<fps>ah, ok! this post helped: https://fpsd.codes/customizing-haunts-base-layout.html
<fps>awesome :)
<fps>hmm, is there a way to add an attribute to the top level html tag via SXML?
<fps>this doesn't do the right thing: `((doctype "html") (@ (style "display: table; margin: auto;"))
<dthompson>fps: you don't have a top level html tag in that example
<fps>yeah, i think i got it :)
<dthompson>((doctype "html") (html (@ (style "...")) ...))
<fps>yep
<fps>thanks!
<dthompson>np
<fps>dthompson: oh, you're the author of haunt. thanks a bunch for writing it :)
<dthompson>fps: yw :)
<graywolf>Is the fact that (foo #:a 1 #:a 2) returns 2 for (define* (foo #:key a) a) something I can rely on or just an implementation detail?
<wingo>so. i am looking at adding a racket-like `struct` form, probably named `define-record-type`, in the default environment. goal is to supersede srfi-9 by allowing record types to be defined declaratively, with space for keyword args for all interesting options, and with generated identifiers.
<wingo>probably eventually supporting record syntax transformers as well.
<wingo>anyone have thoughts on this?
<wingo>also do we have a gitlab or something at this point
<dthompson>generated identifiers, like for getters/setters?
<dsmith>Another record type? https://xkcd.com/927/
<rlb>wingo: so a superset of srfi-9, or...?
<dsmith>(jk)
<dthompson>in general I am on board with this. srfi-9 lacks some commonly needed features like setting a custom printer
<wingo>dthompson: yeah. but also constructor and predicate. overridable, but probably will compute stem by trimming leading/trailing % and <>
<wingo>rlb: yes. srfi-9 could expand into this.
<dthompson>wingo: I'm not sure how I feel about that because of hygiene
<rlb>wingo: and possibly not relevant, but I always wonder about introducing new bindings vs some kind of opt-in.
<rlb>(for any given module)
<rlb>But not arguing strongly against it or anything atm.
<wingo>and of course as you probably are aware it would use the same record representation, b/c srfi-9 and r6rs and core guile records are all the same representation
<dthompson>one of things I *really* disliked in my days doing ruby professionally, particularly with rails, is that *a lot* of identifiers were generated and it was so difficult to figure out where something was defined in a codebase.
<wingo>dthompson: yeah i think it's a cultural issue -- hygiene is strictly supported, the derived identifiers are based on the scope of the record name
<wingo>but yeah grepping for "wtf where is this defined..."; dunno
<wingo>in racket they typically make the struct name the constructor, without any `make-` prefix or the like
<dthompson>yeah, I've seen some examples of that. I'm mixed.
<wingo>field accessors are structname-field
<dthompson>I like the terseness of it
<wingo>like right now defining a record type is... very ceremonious
<dthompson>it seems silly to type it out manually when you're just following an established naming convention
<wingo>it's like, you have to get into evening wear for dinner
<dthompson>I like the idea of stripping <> from type names for things like printers
<dthompson>#<<foo> bar: "baz"> looks silly
<dthompson>like why is there a spaceship in my spaceship?
<wingo>hehehe
<dthompson>most of the time my custom printers are just to get rid of that
<dthompson>what kind of interesting options are you thinking of beyond printers? opacity? other things?
<dthompson>it would be cool if constructors were more expressive so you could specify default args and such
<wingo>supertypes. opacity. prefab (so we can read and write them). all the r6rs things
<dthompson>I have not seen prefabs in use before
<wingo>and then, i would like for (system foreign) to be able to nicely extend the define-record-type form to add a few others: read/write from/to bytevector, etc
<dthompson>!
<wingo>you would have to opt into that one via (system foreign) of course
<dthompson>I have spent a lot of time trying to approximate chez scheme ftypes as of late
<dthompson>so this is of interest to me
<wingo>but right now the syntax is too gnarly, there is no obvious place to extend with arguments
<wingo>racket syntax has the advantage of a nice fixed prefix, it's (struct id (field ...) . options)
<wingo>optionally with a supertype after id
<rlb>I might really like solid and convenient support for immutable records, if that's feasible.
<wingo>yes!
<wingo>by default records would be immutable. they could be mutated under the hood via struct-set by index tho
<wingo>struct-set! is just too powerful to expose to users :P
<wingo>s/users/untrusted parties/
<dthompson>yeah
<dthompson>I have a pretty gnarly macro called define-bytestruct (and a set of related macros) that allow defining structs that are a wrapper around a bytevector and an offset and provide structured access to the contents
<rlb>...fwiw, clojure's defrecord defines a compact java class that masquerades as a map (but the named fields are much more efficient. But it's still a map, and of course immutable, so you can assoc/dissoc, etc. (if you assoc unrelated keys, they're handled, but if you dissoc a record "key", the type changes from the record type to a generic map)
<dthompson>similar to chez's ftypes
<wingo>dthompson: i think there's a place for that. i think there's also a place for a wrapper that copies out into a guile struct
<rlb>Not that we'd be likely to want much of that.
<dthompson>wingo: yeah depends on the situation
<wingo>depends on your model, specifically whether the bytevector is something whose lifetime you can control or not
<dthompson>right
<wingo>so i suspect a define-bytestruct probably still makes sense. still would be nice to converge on the shape of the syntax
<rlb>wingo: another thing I've wondered about wrt immutability (solid basic support for useful types) -- if we ever pursue that, is hashes.
<dthompson>for me, it's all about a ref compiling down to a direct bytevector-*-ref call
<dthompson>etc.
<rlb>i.e. you probably don't want to dynamically compute the hash of a giant recursive thing every time.
<rlb>(wrt equality -- but that's a much bigger can of worms)
<dthompson>all this to say, yes, would love a new define-record-type that was actually good :)
<dthompson>and improvements to the ffi that allow for defining C-like structs in scheme a la ftype as well
<wingo>rlb: ah i see what you mean. i guess a weak map can work as mechanism if you can be sure that the underlying data won't change
<rlb>In the clj world, the record would just have a hash field I think, that might or might not eb computed lazily/atomically. That's what I did for lokke, fwiw.
<rlb>"be computed"
<dthompson>sounds like what hoot does for heap types
<rlb>Of course, our current hashing is a bit surprising (to me), and I know we've had some issues with it (and without immutability, you're more constrained), i.e. that our recursive structure (lists, etc.) hash value is just ad-hoc "sampling" of the subtree.
<rlb>wingo: not sure it's feasible one thing we could consider is reserved/special methods, i.e. in the java world, that's (.hashCode thing). Then the equality predicates can favor that when it's available, and the tradeoffs are up to the type.
<rlb>"feasible, but"
<wingo>yeah. we could certainly add a hash field to all objects. not sure that would be a win though
<rlb>Well if you just make it a method, then there might or might not be any storage.
<rlb>But then you have the cost of checking for method existence in the dispatch predicates.
<rlb>s/dispatch/equality/
<rlb>(etc.
<rlb>)
<rlb>Make it an *optional* method I mean.
<wingo>guile's pair hashes are quite terrible :P
<daviid>dthompson: isn't guix doing this 'already', i mean some sort of define-bytestruct that effectively improve ffi struct (compiled time accessors to the struct elements ..)?
<dthompson>daviid: if guix is doing it then I don't know about it. there's a bytestructures project out there but it didn't seem to do everything I needed when I looked at it.
<dthompson>I don't know if anything that could be shipped in guile would do everything I need, anyway
<dthompson>my bytestructs also allow for packing/unpacking bytevectors directly without a wrapper struct, which is something I need for efficiently filling gpu buffers but probably most people don't need
<dthompson>it's an expansion of wingo's define-packed-struct from guile-opengl in several ways
<wingo>hoo, deep cuts
<dthompson>;)
<dthompson>but it allows for structs, unions, arrays, etc.
<dthompson>pointers for the C FFI case, recursive types, etc.
<dthompson>the venn diagrams of bytestructs and chez scheme ftypes almost overlap. there's a couple things I don't have, and some things chez doesn't have to support the gpu use-case
<dthompson>the pointer stuff is scary. it's the wild west once you need those.
<wingo>yes. i want to add a keepalive construct to the compiler
<daviid>dthompson: https://git.savannah.gnu.org/cgit/guix.git/tree/guix/build/syscalls.scm#n235 line 377 for define-c-struct-macro and 400 for define-c-struct
<wingo>otherwise it is almost impossible to use pointers safely :P
<wingo>daviid: excellent link, thank you!!!
<dthompson>daviid: ah yes, I had forgotten about this. this does a little bit of what bytestructs do.
<wingo>that is some serious macrology
<dthompson>thanks
<daviid>welcome!
<dthompson>this is the most C struct stuff I have for bytestructs currently, for some vorbis libraries: https://git.dthompson.us/chickadee/tree/chickadee/audio/vorbis.scm#n58
<dthompson>doesn't show off unions, unfortunately
<dthompson>and an example of a record-like macro on top: https://git.dthompson.us/chickadee/tree/chickadee/math/vector.scm#n80
<rlb>dthompson: I'm all in favor of making it at least *possible* to avoid "extra" allocations (or copying) in some of the cases I think you're talking about (even if it's some extra work -- i.e. as a lower level interface or whatever).
<dthompson>I think the big missing piece with guix's define-c-struct (which they don't seem to need) is being able to compose structs together
<dthompson>I don't see any code that allows the type of a struct field to be a type defined with an earlier define-c-struct form
<rlb>You mean "inlining" them, storage-wise.
<dthompson>yeah, like in C
<dthompson>ftypes allow this, and I followed their lead
<dthompson>I made it work by copying a trick I saw wingo use in hoot
<rlb>sounds like something I'd want, at least as an option.
<dthompson>it's a lot more macrology to do this, but the result is composable types
<dthompson>the vorbis code above uses it
<dthompson>recursive types is yet another complication, but ftypes allow it so I wasn't gonna just let them win ;)
<rlb>Hah.
<dthompson>probably also guix's define-c-struct doesn't generate code that's as optimizable, but they aren't fighting the gc tooth and nail like I am :)
<dthompson>at least I think I see some stuff that will prevent unboxing optimizations in some cases
<civodul>dthompson: re define-c-struct and “nested” structs, i think you’re right
<civodul>it’s very much biased towards libc interfaces, which are usually rather simple
<civodul>i’m not fond of bytestructures for FFI stuff
<civodul>(at least not the way it’s used in Guile-Git)
<dthompson>civodul: what don't you like?
<civodul>(chickadee data bytestruct) looks very cool though!
<civodul>dthompson: in Guile-Git it’s all run-time
<dthompson>ah! that was my fear when I looked at it awhile ago
<civodul>yeah
<civodul>so it’s not much better than ‘make-c-struct’ et al
<dthompson>make-c-struct seems to do a good amount at compile time
<civodul>it’s a procedure
<dthompson>bytestructs (I know, I know, too close to a name collision) does nearly everything at compile time
<dthompson>civodul: er, sorry, define-c-struct
<civodul>ah yes, define-c-struct does everything at compile time, that was the goal
<civodul>the limitation is nested structs and things like that
<dthompson>probably my bytestructs can be simplified some, but it's a close replica of ftypes syntax
<dthompson>ftypes.ss is near unreadable imo, I think my code is at least a little better
<dthompson>I don't consider it done, there's little things about the syntax and such that could be better. but it's working.
<dthompson>between all of us, surely we could produce something for inclusion in guile that makes everyone happy :)
<dthompson>the ftypes source is bad, but the paper is excellent. http://scheme2011.ucombinator.org/papers/Keep2011.pdf
<civodul>ftypes?
<dthompson>civodul: chez scheme's "foreign types" API for their FFI
<dthompson>it's very good
<civodul>so define-bytestruct computes everything at expansion time, right?
<dthompson>yeah, basically.
<dthompson>it generates a macro that does so when you use the bytestruct, anyway
<civodul>but there’s run-time <bytestruct> record if i read it right?
<civodul>i guess i should try it at the REPL :-)
<dthompson>yes, for runtime type checking
<civodul>ok
<dthompson>civodul: test file https://git.dthompson.us/chickadee/tree/tests/bytestruct.scm
<dthompson>(bytestruct-ref <vec2> (x) my-vec2) will expand to code that type checks 'my-vec2' at runtime, and then does a bytevector-ieee-native-ref on the underlying bytevector with a precomputed offset
<dthompson>so if you need an unboxed float, you'll have one
<civodul>ACTION just tried: ,optimize (bytestruct-alloc <vec2> ((x) 2) ((y) 2))
<civodul>neat!
<civodul>i could live without the intermediate <bytestruct> record
<civodul>but i guess that’s a tradeoff
<civodul>very impressive anyway
<civodul>we should get this into Guile proper
<daviid>yes! :)