Live data from Hacker News

Linus vs C++, again

realworldtech.com

141–150 of 209 posts

Re: Linus vs C++, again

#141
post #104
post #31

Earlier quoted context omitted.

write(fd, buf, size); Can you list all the caveats, possible side effects, reasons of failure of this simple C function call? Hint: remember, fd can be a file, as well as a NFS-mounted file, pipe, network or local socket, FIFO, device, etc. Hint2: I doubt anyone can give a comprehensive description of the possible consequences of this call. Bottom line being, C can be incredibly hard to understand, or C++ can be clea…

In addition to the other already-good answers, I want to add the following answer, which I believe is even closer to the "real" answer Linus had in mind. Of course you can not look at the function and immediately know all consequences. The real point is that there is a procedure you can follow which will let you determine the answer. 1. Locate the "write" function. There will only be one, because C has no namespaces.…

This comment made things a bit clearer for me. This seems to also be an argument in favor of a Lisp-1 over a Lisp-2 (same symbol found in multiple packages) as well as an argument against use of generic methods (have to understand the types to find the right implementation). Something to think about.

Re: Linus vs C++, again

#142
post #104

Earlier quoted context omitted.

In addition to the other already-good answers, I want to add the following answer, which I believe is even closer to the "real" answer Linus had in mind. Of course you can not look at the function and immediately know all consequences. The real point is that there is a procedure you can follow which will let you determine the answer. 1. Locate the "write" function. There will only be one, because C has no namespaces.…

This comment made things a bit clearer for me. This seems to also be an argument in favor of a Lisp-1 over a Lisp-2 (same symbol found in multiple packages) as well as an argument against use of generic methods (have to understand the types to find the right implementation). Something to think about.

Lisp-1 vs Lisp-2 is about whether functions and other variables are in the same namespace or not. Packages are orthogonal to this.

Also, generic functions in Common Lisp don't suffer from nearly the same amount of complexity as can be found in C++: there is always only one signature (lambda-list) for any function name, whether generic or not, there are no implicit conversions, no memory-allocation details, value/pointer/reference distinction, constness, virtualness, overloading of assignment operators etc.

Re: Linus vs C++, again

#143
post #31
post #9

As I get older and grumpier I tend to appreciate Linus' point of view more and more. It's easy to get swept up by arguments of the expressiveness of a language, particularly in small examples. However, I think in the long run it's better to have very explicit code. The less jumping around and inference I have to do to figure out what a block of code does the more likely it is that I understand it and that I can quick…

write(fd, buf, size); Can you list all the caveats, possible side effects, reasons of failure of this simple C function call? Hint: remember, fd can be a file, as well as a NFS-mounted file, pipe, network or local socket, FIFO, device, etc. Hint2: I doubt anyone can give a comprehensive description of the possible consequences of this call. Bottom line being, C can be incredibly hard to understand, or C++ can be clea…

Ugh, in C under UNIX this could mean two things:

* If some moron created a "write()" macro, it means expand that macro (preferably it should also mean email the director of HR to suggest the author of the macro consider having the company pay for their MBA, to make sure they aren't allowed to touch code again)

* Otherwise, if a header has a definition for write use that. Otherwise, emit instructions to call put "fd, buf, size" on the stack and call write.

In C++ it could mean:

* There's a class "write" which has a constructor that takes three arguments

* There's a function in the global namespace called "write" that takes three arguments

* There's a macro called write

* There's method called write in the local class. That method could be invoked virtually or non-virtually. It could be inherited from a parent class.

* write could be an instance of an class that has "operator ()" defined

I probably left out some more. In fact, there's likely a firm somewhere that thinks "what could write(a, b, c) mean in C++" is a wonderful interview question (perhaps they could ask it to all those losers who don't know what "explicit" keyword does but still have the gall to think they're competent enough to work for them!)

In a UNIX system, with right headers included, what write does is specified by the POSIX API. POSIX is one of the best defined and cleanest APIs. It has existed before the world of IDEs and plug-and-play libraries. I can write non-blocking C network code for a UNIX OS with vi, from muscle memory after reading through man pages and working through Richard Stevens books.

Writing Java NIO code requires: an IDE to prevent RSI, traversing Javadocs to understand the non-intuitive APIs and searching mailing lists through Google to e.g., find out that Java NIO selector doesn't let me use edge triggered epoll because it would involve "tight coupling" (read: it might be difficult for somebody writing code on an AS/400 to use it).

JDK7 NIO2 potentially changes this (I can implement internals of a selector myself). I'm also sure I'll be able to target JDK7 with a Perl6 compiler... that I'll use to implement the firmware for my flying car, in which I'll travel pick up Hans Reiser when he's paroled from prison.

Note: in this case, it has nothing to do with the language. java.util.concurrent API is very well defined because it was written by great programmers (Doug Lea and Joshua Bloich) who are apt at API design. Unfortunately, Java doesn't "force you" to create a clean API like C does: there are no design patterns available, no IDEs, no built-in tools for literate programming in C; you either build a clean API, or no one will use it. While I'm in no way of Joshua Bloch's caliber, I can relate to him when he says that he stayed with imperative C until finding Java.

While Java doesn't force you to build a clean API, C++ almost makes it impossible to build a clean API: witness boost::spirit ("generic programming", C++'s idiom for extending the language), compare with lex/yacc (external DSLs) and parser combinators (internal DSLs) in Haskell or Scala.

I want to like C++. I have programmed it for a living before and will almost certainly do so again: there's a certain combination that requires low-level code with no memory management and Object Orientation; my chosen specialty (distributed systems) often requires that combination (fortunately, not always: Erlang and JVM languages have been used to build some incredibly impressive systems).

