zerodensity
Joined 3 years ago
Joined 3 years ago
That being said, functional verification is a huge time sink and is really only economical if it's very important for the code to always be correct. That is, people die if your software has a bug. A few examples would be pacemakers, aircraft autopilots or your car brakes.
If your not working one of these domains then maybe immutable and pure functional code can save you a few bugs? I have not read any peer reviewed study that shows this is the case. But if you have any such paper i would be happy to read it.
Don't have to like it but the law is the law.
Take this:
```
int bar(int arg); // May throw
int foo(int arg) {
int b = bar(arg);
return b * 5;
}```
VS:
```
Error<int> bar(int arg); // Uses error type
Error<int> foo(int arg) {
auto b = bar(arg);
if(b.ok()) { // Happy Path
return b.unwrap() * 5;
}
return e; // Exceptional Path
}```
In the happy case (no exception) how can the first version be harder to optimize than the second one? In the exceptional case exceptions will probably be slower. You trade fast common case for slow exceptional case so it makes sense to me. Is the slower one the one that is hard to optimize? Is this what we are talking about when optimizations are harder to reason about? Or are there some other things that become harder because of exception? Things like RAII, defer, goto stuff?
From my experience a substantial fraction of programmers learn the absolute minimum to get a job.
Then they either learn on the job or ask the same questions over and over again, never learning. The latter being the really annoying people to work with.
I don't really think anyone expects a c abi to have multiple implementation defined string types. They want there to be a pointer + length string interface removing the use of null pointer style strings alltogether.
> If this new style ABI returns a 'string' (pointer and length) of some sort, you have to package it up in your own object format
A c function with proper error, (that is something you want to have for all your interface functions). Normally looks something like this.
int name(T1 param_1, T2 param_2, ..., TN param_n, R1* return_1, R2* return_2, ..., RN* return_n);
Where the return int is the error code. param_1-param_n the input parameters. result_1-result_n the results of the function.
When writing these kinds of functions having an extra parameter for the size of the strings either for input or output is not a huge complexity increase.
> Will you need an extra object type to represent 'string I got from an ABI, whose memory is managed differently'?
Which memory management system you use does not impact if you use null terminated strings or a pointer + length pair. Both support stack, manual, managed or gc memory. It's just about the string representation.
For example:
I use a gc language.
I call a c library which returns a string that I get ownership of.
Now I want to leverage the gc to automatically free the string at some point. What I do is tell the gc how to free it, I have to do this no matter how the string is represented.
Or take the inverse.
I send in a string to the c library, which takes ownership of it.
Now the library must know how to free the memory. Typically this is done by allocating it with a library allocator (which can be malloc) before sending it to the function. Importantly the allocator is not the same as the one we use for everything else.
What I am getting at is that if you are not using the same memory system in the caller and the calle you have to marshal between them always. No matter if you are using null terminated strings or a pointer + length pair.
Personally I feel it's not complicated enough. Where is my function overloading, variadic templates and usable compile time reflection? (Sure you can sometimes use macros but ew macros)