osdir.com

# Any SML coders able to translate this to Python?

```On Thu, Sep 6, 2018 at 7:22 PM, Antoon Pardon <antoon.pardon at vub.be> wrote:
> On 06-09-18 10:50, Chris Angelico wrote:
>> On Thu, Sep 6, 2018 at 6:44 PM, Marko Rauhamaa <marko at pacujo.net> wrote:
>>> Chris Angelico <rosuav at gmail.com>:
>>>
>>>> On Thu, Sep 6, 2018 at 2:29 PM, Marko Rauhamaa <marko at pacujo.net> wrote:
>>>>> Marko Rauhamaa <marko at pacujo.net> (Marko Rauhamaa):
>>>>>> Steven D'Aprano <steve+comp.lang.python at 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

```