On Thu, Sep 6, 2018 at 7:22 PM, Antoon Pardon <antoon.par...@vub.be> wrote: > On 06-09-18 10:50, Chris Angelico wrote: >> On Thu, Sep 6, 2018 at 6:44 PM, Marko Rauhamaa <ma...@pacujo.net> wrote: >>> Chris Angelico <ros...@gmail.com>: >>> >>>> On Thu, Sep 6, 2018 at 2:29 PM, Marko Rauhamaa <ma...@pacujo.net> wrote: >>>>> Marko Rauhamaa <ma...@pacujo.net> (Marko Rauhamaa): >>>>>> Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info>: >>>>>>> I have this snippet of SML code which I'm trying to translate to Python: >>>>>>> >>>>>>> fun isqrt n = if n=0 then 0 >>>>>>> else let val r = isqrt (n/4) >>>>>>> in >>>>>>> if n < (2*r+1)^2 then 2*r >>>>>>> else 2*r+1 >>>>>>> end >>>>>> [...] >>>>>> You must make sure "r" doesn't leak outside its syntactic context so: >>>>>> >>>>>> def isqrt(n): >>>>>> if n == 0: >>>>>> return 0 >>>>>> else: >>>>>> def f2398478957(): >>>>>> r = isqrt(n//4) >>>>>> if n < (2*r+1)**2: >>>>>> return 2*r >>>>>> else: >>>>>> return 2*r+1 >>>>>> return f2398478957() >>>>> Actually, this is a more direct translation: >>>>> >>>>> def isqrt(n): >>>>> if n == 0: >>>>> return 0 >>>>> else: >>>>> def f2398478957(r): >>>>> if n < (2*r+1)**2: >>>>> return 2*r >>>>> else: >>>>> return 2*r+1 >>>>> return f2398478957(isqrt(n//4)) >>>>> >>>> I don't understand why you created that nested function instead of >>>> something simple like renaming the variable. Is there a difference >>>> here? >>> Yes, in understanding the semantics of "let." >>> >>> "let" is used to introduce local bindings in some functional programming >>> languages. I must admit I'm not fully versed in ML but it looks like the >>> analogue in Lisp variants. This is how the above function would be >>> written in Scheme: >>> >>> (define (isqrt n) >>> (if (= n 0) >>> 0 >>> (let ((r (isqrt (quotient n 4)))) >>> (if (< n (expt (1+ (* 2 r)) 2)) >>> (* 2 r) >>> (1+ (* 2 r)))))) >>> >>> Now, Lisp's "let" can be implemented/defined using "lambda": >>> >>> (let ((X A) (Y B) ...) . BODY) >>> >>> => >>> >>> ((lambda (X Y ...) . BODY) A B ...) >>> >>> which gives us: >>> >>> (define (isqrt n) >>> (if (= n 0) >>> 0 >>> ((lambda (r) >>> (if (< n (expt (1+ (* 2 r)) 2)) >>> (* 2 r) >>> (1+ (* 2 r)))) >>> (isqrt (quotient n 4))))) >>> >>> Python does have a limited form of "lambda" and even a conditional >>> expression so--as others have mentioned--this particular function could >>> be translated pretty directly into Python using its lambda. >>> >>> More generally and idiomatically, though, Python's functions are named. >>> So that explains the version I give above. >> And even more idiomatically, Python doesn't require a new scope just >> for a new variable. > > You may have overlooked where Marko wrote: > Actually, this is a more *direct* translation
That was *after* stating this: > You must make sure "r" doesn't leak outside its syntactic context so: Why "must"? The request was to translate this into Python, not to slavishly imitate every possible semantic difference even if it won't actually affect behaviour. If there were some way in which the name actually HAD to be kept scoped in, then sure - maybe a name collision or something - but I can't see that here. So by insisting that the translation maintain an unnecessary inner function, Marko is distracting from a logical and semantic translation of the behaviour of the function. Unless I'm missing something, and there actually IS a good reason for the inner function, other than "well, that's how it works in the source language". ChrisA -- https://mail.python.org/mailman/listinfo/python-list