Live data from Hacker News

Rob Pike: Simplicity Is Complicated [video]

thedotpost.com

71–80 of 152 posts

Re: Rob Pike: Simplicity Is Complicated [video]

#71

Earlier quoted context omitted.

However, GADTs and TFs are completely opt-in, so it seems a bit of a stretch to construe this as a generally bad thing. IME it's not as if library authors are arbitrarily (i.e. for no good reason) using GADTs or TFs instead of plain old type parameters in their APIs.

Reflection, downcasts and assigning `null` to pointers are completely opt-in in Java too. With respect to type families, I'm probably being a little bit unfair. Personally, I don't have much against associated type families. (Although I think Rust handles them much more gracefully than GHC.) But very important libraries in the GHC ecosystem like vector and lens make extensive use of free-floating type families, which…

> Reflection, downcasts and assigning `null` to pointers are completely opt-in in Java too.

No, they're not -- not in the same sense, at least. A GADT/TypeFamily is going to be visible in the API. None of the things you mentioned are visible in the API.

There's a HUGE difference.

Re: Rob Pike: Simplicity Is Complicated [video]

#72
post #47

Earlier quoted context omitted.

Go is a simple language, with 1970's features. It is very easy to implement, and leaves a lot of the complexity (null pointers, generics, etc) to the user instead of solving it in the language. This is a classic example of worse-is-better. An MIT-style language would be Rust, which indeed struggled to get to v1.0 and Go vs. Rust plays out quite similarly to what worse-is-better would predict.

> This is a classic example of worse-is-better. C won over Lisp, not because “worse is better”, but because the C's advantages over Lisp (performance on cheap machines) were more pronounced than the other way around (“safety” achieved by means of lots of runtime checking - by no means was it possible to statically rule out errors). Lispers fancy their language of choice the pinnacle of computer science, but the falsi…

And this 'win' is ill defined. Both won on their market. C was great to do what it did, Lisp too. All the research and crazy idea spawned thanks to high level symbolic thinking is still bearing fruit today. It's not a win as in market domination but gene spreading and still being alive too.

Re: Rob Pike: Simplicity Is Complicated [video]

#73
post #67

Earlier quoted context omitted.

