[racket] making Racket code more idiomatic

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Tue Apr 17 12:54:01 EDT 2012

Blindly refactoring the code, I'd use `for/fold' and add a `lst'
accumulator to `loop':

(define (euler29c)
  ; calculate 99^2 - duplicates
  (- (sqr 99)
     (for/sum ([d '(2 3 5 6 7 10)])
       (let loop ([lst '()] [exp 1])
         (if (> (expt d exp) 100) 
             (- (length lst) (length (remove-duplicates lst)))
             (loop (for/fold ([lst lst]) ([i (in-range 2 101)])
                     (cons (* i exp) lst))
                   (add1 exp)))))))

At Tue, 17 Apr 2012 09:45:50 -0700, Joe Gilray wrote:
> Hi,
> 
> To continue our conversation about creating idiomatic Racket code, here is
> some code I wrote last night to solve projecteuler.net problem #29:
> 
> (define (euler29a)
>   ; calculate 99^2 - duplicates
>   (- (sqr 99)
>      (for/sum ([d '(2 3 5 6 7 10)])
>               (let ([lst '()])
>                 (let loop ([exp 1])
>                   (if (> (expt d exp) 100) (- (length lst) (length
> (remove-duplicates lst)))
>                       (begin
>                         (for ([i (in-range 2 101)]) (set! lst (cons (* i
> exp) lst)))
>                         (loop (add1 exp)))))))))
> 
> It's fast (it avoids calculating a bunch of huge numbers), it gives the
> correct answer, so what's not to love?!
> 
> Well, it starts off OK, but my eye stumbles over the following:
> 
> 1) predeclaring lst and accessing it twice, related to each other
> 2) ugly single parameter named-let loop
> 3) ugly "begin" - not a big deal, but I just dislike when having to use
> begin
> 4) use of set!
> 
> Here is a quick rewrite:
> 
> (define (euler29b)
>   ; calculate 99^2 - duplicates
>   (- (sqr 99)
>      (for/sum ([d '(2 3 5 6 7 10)])
>               (let ([lst '()])
>                 (do ([exp 1 (add1 exp)])
>                   ((> (expt d exp) 100) (- (length lst) (length
> (remove-duplicates lst))))
>                   (for ([i (in-range 2 101)]) (set! lst (cons (* i exp)
> lst))))))))
> 
> It solves #2 and #3 above, but it is still fundamentally clunky.
> 
> Can someone help and teach us all some tricks?  My instincts say it should
> be possible to use append-map, for/list and/or foldl to build a list of the
> duplicates then simply count them in the for/sum loop, but am still unable
> to do it.
> 
> Thanks,
> -Joe
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users

Posted on the users mailing list.