views:

439

answers:

9

It seems that most new programming languages that have appeared in the last 20 years have been written in C. This makes complete sense as C can be seen as a sort of portable assembly language. But what I'm curious about is whether this has constrained the design of the languages in any way. What prompted my question was thinking about how the C stack is used directly in Python for calling functions. Obviously the programming language designer can do whatever they want in whatever language they want, but it seems to me that the language you choose to write your new language in puts you in a certain mindset and gives you certain shortcuts that are difficult to ignore. Are there other characteristics of these languages that come from being written in that language (good or bad)?

+4  A: 

No, in short. The reality is, look around at the languages that are written in C. Lua, for example, is about as far from C as you can get without becoming Perl. It has first-class functions, fully automated memory management, etc.

It's unusual for new languages to be affected by their implementation language, unless said language contains serious limitations. While I definitely disapprove of C, it's not a limited language, just very error-prone and slow to program in compared to more modern languages. Oh, except in the CRT. For example, Lua doesn't contain directory functionality, because it's not part of the CRT so they can't portably implement it in standard C. That is one way in which C is limited. But in terms of language features, it's not limited.

If you wanted to construct an argument saying that languages implemented in C have XYZ limitations or characteristics, you would have to show that doing things another way is impossible in C.

DeadMG
You got a point and I upvoted, but note that even lua and perl are still imperative languages. Functional languages (Haskell, ML-derivates, Pure, Clean) usually aren't done in C. I blame this on the fact that those who create such a language already know other functional languages, most of which are waaay better for compiler writing than C.
delnan
You "disapprove of c"? Wow, that seems harsh. While I "dislike" and choose not to use Java, I save my disapproval for more heinous things like whale hunting and wearing socks with sandals.
AShelly
@delnan: Check bdonlan's answer. They preprocessed Haskell into C. @AShelly: It's really not the point of the answer.
DeadMG
@DeadMG: I know GHC can output C and compile it via gcc, but something different - first, it's only one of several ways of running Haskell, second, GHC itself is written in Haskell.
delnan
@delnan: So what? You can process Haskell into C. That's the point of my answer.
DeadMG
Saying that a language is close to perl is definitely NOT saying that it's far from C. :-) Perl fits into the C worldview as far as I'm concerned. Python, Perl, Ruby, Java are all HEAVILY influenced by C and fit within C's sphere of influence.
guidoism
@DeadMG: You *can* (in theory, and most of the time in practice) compile any language to any other language. That doesn't say anything about either language.
delnan
@delnan: Except that the destination language does not limit the languages implementable in it. Which is the point of this question.
DeadMG
A: 

One thing I can think of is that functions are not necessarily first class members in the language, and this is can't be blamed on C alone (I am not talking about passing a function pointer, though it can be argued that C provides you with that feature).

If one were to write a DSL in groovy (/scheme/lisp/haskell/lua/javascript/and some more that I am not sure of), functions can become first class members. Making functions first class members and allowing for anonymous functions allows to write concise and more human readable code (like demonstrated by LINQ).

Yes, eventually all of these are running under C (or assembly if you want to get to that level), but in terms of providing the user of the language the ability to express themselves better, these abstractions do a wonderful job.

Gangadhar
It's very ugly to do something in C which looks like first-class functions to the implemented language, yeah. But same applies for dynamic typing, objects, and a dozen other features C-based languages have anyway.
delnan
+3  A: 

Even with a C implementation, you're surprisingly free in terms of implementation. For example, chicken scheme uses C as an intermediate, but still manages to use the stack as a nursery generation in its garbage collector.

That said, there are some cases where there are constraints. Case in point: The GHC haskell compiler has a perl script called the Evil Mangler to alter the GCC-outputted assembly code to implement some important optimizations. They've been moving to internally-generated assembly and LLVM partially for that reason. That said, this hasn't constrained the language design - only the compiler's choice of available optimizations.

bdonlan
+6  A: 
stakx
IIRC, C and most other imperative languages are classed as "ALGOL-like languages" since they are heavily influenced by ALGOL.
rmeador
Last time I checked, it's the C-family.
DeadMG
Both @rmeador and @DeadMG are correct, IMHO. ALGOL has provided some main language concepts (found in languages such as C or Pascal), and C has later provided a popular syntax.
stakx
+1  A: 

Garbage collection. Language implementations on top of Java or .NET use the VM's GC. Those on top of C tend to use reference counting.

