Skip to content

Non-literal list concatenation and sorting: TypeError: t.py_sort is not a function #679

Closed

Description

@darthglowball

Hi,

sorting a non-literal concatenated list causes the error: TypeError: t.py_sort is not a function. While the lists are literals, the concatenation is done by variables and the plus operator.

a = [5,6,7]
b = [8,9,10]
t = a + b
t.sort()
print(t)

Activity

  1. vkbsb commented on Oct 4, 2019

    @vkbsb

    have you tried t.js_sort() instead?

  2. darthglowball commented on Oct 4, 2019

    @darthglowball
    Author

    @vkbsb no, thanks, but I fixed it with some after-processing on the Javascript by changing a + b to a.concat(b) while keeping py_sort. But it's still a Transcrypt bug. I want to keep my code as Pythonic as possible, so I think using a js_sort would defeat that purpose (maybe not for this example, but for others).

  3. fzzylogic commented on Oct 5, 2019

    @fzzylogic

    @darthglowball You may want to enabe operator overloading when compiling (using -o switch for global, or pragma('opov') for local).

  4. darthglowball commented on Oct 5, 2019

    @darthglowball
    Author

    @fzzylogic something happens now, but in Firefox I get the incorrect result [10, 5, 6, 7, 8, 9]. Nevermind my after-processing solution with a.concat(b): it produces the same incorrect result. Same with using Javascript's .sort() without imported Transcrypt variables. Looks like Javascript has this way of sorting that I don't understand.

  5. darthglowball commented on Oct 5, 2019

    @darthglowball
    Author

    Even with the -o switch, you get a py_sort in the generated code:

    (function () {
    	var __accu0__ = t;
    	return __call__ (__accu0__.py_sort, __accu0__);
    }) ();
    

    That doesn't behave like a Python sort (see previous post).

  6. AlexECX commented on Oct 26, 2019

    @AlexECX

    In the transcrypt runtime.js the sort function used is the javascript .sort() (__sort__ function, Line:1976). The problem is that, in javascript, .sort() treats strings and/or numbers as strings and sort alphabetically. To correct this, Line:1976 should be changed from:
    iterable.sort ();
    to:
    iterable.sort ((a,b) => a > b ? 1 : -(1));

    Even better would be to change Line:1972 and Line:1976 to use __gt__(a,b) instead of a > b.

    @darthglowball incidentally, .py_sort will branch to a code section that does exactly what this fix will do when using the key parameter of the python .sort(). Using t.sort(lambda a:a) will sort correctly.

  7. AlexECX commented on Oct 28, 2019

    @AlexECX

    related to #605

  8. AlexECX commented on Oct 28, 2019

    @AlexECX

    More precisely in transcrypt/modules/org/transcrypt/__runtime__.py:

    107| iterable.sort () # JavaScript sort
    could be :
    107| iterable.sort (lambda a, b: 1 if a > b else -1)

    Output:

    > [10,1,2,20,9].sort()
     [1, 2, 9, 10, 20]
    
    > ["10","1","2","20","9"].sort()
    ["1", "10", "2", "20", "9"]
    
  9. darthglowball commented on Oct 28, 2019

    @darthglowball
    Author

    @AlexECX yes, Python t.sort() maps to Javascript t.sort(function(a,b){return a>b}) but while Transcrypt allows a positional or keyword argument in sort, it should be a keyword argument in Python 2.7.16 & 3.7.2.

  10. AlexECX commented on Oct 28, 2019

    @AlexECX

    @AlexECX yes, Python t.sort() maps to Javascript t.sort(function(a,b){return a>b}) but while Transcrypt allows a positional or keyword argument in sort, it should be a keyword argument in Python 2.7.16 & 3.7.2.

    Currently Transcrypts .sort() maps to Javascript's .sort(), which is why it sorts alphabetically. Mapping it to .sort ((a,b) => a > b ? 1 : -(1)) instead will resolve the sorting order. (Note that .sort(function(a,b){return a>b}) has the same problem, at least in chrome).

    I believe the Transcrypt sort() signature is practically the same as Python's (key = None, reverse = False), but currently the arguments are not passed properly (see #687).

  11. darthglowball commented on Oct 29, 2019

    @darthglowball
    Author

    @AlexECX you're right about Chrome giving the incorrect result with .sort(function(a,b){return a>b}). Same problem with Opera. Firefox does it correctly. .sort ((a,b) => a > b ? 1 : -(1)) works on all three. Good catch.

  12. self-assigned this
    on Jul 5, 2024
  13. JennaSys commented on Jul 6, 2024

    @JennaSys
    Collaborator

    More precisely in transcrypt/modules/org/transcrypt/__runtime__.py:

    107| iterable.sort () # JavaScript sort could be : 107| iterable.sort (lambda a, b: 1 if a > b else -1)

    This has been implemented in the dev_3.9.3 branch to be released in v3.9.3

  14. JennaSys commented on Jul 17, 2024

    @JennaSys
    Collaborator

    Merged to master on PR #876

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions