I don't think one can see `for` in Racket as equivalent to generators in 
Python.

Generators in Python are used when you want to save memory by not producing 
all values at once, but want to go value by value (which to my knowledge 
Racket's `for` variants do not do, but I'd like to be corrected, if I am 
wrong about this, as it would mean, that those `for` are even more awesome 
than I knew.) They are more like lazy possibly infinite lists. I think lazy 
Racket has that and that there was some advice about not calling `length` 
on an infinite list.

Python, I believe, has some kind of `Iterable` interface, which a generator 
satisfies and which specifies the method to call to get the next value. In 
Racket maybe one would have to do with a convention of how to get a next 
value from a lazy list.

I believe something like the following could be an example. I did not yet 
think about macros, nor am I experienced with that, so maybe one can create 
something more elegant than what I am posting:

~~~
#lang racket

;; ================
;; DATA ABSTRACTION
;; ================

;; The value is always the first value of the generator.
(define get-value car)

;; A generator's producing procedure needs to be applied to get the
;; next thing.
(define (get-next a-gen)
  ((cdr a-gen)))

;; A generator is only a tuple containing the current value and the
;; procedure to create the next value
(define (make-gen proc start)
  (cons start
        (lambda ()
          (make-gen proc (proc start)))))

(define STOP-SYMBOL 'none)

;; ========
;; EXAMPLES
;; ========

;; An infinite list of numbers.
(define natural-numbers
  (make-gen (lambda (x) (+ x 1))
            0))

;; A limited list of natural numbers.
(define (limited-natural-numbers limit)
  (make-gen (lambda (x)
              (cond [(< x limit) (+ x 1)]
                    [else STOP-SYMBOL]))
            0))

;; Print a certain amount of natural numbers.
(define (print-natural-numbers natural-numbers limit)
  (let ([current-number (get-value natural-numbers)])
    (cond
      [(and (symbol? current-number) (symbol=? current-number STOP-SYMBOL))
       (displayln "No more numbers available!")]
      [(< current-number limit)
       (displayln current-number)
       (print-natural-numbers (get-next natural-numbers) limit)]
      [else
       (displayln "Done")])))
~~~

Here the conventions are the structure of the generator and the stop 
symbol. In Python those are already taken care of by the standard library's 
generator interface.


On Wednesday, February 20, 2019 at 10:10:16 PM UTC, Jens Axel Søgaard wrote:
>
> Den ons. 20. feb. 2019 kl. 22.25 skrev Dave McDaniel <mcdani...@gmail.com 
> <javascript:>>:
>
>> Hello,
>>
>> I have interest in picking up racket and have done some koans and also 
>> have been doing the racket track on exercism.
>>
>> There is a fairly simple exercise called `etl` on exercism related to 
>> taking a hash for scoring scrabble letters and unpacking it into a flatter, 
>> more efficient structure for lookups.
>>
>> The input hash has score as the key and a list of letters of that score 
>> as the value.  The output is a hash of letter -> score.  One pair per 
>> letter instead of one pair per score.
>>
>> It was easy enough to solve with `for-each` using side-effects to update 
>> a mutable hash, however I think using a generator is a cleaner approach and 
>> doesn't require mutability.  
>>
>
> FWIW here is a solution using immutable hashes. I see `for` and friends as 
> Racket "generators". 
>
> /Jens Axel
>
>
> #lang racket
> (require racket/hash)
>
> ; In Scrabble each letter gives a certain number of points.
> ; In the old data we have for each point a list of numbers,
> ; that awarded the given number of points.
>
> (define old-data
>   ; list of associations from point to list of strings (letters)
>   '((1  "A" "E" "I" "O" "U" "L" "N" "R" "S" "T")
>     (2  "D" "G")
>     (3  "B" "C" "M" "P")
>     (4  "F" "H" "V" "W" "Y")
>     (5  "K")
>     (8  "J" "X")
>     (10 "Q" "Z")))
>
>
> ; Each point list needs to be transformed to a
> ; hash table from letters to points.
>
> (define (transform association)
>   (match association
>     [(list point letters ...)
>      (for/hash ([letter letters])
>        (values (string-downcase letter) point))]))
>
> ; Now we only need to combine the hash lists.
> (define ht
>   (apply hash-union
>        (hash)
>        (for/list ([association old-data])
>          (transform association))))
>
> (define (lookup letter)
>   (hash-ref ht letter #f))
>
> (lookup "e")
> (lookup "x")
>
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to