The Difference Between a Program and a Script

chromatic on 2008-03-01T01:59:02

The difference between a program and a script isn't as subtle as most people think. A script is interpreted, and a program is compiled.

Of course, there's no reason you can't write a compiler that immediately executes the compiled form of a program without writing compilation artifacts to disk, but that's an implementation detail, and precision in technical matters is important.

Though Perl 5, for example, doesn't write out the artifacts of compilation to disk and Java and .Net do, Perl 5 is clearly an interpreter even though it evaluates the compiled form of code in the same way that the JVM and the CLR do. Why? Because it's a scripting language.

Okay, that's a facetious explanation.

The difference between a program and a script is if there's native compilation available in at least one widely-used implementation. Thus Java before the prevalence of even the HotSpot JVM and its JIT was a scripting language and now it's a programming language, except that you can write a C interpreter that doesn't have a JIT and C programs become scripts.

Hm.

Of course, if someone were to write an extra optimizer step for Perl 5 to evaluate certain parts of the optree and generate native code in memory on certain platforms without writing it out to disk (uh oh...) and then execute that code under certain conditions, all Perl 5 scripts would automatically turn into programs.

You know, like .pmc files, or Python's .pyc files. Uh.

As well, if more people use Punie (Perl 1 on Parrot) this year than native Perl 1 -- a possibility -- then Perl 1 scripts automatically become Perl 1 programs because Punie can use Parrot's JIT. I don't know if this powerful upgrade from script to program is retroactive, but I see no reason why not.

Perl 5 scripts were briefly programs while Ponie was viable, but the removal of the code from the Parrot tree has now downgraded them back to scripts. We apologize for the inconvenience.

To summarize, if you have a separate compilation step visible to developers, you have programs. If not, you have scripts. An exception is that if you have a separate, partial compilation step at runtime and not visible to users, then you may have programs. The presence of one implementation that performs additional compilationy thingies at runtime instantly upgrades all scripts to programs, while the presence of an interpreter for a language in which people normally write programs, not scripts, does not downgrade programs to scripts. Program-ness is sticky.

I hope this is now clear.

Ironically some JavaScript implementations have JITs, so the colloquial name of the language should change from JavaScript to JavaProgram.

Script bad, four-legs good.


compiled vs. interpreted

mauzo on 2008-03-01T04:36:54

While I don't think the script/program distinction is useful (uh, duh?), I think there is a useful distinction between 'compiled' or perhaps 'compilable' languages and 'interpreted' ones. A compilable language is one which can be translated into a form that doesn't depend on the compiler; or, an interpreted language is one with 'eval'. Perl is an interpreted language by this definition: this is one of the reasons why PAR is a much more successful way of turning a Perl program into an executable than B::C ever was.

Re:compiled vs. interpreted

chromatic on 2008-03-01T06:32:35

A compilable language is one which can be translated into a form that doesn't depend on the compiler; or, an interpreted language is one with 'eval'.

The first half of that may be true. It may not be; consider a self-hosted language. The latter half is likely not true, as I can write eval for C in C if I can make system calls, open shared libraries, and call functions from shared libraries.

"Compiled" and "interpreted" are characteristics of execution models and are rarely intrinsic to the language.

Re:compiled vs. interpreted

mauzo on 2008-03-01T08:16:31

The first half of that may be true. It may not be; consider a self-hosted language.

I was proposing it as a definition, not a statement of fact :). The only thing that might not be true is that the two halves are equivalent; obviously, they aren't: the latter implies the former but not vice versa. Still, a language that required its compiler to run but didn't provide 'eval' would be rather odd, and probably could be implemented better, so I don't think that matters.

I'm not sure what you mean by a 'self-hosted' language. If you mean languages where (most of) the runtime and the compiler itself are written in the language in question, like C and GHC's Haskell, then they aren't counter-examples. Neither compiled C programs nor GHC-compiled Haskell programs require the compiler to run. They require the runtime, which happened to be written in C/Haskell before being compiled, but that's a different matter. If you mean languages like Lisp, where the basic operation of the runtime requires the compiler, then these are exactly the languages I am calling 'interpreted'. The fact Lisp implementations can typically compile out to machine code is an implementation detail.

