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. So a much more idiomatic translation would be to simply ensure that the inner variable can't collide, and then ignore the function boundary. And I'm not sure if there even is a name collision. What's the issue with scoping at all here? What's the inner function actually achieving? ChrisA -- https://mail.python.org/mailman/listinfo/python-list