Live data from Hacker News

Optimizing Guile Scheme

dthompson.us

61–70 of 82 posts

Re: Optimizing Guile Scheme

#61

I have such mixed feelings about dynamically typed languages. I've designed a whole pile of hobby programming languages, and dynamically typed languages are at least an order of magnitude simpler to design and for users to learn and start using. At the same time, they inevitably seem to lead to user stories like this where a user really does know exactly what types they're working with and wants the language to know…

I'm happy with dynamic languages for almost everything I do and generally do not want to sacrifice flexibility, which is the price to pay for a static type system. However, certain parts of a program become more crystalline over time, whether for performance or correctness reasons, and being able to express those parts using a static type system makes a lot of sense. PreScheme [0] is an example of a statically typed…

Yeah prescheme is really interesting, I really liked the SystemCrafters exploration of it:

https://www.youtube.com/watch?v=QqKuHylIqBs

Re: Optimizing Guile Scheme

#62
post #42

I have such mixed feelings about dynamically typed languages. I've designed a whole pile of hobby programming languages, and dynamically typed languages are at least an order of magnitude simpler to design and for users to learn and start using. At the same time, they inevitably seem to lead to user stories like this where a user really does know exactly what types they're working with and wants the language to know…

As a long-time Python and JavaScript user, I've come to the conclusion that dynamic typing is just not a good idea for anything beyond exploratory or very small projects. The problem is that you invariably have to think about types. If you mistakenly pass a string to a function expecting an integer, you better hope that that is properly handled, otherwise you risk having type errors at runtime, or worse—no errors, an…

I was strongly in the static typing camp for a long time, with Haskell, Purescript, Idris, OCaml, and Typescript, but over time I realized that the costs mostly outweigh the benefits.

> The problem is that you invariably have to think about types. If you mistakenly pass a string to a function expecting an integer, you better hope that that is properly handled, otherwise you risk having type errors at runtime, or worse—no errors, and silent data corruption.

The silent data corruption is really only a problem with weak dynamic typing, that usually automatically coerces types. A lot of dynamically typed languages still have strong typing and will immediately error out. And usually in practice you end up testing all of the code you're writing anyone, so this almost never happens in practice except when someone is refactoring without thoroughly testing what they did, which should be done anyway whether there are types or not.

> Primarily that if specifying types is optional, most programmers will not bother, or will just default to `any` to silence the type checker.

They probably do bother when it's an important module, or a an edge boundary that needs to be documented with a contract, or during times of significant refactoring. And these days LLMs can generate the specs, optional types, and tests pretty easily for any sort of self-contained, modular, reasonably well written code.

So now with LLMs I think there's even better reasons to use dynamic typing. And type completion in an IDE still exists for a bunch of dynamically typed languages anyway, like javascript.

Re: Optimizing Guile Scheme

#63
The monomorphic vs polymorphic argument is an interesting one. I think that you could explicitly get unboxing if you used something like CLOS style multimethods to dispatch based on the type, so that (add ) would dispatch to the function that uses fadd on those operands. I never realized that you could use this kind functionality, multimethods or free monad interpreters, to write in-code optimizations that are conveniently abstracted away in actual code usage.

Edit: nevermind, that's also dynamic dispatch. You'd have to add static dispatch via macros or some external transpilation step.

Re: Optimizing Guile Scheme

#64
post #36
post #6

Earlier quoted context omitted.

The slogan I've proposed for the language is "Guile goes with everything." Because Guile was designed from the outset to run embedded or standalone, and to transpile other extension languages to Scheme or a Scheme-compatible representation, I think that fitting. See: https://knowyourmeme.com/memes/guiles-theme-goes-with-everyt...

Should it be "Guile Scheme goes with everything" for the rhyme?

This is too good not to use.

(My favourite use of Guile's Theme is by Team Teamwork: https://www.youtube.com/watch?v=w5JuYmQ2_ns but I bet one of rms's many songs could be found to fit.)

Re: Optimizing Guile Scheme

#65
The guile source->source Optimizer is such a nice tool to see what is going on. Especially when writing macros. I really recommend Kent Dybvig's "the macro writer's bill of rights" to see how useful it can be.

Re: Optimizing Guile Scheme

#66
post #54
post #40

Earlier quoted context omitted.

Thanks for the context! It's been a while since I did serious work in the Lisps. (I've moved on to the ML family.) > [...] GNU/MIT Scheme is what you want to follow along with MIT publications working in Scheme (like Structure and Interpretation of Computer Programs, Structure and Interpretation of Classical Mechanics, and The Art of the Propagator). Definitely, though I suspect if you need a language that's exactly…

In SICM they frequently make use of a kind of implicit applicative lifting (I can't remember what they call it) where you apply a vector-of-functions as if it were a function itself. In psuedo-Haskell: lift :: Vec (a->b) -> (a->Vec b) lift [] a = [] lift f:fs = (f a):(lift fs $ a) so that you can write natural-looking multidimensional physics expressions like ((fx fy fz) r) without having to invoke macros or restruct…

Clojure has a really nice `juxt` function for that, which I have an implementation of in my `.guile` file.

  (define (juxt . fns)
    (lambda args
      (map (lambda (fn) (apply fn args)) fns)))

Re: Optimizing Guile Scheme

#68

Earlier quoted context omitted.

I agree completely. At the same time, no one wants their code to run 100x slower than it would in any typical statically typed language. Unoptimized dynamic languages are sloooooow .

Rpython and Graal (and what else?) provide JIT-for-free (or at least cheap). Of course, this really only works for code that is (a) statically polymorphic but dynamically monomorphic, and (b) has hot loops, but qualitatively that conjunction does seem like it ought to cover a lot of low-hanging fruit. Anyone have quantitative measures?

There is only so much a compiler can do when any operation can result in a complex function call or variable sized data.

Re: Optimizing Guile Scheme

#69

The full numeric tower sounds like a great idea. But in retrospect you almost never want uint32 silently converting to bignum, or ending up with a low precision float. Has anyone had a positive experience?

I love the numeric tower most of the time. Not having to worry about integer overflow bugs is great. I like that I can express the fraction 1/3 exactly rather than approximately with a float. It's only in the cases of very sensitive code that I have to worry about the details of how numbers are represented at runtime.

Re: Optimizing Guile Scheme

#70

Earlier quoted context omitted.

No doubt you know this, but Common Lisp's standardization gave leeway to implementations. So you could choose which implementation suits you better. Common Lisp is an umbrella for different Lisps to have some commonality. It was a process of negotiation, during a time when there were many design forks in the road, and diverse use-cases For example, type declarations can enable performance optimizations, compiletime t…

As someone who doesn't know much about types, do SBCL type declarations provide as good type-based development experience as OCaml and Rust? And perhaps I wouldn't get your answer, I mean is there something fundamentally inadequate in the way SBCL declares types? I think there is a phrase for it in CS theory.

To add to the other comment, it is also important to understand in the more interactive mode of developing in CL. You basically have the program always running, fixing bugs and adding features while it is running.

You simply don't have the problem of batch style programming where you have written a bunch of code and now you want to know if it works so you run a lot of static analysis on it beforehand because running it and getting it to the point and state that is relevant costs time.

In CL you don't end up with lots of code that has never been run. You have constantly run it during development and are much more confident about its behavior. So just having this interactive way of programming already leads to much more reliable software. It is not a replacement for static analysis or unit testing of course but another pillar to help you write more correct software.

Post reply on HN