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…
Optimizing Guile Scheme
71–80 of 82 posts
Re: Optimizing Guile Scheme
#72Earlier quoted context omitted.
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…
lift = sequenceA @[] @(a ->)
lift = fix ((`ap` tail) . (. head) . flip ((.) . liftM2 (:)))
As far as I know it's not possible to get this functionality in Haskell even with clever instance magic, but I'd love to be proved wrong.Re: Optimizing Guile Scheme
#73The 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?
Re: Optimizing Guile Scheme
#74Earlier quoted context omitted.
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 wors…
That's not necessarily true. A function could serialize the passed value, which would work without type conversion, and it could still result in data corruption somewhere down the line. The point is that with dynamic typing there's no guarantee of correctness. It has nothing to do with strong vs. weak typing, which incidentally I don't find helpful debating, since there's no single definition for those terms, and most languages can behave arbitrarily depending on the situation.
Furthermore, you ignored my primary point of runtime type errors. These are very common in Python, and there's really no solution to them besides doing offline type checking, which as I said, has its own problems and is not a silver bullet either.
> 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.
Assuming you were referring to data corruption, maybe. But type errors happen very often in practice, and no amount of testing can guarantee you won't run into them. Besides, most teams I've worked with weren't disciplined enough to achieve even 100% statement coverage, let alone branch coverage, or do more sophisticated testing like fuzzing. So while type errors are close to impossible to prevent by testing, even data corruption can easily fly under the radar.
Static typing gives you this safety net, _for free_. This alone is worth the minor inconvenience of having to specify type information, and think about types explicitly.
> 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.
This requires experience to know good practices, when to follow them, and the discipline to do so. IME very few developers are this diligent 100% of the time, and most, if given the option, will do the minimum amount of work necessary. I'm not just blaming others, I've been lazy about good practices myself many times. This is why gradual or optional typing is not a solution to these issues.
Looking at it from the other direction, most statically typed languages can do type inference. This avoids the tedium of having to be explicit all the time, while still giving you the benefits of type checking at compile time. This is a much safer solution.
> 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.
Seriously? LLMs have no place in a discussion about correctness. They're glorified autocomplete engines, which can be useful, but trusting them to give you correct output for these issues is incredibly risky. At best you would need to manually verify everything they do, and I trust myself to do a quicker job in most situations with macros and `sed`.
> And type completion in an IDE still exists for a bunch of dynamically typed languages anyway, like javascript.
I feel like we're talking about two different things, and you're ignoring the main issue of type errors at runtime.
Re: Optimizing Guile Scheme
#75The 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?
Re: Optimizing Guile Scheme
#76You probably shouldn’t do those things. The point of a high level language is to not have to think about such details. If you can’t get the performance you need, you should use a different tool, instead of trying to circumvent implicit limitations.
Re: Optimizing Guile Scheme
#77I 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…
Roc is looking pretty nice (especially once your editor can paste in the inferred type like they want to do), but I still think there’s an empty space for an imperative language where type inference makes it feel as untyped (or at least as unceremonious) as (pre-annotation) Python
Re: Optimizing Guile Scheme
#78You probably shouldn’t do those things. The point of a high level language is to not have to think about such details. If you can’t get the performance you need, you should use a different tool, instead of trying to circumvent implicit limitations.
Sometimes you can write mostly high level code and only add trick and annotations for speed to very hot loops.
In contrast to this approach, I'd point at Numpy. It optimises specific cases in Python code, but does so in an explicit way and its interface is even sufficiently high level to match Python well.
Re: Optimizing Guile Scheme
#79Earlier quoted context omitted.
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…
lift = sequenceA @[] @(a ->)
lift = flip $ \a -> ($a)Re: Optimizing Guile Scheme
#80Earlier quoted context omitted.
Sometimes you can write mostly high level code and only add trick and annotations for speed to very hot loops.
There are two major problems with this approach. First of all, the intent is implicit, so it won't be clear for a new set of eyes. Second, by peeking behind the curtain you can get some gains, but only as long as everything behind this curtain stays the same. Author written about Guile 3, but is it also true of Guile 2 or 1? Will it hold true for Guile 4? Anybody's guess really. In contrast to this approach, I'd poin…
> First of all, the intent is implicit, so it won't be clear for a new set of eyes.
Yep. Many times the change is obvious, like changing + to fx+ But if the change needs a big rewrite, it probably needs a good comment explaining the simple versions and the tricks to make it faster. Even better, have the functions `something` and also `something_slow` with the simple slow implementation so you can make a few test and check they give the same result. I've used that for big refactoring/rewriting, in the moment I run the two functions and the results differ by more than 1E-10, I made a mistake and I have to revert the last change (hopefully).
> Author written about Guile 3, but is it also true of Guile 2 or 1? Will it hold true for Guile 4?
I don't know about the details of Guile, but I know about Racket. (I guess Guile has a similar culture.)
It the code is fast in the current version 8, then nobody is sure if it's also fast in the previous versions 7 or 6 or ... The compiler get a lot of tiny invisible improvements and perhaps one of them made your code fast. It's difficult to know.
About version 9 ...
There is an informal implicit promise to make idiomatic code faster. So I expect fast idiomatic code in version 8 to be fast in version 9. Moreover, I'd classify a big slowdown as a almost-bug and hope it's fixed for next edition. (It happened in the 7 -> 8 transition when the back end was changed completely, but the problems were rare.)
Non idiomatic code is more problematic, for example if you use too many `set!` to make the code faster. I don't expect that code with `set!` to be slower in version 9, but perhaps the version without `set!` may be faster in the new release.
About the changes proposed in the article, I don't expect them to cause problems in the future. Perhaps the Guile compiler will be improved to make them unnecessary, but they don't look problematic.