hayley-patton
Joined 5 years ago
Joined 5 years ago
Not really your question--others have provided examples of type systems as macros--but they can't, they can only do local rewrites. You couldn't, for example, express mutation or non-local control flow if you didn't have them already; On the expressive power of programming languages [0] is rather theoretical but does set out the boundary of what macros can and can't do. That they're local means everyone has to buy into your type system if you want it to be a macro, though.
[0] https://www.sciencedirect.com/science/article/pii/0167642391... though https://www.youtube.com/watch?v=43XaZEn2aLc might be a useful walkthrough of the ideas being presented
That's indeed what I meant, I meant the opposite of taking a dig at Kernel. My understanding is Shutt thought fexprs got a bad wrap because of dynamic scoping; quoth the Kernel website:
> they made a mess out of the language semantics because they were non-orthogonal to the ordinary variety of procedures constructed via lambda — and, more insidiously, because at that time the mainstream Lisps were dynamically scoped (a language feature that causes more problems for fexprs than it does for the less powerful macros).
My belated apologies for the ambiguity.
No, I don't.
About "Since allocations are expensive due to them requiring a system interaction via syscalls" and "For this only bump allocation is an option, simply because syscalls are slow, multiple for many small objects are even slower and hot paths would explode" there's no reason that a free-list allocator has to do more syscalls than a bump allocator; any malloc under the sun is going to have at least one layer of caching before it makes a syscall for more memory. You could do a doubling scheme like with the bump allocator, or allocate a lot at a time; mimalloc for example requests segments of 4MiB from the kernel [2].
[0] It's approximately steps #1 and #3 fused together, then #2 in https://en.wikipedia.org/wiki/Mark%E2%80%93compact_algorithm...
[1] Something like for (void *object = segment->start; object < segment->end; object += size_in_words(object))
[2] https://www.microsoft.com/en-us/research/wp-content/uploads/...
This is approximately exactly what Azul Systems did, doing a bog-standard RISC with hardware GC barriers and transactional memory. Cliff Click gave an excellent talk on it [0] and makes your argument around 20:14.
> And at the time, we thought it was impossible to make this language run efficiently, because it did all these things that were more abstract than languages of the time ...
That's making much use of hindsight though: the creators of Self didn't think it would run fast, until it did [0]. The HOPL paper on Self [1] spends many words recounting the challenge of making Self fast.
[0] This is arguably a stronger claim than what appears in HOPL; I think it's from a talk by Dave Ungar, I'd have to check.
Expect that you don't, and deoptimise when you do: https://bibliography.selflanguage.org/_static/dynamic-deopti...
It's really not that impossible.