Perhaps Go and D could come along and step up to that challenge, but I am skeptical: Modula-3, despite influencing other languages hasn't been able to step up to that plate. I feel C++ 0x, Intel collections for C++ and some parts of boost, STL and tr1 e.g., tr1::unordered_map, boost::scoped_ptr are very cool and useful. Boost Graph library is simply awesome and has no equivalent.

It seems, though, as if C++ was built by warring hordes: one horde that wanted generic programming and thought OO was pointless, another horde that wanted OO but thought generic programming was pointless and yet another that hated both. Neither won nor lost, each side said "mission accomplished" and developers were treated as "collateral damage". I could care less about which one of those to use: I am productive doing OO programming in Perl, Python, Scala and Java. I am also productive doing generic programming with CLOS in Common Lisp or with type classes (or their equivalents) in statically typed languages. Likewise, I am perfectly productive writing imperative code in C. I just want clean, easy to program to APIs with understandable error messages (either at run time or compile time, I am not picky about dynamic vs. static typing -- they're tools, means to an end) and C++ doesn't allow for that.

Re: Linus vs C++, again

#144
post #130
post #79

Earlier quoted context omitted.

That same write call can exist in C++ too, with exactly the same consequences. Everything ugly in C can be done in C++, but C++ lets you be so much uglier. int i = 42; foo->bar(i); In C, we can tell that foo is either a "struct S* foo" or "union U* foo" which has a member "X (*bar)(Y)". Type X is unknown from this context, but Y is some type compatible with int. We will call the function which bar points to with a si…

This is one reason why idioms and patterns are important. I don't think there are many reasonable C++ coders out there who would override operator-> in such a way as to introduce such ambiguity.

Unfortunately that particular override comes up a lot when doing "smart pointers". Smart pointers are crazy difficult to write and fail in all kinds of subtle ways.

Re: Linus vs C++, again

#145
post #76

This rings hollow. It's like saying "C++ feature X can go horribly wrong when used without adult supervision, therefore C++ is unusable." This is especially silly coming from someone who favors a professional stunt language like C. If somebody uses too much overloading, reject their patch. If somebody makes a template tarpit, abuses operator(), or gets too fancy with operator overloading, send it back to 'em. Context…

I think his main point vis-a-vis C and C++ is that the kernel has a unified C culture and adding C++ would import a bunch of different C++ cultures. As a C++ developer in a C++ shop, I can appreciate this. Our shop has a very solid and consistent C++ culture. We can read each others' code because we all use the same language features and coding style. You can't do coherent C++ development without having this unity. T…

GCC is now allowing C++ code. It will be interesting how they can keep C and C++ style unified and coherent.

Re: Linus vs C++, again

#146

I know no tool would solve every problem, but I can't help but wondering if someone developed and IDE that truly got C++ would that allow C++ to be used by more projects. Seeing grep referenced for code searches reminds me that grep has no knowledge of the context of anything in a searched file. It almost seems like C is the only choice if you can't go beyond context-less tools. //a grep specifically for C++ code - h…

One problem with C++: It is hard to build tools for, because parsing it is nearly impossible. Clang and GCC plugins may change this situation, though.

Re: Linus vs C++, again

#147
Somewhere down the list, someone asks about Go

Hey, I think Go picked a few good and important things to look at, but I think they called it "experimental" for a reason. I think it looks like they made a lot of reasonable choices.

But introducing a new language? It's hard. Give it a couple of decades, and see where it is then.

Linus

(http://www.realworldtech.com/forums/index.cfm?action=detail&...)

Re: Linus vs C++, again

#148
post #109

This rings hollow. It's like saying "C++ feature X can go horribly wrong when used without adult supervision, therefore C++ is unusable." This is especially silly coming from someone who favors a professional stunt language like C. If somebody uses too much overloading, reject their patch. If somebody makes a template tarpit, abuses operator(), or gets too fancy with operator overloading, send it back to 'em. Context…

> Polymorphism also gives you what amounts to functional programming without touching C's awful function pointer syntax. Which aspects of functional programming are you talking about?

Probably operator() and passing classes that have this operator implemented around.

For me it isn't better than function pointers, also because of method - function distinction we have 2 different incompatibile kinds of functions.

Re: Linus vs C++, again

#149
post #130

Earlier quoted context omitted.

This is one reason why idioms and patterns are important. I don't think there are many reasonable C++ coders out there who would override operator-> in such a way as to introduce such ambiguity.

Unfortunately that particular override comes up a lot when doing "smart pointers". Smart pointers are crazy difficult to write and fail in all kinds of subtle ways.

I've never had any problem with Qt or Boost smart pointers. They may be delicate to write, especially in multithreaded use cases, but once it's written it works rather well.

Re: Linus vs C++, again

#150

Earlier quoted context omitted.

How do you explain the success of ActiveRecord? Do you think it's illusory? The exception that proves the rule? Something else? http://blog.objectmentor.com/articles/2009/07/13/ending-the-... "The fact that it took decades for the industry to arrive at something as useful as ActiveRecord in Rails is due primarily to the attitude that some language features [in this case, meta-programming] are just too powerful for ev…

I think ActiveRecord has exactly the sort of problems that Linus describes, when you get to large codebases and large teams. For example, what does 'save!' do? Well, it doesn't just update the row in the database; it also runs any validations on the object, and any before/after validation/save hooks. So, in general, you need that context to know whether a patch that updates something is correct or reasonable. And if…

"a tool that make simple things easy" - thank you for this =)
Post reply on HN