flexxui / pscript

Python to JavaScript compiler
http://pscript.readthedocs.io
BSD 2-Clause "Simplified" License
260 stars 25 forks source link

Error with join method #51

Closed ed2050 closed 3 years ago

ed2050 commented 3 years ago

Found what seems to be a pscript bug. My code has the following convenience function:

def css (rules, important = false) :
    'turn a dict of { property : value } pairs into css styles'
    decs = []
    imp = important and '!important' or ''
    for k,v in rules.items () :
        decs += '%s: %s %s; ' % (k, v, imp)
    return ''.join (decs)

Running this code gives the following error:

myapp.js:199 Uncaught TypeError: x.join is not a function
    at String._pymeth_join (myapp.js:199)
    at flx_css (myapp.js:369)

Which traces to this bit of transpiled code in myapp.js (line nums shown):

197: var _pymeth_join = function (x) { // nargs: 1
198:     if (this.constructor !== String) return this.join.apply(this, arguments);
199:     return x.join(this);  // call join on the list instead of the string.
200: };
...
369:     return _pymeth_join.call("", decs);

Not sure what the problem is. What I do notice:

  1. My code calls join on a string with a list as argument.
  2. The pymeth_join code seems to do the same. Line 369 would indicate "this" is a string and x is a list (array) when pymeth_join is called.
  3. Line 199 should thus be calling array.join (string). Which is valid js and should work. Not sure why the error says "x.join is not a function".

My python code is valid and works in cpython. It should work in pscript. Not sure why it doesn't.

I did find a workaround for pscript. Changing the inner loop from += to append fixes the problem with pscript. Which is better practice anyway, since list += string adds each character as a separate list item (this is very old code, prob >10 years). So I did "solve" it. But the original code should still work, even if suboptimal. Seems like a bug in pscript.

almarklein commented 3 years ago

I think you meant: decs += -> decs.append(...)

almarklein commented 3 years ago

To expand a bit: in JS you can add a list and a string (sigh) and the result will be a string. The _pymeth_join comes from PScript, and it performs the join using the JS Array.join, but this fails because the argument is not an array, but a string.

ed2050 commented 3 years ago

Yes that code would have been better. Both work in python though.

Thanks for the explanation. It still seems like an issue with pscript to me. Regardless of funky js conversions, the behavior is different from python and will surprise people.

How about mentioning it in the docs under Caveats? To avoid adding list + str because it =str in pscript instead of =list in python. Thanks for your help.

almarklein commented 3 years ago

Well in Python you cannot add a list or a string: you'd get error. So it's not surprising that it actually works, which I think is the JavaScript shining through section.

ed2050 commented 3 years ago

We're talking about two different things. 🙂 My code does += while you're talking about straight +. list += str does in fact work. In cpython 3.8:

l = []

l += 'abc'

l

['a', 'b', 'c']

You're correct that straight + doesn't work:

[] + 'abc'

Traceback (most recent call last):

File "", line 1, in

TypeError: can only concatenate list (not "str") to list

It's very odd that += works when + doesn't, but that's cpython behavior. Almost as weird as adding each character as a separate list element. But that's python. 🤷‍♂️

My point is that it should be documented somewhere that += has different behavior in pscript. You know better than me where that goes.

I haven't tested list + str in pscript. If that results in a string, ok. As you said, that's a case where javascript "works"... if you consider that working behavior. 😉

On Sat, Jan 2, 2021 at 8:28 PM Almar Klein notifications@github.com wrote:

Well in Python you cannot add a list or a string: you'd get error. So it's not surprising that it actually works, which I think is the JavaScript shining through section.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/flexxui/pscript/issues/51#issuecomment-753519061, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIKNAOFMLPS6FGVSCQQPQNLSX5XV7ANCNFSM4VIG4WWA .

almarklein commented 3 years ago

I think I was not really aware that you could do some_list += some_iterable ! I'm not sure whether I like this feature much though :P the asymmetry with + is indeed surprising.

In that case, yes, we should document this.

almarklein commented 3 years ago

done