Re: Any SML coders able to translate this to Python?
On Fri, 07 Sep 2018 15:10:10 +0100, Paul Moore wrote: > On Fri, 7 Sep 2018 at 14:06, Steven D'Aprano > wrote: [...] >> However I have a follow up question. Why the "let" construct in the >> first place? Is this just a matter of principle, "put everything in its >> own scope as a matter of precautionary code hygiene"? Because I can't >> see any advantage to the inner function: > > My impression is that this is just functional programming "good style". > As you say, it's not needed, it's just "keep things valid in the > smallest range possible". Probably also related to the mathematical > style of naming sub-expressions. Also, it's probably the case that in a > (compiled) functional language like SML, the compiler can optimise this > to avoid any actual inner function, leaving it as nothing more than a > temporary name. I guessed it would be something like that. Thanks Paul, and especially Marko for going above and beyond the call of duty with his multiple translations into functional-style Python, and everyone else who answered. -- Steven D'Aprano "Ever since I learned about confirmation bias, I've been seeing it everywhere." -- Jon Ronson -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
Marko Rauhamaa : > def f(n): > def auxf1(sum, m, i): > if i == n: > return sum > else: > def auxf2(sum, m, i): > if sum % m == 0: > return auxf1(sum, m + 1, i) > else: > return auxf1(sum, m, i) > return auxf2(sum + m * i, m, i + 1) > return auxf1(0, 1, 0) > > cheating slightly with locally named functions. > > If cheating is not allowed, you will need a Y combinator construct... ... and here's the same function without cheating: f = (lambda n: (lambda auxf1, auxf2: auxf1(auxf1, auxf2, 0, 1, 0))( lambda auxf1, auxf2, sum, m, i: sum if i == n else auxf2(auxf1, auxf2, sum + m * i, m, i + 1), lambda auxf1, auxf2, sum, m, i: auxf1(auxf1, auxf2, sum, m + 1, i) if sum % m == 0 else auxf1(auxf1, auxf2, sum, m, i))) ... or replacing the conditional with arrays: f = (lambda n: (lambda auxf1, auxf2: auxf1(auxf1, auxf2, 0, 1, 0))( lambda auxf1, auxf2, sum, m, i: [lambda m: auxf2(auxf1, auxf2, sum + m * i, m, i + 1), lambda m: sum][i == n](m), lambda auxf1, auxf2, sum, m, i: [lambda m: auxf1(auxf1, auxf2, sum, m, i), lambda m: auxf1(auxf1, auxf2, sum, m + 1, i)][sum % m == 0](m))) It is possible to get rid of the arrays and numbers, too. Combinatory logic would allow us to get rid of the local variables. At the pinnacle of functional programming is iota: https://en.wikipedia.org/wiki/Iota_and_Jot> The iota programming language has only one primitive value, the Swiss-army-knife function ι, which can express Life, Universe and Everything: ι = lambda f: (f(lambda x: lambda y: lambda z: (x(z))(y(z( lambda q: lambda i: q) Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
Paul Moore : > On Fri, 7 Sep 2018 at 15:10, Paul Moore wrote: >> >> On Fri, 7 Sep 2018 at 14:06, Steven D'Aprano >> wrote: >> > However I have a follow up question. Why the "let" construct in the >> > first place? Is this just a matter of principle, "put everything in >> > its own scope as a matter of precautionary code hygiene"? Because I >> > can't see any advantage to the inner function: >> >> My impression is that this is just functional programming "good >> style". [...] > > It's also worth noting that functional languages don't typically have > variables or assignments (more accurately, such things aren't > fundamental to the programming model the way they are in imperative > languages). So although technically let introduces a new scope, in > practical terms it's basically just "how functional programmers do > assignments". To put it succinctly, SML does it because there's no other way to introduce local variables. IOW, in many functional programming languages, the only local variables are function arguments. And if you want to go really functional, you can't even alter bindings. So to implement a for loop in Python under these constraints, you would implement: def f(n): sum = 0 m = 1 for i in range(n): sum += m * i if sum % m == 0: m += 1 return sum like this: def f(n): def auxf1(sum, m, i): if i == n: return sum else: def auxf2(sum, m, i): if sum % m == 0: return auxf1(sum, m + 1, i) else: return auxf1(sum, m, i) return auxf2(sum + m * i, m, i + 1) return auxf1(0, 1, 0) cheating slightly with locally named functions. If cheating is not allowed, you will need a Y combinator construct... Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
On Fri, 7 Sep 2018 at 15:10, Paul Moore wrote: > > On Fri, 7 Sep 2018 at 14:06, Steven D'Aprano > wrote: > > > > On Thu, 06 Sep 2018 13:48:54 +0300, Marko Rauhamaa wrote: > > > > > Chris Angelico : > > >> The request was to translate this into Python, not to slavishly imitate > > >> every possible semantic difference even if it won't actually affect > > >> behaviour. > > > > > > I trust Steven to be able to refactor the code into something more > > > likable. His only tripping point was the meaning of the "let" construct. > > > > Thanks for the vote of confidence :-) > > > > However I have a follow up question. Why the "let" construct in the first > > place? Is this just a matter of principle, "put everything in its own > > scope as a matter of precautionary code hygiene"? Because I can't see any > > advantage to the inner function: > > My impression is that this is just functional programming "good > style". As you say, it's not needed, it's just "keep things valid in > the smallest range possible". Probably also related to the > mathematical style of naming sub-expressions. Also, it's probably the > case that in a (compiled) functional language like SML, the compiler > can optimise this to avoid any actual inner function, leaving it as > nothing more than a temporary name. It's also worth noting that functional languages don't typically have variables or assignments (more accurately, such things aren't fundamental to the programming model the way they are in imperative languages). So although technically let introduces a new scope, in practical terms it's basically just "how functional programmers do assignments". Paul -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
On 2018-09-07, Steven D'Aprano wrote: > On Thu, 06 Sep 2018 13:48:54 +0300, Marko Rauhamaa wrote: > >> Chris Angelico : >>> The request was to translate this into Python, not to slavishly imitate >>> every possible semantic difference even if it won't actually affect >>> behaviour. >> >> I trust Steven to be able to refactor the code into something more >> likable. His only tripping point was the meaning of the "let" construct. > > Thanks for the vote of confidence :-) > > However I have a follow up question. Why the "let" construct in > the first place? Is this just a matter of principle, "put > everything in its own scope as a matter of precautionary code > hygiene"? Because I can't see any advantage to the inner > function: let is a convenient way for functional languages to introduce new names for things. You'd consider it wherever you'd consider assigning something to a new name in Python. In this case, it was probably just to avoid writing out that square root calculation twice. Though you could use lambda calculus directly instead, that might be considered painful, and the first thing you'd then do is write a let macro. -- Neil Cerutti -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
On Fri, 7 Sep 2018 at 14:06, Steven D'Aprano wrote: > > On Thu, 06 Sep 2018 13:48:54 +0300, Marko Rauhamaa wrote: > > > Chris Angelico : > >> The request was to translate this into Python, not to slavishly imitate > >> every possible semantic difference even if it won't actually affect > >> behaviour. > > > > I trust Steven to be able to refactor the code into something more > > likable. His only tripping point was the meaning of the "let" construct. > > Thanks for the vote of confidence :-) > > However I have a follow up question. Why the "let" construct in the first > place? Is this just a matter of principle, "put everything in its own > scope as a matter of precautionary code hygiene"? Because I can't see any > advantage to the inner function: My impression is that this is just functional programming "good style". As you say, it's not needed, it's just "keep things valid in the smallest range possible". Probably also related to the mathematical style of naming sub-expressions. Also, it's probably the case that in a (compiled) functional language like SML, the compiler can optimise this to avoid any actual inner function, leaving it as nothing more than a temporary name. Paul -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
On Thu, 06 Sep 2018 13:48:54 +0300, Marko Rauhamaa wrote: > Chris Angelico : >> The request was to translate this into Python, not to slavishly imitate >> every possible semantic difference even if it won't actually affect >> behaviour. > > I trust Steven to be able to refactor the code into something more > likable. His only tripping point was the meaning of the "let" construct. Thanks for the vote of confidence :-) However I have a follow up question. Why the "let" construct in the first place? Is this just a matter of principle, "put everything in its own scope as a matter of precautionary code hygiene"? Because I can't see any advantage to the inner function: 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)) Sure, it ensures that r is in its own namespace. But why is that an advantage in a function so small? Perhaps its a SML functional- programming thing. Putting aside the observation that recursion may not be the best way to do this in Python, I don't think that the inner function is actually needed. We can just write: def isqrt(n): if n == 0: return 0 else: r = isqrt(n//4) if n < (2*r+1)**2: return 2*r else: return 2*r+1 By the way I got this from this paper: https://www.cs.uni-potsdam.de/ti/kreitz/PDF/03cucs-intsqrt.pdf -- Steven D'Aprano "Ever since I learned about confirmation bias, I've been seeing it everywhere." -- Jon Ronson -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
Chris Angelico : > The request was to translate this into Python, not to slavishly > imitate every possible semantic difference even if it won't actually > affect behaviour. I trust Steven to be able to refactor the code into something more likable. His only tripping point was the meaning of the "let" construct. Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
On Thu, Sep 6, 2018 at 7:22 PM, Antoon Pardon wrote: > On 06-09-18 10:50, Chris Angelico wrote: >> On Thu, Sep 6, 2018 at 6:44 PM, Marko Rauhamaa wrote: >>> Chris Angelico : >>> On Thu, Sep 6, 2018 at 2:29 PM, Marko Rauhamaa wrote: > Marko Rauhamaa (Marko Rauhamaa): >> Steven D'Aprano : >>> 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
Re: Any SML coders able to translate this to Python?
On 06-09-18 10:50, Chris Angelico wrote: > On Thu, Sep 6, 2018 at 6:44 PM, Marko Rauhamaa wrote: >> Chris Angelico : >> >>> On Thu, Sep 6, 2018 at 2:29 PM, Marko Rauhamaa wrote: Marko Rauhamaa (Marko Rauhamaa): > Steven D'Aprano : >> 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 -- Antoon. -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
Chris Angelico : > On Thu, Sep 6, 2018 at 6:44 PM, Marko Rauhamaa wrote: > 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? We can debate what the inner function is achieving. The main point is that functional languages create an inner function for each "let" statement. Steve was wondering what "let" meant, and the Python code--I hope--helped illustrate it. Typical Scheme code is riddled with inner functions. Local variables? An inner function. A loop? An inner function. Exception handling? An inner function. Scheme can also be written procedurally through macros, but those macros generate inner functions. Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
On Thu, Sep 6, 2018 at 6:44 PM, Marko Rauhamaa wrote: > Chris Angelico : > >> On Thu, Sep 6, 2018 at 2:29 PM, Marko Rauhamaa wrote: >>> Marko Rauhamaa (Marko Rauhamaa): Steven D'Aprano : > 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
Re: Any SML coders able to translate this to Python?
Chris Angelico : > On Thu, Sep 6, 2018 at 2:29 PM, Marko Rauhamaa wrote: >> Marko Rauhamaa (Marko Rauhamaa): >>> Steven D'Aprano : 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. Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
On Thu, Sep 6, 2018 at 2:29 PM, Marko Rauhamaa wrote: > Marko Rauhamaa (Marko Rauhamaa): >> Steven D'Aprano : >>> 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? ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
Marko Rauhamaa (Marko Rauhamaa): > Steven D'Aprano : >> 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)) Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
Steven D'Aprano : > 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 > > > I've tried reading up on SML and can't make heads or tails of the > "let...in...end" construct. > > > The best I've come up with is this: > > def isqrt(n): > if n == 0: > return 0 > else: > r = isqrt(n/4) > if n < (2*r+1)**2: > return 2*r > else: > return 2*r+1 > > but I don't understand the let ... in part so I'm not sure if I'm doing > it right. 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() (Also use // instead of /: isqrt = integer square root.) Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
On Tue, 4 Sep 2018 at 13:31, Steven D'Aprano wrote: > > 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 > > > I've tried reading up on SML and can't make heads or tails of the > "let...in...end" construct. > > > The best I've come up with is this: > > def isqrt(n): > if n == 0: > return 0 > else: > r = isqrt(n/4) > if n < (2*r+1)**2: > return 2*r > else: > return 2*r+1 > > but I don't understand the let ... in part so I'm not sure if I'm doing > it right. I've not used SML much, but what you have looks right. let ... in is basically a local binding "let x = 12 in x+2" is saying "the value of x+2 with x set to 12". As I'm sure you realise (but I'll add it here for the sake of any newcomers who read this), the recursive approach is not natural (or efficient) in Python, whereas it's the natural approach in functional languages like SML. In Python an iterative solution would be better. Paul -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
On 2018-09-04 14:26, Steven D'Aprano wrote: > 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 > > > I've tried reading up on SML and can't make heads or tails of the > "let...in...end" construct. I don't know SML specifically, but my guess would be that let X = Y in A end means "A, evaluated in a local scope where X refers to Y". Reasoning: often (e.g. in JavaScript), 'let' sets something in a local scope, and I think Haskell has a construct like this? It's been a while since I played around with Haskell though... In an as-direct-as-possible Python translation, (lambda X=Y: A)() So, isqrt = (lambda n: 0 if n == 0 else (lambda r=isqrt(n//4): 2*r if n < (2*r+1)**2 else 2*r+1)()) This is obviously the same as your multi-expression function, with the addition of the integer division as suggested by Marko. Cheers, Thomas > > The best I've come up with is this: > > def isqrt(n): > if n == 0: > return 0 > else: > r = isqrt(n/4) > if n < (2*r+1)**2: > return 2*r > else: > return 2*r+1 > > but I don't understand the let ... in part so I'm not sure if I'm doing > it right. > > -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
Steven D'Aprano : > 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 > > > I've tried reading up on SML and can't make heads or tails of the > "let...in...end" construct. > > > The best I've come up with is this: > > def isqrt(n): > if n == 0: > return 0 > else: > r = isqrt(n/4) > if n < (2*r+1)**2: > return 2*r > else: > return 2*r+1 > > but I don't understand the let ... in part so I'm not sure if I'm doing > it right. 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() (Also use // instead of /: isqrt = integer square root.) Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Any SML coders able to translate this to Python?
On Tue, 4 Sep 2018 at 13:31, Steven D'Aprano wrote: > > 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 > > > I've tried reading up on SML and can't make heads or tails of the > "let...in...end" construct. > > > The best I've come up with is this: > > def isqrt(n): > if n == 0: > return 0 > else: > r = isqrt(n/4) > if n < (2*r+1)**2: > return 2*r > else: > return 2*r+1 > > but I don't understand the let ... in part so I'm not sure if I'm doing > it right. I've not used SML much, but what you have looks right. let ... in is basically a local binding "let x = 12 in x+2" is saying "the value of x+2 with x set to 12". As I'm sure you realise (but I'll add it here for the sake of any newcomers who read this), the recursive approach is not natural (or efficient) in Python, whereas it's the natural approach in functional languages like SML. In Python an iterative solution would be better. Paul -- https://mail.python.org/mailman/listinfo/python-list