S
Steven D'Aprano
But seriously... I'm not a language or architecture guru. Is there any
real difference between a JVM and an interpreter? I mean, I have some
general feel that bytecode is a lower-level, more direct and more efficient
thing to be interpreting that Java or Python source, but at the bottom
level, you are still running an interpreter which is going to be
(significantly?) more inefficient than executing native machine instructions
directly on the CPU, right?
Thirty (or more?) years ago, the differences between compilers and
interpreters was fairly large. Interpreters would scan the source code of
each and every line. If you had a loop, each line in the loop would be
parsed each time around the loop. Despite 30+ years of progress, that's
still the model that many (most?) people have in their head when they
think of "interpreted language". That's why "interpreted" is the Kiss of
Death to anyone interested in speed -- whether true or not.
def if_(): # interpreted function
exec 'x = 0'
exec """for i in range(100):
exec 'x += i'"""
return x
def cf(): # compiled function
x = 0
for i in range(100):
x += i
return x
[16.228797912597656, 16.261317014694214, 15.885524034500122]timeit.Timer('cf()', 'from __main__ import cf').repeat(3, 1000) [0.054703950881958008, 0.038740158081054688, 0.041306018829345703]
timeit.Timer('if_()', 'from __main__ import if_').repeat(3, 1000)
But these days, and probably for the last decade at least, the nice neat
lines between "compiled" and "interpreted" is much fuzzier. So-called
interpreted languages don't parse the source code every time it is run.
They compile to byte-code, which is interpreted in a virtual machine in
the same way that compiled code is interpreted in a real machine.
Even that distinction isn't necessarily cut and dried. On modern CPUs,
machine code itself can be implemented in a mini-language, which naturally
is interpreted by an interpreter built into the CPU. The "real" machine on
the CPU is likely to itself include "virtual" machines, up to and
including entire emulators of other CPUs.
(Note: for each and every generalization I have made, there are almost
certainly exceptions. I think that just supports my contention that the
generalizations about "compiled" and "interpreted" languages are more
misleading than useful.)
Why is Python able to automatically compile source into bytecode on the
fly (when needed) but Java still forces you to do so explicitly?
That probably has more to do with different programming models than
different technologies. I'm sure somebody could build an interactive
complier/interpreter for Java like Python's. If nobody has, it is probably
more to do with nobody seeing the need of such than because it can't be
done.
I suspect that the advantages of an interactive system are much less for
languages like Java that have static type declarations.
I don't mean to bash Java - I think it has it's place as well, but I
mean to note that Java is very carefully marketed whereas Python's image is
not managed by a major, international corporation.
Exactly. And that's why I think it does Python no favours at all to
keep emphasising the interpreter over the compiler. It gives too many
people the wrong idea.