Skip to main content


Still working on arity-checking, one simple type that has eluded me until now is when a function doesn't return at all, but falls into the next one.

Finally got around to validating for this one.

This entry was edited (1 year ago)
in reply to Devine Lu Linvega

I remember once explaining uxntal as "simple" language, well, needless to say you won't be catching me calling uxntal simple again.
in reply to Devine Lu Linvega

Yeah so it turns out that languages which are human-simple to write are the most complex to typecheck and the languages which are the simplest to typecheck are the most human-complex to understand and write
in reply to mcc

@mcc It's been a long time since I wrote code in a strongly-typed language but I'll take strong type checking at compile time over trying to figure out what someone else's code does in a duck typing language.

Then again, I was trained as an applied mathematician / scientific applications programmer. Types are part of our innate toolset.

@mcc
in reply to Zorro Notorious MEB 😡

@AlgoCompSynth @mcc This is why I'm starting to feel like Crystal > Ruby for me (although I currently don't get to work with either). I know Ruby kind of has type checking now? But putting the types in another file seems perverse.
in reply to Andy Jones

@andy_twosticks @mcc I work mostly in R/RStudio. The workflow is about as optimum as it can be, but even with that I still have run a lengthy validation suite that catches a few errors the syntax checker allows. And it's more of a linter than anything else.

R is garbage-collected, of course. I think that's

a) cheating, and
b) a sign you don't care about resource usage.

in reply to Zorro Notorious MEB 😡

@AlgoCompSynth @mcc Hard opposite here. I feel like the fact C doesn't clean up after itself is Why We Can't Have Nice Things. Coders will always make mistakes.

Rust's approach is … interesting. But I feel like making the language a lot more complex in order to avoid both memory leaks and garbage collection is probably the wrong (but a damn clever) idea.

in reply to Andy Jones

@andy_twosticks @AlgoCompSynth R is an "offline processing"/batch processing language. This makes it well suited for GC. My understanding is GC languages can and often do match or beat exact languages on amortized resource usage, the problem is GC languages are bad at making time guarantees in interactive mode because GCs are an unpredictable element. I write a lot of soft realtime code so Rust is appealing to me for that reason.
in reply to mcc

Modern GCs behave no worse than manual memory management in terms of time guarantees, as everything happens incrementally and in parallel. Hard realtime GCs exist.
in reply to andreasdotorg

@andreasdotorg @mcc @AlgoCompSynth @andy_twosticks and let us not forget what happens in a manual environment when you free a huge quantity of data in one batch, eg delete a large dictionary or whatever. Much longer pause time than an incremental GC.

Though one assumes you don't do that in a time-critical place 😀

in reply to William

@andreasdotorg @mcc @AlgoCompSynth @andy_twosticks the memory safety in rust is awesome, except they insisted on building smart pointers (Box etc) on top of it for half-assed reference-counting memory management, though the last 30 years tells us that's not good enough.

Automated memory management requires a global not local (per pointer) view of liveness.

I want to see rust with real GC 😀

This entry was edited (1 year ago)
in reply to William

@phenidone @andreasdotorg @mcc @andy_twosticks

My most recent disappointment with garbage collection involves R and `tidyverse` pipes on some large-ish transit data in an 8 GB laptop. By breaking the pipe chains into single steps and forcing a garbage collect after each step I was able to run it.

#RStats

This entry was edited (1 year ago)
in reply to Zorro Notorious MEB 😡

After that I

1. Upgraded the laptop to 32 GB, and
2. Rewrote the code using `data.table`, which can do the heavy lifting in place, rather that having multiple copies of large tables lying around.

#RStats

in reply to Zorro Notorious MEB 😡

@phenidone @andreasdotorg @mcc @andy_twosticks

Laziness is not always a virtue, especially in large-scale scientific computing where getting bounds on resource usage during the software engineering process is fairly easy (compared to, say a compiler or a theorem prover).

This entry was edited (1 year ago)
in reply to Zorro Notorious MEB 😡

"Laziness" ist just a funny word for saying "the work of a programmer is not free". Programmer time vs. execution resources needs to be judged on a case by case basis. Surprisingly often, renting a beefy EC2 instance is the economic choice over even beginning to optimize a piece of code. And even for code run at scale, considerations like time to market and turnaround time for code changes are important factors.
in reply to andreasdotorg

