IRC channel logs
2024-01-31.log
back to list of logs
<dthompson>is there a set of predicates one can apply to an argument that is expected to be an inexact real so that the compiler will unbox it as an f64? I thought (and (real? x) (inexact? x)) might do it but it doesn't seem to work. <dthompson>perhaps it's just not implemented but I've seen the type inferencer figure out some pretty neat stuff before <dthompson>like if you gate a branch with exact-integer? and then divide the compiler will optimize it to a right shift rather than using generic division <mwette>in 3.0.9, language/cps/specialize-numbers.scm, line 809 <dthompson>thanks I've been looking in the cps code but I haven't found a clear answer. <dthompson>it doesn't seem like what I'd like to do is currently possible <dthompson>that specialize-numbers code happens after boxing/unboxing primcalls are generated <dthompson>the only reliable way I know of to use unboxed floats is through bytevectors <dsmith>dthompson, That kinda vaguely sounds familar <dthompson>seems scm->f64 only happens for bytevector sets <old>is there something in core guile for comparing semantic versions? <old>I see there is guile-semver <dthompson>correct me if I'm wrong but I think semantic versions can be compared with simple string comparisons like string<? <dthompson>well maybe they can't. I don't remember if they sort lexicographically... <old>I mean, I could parse them, nothing hard <old>but I suspect that there are corner case in semantic versioning <old>like release candidate (rcN) <old>I could just copy guile-semver in my project that ought to work :-) <dthompson>I know guix has code for version number comparison <old>right guix/utils.scm <dthompson>I think this shows that some additional logic is necessary and lexicographical order isn't enough in general <old>right I'm more interested by comparing modversion from pkg-config <old>right. we manage to make a mess even with versioning <dthompson>for example (string<? "1.0.0-alpha1" "1.0.0") is #f but 1.0.0 is considered the greater version <old>hmm guix use strverscmp from glibc <old>that ought to be in Guile core I think (strverscmp). It is a neat thing but a GNU extension to libc <old>in the mean time, using the FFI is enought for this <old>thanks for your inputs! <dthompson>this is unrelated to the above discussion but to put a bow on the question I asked last night about unboxing floats... <dthompson>guile 3.0.9 does not do what I expect, but guile built from main *does* <dthompson>guarding the relevant code path with 'real?' and 'inexact?' predicates leads to unboxed floats on main, which is just great <dsmith>Also lexically, (string<? "1.2.0" "1.10.0") => #f <old>dthompson: what's float unboxing? <old>I suppose it has something to do with bytevector? <dthompson>guile allocates certain numeric types on the heap, including floating point numbers. <dthompson>if you do (+ x y) and the result is a float, a new float is allocated on the heap <dthompson>the number is "boxed" inside of a heap object <dthompson>unboxing is a compiler optimization that will take a value out of its box, run some number of additional instructions with it, and only box the final result. <old>ah okay and so you want the raw bits of the floting point? <dthompson>if you have a complicated math routine, this will avoid the intermediate values being boxed and thus allocated on the heap <dthompson>it improves efficiency because specialized instructions built for specific types can be used rather than generic ones that need to operate on all types <old>Right. But the compiler optimization is not already all that? <dthompson>since scheme is a dynamic language, you need to be aware of this when writing code so you can give the compiler the information it needs to perform the optimization <old>you need to give hint to the compiler by guarding the critial path with predicate <old>so the compiler can be sure that the values are of a certain type <old>in another word, a typing system could do the same <old>and so GOOPS ought to do the trick here <old>why not? Because of indirection and dispatching? <dthompson>goops will make things more generic, not less <old>but my point is that GOOPS will do the predicates and dispatch to the correct version. And if this version is specialized, then it could be optimized <dthompson>in a statically typed language, you could say that function argument 'x' is a float or something <old>and so you remove the predicates from your code and encode them as type symbols <dthompson>and the boxing would have to happen at each intermediate step <dthompson>you don't need goops to do what you are saying. the scheme numeric tower already works this way. <dthompson>but for critical paths you want to constrain your inputs so the compiler can specialize. <old>is it fast enough tho? I mean even with the compiler optmization <old>or is it better to call C for that? <old>even though there is a cost to call C <dsmith>ISTR that r6rs introduced "fixed" or "float" or something operators. Supposedly for not having to dispatch on the type? <old>what's your use case? <dthompson>using the ffi would be faster if you were offloading a huge operation that outweighs the ffi overhead <dthompson>but personally I want to keep writing scheme, not c :) <old>ofc. Right scheme and only C when you really need low-level optimization <dthompson>but you need to do a bunch of work on the cpu so that you have something to send the gpu <old>That would be neat lol <dthompson>all sorts of linear algebra is necessary to prepare a frame for the gpu <old>Right with the camera <dthompson>with everything. positions of objects. their velocities if they are moving. their hitboxes for collision detection. <old>I guess you do not have millions of positions to compute <old>I would assume that Scheme you be on its knees for that <dthompson>with compiler optimizations + jit things can go quite fast <old>does the JIT generates SIMD instructions? <dthompson>I've been able to render upwards of 50k dynamic sprites at 60fps <old>I wonder one thing tho <old>if you compute tons of positions. Are they all allocated close together? <old>Because if they are allocated on the heap, then cache locality is not good at all <old>well if you do a huge allocation but that's about it <dthompson>being on the heap doesn't necessarily mean cache locality is bad, though <dthompson>I suspect the upcoming whippet gc will have improvements there <dthompson>but when I need locality I just allocate a big bytevector <old>But then you need to heap allocate a boxed float for each in the bytevector? <old>then write the result back in the bytevector? <old>or is there a way to tell guile: ASsume the following memeory to be a float and mutate it <dthompson>bytevector accessors work with unboxed values <old>I know there's bytvector-*ref getters <old>But I always assume they returned a copy of the underlying bytevector or something like that <dthompson>for example, (bytevector-ieee-double-native-ref bv 0) will produce an f64 that will only get boxed if it needs to be <old>and how do you change the underlying value in the bytevector? <dthompson>a lot of my linear algebra code boils down to pulling floats out of bytevectors, doing some math, and stuffing the results in another bytevector <old>Will the operation on the result of (bytevector-ieee-double-native-ref bv 0) be reflected directly? <old>so it does a copy and you write it back <dthompson>example: (bytevector-ieee-double-native-set! bv 8 (* (bytevector-ieee-double-native-ref bv 0) 2.0)) <dthompson>gets an f64 from index 0, doubles it, stores it to index 8 <old>the intermediate value is copied onto the stack? <dthompson>the multiplication would be done with fmul and not generic mul <old>where did you learn all of this? This is not in the manual AFAIK! <dthompson>years of messing with guile and asking questions in this irc channel <dthompson>I have a list of "blog posts I'd like to write" and a guile optimization post is on the list <dthompson>I used guile before any of these fancy optimizations were around <dthompson>so I ended up learning the hard way why things were slow <old>I guess all dynamic language were kind of slow at some epoch <old>certain are still very slow -- looking at you CPython -- <dthompson>some are kind of doomed to be slow due to their semantics like python <Arsen>ruby's extremely dynamic, yeah <Arsen>py can static-type sometimes at least.. that constrains it heavily and could enable some optimizations if cpy was to make use of it (which I doubt will happen any time soon) <old>and yet they are more popular :-( <dsmith>Popularity is overrated. "10 billion flies can't be wrong, can they?" <teddd>hi guiler, I was wondering if someone knows about a lib to parse config files like .ini or the like ? Alternatively is there a templating library in guile similar to jinja in python ? <dsmith>Scheme mostly (ab)uses quasiqote for templating I think. <teddd>dsmith: thanks for the reference ! <dsmith>There is the sxml stuff to create html and xml from s-expressions <teddd>Yes most lispers just prefer lisp as data structure. Understandable. But I need to extract data from the rest of the world :) <teddd>Oh yes sxml looks nice. I'll definitly use it if I do we in guile <teddd>For now I just want parse config files. <dthompson>teddd: I'll pile on to say that a lot of scheme programs do the "configuration as code" thing and do not use a separate config language. <teddd>dthompson: Yes I also do it like this when I stay in lisp world. <teddd>I thought about using it to parse conf files. Would you recommand ? <dthompson>teddd: that was a little experiment. it's not a properly packaged library or anything. <teddd>dthompson: I see looked promising and easy to use :) <dthompson>I like parser combinators, you should feel free to snarf any of the code there <dthompson>streams make the code pretty nice, but it's not going to perform nearly as well as using ports directly <teddd>dthompson: cool, I'll take a look, though I'll probably not find time to push it further <dthompson>for .ini files, guile-ini already exists as mentioned above <dthompson>you can also do s-exp config that isn't executable scheme code by just using 'read' <teddd>Yes I the guile-ini would be great, unfortunatly I realised I really need something more flexible and add things to a lot of different file formats. I guess I would need something like a templating framework linke jinja or noweb <dsmith>I don't understand. Aren't templating frameworks for *writing* files? <dsmith>Was a pretty cool idea. Added ] [ as string delimeters. And a file started out in string mode. <dsmith>lots of text [(scheme expression)] back to text... <dsmith>expands to: "lots of text " (scheme expression) " back to text.." <teddd>dsmith: my understanding is that 1. you write a template, 2. it gets read by the templating program 3. it spits out a file. Like if I give you "echo [1 + 3]" a simple program could return "echo 4" <teddd>dsmith: yes brl looks like the kind stuff I would need ! <teddd>but I would need this in guile <dthompson>if you need something like jinja2 I guess I don't see much point in using guile <teddd>my project is in guile so it would be anoying to add a python dependency <dsmith>A long long time ago I kinda ported brl to guile. But I used #> and #< instead of ] and [ That was like guile 1.4 or 1.6 I think. <dthompson>the scheme way is to use quasiquote. it is the universal templating language. this would require serializers for each format you need to emit <dthompson>I don't know of any pre-existing unstructured templating system for guile but maybe there is one <dsmith>#> becuse I could use read-hash-extend <dthompson>unstructured templating is heavily discouraged in scheme land <teddd>I'll probably resort to wildly waving rexeps around in a first place and start a templating system from there <teddd>dsmith: interesting. Maybe I'll start with that <dthompson>about why unstructured templating is an open invitation for injection attacks and other bugs <teddd>I think I really just need to drop variable values in the files. I don't intend to make them able to request a computation. Does that make it safer ? What could go wrong when just looking up for a variable name ? <dthompson>injection bugs are probably not a concern for you here, but I just wanted to point out the general problem with string-based templating. because the templating system has no idea about the structure of the thing it is building, it's easy to screw up the output. <dthompson>and it explains the general lack of a jinja2 equivalent <dthompson>(though maybe I'm wrong and there is something! I certainly haven't gone looking for it) <teddd>I see. So you say jinja2 is vulnerable ? What could go wrong for example ? <dthompson>with jinja2, or any similar templating language, you have to make sure you are escaping input for every single substitution <dthompson>it could lead to something as serious as an injection attack in the case of a web app, but it more commonly leads to annoying things like not escaping double quotes and generating an invalid file or something <teddd>I see so the problem is when you mix user input and templating at the same time. But say you want to geerate a static site and use jinja2 for generating it, then there is no problem, right ? <dthompson>if all you need are some regexp replacements, go for it. not trying to discourage. just trying to explain "the scheme way" if you will <dthompson>teddd: right there's no security issue if it's all your own trusted input. <dsmith>teddd, Well, it seems the code is lost forever. Was a long time ago, and the code that is in SVN (yes. pre-dates git) doesn't include any .scm files. <dthompson>but I personally would not want to use jinja2 to generate a static site :) <teddd>dsmith: :( I'll start from scratch and maybe use the syntax then ;) <teddd>Oh yes I also would prefer using scheme for a website <dthompson>anyway I'm starting to feel like I'm talking too much. I don't want to discourage a quick hack that gets things done for you. we all need those ;) <dsmith>I would think sxml would be prefereable. <teddd>just cited this example because its probably how most of websites are built juging by the popularity of Django <dthompson>do what feels right for you. no one knows your needs better than you do. <dthompson>I've done plenty of erb and handlebars templating at past jobs <dsmith>Wow. I did that gbrl thing 22 years ago! <Arsen> 22:57:35 <dthompson> not when I have quasiquote and sxml <rebiw>How can I get the text from an error port in guile?. I'm not sure how to use the current-error-port to get the output. <apteryx>how do I alias a syntax transformer to something else? <apteryx>e.g. I have (define-syntax pkgconf-as-pkg-config (identifier-syntax ...)) that I want to export as pkg-config <dthompson>apteryx: #:export ((pkgconf-as-pkg-config . pkgconfig) ...) in your define-module form I think <dthompson>going from memory, syntax might be slightly different <dthompson>the manual says this is the syntax for exporting with a different name <apteryx>can I export both the original symbol as well as its renamed variant? <dthompson>apteryx: why would you want to export it twice? <apteryx>the rewrite is a hack to keep pkg-config in the code base but point to pkgconf <apteryx>it still makes sense to have a handle on pkgconf-as-pkg-config at the REPL <apteryx>other things I have tried that also didn't work: (define-public new-name old-name) <apteryx>where old-name is a syntax transformer <lloda>if you only use the old binding internally you can either use @@ or do a wrapper module for the new binding <apteryx>actually it seems to work at the REPL using (define-public new old)