[racket] making Racket code more idiomatic

From: Maxim Romashchenko (max at anahoret.com)
Date: Wed Apr 18 08:33:10 EDT 2012

What about for*/set ?

#lang racket
(require racket/set)
(define (generate-powers lower upper)
   (for*/set ([a (in-range lower (add1 upper))]
              [b (in-range lower (add1 upper))])
             (expt a b)))
(set-count (generate-powers 2 5))
(set-count (generate-powers 2 100))

Best regards, Maxim.


On 2012-04-17 21:01, Cristian Esquivias wrote:
> I used Project Euler to try out new languages as well. Here was my
> attempt at Problem 29 for reference.
>
> (define (prob29 a b)
>    (set-count
>     (for*/fold
>         ([nums (set)])
>       ([i (in-range 2 (add1 a))]
>        [j (in-range 2 (add1 b))])
>       (values (set-add nums (expt i j))))))
>
>
> - Cristian
>
> On Tue, Apr 17, 2012 at 9:54 AM, Matthew Flatt<mflatt at cs.utah.edu>  wrote:
>> 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
>> ____________________
>>   Racket Users list:
>>   http://lists.racket-lang.org/users
>
> ____________________
>    Racket Users list:
>    http://lists.racket-lang.org/users

Posted on the users mailing list.