IRC channel logs

2024-05-10.log

back to list of logs

<ArneBab>(I’m sure I’m not the first, but I wanted to try whether it’s really that simple)
<ArneBab>Can I delete a defined procedure? (define (a) #f) ⇒ get rid of it again?
<ArneBab>And does one of you have a cleaner define-typed which supports procedure-properties?
<ArneBab>(I just did too many unclean tries including helper functions which would pollute the namespace, so I think asking is better ☺)
<ArneBab>… and as usual, the moment I gave up I found a way: https://www.draketo.de/software/guile-snippets.html#define-typed — (define-typed (hello world) (string? string?) world) now with full procedure-properties support.
<ArneBab>If you have ideas for better names than (define-typed …), please write them!
<ArneBab>(define-guarded?)
<ArneBab>Because this doesn’t really provide static types, but runtime guarantees. As such it’s the inverse of typescript that adds static linting but actually provides no runtime guarantees.
<ArneBab>(I recently hit a place with that where someone had mistyped an API, but the code worked regardless, because the runtime was flexible enough …)
<flatwhatson>re: string formatting, maybe a guile port of srfi-166 would be nice
<flatwhatson> https://srfi.schemers.org/srfi-166/srfi-166.html
<dthompson>yeah it would be nice to have something like that and deprecate format, imo
<dthompson>though I don't know how realistic it is to deprecate it :)
<dthompson>not a hill I want to die on, of course, I just don't like format
<flatwhatson>agreed, like you come to lisp/scheme fresh and excited about sexprs and uniform representation, and now you want to print something, format strings are a letdown
<dthompson>yeah, feels like the bad old days
<dthompson>do better, Scheme!
<haugh>based on you guilers' experience with guile development, do you think it's more likely that FORMAT would be replaced then deprecated or that an additional layer that "compiles" to format would be added?
<haugh>that is, putting aside what you think would be better and thinking of what is actually more likely to be accepted
<dthompson>either way would be fine
<dthompson>though I'd think there wouldn't be much sense in compiling to a format string
<singpolyma>If you want to format a string with sexp (string-append) already exists ...
<dthompson>but you don't necessarily want to make a string, you want to write to a port
<flatwhatson>guile doesn't tend to aggressively deprecate things, so a back-compat-friendly approach seems more likely to me
<dthompson>and sure you could just write to the port
<dthompson>but it would be nice to have a somewhat terse but readable syntax for expressing formatting
<dthompson>that actually used s-expressions!
<dsmith>format in Guile comes from CL
<coyote>i'd like to see srfi-166 in guile
<coyote>it looks very cool
<apteryx>no srfi 166, but a bunch of srfis waiting to be looked at are lined up here: https://lists.nongnu.org/archive/html/guile-devel/2023-12/msg00018.html
<old>ArneBab: Nice thanks! I'm however more looking toward something that provide static type hint to the compiler for more agressive optimization
<dthompson>that does provide hints to the compiler for more optimized bytecode
<dthompson>if a procedure has unknown callers, and thus is truly a procedure at runtime, then in order to have assurances about argument types some runtime checks must be performed
<old>it may. But it also does not static check thing by preventing compilation. i.e. I could pass a literal string to a procedure only expecting integer and the compiler won't tell me a thing AFAIK
<dthompson>in the presence of those checks, the inside of the procedure can be optimized.
<dthompson>but to make such a system work with scheme there *has* to be dynamic type checking at some point
<old>dthompson: yeah like in your post. But these checks are often redundant if procedure are not inlined unfortunatelly
<dthompson>it sounds like you're looking for a language other than scheme
<old>why? because it is a dynamic type language?
<flatwhatson>perhaps some statically-typed subset of scheme
<dthompson>sort of like a... pre-scheme
<old>well that's different if you compile to C
<old>Python is also dynamic and has type hint that a static checker can use
<dthompson>but it's the same deal in python... there's a boundary where runtime type checking needs to happen
<old>TypeScript is basically javascript with static check for type. So why would Scheme be different
<dthompson>same in typed racket
<old>yeah ofc
<dthompson>typescript is a different language
<dthompson>it sounds like what you'd want is a new scheme-like language for the guile vm. I think that would be cool, too.
<Kolev>I can't wait for Guile Emacs.
<dthompson>for hoot I worked on a wasm interpreter in scheme. wasm is statically typed, so inside the interpreter everything has been type checked ahead of time, but calling into wasm from scheme requires runtime type checking
<old>Maybe. Thats' been said, I would not remove dynamic type in that language. Just like TypeScript has the `any' type, it is still useful to have them
<dthompson>you're describing a to-be-implemented typed-guile lang that can run on the guile vm
<old>yes I guess!
<dthompson>it would be interesting. someone should do it.
<Kolev>TypeScheme.
<dthompson>Kolev: you'll be waiting awhile for guile-emacs. was a nice idea but it's not happening.
<Kolev>dthompson: Not? :(
<haugh>We will get widespread fusion reactors before the emacs community admits elips was a mistake
<dthompson>I don't think much has happened in that space in nearly 10 years
<Kolev>haugh: Guile Emacs does not replace Emacs Lisp.
<dthompson>it's sad that the emacs community was so opposed to it
<dthompson>would have been great.
<Kolev>I know RMS doesn't call the shots, but he said another type of Lisp would be fine.
<Kolev>dthompson: So Emacs doesn't want to ever merge Guile's Emacs Lisp interpreter?
<old>My use case here btw is that I aim to have a VM executing bytecode in dynamic probes (tracepoints). Think of it like eBPF but for UserSpace. And I want a front end language like Scheme
<dthompson>Kolev: no, and the elisp implementation has gotten significantly more complex in the years since
<dthompson>when guile-emacs was being developed, elisp didn't have threads or native compilation
<old>However, the execution of a probe is the order of nano-second. The dispatching of dynamic instrumentation itself cost 50 ns. This is why I could like static scheme, so I can avoid any runtime check
<dthompson>the argument was that if emacs ran on top of the guile vm it would just get threads and stuff
<dthompson>and then JIT when that became a thing
<Kolev>So there's now no incentive to run Emacs Lisp on Guile.
<Kolev>I don't like how GNU has two Lisps in use.
<Kolev>Oh well.
<flatwhatson>oh there are more than two!
<Kolev>flatwhatson: Nobody uses MIT Scheme.
<flatwhatson>that's not really true
<flatwhatson>Software Design for Flexibility (the successor to SICP) is written for mit/gnu scheme
<flatwhatson>also kawa scheme (on the jvm) is a gnu project
<Kolev>Hm. Damn. A mess.
<flatwhatson>anarchy!
<Kolev>flatwhatson: I thought Java already had Clojure.
<flatwhatson>somebody should get all the lisp communities together and get them to agree on some kind of common standard so they can all start working together
<haugh>lol
<flatwhatson>old: the missing piece for a typed scheme is type inference; you need to know the types you're calling with at compile-time so you can reject them at compile-time
<flatwhatson>prescheme does type inference on scheme code (with caveats), and it should be possible to just use the type-inference bit of the compiler stand-alone
<old>flatwhatson: Type inference is nice to have and I definetely want it. But explicit type is more robust I think? It also has the advantage of self documentation
<old>flatwhatson: I will check the type inference algorithm then. It is written in Scheme?
<flatwhatson>maybe we can agree on optional typing :)
<old>yes! Like f#
<shawnw>Commoner Lisp?
<flatwhatson>old: yes, it's an implementation of hindley-milner, the bulk of it is here:
<flatwhatson> https://notabug.org/flatwhatson/guile-prescheme/src/main/ps-compiler/prescheme/infer-early.scm
<daviid>i was gona say, iirc, in cl, one can use, i.e., (declare ((speed 3) (safety 0) (debug 0) (a float) ...) then the compiler would generate code that does not perform any runtime check - and with some experience and fine tuning, optimizing your code as well, one can acheive C speed
<flatwhatson> https://notabug.org/flatwhatson/guile-prescheme/src/main/ps-compiler/prescheme/inference.scm
<dthompson>I would like to statically type a very small subset of my code when I want all the perf
<daviid>this is a nice approach, because you start with (safety 3) (debug 3) (sped 0) and track your bugs, till you can specify the above instead and achieve light speed code without segfault (in the max speed config, any error would segfault, afaicr)
<dthompson>but mostly I do not want static typing, just gets in my way mostly
<dthompson>the obsession with static types these days is exhausting to me
<dthompson>the "software design for flexibility" book is a nice antidote
<dthompson>but I love that scheme is multi-paradigm in a way most languages aren't so I'd like that to include some kind of static paradigm too
<daviid>dthompson: i agree, but the nice approach of cl, is that you can ignore and never use declare if you don1t want to, however, in chickadee, or guile-cv, it would be nice to just declare things so the compiler can take advantage of and generate high performing code
<old>dthompson: Love that book!
<dthompson>yeah I'd like to not sacrifice safety
<dthompson>but still, a thing or two could be snarfed from SBCL
<old>daviid: Do you have a example in the wild of this `declare' ?
<old>flatwhatson: thanks I'll have a look
<old>dthompson: I wonder, for hoot, at which level of the compiler tower is hoot placed for emiting WASM bytecode? Is it a CPS, Tree-il?
<daviid>dthompson: but we ought to be able to if we want to, so speed is maximased, and you trust your code to be bug free - it is the only way to acheive C speed in cl[hopefully guile scheme one day]
<dthompson>old: cps
<daviid>*maximized
<old>daviid: I do not think that a VM can reach C speed in all cases. I know that Java HotSpot can be faster than C in some benchmark with some very agressive JIT
<old>close to C speed is good enough for 99% cases IMO, even video game
<dthompson>native compilation is doable... eventually. funny that we'll have AOT wasm compilation first
<daviid>old: AOT can, as CL can actually produce code that runs faster then C
<old>AOT? sorry
<daviid>ahead of time compiler
<daviid>not jit
<old>ah similar to jit but stored on disk?
<daviid>yes i can find an example, i'd need to dig in my 'cavern' :)
<old>well I would argue who's writting the C code and which techniques is been used
<daviid>CL compilers are written in CL
<daviid>lispworks also produce as fast as C code, its compiler is about one million od lines of code ...
<daviid>we're not there yet ... but who knows, one day maybe ..
<old>I meant that CL could certainly produce code that run faster than C, but it really depend on the application here and who's writting the C
<daviid>ah ok, well yes, but that is true for who's writting the cl code as well :)
<old>ofc yes
<flatwhatson>and on the c compiler and its optimizations
<old>Oh awesome, I did not know that Guile VM supports goto labels (threaded code)
<daviid>old: fwiw, the doc is here - https://www.lispworks.com/documentation/HyperSpec/Body/s_declar.htm -
<daviid>s/the doc/the spec
<old>daviid: thx
<rlb>...it also depends on the code. Hand coded C can't know what the data will look like at runtime, but a fancy jit can. i.e. for polymorphic dispatch, etc.
<rlb>And possibly interesting on the optimization front: https://raw.githubusercontent.com/barak/stalin/master/README One notable thing is that since it assumed/required a closed-world, it compiled much of the program to more or less one giant C function with jump labels. I believe it also aggressively allocated things in local scopes / on the stack, and used native C types when it could prove that was sufficient (with some of the
<rlb>requisite behavioral tradeoffs).
<rlb>(falling back to boehm gc)
<rlb>I've long wanted some way to annotate some regions of code vaguely like cl declare or other gradual systems. iirc rscheme may have had some interesting bits along those lines too.
<rlb>"I've also"
<rlb>(I was happy to hear (if I heard right) that the optimizer can now introduce some optimizations after type checks.)
<daviid>i really like the cl declare 'system' - nice, clean, easy to understand, use, quite complete but extendable, users can gradualy raise the level of optimization, or temporarily comment the sexpr, they can declare if a function is inlinable ...
<daviid>cl also has a 'the' declaration op, as in https://paste.rs/00RKO.lsp
<rlb>...it'd be nice to be able to declare some bindings as say 64-bit unsigned with wraparound on overflow, or 8-byte IEEE float, and have that hold for the body with attendant assembly optimizations, "or something".
<rlb>clojure doesn't go very far on its own (the jvm's fairly fancy), but a related bit is that it just provides a parallel set of arithmetic operators e.g. https://clojuredocs.org/clojure.core/unchecked-add
<rlb>(Unsigned on the jvm/java is "interesting" (and used to be nonexistent-ish)...)
<rlb>In truth, I don't really know exactly what I want, I mostly know I want fewer reasons to have to drop out of the languages I like to "something else" :)
<daviid>anything that uses an (s)expr based system, that can occur in a lambda expression or in any of the forms listed in ... as opposed to, for example, the 'kawa way': (define foo (a :int b :int) (+ a b)) - non merci :)
<daviid>anyway, back to hack ...
<flatwhatson>(+ (the integer 1) (the integer 2))
<flatwhatson>that seems like a pretty elegant way to express type constraints
<ArneBab>haugh: I can’t say that much about Guiler’s expectations for format, because 95% of my day job is in JS and Java (the rest is Python … and R ☺) but what I see in other languages is rather that they move toward stringly embedding of more complex formatting. (f "ab%5,8d" 1,23) becomes f("ab{dec 1,23 5 8}")
<ArneBab>old: typescript is a glorified linter that limits what you can do because it is usually set to "never any". I recently had problems with mistypings that still worked because the runtime could still work with it. „it says it is a string, but the endpoint returns a map, why does it still work?“
<ArneBab>(which is super-annoying)
<ArneBab>Kolev: there *are* still incentives for Scheme in Emacs, but Guile Emacs never got to the point where it was faster, because the one doing it had to stop before breaking the essential barrier of using cached bytecode. So the startup time was abysmal. After that it became harder, because elisp development took up steam again.
<ArneBab>⇒ now it would be chasing a moving target.
<KE0VVT>ArneBab: No Scheme Emacs anytime soon. :(
<ArneBab>old: you may be able to tell that I’m pretty annoyed by typescript … it provides working auto-completion but above that it’s mainly a cost for me (besides explicit APIs between different parts of the code — and that’s where the mistyping was …).
<ArneBab>old: so the define-typed I wrote is rather the opposite: it helps the compiler optimize but it does not provide auto-completion.
<ArneBab>and I nowadays think it’s important to limit static typing support — not to try to type everything, because otherwise people do and build pyramids of types that in the end produce more code without actually making it better.
<ArneBab>though I don’t really trust my reasoning there — I’m not sure whether I just reason about what I have not what’s right. Because Java went the opposite way with adding its generics.
<ArneBab>but I feel like typing goes wrong once types contain types contain types — and the typing goes ever further away from the actual primitive compiler-level data that’s passed around.
<lilyp>Having spent time with C++ concepts, I feel you. It's sad, that we still live in a world where requirements and types show so much disconnect.
<anthk_>hello, can the picture language from guile-studio be used with the SICP exercises?
<ArneBab>anthk_: I think that was part of the goal, but I’m not sure … ⇒ rekado may know.
<old>ArneBab: I agree with you. I also concur on TypeScript being crap. But my case here is really to do very optimized code for a custom VM. And some others here would also want a static-Scheme for the same reason I believe.
<old>ArneBab: Correct me if I'm wrong, but your define-typed will not remove runtime type check right?
<ArneBab>old: yes. It actually *adds* runtime-type checks — because if these are done *before* a hot loop, the Guile compiler will remove the runtime type checks inside the hot loop.
<old>And if it does, procedures need to be inlined I believe. While typing offer a contract that the compiler can ensure, thus removing runtime type check across procedure boundaries
<old>Yes. So my goal here is to remove _all_ runtime check across a set of procedures
<ArneBab>⇒ define-typed for the API, then define-inlinable for the inner procedures.
<old>So you do runtime check once at the top level before entering a critical region. Then, all procedures under that level won't have to do any check
<ArneBab>(or do not export them)
<old>yes but that is a problem on its own! Having to inline!
<ArneBab>I’m not sure whether not exporting the procedures from their module helps.
<old>One could argue that if I'm looking for high performance code, I want to inline anyway so
<ArneBab>You’ll need to ask dthompson or wingo — if the module is declarative, do non-exported procedures inherit the type checks done in exported procedures that call them?
<ArneBab>Also look at the chickadee sources for tricks. chickadee has pretty nice performance. https://dthompson.us/projects/chickadee.html
<ArneBab>dthompson: aside: I have some hacks for guile-websocket in dryads-wake/dryads-sun to make that work with fibers, but these are all just hacks … https://hg.sr.ht/~arnebab/dryads-sun/browse/websocket.w?rev=tip#L109
<dthompson>ArneBab: regarding declarative modules, I think that would depend on how cross-module inlining shakes out.
<dthompson>like if a bunch of stuff gets inlined across modules, then redundant type checks can be eliminated by a later pass
<anthk_>ArneBab: thanks
<anthk_>there's chicken with the 203 and 216 srfi's, but guile doesn't implement them
<anthk_>having sicp workable with guile studio (there's a texinfo version of sicp too) would be the ultimate sicp learning env, and a great guide for guix