
Why Are There So Many Pythons? - akbarnama
http://www.toptal.com/python/why-are-there-so-many-pythons
======
Foxboron
I'll give a shoutout too Hy. It removes the Python interface, and replace it
with a LISP interface. The neat part is that its currently compatible, and
bidirectional, with 2.6, 2.7, 3.2, 3.3 and pypy. We even added a few steps so
we will have support for 3.4!

[https://github.com/hylang/hy](https://github.com/hylang/hy)

It's a great example of how Python isn't that different from LLVM and JVM!

~~~
neurostimulant
I wish I knew this sooner! The online console is really cool too: [http://try-
hy.appspot.com/](http://try-hy.appspot.com/)

------
shadowmint

        > It’s fast because it compiles source code to native code 
    

Actually, that's why it's slow. pypy is significantly slower than cpython in
fact, primarily for short-life scripts.

The initial start time can easily double or _triple_ the run time in some
cases.

To be fair, it's only a couple of seconds extra, but for many tiny scripts
this amounts to a lot of wasted time. It's not a magical cure all in all
situations.

...that said, its so fantastically easy to drop in, in most cases its worth
trying to see how it performs just for fun~

    
    
        pypy setup.py install
        pypy app.py
        [INFO              ] Kivy v1.8.0-dev
        [INFO              ] [Logger      ] Record log in /Users/d/.kivy/logs/kivy_14-01-15_2.txt
        [INFO              ] [Factory     ] 156 symbols loaded
        ...
    

(drop in replacement for fun times? without having to change all your print
and import statements? yes please~)

~~~
usefulcat
Sooo... the next logical step would be to add to pypy the ability to produce a
natively executable file? Or has that already been done? (Disclaimer: I know
relatively little about the python ecosystem).

~~~
maxerickson
It hasn't been done. If I understand correctly, it would be more like 'rewrite
pypy to' rather than 'add to pypy'.

Pypy does have tooling to convert a limited subset of python ( they call it
RPython) into an exe.

~~~
sitkack
It isn't that limited. Also take a look at shedskin.
[http://en.wikipedia.org/wiki/Shed_Skin](http://en.wikipedia.org/wiki/Shed_Skin)

------
chowells
Futamura projections would completely blow this guy's mind. It's amazing what
ignorance of computer science causes people to think is new and special.

[http://en.wikipedia.org/wiki/Partial_evaluation#Futamura_pro...](http://en.wikipedia.org/wiki/Partial_evaluation#Futamura_projections)

~~~
ced
Are Futamura projections used anywhere, or are they mostly of theoretical
interest?

~~~
cliffbean
Futamura projections are what PyPy is doing, as described in this blog post.
PyPy uses the first and second projections. In fact, it's likely that the
author is actually familiar with the Futamura projections, but wanted to
describe PyPy in more detail instead of relying on jargon.

~~~
rwallace
Which blog post are you referring to? (Did you forget to add a link?)

~~~
cliffbean
I meant the "Why Are There So Many Pythons" blog post that is the topic of
this conversation.

------
wikwocket
Well, with a habitat that reaches across Africa and Asia, and their ability to
thrive in rain forests and grasslands, there are.... Oh. _Ohhh._ Never mind.

~~~
mjcohen
Also in Florida.

------
pjmlp
Funny that an article written to describe why there are so many Python
implementations, fails when comparing Python with C and Java.

There are quite a few interpreters available for C.

Although Sun/Oracle's implementation is JIT based only, there are other Java
vendors with toolchains that support ahead of time compilation to native code.

~~~
weland
Aye. The article also makes the well-know blunder of asking this question:

> Is Python interpreted or compiled? The question isn't really well-formed.

which is then repeated:

> C compiles to machine code, which is then run directly on your processor.
> Each instruction instructs your CPU to move stuff around.

No, "C" does not "compile" to machine code. The C compiler compiles C, and
sometimes does so to machine code, and there are a C compilers that compile
first to a form of bytecode or other symbolic representation, then to native.
<language> is compiled/interpreted is a sad leftover from the heavily-diluted
introductory computer books in the 1980s.

~~~
tadfisher
I think another source of confusion is that the term "compiler" has gained
this connotation that all compilers generate low-level code from a high-level
source language. However, once you understand the concepts, you realize that
many things are technically compilers; source-to-source translators, for
example, or ORM code generators.

Hell, I would call Python's own 2to3 tool a compiler: it generates a full
parse tree using a grammar, it runs some translation rules, and it generates
Python 3 code.

~~~
xmonkee
There are no compilers. There are translators and optimizers.

~~~
14113
That's the definition of a compiler though, "A compiler is a computer program
(or set of programs) that transforms source code written in a programming
language (the source language) into another computer language (the target
language)."

All a compiler is is a combination of a translator and (possibly - but not
necessarily) an optimiser.

------
obblekk
Why isn't there a branch of python 2.7.2 which introduces the features from
3.x that don't require syntax changes and fixes known bugs in 2.7.2?

I get that these are the reward for upgrading, but it seems unreasonable to
hold back.

~~~
est
> Why isn't there a branch of python 2.7.2 which introduces the features from
> 3.x

Because 2.7 was born for this exact reason.

People use good enough 2.6 and need a bridge version between 2.6 and py3k.
Many py3k features were backported to 2.7 as well.

Now you want bridge over bridge?

~~~
sitkack
That would be bridge-on-bridge technology and I have a patent for that.

------
vezzy-fnord
This is basically an article for beginners that explains the difference
between a language's specification and its actual implementation, using Python
as its illustration.

~~~
m_mueller
The most interesting aspect for me is that I can run Flask / Django in PyPy /
I wasn't aware of this yet.

~~~
erichurkman
You may be missing some specific extensions that are based on C, though. When
I tried it last, the database libs I used were not functional. That said,
there pure-Python database libraries that worked just as well. The performance
loss was negligible -- database IO completely drowned out any measurable loss
in my use case.

~~~
lmm
If performance was dominated by database IO, why use Pypy at all?

~~~
pyre
The parent is referring to the performance of the database driver. The
performance of the database driver doesn't affect the performance of the rest
of the application.

------
fredsanford
"In very brief terms: machine code is much faster, but bytecode is more
portable and secure."

Does anyone else have trouble with that statement?

Maybe it should read "bytecode is more portable and is easier to secure." ?

Java is what, 20 years old and based on bytecode and despite Sun/Oracle's
efforts still has security problems.

~~~
crntaylor
I think you need to parse it as

    
    
      more (portable and secure)
    

rather than

    
    
      (more portable) and secure

~~~
anonymfus
portable and securable

------
rrosen326
Question: This, and many other posts, suggest that PyPy is the way to go (as a
user). Faster and compatible - what's not to like? But elsewhere I read, 'hold
on'. It actually isn't faster with things that use a lot of C optimizations
(like numpy and pandas, which I use extensively). I don't mind small startup
JIT penalties, but I don't want to have my core code run more slowly, or fail.
Is there a simple direction? (ie: Use standard cPython or use PyPy) Or is it,
as always, 'it depends'?

------
carlob

        x = random.choice([1, "foo"])
    

this is given as an example of why Python could never be strongly typed.

Honest question: isn't this solved using Either in Haskell?

~~~
samth
Using Either in Haskell would require changing the program a little to add
injections. But that _exact_ program (modulo syntax) can be written in Typed
Racket:

    
    
        #lang typed/racket
        
        (: choose : (All (A) (Listof A) -> A))
        (define (choose e)
          (list-ref e (random (length e))))
        
        (define x (choose (list 1 "foo")))
    

Unfortunately, people tend to assume that "type systems" and "the type system
in Java/ML/Haskell" have the same level of expressiveness.

~~~
sitkack
I just realized that all programs have types and type systems. Some
dynamically typed programs have hairy n-dimensional fractal type systems that
no human would ever figure out (usually from bad code).

The inferred languages just have this dude that watches your code and says,
"yeah, I understand what is going on, your stuff is internally consistent"

~~~
samth
Well, I don't think that's correct -- it would make the term "type system"
meaningless. In particular, lots of programs have bugs that type systems can
catch.

For more on whether all programs have types, I wrote this:
[https://medium.com/p/8a3b4bedf68c](https://medium.com/p/8a3b4bedf68c)

~~~
sitkack
I don't think it makes the standard definition of "type system" meaningless.
Maybe what I am referring to above is a "type space".

I agree with some of what you said in the medium link. Python does have a type
system, structural and dynamic strong. The way the plus operator works was a
mistake, Lua is superior in this regard.

Take a look at the type inferencing that Shedskin and RPython in PyPy can do.
If there wasn't a type system, how are those 'static strong' programs created?

The programer and the program has a type system where the language may not.

~~~
samth
What is a "type space"?

As I say pretty explicitly in linked post, Python doesn't have a type system.
Also, the term "strong" type system doesn't mean anything. Also^2,
"structural" type systems are about how types are compared, and to whatever
degree Python compares types, it isn't structurally.

RPython is a different programming language, which is statically type.
Shedskin is similar.

~~~
sitkack
[http://stackoverflow.com/questions/2351190/static-dynamic-
vs...](http://stackoverflow.com/questions/2351190/static-dynamic-vs-strong-
weak)

RPython and Shedskin as not different languages, they are subsets. All
programs in RPython and Shedskin are proper python programs with the same
semantics.

~~~
samth
First, as the second answer points out, the terms "strong" and "weak"
shouldn't be used and are confusing.

Second, having a type system makes a language very different! Language subsets
are different languages.

~~~
sitkack
So when I use quickcheck with Python or Erlang I am creating a different
language? Linguistically I don't understand how a proper Shedskin program
which is also a Python program with the same semantics is in another language.
By that definition, the runtime system effects what the language is, but this
happens _after_ it is written, so how can it do that?

~~~
samth
No, quickcheck is a testing tool, not a type system. It never rejects your
program.

What you're saying is that Shedskin and Python have a non-empty intersection.
But would the language of numbers with `+` be the "same language" as Python?
It has the same relationship as Shedskin.

~~~
sitkack
We might run out of reply space.

I made a mistake when I said quickcheck, I was thinking of the combination of
Dialyzer and Typer in Erlang (
[http://www.slideshare.net/konstantinvsorokin/kostis-
sagonas-...](http://www.slideshare.net/konstantinvsorokin/kostis-sagonas-cool-
tools-for-modern-erlang-program-developmen) )

I think I get what you are saying, that you have to take the totality of
language in the current context.

And I would have to say yes, the language of numbers with "+" is in fact
Python. I think it is also Haskell and lots of other languages. If I look at a
corpus of language through a slit, I will always see a subset of that
language. But it doesn't stop being that language by looking at with a
microscope. What happens we see a code snippet like

    
    
      a = 5 + b - 10
    

We don't know what language it is, but it doesn't matter. It is valid
Ruby,Python,Lua,JavaScript, etc.

Are we,me splitting hairs? I am just a layperson, I would like to fix any
discrepancies in my knowledge.

------
DonGateley
"CPython makes it very easy to write C-extensions for your Python code because
in the end it is executed by a C interpreter."

Say what? What C interpreter might that be? In the end it is executed by
machine code compiled from C programs designed so as to implement a Python
virtual machine. Much, much different and much harder to make the intended
connection.

Now why, really, is it easy to write C extensions for your Python code?

~~~
yetanotherphd
Since it is written in C, it is easy for the interpreter to define a C API
that exposes the Python runtime (Python.h). This means python C extensions can
have access to the python runtime.

------
hardwaresofton
Awesome article, I thoroughly enjoyed it -- sent me on a tangent to learn more
about Tracing JIT compilers, RPython (and eventually I started looking for
python-interpreted lisp, haha).

blog posts that helps me understand my tools/ecosystem better (rather than
just harp on some recent happening in SV, for example) is awesome.

~~~
rrosen326
I second this. I read the other comments about the flaws in the article, and
I'll take them as valid. Even barring them, I understand a lot more about the
different types of python and, the different layers in the stack, and even a
bit about compilation, JIT, etc. etc. Imperfect? Maybe. Extremely helpful to
me? Definitely. Thanks!

------
Grue3
That's not many. Most of older languages have even more implementations.

------
grdvnl
Why does one need a Jython Interpreter once the byte code is available for a
JVM. Isn't there the standard java that I can use?

~~~
CmonDev
No built-in dynamic typing support before Java 7.

~~~
grdvnl
Ok, thanks for clarifying that. I just looked it up and learnt than an
interpreter-based approach is another option compared to other ways of
supporting a dynamic typed language( by reflection, base object declaration)

------
bsaul
Since the JVM is also JIT compiled to native, is the jvm python implementation
as fast as pypy ?

------
goodwink
This really should have been written in the form of a parody of Snakes on a
Plane.

------
spacemanmatt
This article lost credibility pretty early for carelessly conflating tokenized
python with Java bytecode. That is unfair to readers that don't already
understand the difference. It's not a trifle.

------
DrJ
TBH there are only 2 versions of Python I feel is worth worrying about/using
2.7 and 3.3

------
CmonDev
"It all starts with an understanding of what ‘Python’ actually is."

It's basically a script language.

~~~
simonw
Using the term "scripting language" to describe things like Python and Ruby
fell out of favour quite a few years ago. Calling something a scripting
language implies that you can't write a full application using it. This has
been proved incorrect a thousand times over.

~~~
stefantalpalaru
> Calling something a scripting language implies that you can't write a full
> application using it

No, it means the language is interpreted instead of being compiled to native
code AOT.

~~~
kyllo
By your definition, Java is a "scripting language" too.

I don't think anyone who's ever programmed in Java would actually consider it
a scripting language.

~~~
stefantalpalaru
You have a point. We need a subset of the interpreted languages. Maybe
something to do with ease of use?

~~~
kyllo
I think that would be a little too squishy.

For me, when most people say "scripting language" they really mean a dynamic
language.

Perl, Ruby, Python, JavaScript, Lisp... These are all considered "scripting"
languages and the main thing they have in common is the dynamic linking and
type systems.

Statically typed languages like Java are generally not used for scripting
purposes.

~~~
stefantalpalaru
I don't think Common Lisp is considered a scripting language, even if it's a
dynamic language. Or Clojure, for that matter.

~~~
kyllo
How about emacs lisp? Would you consider that a scripting language?

~~~
stefantalpalaru
When used like this, yes: [http://www.leancrew.com/all-this/2008/04/emacs-
lisp-as-a-scr...](http://www.leancrew.com/all-this/2008/04/emacs-lisp-as-a-
scripting-language/)

------
wmnwmn
The real question is why is there one python. Perl was already doing
everything python can do and it is pointless to write every supporting library
in 20 different languages. You can write good or bad code in any language; the
language is nearly irrelevant. Of course, I wouldn't propose going to Bourne
shell or something.

~~~
prodigal_erik
It's much harder to write correct software in Perl because there are so many
bugs it doesn't catch. Almost everything converts a string that isn't numeric
to zero instead of dying. ++$a{$x} doesn't even check that %a is initialized,
much less actually has $x as a key. By default syscalls that fail set $?
(which can be ignored and usually is) and don't die, and making them die
breaks a lot of library code that only "works" because it ignores errors. And
the production version _still_ makes ridiculous legacy distinctions like

    
    
      @a = (1, 2, 3); print "@a\n";
      $a = [1, 2, 3]; print "@$a\n";
    

which have no expressive value (if lists and hashes had been first-class
values there'd be no reason for references to exist as a type) but only cause
subtle mistakes.

~~~
justinator
Here's the script:

    
    
        #!/usr/bin/perl 
        use strict; 
    
        ++$a{$x}; 
    

and when run, produces,

    
    
        Global symbol "%a" requires explicit package name at ./test3.pl line 4.
        Global symbol "$x" requires explicit package name at ./test3.pl line 4.
    

So, I'm not sure if I see that point. Are you not a fan of autovivification?
Because it: rules. I think the only thing one has to understand is the use of
exists(), to see if there is, say, a key in a hash, rather than defined():

    
    
        #!/usr/bin/perl 
        use strict; 
    
        my %foo = (batz => undef); 
    
        for (qw(bar batz)){ 
            if(exists($foo{$_})){ 
                print "$_ exists!\n"; 
                if(defined($foo{$_})){ 
                    print "and $_ is defined.\n"; 
                }
                else { 
                    print "and $_ is undefined.\n"; 
                }
            }
            else { 
                print "$_ doesn't actually exist\n"; 
        
            }
        }
    

prints,

    
    
        bar doesn't actually exist
        batz exists!
        and batz is undefined.

~~~
bonemachine
As it happens, hashes in Perl 5 autovivify by default (rather like
defaultdicts in Python). In retrospect, this can seem rather surprising (if
not off-putting) to newcomers, so an argument can be made that a more
conservative default behavior should have been chosen (like the more "hard-
nosed" behavior of standard dicts in Python).

OTOH Perl people tend to like the way we can, for example, create histograms
(and nested structures like graphs) a bit more fluently with autovivifying
hashes, e.g.:

    
    
        my %a;
        for my $x (@x)  { $a{$x}++ }
    

than if we always had to be saying

    
    
        if (exists $a{$x})  {
            $a{$x}++
        }
        else  {
            $a{$x} = 0
        }
    

Or as Perlistas would be more prone to write (if forced to use a non-vivifying
hash):

    
    
        exists $a{$x} ? $a{$x}++ : { $a{$x} = 0 }
    

Or gosh, who knows:

    
    
        $a{$x} = exists $a{$x} ? $a{$x}+1 : 0
    

Or to have sat around and waited for 10 years or so until Hash::Util was
invented (after Perl 4's initial release), provided then you knew to look for
it, and how), at which point you'd finally be able to say:

    
    
        use Hash::Util 'unlock_keys';
    

But as it happens, when Perl 4 first came out, autovivification (and its
cohort, promiscuous ducktyping) were chosen as the default behavior for many
of the language's core constructs (not just hashes and arrays). It's just the
way Perl rolls. Whether it's the "right" tradeoff to make or not, from a
socio-engineering perspective, is an interesting question (and partially a
matter of taste). But in general Perl has been pretty consistent in its
approach to tradeoffs like these.

