javascript to python

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Fri Oct 3 06:29:17 EDT 2008


lkcl a écrit :
> On Oct 2, 7:42 pm, Bruno Desthuilliers
> <bdesth.quelquech... at free.quelquepart.fr> wrote:
>> lkcl a écrit :
(snip)

>>> for fits and giggles, compile the above python using
>>> pyjs.py, the python-to-javascript compiler
>>> (seehttp://pyjamas.sf.net) and compare the
>>> resultant javascript to your original code-fragment.
>>> l.
>> I did. Here's the result:
> 
>  ok - these are the "important" bits.  notice that the pyjamas
> compiler is doing a little bit more than your original code:

Not 'mine' - I'm not the OP. And as far as I'm concerned, the point is 
exactly here : it's doing "a little bit more" than the original code. 
This "little bit" requires 6 times the original code (cf below), and is 
actually useless for the OP's use case (else the OP's code wouldn't use 
litteral object notation but a full-blown prototype).

> it's
> overriding the "prototype" of dataListener, making it a true "class"
> object.

There's nothing like a notion of "class" in javascript - as you of 
course already know.

> this is where there's a key departure from the original code and the
> translation to python: the original code isn't actually a class,  at
> all

Indeed. Why would it need to be ?

> - it's more like a.... c struct that has function pointers in it.

It's an object. What's wrong with objects ?

> by declaring a python "class", the javascript equivalent is to add to
> "prototypes".

Indeed. But the point is that Python - while close to a prototype-based 
language in many aspects - is still class-based. The closer Python 
translation of the OP's javascript snippet is probably the one I gave 
using a 'class singleton' - that is, using the class itself as an 
object. But retranslating this to javascript using a 
python-source-to-javascript-source tool like pyjamas won't give you back 
the original javascript snippet (which is by no mean a criticism of 
pyjamas - it would just be way too complicated to automatize such a 
translation).

> 
>>      __dataListener.prototype.__init__ = function() {
>>      var data = '';
>>      };
> 
> [ ... so for example here, now when you declare _any number_ of
> "dataListener"s,

What for ? In the original snippet, there's clearly only a need for a 
single one - and that's a *very* common pattern in browser-side 
javascript scripting. The original snippet is 12 lines, 29 words, 369 
bytes long (according to wc). The pyjamas translation of the Python 
translation of the original javascript snippet  is 49 lines, 126 words, 
2285 bytes long. That's 6 times more code (to download and parse) - for 
an unneeded feature. Often, less is better.

> each and every one will have its __init__ function
> called.  in your original example,

"my" ? I repeat : I'm *not* the OP.

> you're effectively making one and
> only one "dataListener".

s/you/the OP/

And yes, indeed, there's only one dataListener object. What makes you 
think there's a need for more than one ?

>  you're kinda... it's a bit like having a
> lambda-class (nameless class) and declaring one and only one instance
> of that python class... ]

It's like having an object. period. While most OOPLs are class-based, 
classes are by no mean a requirement of OO.

> so - yeah, you can see that (apart from the .prototype, which is
> necessary to make a "class a la javascript") it's a pretty accurate
> translation back to the original javascript.

I don't mean it's not working. I mean that it's a lot of unnecessary 
code for an unnecessary feature. Believe me, 6 times more code makes a 
*huge* difference when it comes to browser-side scripting and 
user-experience.

Also and IMHO, it's trying to forcefit alien idioms in javascript. Being 
prototype-based is by design - it's not a shortcoming.

> 
>> All this, and more, thanks to the strange idea that it would be better
>> to write javascript in Python instead of writing it in javascript !-)
> 
>   *lol* :)   fortunately, pyjs.py does that translation for you ha
> ha.  like they say on brainiac, "STOP!  we do these experiments, so
> you don't have to".

"fortunately" is judgement call. As far as I'm concerned, and despite a 
couple warts (but hey, no language is wart-free, and Python has it's own 
share, isn't it ?), I like javascript as a language, and enjoy coding in 
javascript almost as much as I enjoy coding in Python.

>   yes - it's because in the translated python, dataListener was
> declared as a class, whereas in the original javascript, the
> corresponding concept (prototypes) are not made use of.

There's probably a reason why the OP didn't use a full blown prototype, 
isn't it ?-)

> if you wanted to experiment, you could try this:
> 
> def onStartRequest(this, request, context):
>     pass
> 
> def onStopRequest(this, request, context, status):
>     instream.close()
>     oustream.close()
>     listener.finished(this.data)
> 
> def onDataAvailable(this, request, context,
>                       inputStream, offset, count):
>     this.data += instream.read(count)
> 
> class dataListener:
>     def __init__(self):
>         self.data = ''
>         self.onStartRequest = onStartRequest
>         self.onStopRequest = onStopRequest
>         self.onDataAvailable = onDataAvailable
> 
> which you will find to be more accurately representative of the
> original javascript, conceptually.

Nope. You defined functions outside the object's scope, and you still 
have to instanciate dataListener. Also, this above code just won't work 
- unless you explicitely pass the dataListener instance to the 
functions, ie:

d = dataListener()
d.onDataAvailable(d, ...)

If you want per-instance methods, you have to invoke the descriptor 
protocol by yourself, ie:

class dataListener:
     def __init__(self):
         self.data = ''
         self.onStartRequest = onStartRequest.__get__(self, type(self))
         self.onStopRequest = onStopRequest.__get__(self, type(self))
         self.onDataAvailable = onDataAvailable.__get__(self, type(self))


But that's still not close to the OP's javascript code, and it's not 
pythonic no more.

>  i.e taking into account that in
> the _original_ javascript, you don't have any "prototypes".
 > but - i don't believe it to be what you actually want, even though
 > it's "a slightly more accurate representation".
 >

It seem you didn't read my other translation proprosal, so I repost it here:

class dataListener(object):
    data = ''

    @classmethod
    def onStartRequest(this, request, context):
        pass

    @classmethod
    def onStopRequest(this, request, context, status):
        instream.close()
        oustream.close()
        listener.finished(this.data)

    @classmethod
    def onDataAvailable(this, request, context,
                          inputStream, offset, count):
        this.data += instream.read(count)


This is probably the closest Python translation one can come with 
(javascript's 'this' semantics set aside) - even if it's not idiomatic 
Python.


As you may have guess by now, I'm more than a bit skeptical about 
'language XXX to javascript source' translations[1] - the target is a 
too hi-level language IMHO. I don't mean that everyone should learn and 
love javascript, but I think that targeting VM specific byte-code is a 
way better approach.

[1] which is not a criticism of pyjamas, pypy's python2js compiler etc 
effort - only my very humble opinion.

My 2 cents...



More information about the Python-list mailing list