dan04
Most Java and .NET VMs are written in C or C++.
Jerry Coffin
And in which language was the JVM/CLR written? Sun's JVM is C++, I guess same applies for the CLR. Okay, that's one step above C, but still...
delnan
I don't see any reason why garbage collection in C should be limited to reference counting schemes (even if that's likely, since reference counting might be easiest to implement). IIRC there's some good GCs for C, e.g. the one by Hans Boehm.
stakx
++ @stakx for mentioning Boehm. It's conservative (e.g. won't catch 'em all, only most), but doesn't use reference counting.
delnan
I think it's safe to say that Microsoft's implementation of the CLR (that is, .NET) is written in C++, using the COM architecture.
stakx
@stakx: I'd put money on the CLR not being written using COM (which was implemented in C).
JeremyP
@JeremyP: I didn't mean to say that .NET's execution environment is implemented *like* COM, but that it (at least partly) *uses* COM itself, and that it's mostly written in C++. This seems like a reasonable guess to me; first, because COM can be seen as the CLR's ancestor; second, some people at Microsoft once made public another implementation of the CLI (the Shared Source CLI, aka Rotor), which is written in C++ / C#. I'm sure their source code at the time wasn't fundamentally different from .NET's source code. There's more clues to this, but in all truth, probably noone can tell for sure.
stakx
+3  A: 

The C stack is just the system stack, and this concept predates C by quite a bit. If you study theory of computing you will see that using a stack is very powerful.

Using C to implement languages has probably had very little effect on those languages, though the familiarity with C (and other C like languages) of people who design and implement languages has probably influenced their design a great deal. It is very difficult to not be influenced by things you've seen before even when you aren't actively copying the best bits of another language.

Many languages do use C as the glue between them and other things, though. Part of this is that many OSes provide a C API, so to access that it's easy to use C. Additionally, C is just so common and simple that many other languages have some sort of way to interface with it. If you want to glue two modules together which are written in different languages then using C as the middle man is probably the easiest solution.

Where implementing a language in C has probably influenced other languages the most is probably things like how escapes are done in strings, which probably isn't that limiting.

nategoose
+2  A: 

The only thing that has constrained language design is the imagination and technical skill of the language designers. As you said, C can be thought of as a "portable assembly language". If that is true, then asking if C has constrained a design is akin to asking if assembly has constrained language design. Since all code written in any language is eventually executed as assembly, every language would suffer the same constraints. Therefore, the C language itself imposes no constraints that would be overcome by using a different language.

That being said, there are some things that are easier to do in one language vs another. Many language designers take this into account. If the language is being designed to be, say, powerful at string processing but performance is not a concern, then using a language with better built-in string processing facilities (such as C++) might be more optimal.

Many developers choose C for several reasons. First, C is a very common language. Open source projects in particular like that it is relatively easier to find an experienced C-language developer than it is to find an equivalently-skilled developer in some other languages. Second, C typically lends itself to micro-optimization. When writing a parser for a scripted language, the efficiency of the parser has a big impact on the overall performance of scripts written in that language. For compiled languages, a more efficient compiler can reduce compile times. Many C compilers are very good at generating extremely optimized code (which is also part of the reason why many embedded systems are programmed in C), and performance-critical code can be written in inline assembly. Also, C is standardized and is generally a static target. Code can be written to the ANSI/C89 standard and not have to worry about it being incompatible with a future version of C. The revisions made in the C99 standard add functionality but don't break existing code. Finally, C is extremely portable. If at least one compiler exists for a given platform, it's most likely a C compiler. Using a highly-portable language like C makes it easier to maximize the number of platforms that can use the new language.

bta
A: 

Implementing a compiler/interpreter in C doesn't have any major limitations. On the other hand, implementing a language X to C compiler does. For example, according to the Wikipedia article on C--, when compiling a higher level language to C you can't do precise garbage collection, efficient exception handling, or tail recursion optimization. This is the kind of problem that C-- was intended to solve.

dsimcha
+1  A: 

The one limitation that comes to mind is extensibility and compiler hosting. Consider the case of C#. The compiler is written in C/C++ and is entirely native code. This makes it very difficult to use in process with a C# application.

This has broad implications for the tooling chain of C#. Any code which wants to take advantage of the real C# parser or binding engine has to have at least one component which is written in native code. This eventually results in most of the tooling chain for the C# language being written in C++ which is a bit backwards for a language.

This doesn't limit the language per say but definitely has an effect on the experience around the language.

JaredPar
...but maybe if they wrote the *next* C# compiler in C# but compiled with the current written-in-C compiler...
FrustratedWithFormsDesigner
@FrustratedWithFormsDesigner indeed that is an option.
JaredPar