> I'm interested in “low cognitive load without sacrificing technical precision.” You don't seem to be interested in low cognitive load at all, otherwise: > No disagreement here. I even stated my personal choice of C. you would have attempted to motivated your choice of reference point in terms of cognitive load. Even if induction mathematics was the way the human mind worked (which it isn't) it's very different from…

> Even if induction mathematics was the way the human mind worked (which it isn't) Even if it isn't how the human mind works, it's how computing itself works. Would you take seriously a physicist who denies gravity? I wouldn't take seriously a computer scientist who denies structural induction.

> it's how computing itself works

but it's not the whole story when it comes to computers.

Re: Rob Pike: Simplicity Is Complicated [video]

#74
I can't even begin to measure the amount of time I've wasted trying to make go code look as concise as what I can have trivially in C where things like macros and do { } while() are available.

Instead of "simplicity" saving me time as Mr. Pike suggests, it leaves me dissatisfied with the results after wasting my time in attempts to prevent my dissatisfaction.

This probably isn't an issue for someone new to programming without the expectations experience with other languages may bring, but for a seasoned C programmer Go often feels like a regression.

IMHO, what largely makes Go useful over C is the language-level support of coroutines, and not because the simplicity of the "go" keyword or channels, but because it eliminates the need to design and integrate with snowflake event loops or the specifics of blocking/non-blocking file descriptors.

As a result, packages are written without concern for how the caller's event loop will be integrated, you just write blocking code everywhere and it can be used by every Go program with significantly less potential for impedance mismatch. The garbage collection and overall elimination of the need for allocating and freeing memory also contributes to this; no longer do you have to understand the resource life-cycle strategy of some C library you've decided to use, or if it's using the C library's allocator or its own, or if it's capable of using your allocator via some elaborate and unique initialization scheme.

Unfortunately Golang's concurrent execution model is also what makes it a pretty terrible language for system programming. Golang's inescapable and largely opaque underlying use of threads is a constant source of pain for anyone programming operating system facilities which influence only the calling thread's state, particularly state inherited by child threads.

I often encounter misuse of runtime.LockOSThread() in attempts to overcome this problem but as of now this is completely inadequate because the Go scheduler creates new OS threads on an as-needed basis from whichever currently-executing OS thread happens to be executing at the time. This leaks whatever unique state the thread may have into a newly created, unlocked OS thread, which may then go execute any goroutine - likely the very thing you were attempting to prevent in using runtime.LockOSThread().

There's plenty more to whine about, but I'll stop here.

Re: Rob Pike: Simplicity Is Complicated [video]

#75

I 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

> Complexity is not about additivity, it's about entanglement. This. And nothing reflects entanglement better than a formal semantics. English (or any other natural language) always lets you sweep it under the rug. The only objective measure of simplicity is the size of a formal semantics. I expand on this here: https://www.reddit.com/r/programming/comments/3sstis/for_bet...

> The only objective measure of simplicity is the size of a formal semantics.

If we accept that, then simplicity alone is not a desirable goal. Something may well be formally simple but at the same time incompatible with human cognition. Indeed, that may not be objective, but since when do we value things only by objective measures? That the only objective measure of simplicity may be the size of formal semantics does not mean that it is the most useful measure of simplicity (if we wish to view simplicity as possessing a positive value that implies ease of understanding).

Re: Rob Pike: Simplicity Is Complicated [video]

#76
post #47

Earlier quoted context omitted.

Go is a simple language, with 1970's features. It is very easy to implement, and leaves a lot of the complexity (null pointers, generics, etc) to the user instead of solving it in the language. This is a classic example of worse-is-better. An MIT-style language would be Rust, which indeed struggled to get to v1.0 and Go vs. Rust plays out quite similarly to what worse-is-better would predict.

> This is a classic example of worse-is-better. C won over Lisp, not because “worse is better”, but because the C's advantages over Lisp (performance on cheap machines) were more pronounced than the other way around (“safety” achieved by means of lots of runtime checking - by no means was it possible to statically rule out errors). Lispers fancy their language of choice the pinnacle of computer science, but the falsi…

I agree with everything you said :)

I also think Lisp is not truly "better" in the sense "worse-is-better" is ascribing. But if we suspend disbelief - then the Go vs. Rust story matches the one described in "Worse is better".

Perhaps Rust will win out in the end and "worse is better" won't prevail. Despite liking the idea of Rust very much, I don't think it will.

Re: Rob Pike: Simplicity Is Complicated [video]

#77

Earlier quoted context omitted.

Reflection, downcasts and assigning `null` to pointers are completely opt-in in Java too. With respect to type families, I'm probably being a little bit unfair. Personally, I don't have much against associated type families. (Although I think Rust handles them much more gracefully than GHC.) But very important libraries in the GHC ecosystem like vector and lens make extensive use of free-floating type families, which…

> Reflection, downcasts and assigning `null` to pointers are completely opt-in in Java too. No, they're not -- not in the same sense, at least. A GADT/TypeFamily is going to be visible in the API. None of the things you mentioned are visible in the API. There's a HUGE difference.

> A GADT/TypeFamily is going to be visible in the API.

Only works if you're never going to make abstract types. Which I guess is technically true in Haskell - the most you can do is hide the constructors of a concrete type. But the ability to make abstract types is very useful.

Don't get me wrong, I love Haskell. It's precisely because I love Haskell that I hate it when they add features that make it as hard to reason about as C++. (Yes, there I said it - type families are morally C++ template specialization.)

Re: Rob Pike: Simplicity Is Complicated [video]

#78
post #44

Earlier quoted context omitted.

How do GADTs or type families weaken parametricity?

Without either GADTs or type families, two types `Foo` and `Bar` with mappings `fw :: Foo -> Bar` and `bw :: Bar -> Foo` that compose in both directions to the identity, are “effectively indistinguishable” from one another in a precise sense. If you have a definition `qux :: T Foo`, for any type function `T` not containing abstract type constructors, you can construct `justAsQuxxy :: T Bar` by applying `fw` and `bw`…

This nice property is not part of 'parametricity' as I know it, though.

Re: Rob Pike: Simplicity Is Complicated [video]

#79
post #58
post #47

Earlier quoted context omitted.

Go is a simple language, with 1970's features. It is very easy to implement, and leaves a lot of the complexity (null pointers, generics, etc) to the user instead of solving it in the language. This is a classic example of worse-is-better. An MIT-style language would be Rust, which indeed struggled to get to v1.0 and Go vs. Rust plays out quite similarly to what worse-is-better would predict.

There isn't one language to rule them all. An advantage of Go over Rust is easier tooling due to a simpler language, an advantage of Rust is a richer type system. These are in opposition.

Eh? Rust tooling is excellent?

Rust can reuse nearly all C tools like kcov, gdb, perf, valgrind. On top of it, it has a solid set of its own tools. For example it has rustfmt, cargo, rustdoc (having the ability to test your Rust documentation is great).

Only thing it truly misses is a IntelliJ IDE for Rust and possibly a Rust oriented coverage system.

Re: Rob Pike: Simplicity Is Complicated [video]

#80
post #12

Earlier quoted context omitted.

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.

> How do you have a large set of language features with them not interacting? The ability to write interesting programs in a language comes from the interaction between its features. The real problem is features that interact in unpleasant ways , which almost always results from a lack of foresight on the language designer's part. > In C++, RAII interacts with exceptions, which is the point but isn't exactly pleasant…

> The interaction between control effects (of which exceptions are a particular case) and substructural types (of which C++'s RAII is a very broken particular case) is certainly nontrivial

A nitpick, but what constitutes an effect is rather arbitrary. An effect in the PFP sense is not an operational definition (other than IO) but a linguistic one. This is why I think that handling errors well, handling mutation well and handling IO well are three completely different problems that are only accidentally bundled into one by PFP for no cognitive/empirical reason other than that the lambda calculus happens to be equally challenged by all three.

There is a fourth effect, which is just as operational as IO (and thus a "truer" effect than errors or mutation) and is often the most interesting, yet it happens to be the one that baffles PFP/LC most: the passage of time. This is why there are usually two ways to sleep in PFP languages, one considered an effect, and the other is not (but happens to be much more operationally disruptive, and thus a stronger "effect").

Post reply on HN