5 ms·
The "right tool for the job" is a myth (EDIT: exaggerating; clearly it applies in some cases). Languages don't work together very well, so you need huge, thick
by jeffdavis 7y ago
The "right tool for the job" is a myth (EDIT: exaggerating; clearly it applies in some cases). Languages don't work together very well, so you need huge, thick boundaries between them, such as serialization/deserialization. Data types don't match up, GCs require special data formats and don't line up with the GCs of other languages, other runtime weirdness, etc. At minimum, you need lots of copying/transformation of the data.
Have a gnarly problem in a Python program that Haskell would be perfect for? Too bad. You'll spend more time figuring out how to transform the data and get the Python code to call into Haskell than you'll save by using the right tool. And in the process, the overhead, complexity, and bugs introduced in this process turn the right tool into the wrong tool.
And that's the reason why C is so important. It actually does work with pretty much any language, because it has a defined ABI, simple data types, minimal runtime, can work on any data formats unmodified, no GC. Very few languages have this superpower.
C++ mostly has that superpower, but some features don't entirely work with unmodified structures (RTTI and virtual functions both require adding magical fields to the class structure). Rust seems to have this superpower (does dynamic dispatch a different way than C++, so can always work on unmodified structures).
The JVM is an interesting case and the ecosystem of languages built on it do work better together because they have the exact same runtime (GC, etc.).
To summarize: we'd all like to use the right tool for the job. But we can't, except for the languages that go out of their way to make this effective, and that list of languages is very short.
- sseagull 7y agoThis really needs to be said more. For those of us not in web devel or microservices, the lower level of coupling between components really makes using multiple languages a pain. Plus, you have to learn all those languages -- sometimes I just want to actually get stuff done. I consider it significant code smell when a project has multiple languages, particularly when each language seems tied to a particular developer.
- saagarjha 7y ago> Rust seems to have this superpower (does dynamic dispatch a different way than C++, so can always work on unmodified structures). This isn't really true.
- jeffdavis 7y agoCan you explain?
- saagarjha 7y agoRust has both static (based on monomorphization, similar to a template instantiation in C++) and dynamic (based on vtables, similar to inheritance in C++) dispatch: https://doc.rust-lang.org/1.8.0/book/trait-objects.html https://doc.rust-lang.org/1.8.0/book/trait-objects.html. Both Rust and C++ are moving in the direction of encouraging static dispatch.
- steveklabnik 7y agoIt may be similar, but it is implemented very differently, in exactly the "so can always work on unmodified structures" sense. Trait objects are a double pointer: one to the vtable, and one to the data. C++'s dynamic dispatch uses a single pointer to a structure that has the vtable and the data. The memory layouts are very different.
- jeffdavis 7y ago"The memory layouts are very different." Clarification: the memory layouts between C++ dynamic dispatch and rust dynamic dispatch are very different. Rust imposes no requirements on the structure layout, whereas C++ adds some magic data. The magic data means it's awkward to make C++ do dynamic dispatch on a C struct pointer; but rust can do dynamic dispatch on a C struct pointer with no problem.
- lliamander 7y agoA really thought-provoking argument. I suppose that when it comes to choosing "the right tool" the important thing is to optimize globally across the problems that your organization will be solving. But if you want to be able to optimize both globally and locally, well that's just an engineering problem! Two examples spring to mind: 1. Lisp. Lisp's metaprogramming facilities allow you to build the language into the specialized tools that you need, while still having the common runtime and base language. 2. Unix. There a hundreds (possibly even thousands) of little programs running on my Linux machine written in probably dozens of languages. For the most part, I have no idea (nor do I care) what language they are written in. That's because the Unix model puts a strong emphasis on the protocols for communicating between programs.
- jeffdavis 7y agoLisp is an interesting point. I guess the argunent is that it's the right tool for every job? Unix is a reasonable example of a polyglot environment, but at a high cost. Lots of serialization/deserialization through text. That has a high cost in terms of bugs, complexity, lines of code, and inefficiency.
- lliamander 7y ago> Lisp is an interesting point. I guess the argunent is that it's the right tool for every job? Yup, that's more or less the argument, though the argument need not only apply to lisp. > Unix is a reasonable example of a polyglot environment, but at a high cost. I'd rather say that Unix is an example of how to effectively drive down the cost of a polyglot environment to a point where it is outweighed by the benefits. Now, of course the cost is still there, but I would argue that beyond a certain scale you cannot optimize globally on a single runtime (perhaps not even with something like lisp) and so the cost of global consistency is outweighed by cost of being unable to optimize locally. To put it more succintly, you could not build a system as complex as Unix in a single language[1] [1] Although Ala Kay's work at VPRI suggests you can, if you choose a sufficiently expressive base language. But even that may have it's limits.
- continuational 7y ago
- ChrisSD 7y agoTo be precise, C does not have a defined ABI (the spec goes out of its way to avoid this). Platforms (OS+Arch) define a C ABI for their own tools. Since this ABI is required to interop with the OS APIs, this will usually become the de-facto standard for the platform. This might seem like nitpicking but it's an important distinction because you can't assume that C data structures can be passed between different platforms (e.g. over a network or even stored in a filesystem).
- jeffdavis 7y agoWhat is the right way to say that without sounding too pedantic every time? "Most platforms define a stable C ABI"?
- pjmlp 7y agoThe only platforms that define a stable C ABI are those whose OS is written in C and exposes a C API to userspace. Symbian did not had a C ABI for example, nor do mainframes, in ChromeOS or Android you also don't have a C ABI exposed to userspace, in Windows a C ABI also won't help you much if you need to speak COM or now UWP.