In the case of programming languages, this is not only a development cost, it's a maintenance cost as well. But this concept seems to apply to many more things than just programming.
Rob Pike: Simplicity Is Complicated [video]
11–20 of 152 posts
Re: Rob Pike: Simplicity Is Complicated [video]
#12I strongly disagree with this notion of "simplicity" as being attributable to scarcity of language features. Some of the languages that I felt were the easiest to use had quite a number of language features, but had simple semantics . I think Rich Hickey nailed this in his "Simple Made Easy"[1] talk. Complexity is not about additivity, it's about entanglement. [1] http://www.infoq.com/presentations/Simple-Made-Easy
In Java, serialization and generics interact with practically everything.
In C++, RAII interacts with exceptions, which is the point but isn't exactly pleasant.
Re: Rob Pike: Simplicity Is Complicated [video]
#13Re: Rob Pike: Simplicity Is Complicated [video]
#14It is also strange that he makes so many claims about readability, considering it is the most subjective attribute of a programming language there is. For example, some code that would have been completely unapproachable to me a couple of years ago is perfectly readable to me today, because I've learned new concepts.
Re: Rob Pike: Simplicity Is Complicated [video]
#15I strongly disagree with this notion of "simplicity" as being attributable to scarcity of language features. Some of the languages that I felt were the easiest to use had quite a number of language features, but had simple semantics . I think Rich Hickey nailed this in his "Simple Made Easy"[1] talk. Complexity is not about additivity, it's about entanglement. [1] http://www.infoq.com/presentations/Simple-Made-Easy
How do you have a large set of language features with them not interacting? In Java, serialization and generics interact with practically everything. In C++, RAII interacts with exceptions, which is the point but isn't exactly pleasant.
Haskell programmers famously point this out with the observation that a generic fmap is safer than one that has knowledge of the concrete types it uses. The type signature of fmap is this:
fmap :: Functor f => (a -> b) -> f a -> f b
In practice, what this means is that you can be assured that your fmap implementation can only apply the passed function over the value(s) wrapped in the functor, because of the fact that it cannot have visibility into what types it will operate on.
In golang, because of a lack of generics, you can write a well-typed fmap function, but it will inherently be coupled with the type of the slice it maps over. It also means the author of such a function has knowledge of all the properties involved in the argument and return type of the function passed, which means the writer of an fmap can do all kinds of things with that data that you have no assurances over.
Re: Rob Pike: Simplicity Is Complicated [video]
#16The mere presence of choice incurs a tangible mental cost, even if that choice is not exercised . In the case of programming languages, this is not only a development cost, it's a maintenance cost as well. But this concept seems to apply to many more things than just programming.
Re: Rob Pike: Simplicity Is Complicated [video]
#17This talk has a lot of very weak points. He made the claim that more features hurt readability (~6:10), because when you are reading you have to waste time thinking about why the programmer chose the set of features he did to write the code. To make that kind of claim without qualifications is just ridiculous - if it were true, why add any feature to a programming language at all? Especially if one believes readabili…
Re: Rob Pike: Simplicity Is Complicated [video]
#18I strongly disagree with this notion of "simplicity" as being attributable to scarcity of language features. Some of the languages that I felt were the easiest to use had quite a number of language features, but had simple semantics . I think Rich Hickey nailed this in his "Simple Made Easy"[1] talk. Complexity is not about additivity, it's about entanglement. [1] http://www.infoq.com/presentations/Simple-Made-Easy
How do you have a large set of language features with them not interacting? In Java, serialization and generics interact with practically everything. In C++, RAII interacts with exceptions, which is the point but isn't exactly pleasant.
Re: Rob Pike: Simplicity Is Complicated [video]
#19System comprehensibility is how long it takes for me to learn the minimal set of atoms in order for me to comprehend an entire system.
Rob Pike criticizes map and reduce and other functional idioms as not machine simple. And although Rob Pike doesn't say this, I might argue on his behalf that functional code has a mild reputation for less readability.
But I would argue that functional idioms permit tasteful tradeoffs between machine simplicity and system comprehensibility. I would also argue that when a system gets to a certain largeness, I would be sometimes okay with sacrificing some readability and machine simplicity for system comprehensibility. I would also say that although I might lose some performance advantages with a functional approach, the improvement to system comprehension might mean an improved cognitive capacity for the human to optimize for distributed multi-core contexts, which might offset the losses from machine simplicity.
Re: Rob Pike: Simplicity Is Complicated [video]
#20I think that code readability is different from system comprehensibility, and that readability is merely a subfactor to comprehensibility. Readability often means the time it takes for me to grok a function, module, or unit of code, and often what fits on my eyeball. System comprehensibility is how long it takes for me to learn the minimal set of atoms in order for me to comprehend an entire system. Rob Pike criticiz…
You don't even need to bring in parallelism for functional approaches to gain in performance. Here's an example (in Rust) of how you'd implement collecting an iterator into a vector using the "machine simple" approach:
let mut array = vec![];
for element in some_iterator {
array.push(element);
}
Now for the functional, less "machine simple" approach: let array = some_iterator.collect();
Which is faster? Without knowing the details of the compiler, you might think the former is faster, because there are fewer function calls and less indirection. But this is wrong, as the compiler will trivially inline "collect" for you and eliminate any indirection.In fact, it turns out that the second approach is often significantly faster, because the standard library contains the equivalent of:
let mut array = Vec::with_capacity(some_iterator.size_hint());
for element in some_iterator {
array.push(element);
}
That is, it uses the size_hint() method to avoid reallocating during the collection operation, reducing the number of memory allocation and array copy operations to O(1) instead of O(log n).What are the chances that you'd do this important optimization manually? Not high: it adds noise, it's esoteric, and it's easy to forget. But if you use the functional idiom, you benefit from the optimized approach every time. That is the true benefit of abstraction, which is really the key point here. "Machine simple" and "fast" are frequently in opposition, and too often people think that the former implies the latter.