I can write eval for C in C if I can make system calls, open shared libraries, and call functions from shared libraries

No you can't; or, at least, you can't without effectively writing a C compiler (most debuggers, for instance, contain a compiler for a language not entirely unlike C). If C had had 'eval' (or, since it was always designed to compile to machine code, separate 'compile' and 'eval' like Lisp) from the beginning, it would have been a rather different language. For one thing, there would have been no need for CPP and configure scripts: just run a little C program that compiles the appropriate bits of code and writes the results out. Shared libraries (including dlopen and everything) would have been built in from the start, instead of being somewhat kludged-in later, as you'd always have needed to be able to link dynamically-generated code. FFI to C would be trivial, instead of requiring nasty assembler tricks to implement generally. And so on.

"Compiled" and "interpreted" are characteristics of execution models and are rarely intrinsic to the language.

While a compiled language can always be interpreted, the reverse is not necessarily true. Both Lisp and Perl, for instance, rely heavily on having access to the compiler (rather than some sort of dynamic linker) at runtime; this is part of what makes them so flexible.

Maybe 'compiled' and 'interpreted' aren't quite the words I'm looking for. Maybe I want 'static' and 'dynamic', though I thought they usually implied more than that, such as static vs. dynamic typing (which is obviously orthogonal to this).

Re:compiled vs. interpreted

chromatic on 2008-03-01T08:47:11

... you can't without effectively writing a C compiler...

I can write system( "/usr/bin/gcc -o mynew.so mynew.c" );. The same thing is possible in a Perl without eval. Neither of us said that portability affected the definition.

Maybe 'compiled' and 'interpreted' aren't quite the words I'm looking for.

As long as our general purpose computing devices use the Von Neumann architecture, any operation that allows you to modify the contents of memory as the program runs makes it possible to allow eval or an equivalent in a language.

Like I said, the line is fuzzy.

Re:compiled vs. interpreted

mauzo on 2008-03-01T09:12:10

I can write system( "/usr/bin/gcc -o mynew.so mynew.c" );.

...at which point your program requires a compiler to run, and is written (by my definitions) in an interpreted language ('C-plus-the-assumption-that-/usr/bin/gcc-is-a-compiler'). I think that if you wrote any sizeable amount of code making use of that construction, or any other like it, you would find you were using a rather more powerful language than C.

Re:compiled vs. interpreted

chromatic on 2008-03-01T19:39:34

... at which point your program requires a compiler to run, and is written (by my definitions) in an interpreted language...

Thus question of whether a language is compiled or interpreted depends on the specific program or script. Suppose instead of invoking an external compiler I used the JIT to generate new code instead of speeding up existing code. If the language itself does not provide eval and I don't invoke an external compiler through a system call, does the language suddenly become interpreted because I can fake the use of eval through a runtime facility?

This is why I think that declaring a language as interpreted or compiled is silly. No matter where you draw the line, the fact that interpretation and compilation are both implementation detail of multiple stages of the process of executing a program mean that you can hinge your definition in several ways.

Re:compiled vs. interpreted

revdiablo on 2008-03-01T22:45:35

This is why I think that declaring a language as interpreted or compiled is silly.
Perhaps a more useful analysis would be how much or how often a particular language is generally used in an "interpreted" or a "compiled" mode of operation? Then it becomes a matter of choosing the appropriate metric and using some basic stats. I don't know if it would be very useful in absolute terms, but it would probably be more useful, at least.

Programs vs. scripts

petdance on 2008-03-01T06:37:02

I think we all know how I stand on this one. :-)

http://xoa.petdance.com/stop_saying_script if you don't.

I agree with Wikipedia

stu42j on 2008-03-03T17:03:40

A scripting language, script language or extension language, is a programming language that controls a software application. "Scripts" are often treated as distinct from "programs", which execute independently from any other application.


http://en.wikipedia.org/wiki/Scripting_language

Re:I agree with Wikipedia

chromatic on 2008-03-04T07:31:57

For that to work, you have to examine the purpose of a specific piece of code. That seems reasonable.