Re: [racket-users] Help with generators from python land!

2019-02-20 Thread Jon Zeppieri
On Wed, Feb 20, 2019 at 9:14 PM Dave McDaniel 
wrote:

> Thanks Jon and Jen, This is a great!  I figured there must be a
> straightforward way to do this with a `for/hash` implementation.  I have
> not seen these 2 methods `in-hash` and `in-list` vs just using the hash or
> list without that sequence modifier.  Can you comment on what is going on
> with this `in-xxx` sequence modification?  The docs indicate that you get
> slightly better performance when using these with `for`, but its not clear
> why and in what situations you must use these modifiers rather than the
> underlying list or hash itself--is it always optional?
>

`in-hash` and `in-list` are optional, but, as you noted, they do make
iteration perform better.[*] This is because the various iterators can
generate better code if they know what kind of sequence they're dealing
with. If they don't know, they have to use generic sequence operations,
which are usually quite a lot less efficient. The difference is not slight.
(Do the docs say it is?)

That said, if you're only iterating over a small sequence, you won't notice
or care.

You can see the difference in generated code by using the Macro Stepper in
Dr. Racket. Write something like:
```
#lang racket/base

(define (fast-foo xs)
  (for/list ([x (in-list xs)])
x))

(define (slow-foo xs)
  (for/list ([x xs])
x))
```

Then click on the Macro Stepper button and then click "End" to see the
fully expanded source, and compare the two different versions.

[*] Rather, they make iteration perform better when they're used inside a
`for` loop. Outside of a `for`, they're just normal procedures. Inside,
they are syntax and direct code generation. You would _not_ get better
performance from:

(slow-foo (in-list my-list))
  than you would from
(slow-foo my-list)

==

However, it's not the case that the `in-` syntax is always
optional. For example, if you have a hash, then

(for ([(k v) hash]) ...)
  and
(for ([(k v) (in-hash hash)]) ...)

will always have the same behavior (though not performance). But if you
want to iterate over explicit key/value _pairs_ (i.e., cons cells), then
you'd need to do:

(for ([pair (in-hash-pairs hash)]) ...)

since the default sequence interpretation for a hash is one that produces
two values (the key and value) per-iteration, instead of one that produces
a single cons cell value per-iteration.

Point is, sometimes `in-` is an optimization; in other cases, it
changes the actual way that the data structure is interpreted as a sequence.

- Jon

-- 
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.


Re: [racket-users] raise an exception in a generator

2019-02-20 Thread Kees-Jochem Wehrmeijer

>
> Yes, you could define an impersonator property and then wrap your 
> generator with `impersonate-procedure`:
>

This is amazing! I feel it now does exactly what I want. Thanks!

 

>
> 
>
> #lang racket
> (require (except-in racket/generator yield)
>  (prefix-in gen: (only-in racket/generator yield))
>  racket/stxparam)
>
> (define-syntax-parameter yield (make-rename-transformer #'gen:yield))
>
> (define-syntax (yield* stx)
>   (syntax-case stx ()
> [(_ . vals)
>  #'(call-with-values (thunk (gen:yield . vals))
>  (case-lambda
>[() (void)]
>[(v) (if (exn? v)
> (raise v)
> v)]
>[vs vs]))]))
>
> (define-values (ideal-world-gen-prop ideal-world-gen? _)
>   (make-impersonator-property 'ideal-world-gen))
>
> (define-syntax (define/ideal-world stx)
>   (syntax-case stx ()
> [(_ ID . BODY)
>  #'(define ID
>  (impersonate-procedure
>   (syntax-parameterize ([yield (make-rename-transformer #'yield*)])
> . BODY)
>   #f ideal-world-gen-prop #t))]))
>
> (define/ideal-world mygenerator
>   (generator ()
>  (with-handlers ([exn? (lambda (e) (yield 42))])
>(yield 1)
>(yield 2)
>(yield 3
>
> (mygenerator) ; 1
> (mygenerator (exn:fail "Welp" (current-continuation-marks))) ; 42
> (generator? mygenerator) ; #t
> (ideal-world-gen? mygenerator) ; #t
>
>

-- 
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.


Re: [racket-users] Help with generators from python land!

2019-02-20 Thread Dave McDaniel
Thanks Jon and Jen, This is a great!  I figured there must be a 
straightforward way to do this with a `for/hash` implementation.  I have 
not seen these 2 methods `in-hash` and `in-list` vs just using the hash or 
list without that sequence modifier.  Can you comment on what is going on 
with this `in-xxx` sequence modification?  The docs indicate that you get 
slightly better performance when using these with `for`, but its not clear 
why and in what situations you must use these modifiers rather than the 
underlying list or hash itself--is it always optional?

On Wednesday, February 20, 2019 at 5:28:06 PM UTC-5, Jon Zeppieri wrote:
>
>
>
> On Wed, Feb 20, 2019 at 5:08 PM Jon Zeppieri  > wrote:
>
>>
>> (define (reverse-hash h)
>>   (for*/fold ([result (hash)])
>>  ([(score letters) (in-hash h)]
>>   [letter (in-list letters)])
>> (hash-set result letter score)))
>>
>>
> As with Jens's answer, we can use `for*/hash` here, as well, and make this 
> slightly shorter:
>
> (define (reverse-hash h)
>   (for*/hash ([(score letters) (in-hash h)]
>   [letter (in-list letters)])
> (values letter score)))
>
> `for*/hash` is really a specialized version of `for*/fold`, which handles 
> the hash accumulator for you. The `(values letter score)` expression in the 
> body indicates how the (implicit) accumulator will be updated.
>
>

-- 
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.


Re: [racket-users] raise an exception in a generator

2019-02-20 Thread Matthew Butterick

> On Feb 20, 2019, at 4:29 PM, Kees-Jochem Wehrmeijer  wrote:
> 
> With your define/ideal-world form, is there a way to test whether something 
> was created using that form? E.g. by generating a predicate like ideal-world? 
> That way I can make sure with a contract that my function gets passed an 
> ideal-world generator.

Yes, you could define an impersonator property and then wrap your generator 
with `impersonate-procedure`:



#lang racket
(require (except-in racket/generator yield)
 (prefix-in gen: (only-in racket/generator yield))
 racket/stxparam)

(define-syntax-parameter yield (make-rename-transformer #'gen:yield))

(define-syntax (yield* stx)
  (syntax-case stx ()
[(_ . vals)
 #'(call-with-values (thunk (gen:yield . vals))
 (case-lambda
   [() (void)]
   [(v) (if (exn? v)
(raise v)
v)]
   [vs vs]))]))

(define-values (ideal-world-gen-prop ideal-world-gen? _)
  (make-impersonator-property 'ideal-world-gen))

(define-syntax (define/ideal-world stx)
  (syntax-case stx ()
[(_ ID . BODY)
 #'(define ID
 (impersonate-procedure
  (syntax-parameterize ([yield (make-rename-transformer #'yield*)])
. BODY)
  #f ideal-world-gen-prop #t))]))

(define/ideal-world mygenerator
  (generator ()
 (with-handlers ([exn? (lambda (e) (yield 42))])
   (yield 1)
   (yield 2)
   (yield 3

(mygenerator) ; 1
(mygenerator (exn:fail "Welp" (current-continuation-marks))) ; 42
(generator? mygenerator) ; #t
(ideal-world-gen? mygenerator) ; #t

-- 
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.


Re: [racket-users] raise an exception in a generator

2019-02-20 Thread Kees-Jochem Wehrmeijer
> You can make a new `define` form where `yield` means something different:
>

Ha that's really cool! I definitely need to read up more on the different
macro tricks. I'm new to Racket (my nearest experience is in Clojure), so
David's point about looking for idiomatic ways is well taken. There's
definitely some cool new things possible that I need to get used to.

With your define/ideal-world form, is there a way to test whether something
was created using that form? E.g. by generating a predicate like
ideal-world? That way I can make sure with a contract that my function gets
passed an ideal-world generator.

cheers,
Kees


>
>
> #lang racket
> (require (except-in racket/generator yield)
>  (prefix-in gen: (only-in racket/generator yield))
>  racket/stxparam)
>
> (define-syntax-parameter yield (λ (stx) #'"error: `yield` not
> parameterized"))
>
> (define-syntax (yield* stx)
>   (syntax-case stx ()
> [(_ . vals)
>  #'(call-with-values (thunk (gen:yield . vals))
>  (case-lambda
>[() (void)]
>[(v) (if (exn? v)
> (raise v)
> v)]
>[vs vs]))]))
>
> (define-syntax (define/ideal-world stx)
>   (syntax-case stx ()
> [(_ ID . BODY)
>  #'(define ID
>  (syntax-parameterize ([yield (make-rename-transformer #'yield*)])
>. BODY))]))
>
> (define/ideal-world mygenerator (generator ()
>(with-handlers ([exn? (lambda
> (e) (yield 42))])
>  (yield 1)
>  (yield 2)
>  (yield 3
> (mygenerator)
>
> (mygenerator (exn:fail "Welp" (current-continuation-marks)))
>
>

-- 
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.


Re: [racket-users] raise an exception in a generator

2019-02-20 Thread Kees-Jochem Wehrmeijer
> You would know better than I would, but I wonder if you are making an
> effort to bring familiar constructs into Racket that don't really fit,
> instead of looking for more idiomatic ways to do what you want.
>

Yeah, I know what you mean. It's always a struggle to remain both concise,
but at the same time complete enough to convey the point. It's definitely
possible there's a more idiomatic way to do it, but it's not immediately
obvious to me. I have actually given this some thought, which is why I
think exceptions are the best way, but I'll be gladly proven wrong.


> What is it that you're trying to achieve?
>

I want a way to interrupt a generator, which would normally stop it, but at
the same time giving this generator a way to handle the interrupt and
gracefully recover. This pattern of aborting, but giving the possibility to
handle it sounds like a good fit for exceptions to me. The challenge is
that the interruption comes from outside the generator, hence the ability
to raise this exception from outside.

Your suggestion of just passing in a value and letting the generator decide
what to do with it is a possibility I also considered, but it requires
every generator to explicitly handle the possibility of an interruption at
every yield. Jon's way works better, but still requires a slightly
different pattern of wrapping every yield in braces to make sure it calls
the thunk.

Hope that clarifies things a little bit.

cheers,
Kees




>
>
> >
> > On Tue, Feb 19, 2019 at 10:36 PM Jon Zeppieri 
> wrote:
> >>
> >>
> >>
> >> On Tue, Feb 19, 2019 at 9:57 PM Kees-Jochem Wehrmeijer <
> henc...@gmail.com> wrote:
> >>>
> >>> Basically when I call the function throw. So e.g.
> >>>
> >>> (define mygenerator (generator ()
> >>>(with-handlers ([exn:fail? (lambda (e)
> 42)])
> >>>  (yield 1)
> >>>  (yield 2)
> >>>  (yield 3
> >>>
> >>> > (mygenerator)
> >>> 1
> >>> > (throw mygenerator)
> >>> 42
> >>>
> >>
> >> The most straightforward thing would be to pass the generator a thunk
> that either raises or does not, e.g,
> >>
> >> #lang racket/base
> >>
> >> (require racket/generator)
> >>
> >> (define mygenerator
> >>   (generator (thunk)
> >>  (with-handlers ([exn:fail? (lambda (e) 42)])
> >>(thunk)
> >>((yield 1))
> >>((yield 2))
> >>((yield 3)
> >>
> >> ===
> >> > (mygenerator void)
> >> 1
> >> > (mygenerator (λ () (raise (exn:fail "wah"
> >> 42
> >>
> > --
> > 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.
>

-- 
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.


Re: [racket-users] raise an exception in a generator

2019-02-20 Thread Matthew Butterick

> On Feb 20, 2019, at 8:47 AM, Kees-Jochem Wehrmeijer  wrote:
> 
> While this scheme works, it silently breaks if a user accidentally calls 
> (yield) instead of ((yield)). It might not be a big deal, but in an ideal 
> world I'd only allow the 'correct' way.


You can make a new `define` form where `yield` means something different:


#lang racket
(require (except-in racket/generator yield)
 (prefix-in gen: (only-in racket/generator yield))
 racket/stxparam)

(define-syntax-parameter yield (λ (stx) #'"error: `yield` not parameterized"))

(define-syntax (yield* stx)
  (syntax-case stx ()
[(_ . vals)
 #'(call-with-values (thunk (gen:yield . vals))
 (case-lambda
   [() (void)]
   [(v) (if (exn? v)
(raise v)
v)]
   [vs vs]))]))

(define-syntax (define/ideal-world stx)
  (syntax-case stx ()
[(_ ID . BODY)
 #'(define ID
 (syntax-parameterize ([yield (make-rename-transformer #'yield*)])
   . BODY))]))

(define/ideal-world mygenerator (generator ()
   (with-handlers ([exn? (lambda (e) 
(yield 42))])
 (yield 1)
 (yield 2)
 (yield 3
(mygenerator)

(mygenerator (exn:fail "Welp" (current-continuation-marks)))

-- 
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.


Re: [racket-users] raise an exception in a generator

2019-02-20 Thread David Storrs
On Wed, Feb 20, 2019 at 11:48 AM Kees-Jochem Wehrmeijer
 wrote:
>
> Yeah, that works. I came up with a similar scheme where if the value that's 
> passed to the generator is an exception, it will raise it. Your scheme is a 
> little simpler, but for completeness I listed mine below too. One thing I'm 
> still a little unhappy with is that whoever uses it, needs to remember to use 
> ((yield)) (or in my version (yield*)). I'm trying to build a discrete event 
> simulator where generators are used as processes. My idea was to use 
> exceptions as a way to interrupt processes (actually it's not really my idea; 
> this is how simpy does it).
> While this scheme works, it silently breaks if a user accidentally calls 
> (yield) instead of ((yield)). It might not be a big deal, but in an ideal 
> world I'd only allow the 'correct' way.
>
> ===
> (define-syntax-rule (yield* . vals)
>   (call-with-values (thunk (yield . vals))
> (case-lambda
>   [() (void)]
>   [(v) (if (exn? v)
>(raise v)
>v)]
>   [vs vs])))
>
> (define mygenerator2 (generator ()
> (with-handlers ([exn? (lambda (e) (yield* 
> 42))])
>   (yield* 1)
>   (yield* 2)
>   (yield* 3
> ===
> > (mygenerator)
> 1
> > (mygenerator (exn:fail "Welp" (current-continuation-marks)))
> 42
>
>

You would know better than I would, but I wonder if you are making an
effort to bring familiar constructs into Racket that don't really fit,
instead of looking for more idiomatic ways to do what you want.

What is it that you're trying to achieve?  Not "how do I make
generators throw exceptions" but (e.g.) "how do I do load testing
where one process represents a server and the rest generate user-like
events against the server?"


>
> On Tue, Feb 19, 2019 at 10:36 PM Jon Zeppieri  wrote:
>>
>>
>>
>> On Tue, Feb 19, 2019 at 9:57 PM Kees-Jochem Wehrmeijer  
>> wrote:
>>>
>>> Basically when I call the function throw. So e.g.
>>>
>>> (define mygenerator (generator ()
>>>(with-handlers ([exn:fail? (lambda (e) 42)])
>>>  (yield 1)
>>>  (yield 2)
>>>  (yield 3
>>>
>>> > (mygenerator)
>>> 1
>>> > (throw mygenerator)
>>> 42
>>>
>>
>> The most straightforward thing would be to pass the generator a thunk that 
>> either raises or does not, e.g,
>>
>> #lang racket/base
>>
>> (require racket/generator)
>>
>> (define mygenerator
>>   (generator (thunk)
>>  (with-handlers ([exn:fail? (lambda (e) 42)])
>>(thunk)
>>((yield 1))
>>((yield 2))
>>((yield 3)
>>
>> ===
>> > (mygenerator void)
>> 1
>> > (mygenerator (λ () (raise (exn:fail "wah"
>> 42
>>
> --
> 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.

-- 
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.


Re: [racket-users] "table" data structure in Racket

2019-02-20 Thread travis . hinkelman
Hi All,

I'm resurrecting this thread to ask if anyone in the Racket community has 
Apache Arrow on their radar. It seems like Apache Arrow might be gaining 
steam.

Apache Arrow is a cross-language development platform for in-memory data. 
> It specifies a standardized language-independent columnar memory format for 
> flat and hierarchical data, organized for efficient analytic operations on 
> modern hardware. It also provides computational libraries and zero-copy 
> streaming messaging and interprocess communication. Languages currently 
> supported include C, C++, C#, Go, Java, JavaScript, MATLAB, Python, R, 
> Ruby, and Rust. [Source 
> 
> ]


I have no clue what it would take to make Racket a supported language. I 
also don't have a sense of what kind of demand the Racket community has for 
this sort of thing. Just curious if anyone is thinking about a Racket and 
Apache Arrow pairing.

Thanks,

Travis 

On Wednesday, April 6, 2016 at 1:27:56 AM UTC-7, Konrad Hinsen wrote:
>
> On 05/04/2016 21:12, Asumu Takikawa wrote: 
>
> > I haven't built anything like that, but I was hoping that we could get a 
> GSoC 
> > student for it (that didn't pan out though obviously). The idea was to 
> use 
> > packages from Python/Julia/R as inspiration: 
> > 
> >http://pandas.pydata.org/pandas-docs/stable/index.html 
> >http://dataframesjl.readthedocs.org/en/latest/ 
> >https://github.com/Rdatatable/data.table/wiki 
>
> Also consider this one: 
>
> https://arrow.apache.org/ 
>
> Konrad. 
>

-- 
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.


Re: [racket-users] Help with generators from python land!

2019-02-20 Thread Jon Zeppieri
On Wed, Feb 20, 2019 at 5:08 PM Jon Zeppieri  wrote:

>
> (define (reverse-hash h)
>   (for*/fold ([result (hash)])
>  ([(score letters) (in-hash h)]
>   [letter (in-list letters)])
> (hash-set result letter score)))
>
>
As with Jens's answer, we can use `for*/hash` here, as well, and make this
slightly shorter:

(define (reverse-hash h)
  (for*/hash ([(score letters) (in-hash h)]
  [letter (in-list letters)])
(values letter score)))

`for*/hash` is really a specialized version of `for*/fold`, which handles
the hash accumulator for you. The `(values letter score)` expression in the
body indicates how the (implicit) accumulator will be updated.

-- 
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.


Re: [racket-users] Help with generators from python land!

2019-02-20 Thread Jens Axel Søgaard
Den ons. 20. feb. 2019 kl. 22.25 skrev Dave McDaniel :

> 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.


Re: [racket-users] Help with generators from python land!

2019-02-20 Thread Jon Zeppieri
On Wed, Feb 20, 2019 at 4:25 PM Dave McDaniel 
wrote:

> 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.  In python using generators would be very
> straightforward:
>
>
>
Generators are a common tool in Python, but not in Racket. (I've written a
lot of Racket code over many years and have used generators, I think, once.)

I'd do this as a fold over the input hash:

===
#lang racket/base

(define mixed-case-input
  (hash 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")))

(define (reverse-hash h)
  (for*/fold ([result (hash)])
 ([(score letters) (in-hash h)]
  [letter (in-list letters)])
(hash-set result letter score)))
===

All of the `for*` operations do nested iteration (as opposed to the `for`
operations without the asterisk, where sequences are iterated in parallel).
So, in this case, we get each `(score letters)` pair fro the hash, and for
each of those, we iterate over the list of letters. On each iteration,
we're updating our accumulator (`result`). The result of the whole
expression is the final value of the accumulator.

- Jon

-- 
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.


[racket-users] Help with generators from python land!

2019-02-20 Thread Dave McDaniel
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.  In python using generators would be very 
straightforward:


def gen(input):
for score, letters in input.items(): 
for l in letters: yield l, score 
dict(gen(input))



I am stumbling on the racket solution using generators and I was wondering if I 
could get some pointers from the list.  This could actually be a good candidate 
for the "from python to racket" idioms that is being discussed in a separate 
thread.

I find that the racket docs are lacking in describing generator use cases that 
yield more than one value.  I tried passing `(void)` as a stop value to the 
`in-producer` call but says it needs a predicate when the producer yields more 
than one value.

Also I would assume if the generator is iterating over a finite sequence we 
would not need to define a stop value, but this doesn't seem to work either.

Thanks in advance for any help!

#lang racket

(require racket/generator)

(provide etl
 etl-gen)

(define mixed-case-input (hash 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")))

 
(define (etl input)
 (define result (make-hash))
 (define/contract (transpose score letters)
 (-> positive? list? any)
 (for-each (lambda (letter)
 (hash-set! result (string-downcase letter) score)) letters))
 (hash-for-each input transpose)
 result)


(define (etl-gen input)
 (define unpack (generator ()
 (for* ([(score letters) input]
 [l letters])
 (yield (string-downcase l) score
 (for/hash ([(letter score) (in-producer unpack)]) (values letter score)))




-- 
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.


Re: [racket-users] How do you make students submit programming assignments online for automatic tests?

2019-02-20 Thread 'John Clements' via Racket Users
Github Classroom is trying to do this, but they’re not doing it well. I’ve used 
it several times, and managed to make it work, but the experience has been very 
me-programming-heavy, and not so great for the students. I think gradescope may 
have just merged with a company that’s trying to provide this. Their solution 
would definitely involve money.

One solution would be to use the command-line version of Racket’s 
handin-server, which is language-agnostic to the degree that it can just submit 
arbitrary files to the server, and what happens on the back end is up to you. 
It also has a web interface, though I don’t recall what it looks like; I 
haven’t used it in years.

I look forward to hearing about anything awesome that others use.

John




> On Feb 20, 2019, at 9:51 AM, Marc Kaufmann  wrote:
> 
> Hi all,
> 
> I will be teaching a course on data analysis in R next year (September), and 
> may at some point add some Racketeering to my other courses (maybe), and I 
> was wondering how those of you who teach programming classes deal with 
> programming assignments. Are there somewhat language-independent platforms 
> for having students submit assignments that have to pass a bunch of 
> pre-specified tests, or would I need to look at what is available for any 
> given platform? Any security issues I should be aware of?
> 
> All recommendations welcome,
> 
> Marc
> 
> -- 
> 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.



-- 
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.


[racket-users] How do you make students submit programming assignments online for automatic tests?

2019-02-20 Thread Marc Kaufmann
Hi all,

I will be teaching a course on data analysis in R next year (September), 
and may at some point add some Racketeering to my other courses (maybe), 
and I was wondering how those of you who teach programming classes deal 
with programming assignments. Are there somewhat language-independent 
platforms for having students submit assignments that have to pass a bunch 
of pre-specified tests, or would I need to look at what is available for 
any given platform? Any security issues I should be aware of?

All recommendations welcome,

Marc

-- 
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.


Re: [racket-users] raise an exception in a generator

2019-02-20 Thread Kees-Jochem Wehrmeijer
Yeah, that works. I came up with a similar scheme where if the value that's
passed to the generator is an exception, it will raise it. Your scheme is a
little simpler, but for completeness I listed mine below too. One thing I'm
still a little unhappy with is that whoever uses it, needs to remember to
use ((yield)) (or in my version (yield*)). I'm trying to build a discrete
event simulator where generators are used as processes. My idea was to use
exceptions as a way to interrupt processes (actually it's not really my
idea; this is how simpy

does it).
While this scheme works, it silently breaks if a user accidentally calls
(yield) instead of ((yield)). It might not be a big deal, but in an ideal
world I'd only allow the 'correct' way.

===
(define-syntax-rule (yield* . vals)
  (call-with-values (thunk (yield . vals))
(case-lambda
  [() (void)]
  [(v) (if (exn? v)
   (raise v)
   v)]
  [vs vs])))

(define mygenerator2 (generator ()
(with-handlers ([exn? (lambda (e) (yield*
42))])
  (yield* 1)
  (yield* 2)
  (yield* 3
===
> (mygenerator)
1
> (mygenerator (exn:fail "Welp" (current-continuation-marks)))
42



On Tue, Feb 19, 2019 at 10:36 PM Jon Zeppieri  wrote:

>
>
> On Tue, Feb 19, 2019 at 9:57 PM Kees-Jochem Wehrmeijer 
> wrote:
>
>> Basically when I call the function throw. So e.g.
>>
>> (define mygenerator (generator ()
>>(with-handlers ([exn:fail? (lambda (e)
>> 42)])
>>  (yield 1)
>>  (yield 2)
>>  (yield 3
>>
>> > (mygenerator)
>> 1
>> > (throw mygenerator)
>> 42
>>
>>
> The most straightforward thing would be to pass the generator a thunk that
> either raises or does not, e.g,
>
> #lang racket/base
>
> (require racket/generator)
>
> (define mygenerator
>   (generator (thunk)
>  (with-handlers ([exn:fail? (lambda (e) 42)])
>(thunk)
>((yield 1))
>((yield 2))
>((yield 3)
>
> ===
> > (mygenerator void)
> 1
> > (mygenerator (λ () (raise (exn:fail "wah"
> 42
>
>

-- 
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.


Re: [racket-users] web-server/http documentation: "You are unlikely to need to construct a request struct." Why?

2019-02-20 Thread Marc Kaufmann
OK, so there is no reason for me to leave the racket world for that type of
tests. Thanks.

On Wed, Feb 20, 2019 at 4:25 PM Jay McCarthy  wrote:

> On Wed, Feb 20, 2019 at 10:23 AM Marc Kaufmann
>  wrote:
> > I came across this statement regarding structure request in the
> documentation: "You are unlikely to need to construct a request struct."
> (See here.)
> >
> > Why does it say this? I want to generate requests (in one form or
> another) for functional tests of my website. Should I use curl for that?
> And is the rationale something to do with security?
>
> What you want to do is basically the only use case for making
> requests. That's why it says this. Sometime people think that they can
> make request structures and use that with something like
> net/http-client to make a request to a site. That's not what they are
> for.
>
> Jay
>
> --
> -=[ Jay McCarthy   http://jeapostrophe.github.io]=-
> -=[ Associate ProfessorPLT @ CS @ UMass Lowell ]=-
> -=[ Moses 1:33: And worlds without number have I created; ]=-
>

-- 
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.


Re: [racket-users] web-server/http documentation: "You are unlikely to need to construct a request struct." Why?

2019-02-20 Thread Jay McCarthy
On Wed, Feb 20, 2019 at 10:23 AM Marc Kaufmann
 wrote:
> I came across this statement regarding structure request in the 
> documentation: "You are unlikely to need to construct a request struct." (See 
> here.)
>
> Why does it say this? I want to generate requests (in one form or another) 
> for functional tests of my website. Should I use curl for that? And is the 
> rationale something to do with security?

What you want to do is basically the only use case for making
requests. That's why it says this. Sometime people think that they can
make request structures and use that with something like
net/http-client to make a request to a site. That's not what they are
for.

Jay

-- 
-=[ Jay McCarthy   http://jeapostrophe.github.io]=-
-=[ Associate ProfessorPLT @ CS @ UMass Lowell ]=-
-=[ Moses 1:33: And worlds without number have I created; ]=-

-- 
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.


[racket-users] web-server/http documentation: "You are unlikely to need to construct a request struct." Why?

2019-02-20 Thread Marc Kaufmann
Hi all,

I came across this statement regarding structure request in the 
documentation: "You are unlikely to need to construct a request struct." 
(See here 

.)

Why does it say this? I want to generate requests (in one form or another) 
for functional tests of my website. Should I use curl for that? And is the 
rationale something to do with security?

Thanks,
Marc

-- 
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.


Re: [racket-users] Transfer code from "intermediate student with lamnda" to "Pretty big"

2019-02-20 Thread Matthias Felleisen


See previous email exchanges and the require necessary to import the tests 
(test-engine/racket-tests) plus the call to the test function. 



> On Feb 19, 2019, at 2:26 PM, orenpa11  wrote:
> 
> Hi
> Is it possible to transfer code from "intermediate student with lamnda" to 
> "Pretty big"
> for exmple :
> 
> (require 2htdp/image)
> (require 2htdp/universe)
> 
> 
> (define (join-together ls1 ls2)
>   (local 
> [; help : [ListOf X] -> [ListOf X]
>  ; (help ls1) drops the invariant argument ls2
>  (define (help ls1)
>(cond
>  [(empty? ls1) ls2]
>  [else (cons (first ls1) 
>  (help (rest ls1)))]))]
> (help ls1)))
> 
> (check-expect (join-together '() '(a b c d e f)) '(a b c d e f))
> (check-expect (join-together '(a)  '(b c d e f)) '(a b c d e f))
> (check-expect (join-together '(a b)  '(c d e f)) '(a b c d e f))
> (check-expect (join-together '(a b c ) '(d e f)) '(a b c d e f))
> (check-expect (join-together '(a b c d)  '(e f)) '(a b c d e f))
> (check-expect (join-together '(a b c d e)  '(f)) '(a b c d e f))
> (check-expect (join-together '(a b c d e f) '()) '(a b c d e f))
> 
> 
> 
> Thanks,
> Or
> 
> p.s. I get the error
> 
> check-expect: undefined;
>  cannot reference an identifier before its definition
> 
> -- 
> 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.

-- 
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.


[racket-users] Scribble: How to change the text for index and table of contents

2019-02-20 Thread xh
Hi, all

I want to change the output text for index and table of contents, which are 
"Index" and "Contents".

I found the value was defined in 
https://github.com/racket/scribble/blob/master/scribble-lib/scribble/html-render.rkt#L937,
 
but is there a way to modify the value in my document source file?

-- 
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.