Transcrypt icon indicating copy to clipboard operation
Transcrypt copied to clipboard

Error in evaluation of function default arguments

Open faerot opened this issue 5 years ago • 3 comments

x = []

for i in range(5):
    x.append(lambda i=i: print(i))

for c in x:
    c()

python output:

0
1
2
3
4

javascript output:

undefined
undefined
undefined
undefined
undefined

The problem is transcrypt postpones evaluation of default arguments to inside function:

export var x = [];
for (var i = 0; i < 5; i++) {
    x.append ((function __lambda__ (i) {
        if (typeof i == 'undefined' || (i != null && i.hasOwnProperty ("__kwargtrans__"))) {;
            var i = i;
        };
        return print (i);
    }));
}
for (var c of x) {
    c ();
}

To fix it we need to wrap function declaration in another closure and have default values locked inside that function call like this:

export var x = [];
for (var i = 0; i < 5; i++) {
    x.append (
    (function() {
        var default_i = i;
        return (function __lambda__ (i) {
            if (typeof i == 'undefined' || (i != null && i.hasOwnProperty ("__kwargtrans__"))) {
                var i = default_i;
            };
            return print (i);
        });
    })()
    
    );
}
for (var c of x) {
    c ();
}

faerot avatar Jul 03 '19 14:07 faerot

Ok, looks like it was already reviewed 3 years ago here: https://github.com/QQuick/Transcrypt/issues/36 and it was suggested to consider it a transcrypt "limitation", but what about my suggested solution above? This requires minimal overhead but should provide correct behavior with python.

faerot avatar Jul 03 '19 14:07 faerot

I find the current limitation very annoying and will take a good look at your solution!

JdeH avatar Aug 14 '19 11:08 JdeH

Is there any update on this issue? This basically prevents using partially evaluated functions to pass around as values. In my usage this is pretty worrysome!

trenta3 avatar Jul 16 '21 18:07 trenta3