@andreasdotorg @mcc @AlgoCompSynth @andy_twosticks "laziness" is also a term usually used to paper over macho Calvinist attitudes to programming, ie The Programmer Must Do It All, with a corollary of The Programmer Is Infallible.

We're writing software so we automate things. GC is automation, and it gets rid of several whole bug classes arising from the Infallible Programmer fallacy.

in reply to William

@andreasdotorg @mcc @AlgoCompSynth @andy_twosticks
As soon as you reject the concept of automation for your own software, you either admit to writing code with memory leaks or you need to build a bad and ad-hoc substitute for GC inside your application, and oh look, here comes yet another implementation of reference-counting smart pointers.
in reply to William

@andreasdotorg @mcc @AlgoCompSynth @andy_twosticks
So currently we seem to have these flavours of language:
1) free for all, go write you a bug (C)
2) static (compile time) automation of (some) object lifetime (C++ and Rust)
3) static analysis of lifetime, plus static bounds on concurrent access (Rust)
4) dynamic detection of lifetime and explicit dynamic access controls (Java etc) but no static borrow checks
This entry was edited (1 year ago)
in reply to William

@andreasdotorg @mcc @AlgoCompSynth @andy_twosticks
IMHO we are sorely missing the ultimate combination of static lifetime analysis and borrow checking, with a modern/complete/incremental GC for the corner cases that a static checker cannot infer.

Basically, Rust with GC instead of smart pointers.

Yes I know I just made everyone angry but really it is for the better 😀

in reply to William

@andreasdotorg @mcc @AlgoCompSynth @andy_twosticks
Rust is kind of halfway there: it has mutexes (runtime access controls) because nobody is insane enough to claim that a static access control checker can work for all cases in a concurrent environment.

It just needs to make the next step and realize that runtime lifetime analysis is also required 😀

in reply to William

@phenidone @andreasdotorg @mcc @andy_twosticks

If I understand the motivation for the design choices the Rust team made, it was to make "system programming" - presumably compilers / interpreters, operating systems, webservers, databases, browsers, etc. - easier to get right on a successful compile without sacrificing performance.

in reply to Zorro Notorious MEB 😡

@phenidone @andreasdotorg @mcc @andy_twosticks

Of that lot I've only done operating system programming, and that was so long ago that doing it in assembly was still the norm. 😀 If I were writing an OS today I'd do it in Rust. Case closed.

Operating systems don't have time for garbage collection. They don't even have time for floating-point computation. But they do need dynamic memory allocation and concurrency, and Rust is designed so the compiler saves the programmer time.

in reply to William

@AlgoCompSynth @andreasdotorg @mcc @andy_twosticks also we are not running on 6502 and 68000 anymore. Cache locality is *critical* to performance, and you can often get measurable speedups using a compacting GC.

Admittedly the concept of "my data can move" is terrifying to people who were raised on C 😀 and there are terrible corner cases.

But you need to not think of GC as having only performance cost.

This entry was edited (1 year ago)
in reply to William

@phenidone @AlgoCompSynth @andreasdotorg @mcc @andy_twosticks Can I please be taken out of this thread please? If you notice that someone hasn't made a single reply, no need to keep them tagged into it while you argue.
in reply to nomand

very much :ouroboros:

edit: To be clear, Uxntal hasn't changed. It's the same language as it was, but writing type inference reveals its hidden intricacies, similarly to how writing a BNF notation for a language might also.

This entry was edited (1 year ago)
Unknown parent

Devine Lu Linvega

Checking them is not too difficult, at the moment I add their stack-effect to the top of the fall-through and it seems to work for most cases. I'm trying to find a case where I can break out, but so far so good.

To be clear, the function does return, but it returns outside of its own scope.

example: https://git.sr.ht/~rabbits/left/tree/main/item/src/left.tal#L492

Functions that don't return like threads and vectors, have their own special type.

This entry was edited (1 year ago)

Lo, thar be cookies on this site to keep track of your login. By clicking 'okay', you are CONSENTING to this.