4

Some languages, including C++ and Python, have "standard libraries" associated with them.

What are the advantages of separating functionality out into standard libraries rather than build it directly into the language, where it would take less effort to access?

Clarification: by "built in" I mean "usable out of the box" - no imports, no #includes. The mechanism might very well work just like includes under the hood - e.g. language standard would declare that headers which aren't used by the program must not be compiled with them, and then compiler would perform static check of whether the name can be found in the "standard library".

  • 4
    why include things your program doesn't need? – TZHX Sep 6 '16 at 15:25
  • @TZHX who said you would? – MatthewRock Sep 6 '16 at 16:36
  • 2
    To the close voters: my quesiton won't get any clearer if you only cast the vote, and not ask for things you don't understand. – MatthewRock Sep 6 '16 at 16:38
  • It seems like the alternative to having a standard library where you include the parts you want is to have all those parts built in, whether you'll use them or not, as your question says. If that's not what you meant, then explain yourself better. – TZHX Sep 6 '16 at 16:38
  • 3
    It is not clear to me who gets the win of "less effort". Less effort for the standard library team, to be sure, but a lot more effort for the language design team! I'm not sure why it is any more or less effort for a user of the language to access a function from an included standard library vs a built in standard library. – Eric Lippert Sep 12 '16 at 16:39
5

To quote Eric Lippert, who worked on the C# design team, and who is paraphrasing and expanding on some words by Eric Gunnerson, who also worked on the C# team:

And (2) just being a good feature is not enough. Features have to be so compelling that they are worth the enormous dollar costs of designing, implementing, testing, documenting and shipping the feature. They have to be worth the cost of complicating the language and making it more difficult to design other features in the future.

(emphasis Mr. Lippert's)

Leaving a language as-is is free. Free is a very big advantage.

Language designers tend to be conservative, and with good reason. A mistake can bite them for a very long time due to the need to maintain backwards compatibility. And breaking backwards compatibility is also painful, just look at the Python 2 to Python 3 transition.

So if you want to introduce a change to a language, you need to have a very strong justification for it. In my opinion, the removal of one or a handful of lines (depending on how your standard library is organized and what you need) per file is a pretty small benefit, especially considering that those lines can be trivially inserted by many IDEs and even text editors, often in a more general manner which can include not just the standard library, but custom and third party libraries as well.

And any time and money the language designers spend working on duplicating minor features of text editors, whether when initially implementing it, or working around it later on, is time and money that they aren't spending on other features.


Sometimes though, designers will decide that doing just what you're suggesting is worth the cost. Common Lisp, for example, makes the entirety of its standard library available by default, without requiring any sort of import statement.

  • I gave them as an example, but I'm not proposing merging the existing resources into the language. Also, I believe that languages like C# might be designed and implemented by the same guys; however, many languages don't. – MatthewRock Sep 7 '16 at 8:44
  • 1
    @MatthewRock What I said all still applies, even for a brand new language. One of the most valuable features of a language is the ability to call code from another file, once you've got that, you can have libraries, and thus you can create a standard library without any additional changes to the language. Adding the ability to recognize specific functions, classes, namespaces, etc, requires time and effort to change the language. – 8bittree Sep 7 '16 at 13:45
  • 1
    @MatthewRock I'm not sure what your point about having design and implementation handled by one team or separate teams is, either way, it doesn't magically make a feature free. – 8bittree Sep 7 '16 at 13:53
  • Yeah, you're right. – MatthewRock Sep 7 '16 at 14:34
  • Thanks for the shout-out. FYI I stopped working on the C# design team in 2012 and Eric G stopped working on the C# design team... in the 1990s? I think. Not sure. Some decades ago at least. – Eric Lippert Sep 12 '16 at 16:37
5

I think the C++17 variant type offers an interesting look at the language vs. library issue.

The C++17 variant type has had a long and semi-torturous history in its development. The big issue has been how to deal with throwing constructors during assignment/emplacement into a live variant object.

The obvious desire would be to provide the strong exception guarantee: if the new object throws during copy/move/emplace into the variant, then the variant is left unchanged. But implementing that has problems. The desired sizeof for a variant is that of an equivalent union + a char to discriminate within them.

Which means that if you assign/emplace into a variant, 2 things have to happen: destroy the old value, then construct the new value in its place. It's #2 that fails; the old value is gone. You can't get it back.

You could try to play games, like moving the old value into a temporary, then moving it back if the construction of the new fails. But move operations are allowed to throw, and there are even standard library types with throwing moves. You can try to double-buffer the data (store 2x the data, so you always have a temporary around), or even allocate memory like boost::variant, but those were considered unacceptable by the committee.

For a language-based variant, this would obviously not be an issue. The standard would simply declare by fiat that it offers the strong exception guarantee and that it is sized appropriately, doesn't allocate memory, etc. Compilers would have to use compiler magic to make it work.

However... what if we could simply expose that "compiler magic" as a first-class language feature? For example, this proposal suggests a way to effectively make move constructors that don't throw. By doing that, we can now use the temporary method to implement variant.

This gives you most-if-not-all of the advantages of a language variant, but it also gives you tools you can use to make your other code more efficient.

If you try to shove anything and everything into the language, what you'll find is that you'll make users overly dependent on the language, rather than using the language to give users the tools to build what they need. This is especially important for a low(er)-level language like C++.

  • Hi, nice post! I like it, but I kind of disagree with the conclusion; while it may be partially hard, I don't think it's that bad if language has good features, and also this doesn't have to be true. Common Lisp has many functionalities that you don't use most of the time, but it also has an excellent macro system that makes the people build things on the language elegantly and efficiently. – MatthewRock Sep 7 '16 at 8:40
  • @MatthewRock: I think you're misunderstanding the point here. If the language provides broad features that allow efficient implementations of various types, what's the point of making those types language features rather than library features? You don't lose any performance or functionality by putting them in the library. And contrary to what you said in your question, using an import or #include directive does not constitute "effort". So why bother? – Nicol Bolas Sep 7 '16 at 14:49
  • To be honest, I'm playing a kind of devil's advocate in here. I feel that this isn't the best idea, but I want to have solid evidence that it's not. The cost argument is imho the best, because you can often work around these issues. As to "what's the point", I don't see any difference. If I have std::vector that I need to #include<vector> first, and std::vector without the include, the only difference is the #include. It doesn't look like it differs much. – MatthewRock Sep 7 '16 at 15:04
3

Because it makes it easier to add further functionality to the standard library without breaking users' existing code - and language committees hate breaking code.

By placing a function in a separate library that has to be included/imported, you reduce the chances that any new functionality will cause name clashes with classes or functions that the programmer has already written themselves.

That's especially true if your library has a sensible naming convention.

  • 1
    This makes sense when thinking of Python(I can think of print issues when it was transformed into function). What about C++, where you've got std namespace, so you're protected against this kind of things? – MatthewRock Sep 6 '16 at 16:35
  • @MatthewRock What part of the std namespace is accessible without including part of the C++ standard library? – Daniel Jour Sep 12 '16 at 17:16
  • @DanielJour what I meant is: Simon claims that introducing new code might take some already used symbols, breaking existing code base as a result. I only wanted to show that in C++ you already have the symbols exist in separate namespace, std, so that wouldn't be a concern. – MatthewRock Sep 13 '16 at 9:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.