"if (ptr == NULL)" is usually two instructions and an instruction pipeline flush. That sucks, but I can't even imagine what the processor ends up executing for the Ruby lambda callback. Slightly more readable code at what cost?
That's not a very good question, `if object == nil` will already be a pretty huge number of instructions in ruby.
Now if the question is "could you have this pattern compile down to little more than a null check", the answer is why not? A bit of flattening/inlining should be able to handle it correctly.
And in most fields, the gain in safety way outweighs the almost unnoticeable (against background noise) loss in efficiency.
The answer for C# and Java, which this issue was directed at, is no.
Email me if you want details.
I'm not sure what you're talking about, you focused on java and C# for odd and unknown reasons, TFA merely uses java as an example of syntactically heavy (or even missing) closures language to illustrate the pattern's gains and differences.
The other day, I saw this example on StackOverflow:
Person person = dataSource.getPersonById(personId);
if (person != null) {
person.setPhoneNumber(phoneNumber);
dataSource.updatePerson(person);
}
This looks like a typical case where we need a null check.If the canonical example under discussion is in Java, I think it is safe to assume the article is about Java.
No. The article is about a pattern of explicit null-check avoidance, java is an example of "a language without blocks or lambdas" but the article is no more about java than it is about ruby, you're not even missing the forest for the trees you're missing the forest for a fallen leaf.
Probably a lot more than the null-check, and yet still undetectable against the background of the db call.
If we keep adopting readability tricks with orders-of-magnitude differences in speed compared to what we're replacing, we'll just keep getting slower and slower code.
I think for most cases where what you want to do isn't throwing an error on null, most of the time null checks are addressing external interfaces (database or otherwise) where the IO is going to be enough bigger than the pattern overhead that if you are able to deal with the load from the basic functionality, the difference between null check and using this "teller" style implementation is going to be negligible.
And, obviously, where you want to error-on-null (whether or not an external interface is involved), this isn't the pattern to apply.
> If we keep adopting readability tricks
Factoring out commonly used boilerplate into a library function isn't a "readability trick", though it does benefit readability and maintainability of code.
And its safety and correctness.
Rust does exactly this.
> your program would be slow as shit due to all the closure allocation in inner loops.
The closure can be stack-allocated or even inlined. It doesn't need to be more expensive than a C block.
> C# and Java people would be pissed.
Meh.
No, Rust solved this problem by using non-nullable references. Closure allocation was a separate consideration.
The question of whether you can invent some arbitrary language that will enable your scenario isn't an interesting one. The problem is languages like Java and C#, which are heavily used and DO have nullable references. This "fix" is not one.
1. its option types provide a number of combinators which use closures, it wouldn't surprise me at all to see this kind of stuff in rust (might even be more efficient, no need to allocate and return an option)
2. and blocks are heavily pushed for use in Rust, all iteration is closure-based for instance
> The problem is languages like Java and C#
I've no idea where you got that from, TFA merely used java to illustrate the "language without syntactically lightweight functions". COBOL being a turd didn't stop people from investigating objects.
Really? We're investigating nullable reference semantics and C# and Java aren't the target? Hell the initial example -- the one that spurred the discussion -- is in Java.
Anyway, "syntactically lightweight" is a red herring -- syntax is surprisingly easy to add.
Modern compilers for languages like JS that heavily use closures optimize for this.
cmp r0, #0
beq exit