deactivateduser60718
2020-5-13 19:36:09

When sequence->stream “eagerly” initiates a sequence, does this imply that it traverses the entire sequence, or just enough to produce the first element?


massung
2020-5-13 19:50:15

is it possible to use match with variables for example, something like… (match codon ((list T A _) ...)) Where T and A are already defined values to be eq? to as opposed to variables to bind?


samth
2020-5-13 19:51:47

@massung you probably want to write (== T) and maybe (== T eq?)


massung
2020-5-13 19:52:14

@samth Thanks


anything
2020-5-13 19:57:17

I’ve got this xexpr:

(html (@ (lang "en-gb") (dir "ltr")) "\n" (head "\n" "\t" (meta (@ (charset "utf-8")))))

What are these @ symbols saying to me? They’re not in the HTML file. Educate me on this?


samth
2020-5-13 19:57:55

@anything that looks like sxml to me


anything
2020-5-13 19:58:24

> (xexpr? x) #t



anything
2020-5-13 19:58:59

You must be right! But the predicate above produces #t. Thanks for the pointer! I’ll probably have a better luck now.


samth
2020-5-13 20:00:28

I think the xexpr? predicate is a little too flexible there (I’m not sure if @ is a valid tag name) but unfortunately there’s a lot of overlap between the two encodings


notjack
2020-5-13 20:08:38

“Initiating” a sequence does not traverse it. It just allocates whatever data structures the sequence uses to keep track of where you are in the traversal. For example initiating a vector sequence might allocate a mutable object that points to your current position in the vector. Sequences can usually be traversed concurrently, so this state is typically traversal-specific.


notjack
2020-5-13 20:09:13

So it’s not even just enough to produce the first element - it’s just enough to prevent the client from forgetting where they are in the sequence.


soegaard2
2020-5-13 20:10:06

@anything The @ means “attributes” ( @ is an at-sign … )


notjack
2020-5-13 20:10:51

What this means for sequence->stream is that it gives you an immutable frozen view of a single traversal of a sequence. If you had a sequence that represented “ten random numbers” and gave you different numbers each time you iterated it, applying sequence->stream would give you a stream that always yields the same ten numbers. Because no matter how many times you traverse the stream, that stream is backed by only a single traversal of the original sequence.


anything
2020-5-13 20:17:31

Indeed. I got that from the link above. Thanks for pointing it out, @soegaard2!


anything
2020-5-14 00:05:01

Here’s a generator. It works as expected.

(define (make-gen) (generator () (for ([e '("a" "b" "c")]) (yield(,e (w yes) (x no) (z no))))))racket@whatcms.rkt> (define more (make-gen))racket@whatcms.rkt> (more)’(“a” (w yes) (x no) (z no))racket@whatcms.rkt> (more)’(“b” (w yes) (x no) (z no))racket@whatcms.rkt> (more)’(“c” (w yes) (x no) (z no))racket@whatcms.rkt> (more) ; #<void>racket@whatcms.rkt>But how can I consume it from within a loop? This doesn't do what I expected.(define (use-gen)(define more (make-gen))(for ([ls (more)])(displayln ls)))racket@whatcms.rkt> (use-gen)a(w yes)(x no)(z no)`

It’s as if each element of the first yield-call comes one at a time in the use-gen for loop. (Never used generators before.)

— Idea: I think the use-gen is looping through only the first yield. Perhaps I need a sequence there.


jaz
2020-5-14 00:11:28

What is it that you expect it to do?


jaz
2020-5-14 00:12:09

(more) is going to be the first yielded value of the generator. So that’s what you’re iterating over.


anything
2020-5-14 00:16:23

The effect that I expected to get was:

(define (use-gen) (for ([ls (in-generator (let loop ([e '("a" "b" "c")]) (when (not (null? e)) (yield(,(car e) (w yes) (x no) (z no)))(loop (cdr e)))))])(displayln ls)))racket@whatcms.rkt> (use-gen)(a (w yes) (x no) (z no))(b (w yes) (x no) (z no))(c (w yes) (x no) (z no))`

But I wanted to write the code that first way.


jaz
2020-5-14 00:19:00

Okay, so in a for loop, when you have something like: for ([x xs]) ...) , x is bound to each successive value in the sequence xs. So xs needs to be a sequence. A generator isn’t a sequence, though.


jaz
2020-5-14 00:20:04

In your code, you were using (more) , which is (as I said before) the result of calling the generator — that is, it’s the first thing that the generator returns, which is a list. And a list is a sequence, which is why the code you had runs, but it doesn’t do what you want.


jaz
2020-5-14 00:20:36

What you need is a sequence that represents each successive call to the generator.


jaz
2020-5-14 00:22:03

There’s a form named in-producer that generates a sequence from a function. But that, by itself, probably isn’t quite what you want either, because a generator doesn’t ever really stop.


samdphillips
2020-5-14 00:23:51

You could just use in-generator which makes a sequence instead of generator


jaz
2020-5-14 00:23:57

So I don’t think there’s a really convenient way to do what you’re trying to do.


jaz
2020-5-14 00:24:22

@samdphillips Right, but that’s what @anything mentioned above.


greg
2020-5-14 00:24:50

Doesn’t a generator produce #&lt;void&gt; when exhausted?


greg
2020-5-14 00:25:22

Would something like (in-producer void the-generator) work?


jaz
2020-5-14 00:25:29

@greg The documentation is kind of hard to square with the example that comes right after it.


jaz
2020-5-14 00:25:51

But in the specific case of this generator — yes.


greg
2020-5-14 00:25:56

Ah OK. I just inferred that from their example, I hardly ever use generators.


jaz
2020-5-14 00:26:06

Me either.


jaz
2020-5-14 00:26:28

And I actually forgot that in-producer has the stop argument, which makes this a lot more convenient.


jaz
2020-5-14 00:26:41

So yeah — that would work.


samdphillips
2020-5-14 00:27:15

In my experience just use in-generator because most likely you want a sequence.


samdphillips
2020-5-14 00:27:43

ugh


jaz
2020-5-14 00:27:44

Oh — after reading the generator docs again, I realize that I missed a word, and now that I see it, it makes more sense.


samdphillips
2020-5-14 00:27:55

I missed reading the use-gen function


jaz
2020-5-14 00:28:19

So yeah — after its final yield, a generator will start yielding the return value. And will keep doing so indefinitely.


samdphillips
2020-5-14 00:28:39

Yes in-producer is your friend. I used to use it all the time for reading until I found in-port


jaz
2020-5-14 00:28:40

So as long as the return value is distinct from a normally yieldable value, you can use that with in-producer.


jaz
2020-5-14 00:29:47

In @anything’s example, the return value is eventually void.


jaz
2020-5-14 00:30:05

Since that’s what a for gives you.


jaz
2020-5-14 00:31:46

So, @anything, it would be for ([ls (in-producer (void) more)]) ... . Note that there are no parens around more . Because more is the producer, whereas (more) is the (first) thing that it produces.


samdphillips
2020-5-14 00:32:20

I use in-generator too much probably. Some things are awkward (or I’m too lazy) to not do in a direct form.


anything
2020-5-14 00:32:27

So the way out I found was to not use the for loop. :-)

racket@whatcms.rkt&gt; (define (make-gen) (generator () (for ([e '("a" "b" "c")]) (yield(,e (w yes) (x no) (z no))))))racket@whatcms.rkt> (define (doit gen)(define x (gen))(when (not (void? x))(displayln x)(doit gen)))racket@whatcms.rkt> (doit (make-gen))(a (w yes) (x no) (z no))(b (w yes) (x no) (z no))(c (w yes) (x no) (z no))racket@whatcms.rkt>`


anything
2020-5-14 00:32:45

Let me try in-producer then


jaz
2020-5-14 00:33:10

I should have tried my code before posting it :slightly_smiling_face:


rokitna
2020-5-14 00:33:57

Perhaps you could have make-gen use in-generator instead of generator? Then you can use that in the for loop more easily


samdphillips
2020-5-14 00:37:21

Does anyone have a good “recipe” for timing out a read? I have a procedure (read-message an-input-port) that reads some number of bytes over the network and I would like to time out and error or return some timeout value.


jaz
2020-5-14 00:38:35

@samdphillips sync/timeout


jaz
2020-5-14 00:40:41

Oh — I had the stop and producer arguments in the wrong order…


jaz
2020-5-14 00:41:00

for ([ls (in-producer more (void))])


jaz
2020-5-14 00:44:01

@samdphillips If you’re just reading bytes, you’d use sync/timeout along with read-bytes-evt. If your read-message is doing something more complicated, you’d need to adjust it to produce a synchronizable event.


samdphillips
2020-5-14 00:44:27

That’s what I was going to ask


samdphillips
2020-5-14 00:44:55

read-message reads a variable amount of bytes based on the message pretty much


anything
2020-5-14 00:46:09

@jaz, but I did catch that. :slightly_smiling_face:


anything
2020-5-14 00:46:18

Thanks for the help you all.


greg
2020-5-14 00:47:04

I think I misled you by putting them backwards in my “would something like this work”.


jaz
2020-5-14 00:48:53

@samdphillips Is the code for read-message too large (or confidential) to post?


greg
2020-5-14 00:49:06

@samdphillips That reminds me — but is different from — something I had to figure out: How to attempt to read an s-expression, but if a complete one isn’t available yet, not get stuck inside the read. What I came up with, for better or worse: https://github.com/greghendershott/racket-mode/blob/master/racket/interactions.rkt#L34-L53


samdphillips
2020-5-14 00:49:21

I can distill it down to something postable. It’s not too much.


greg
2020-5-14 00:50:10

One obvious flaw here is the 4096 buffer size, but in the context of REPL reads, it seemed not totally horrible (I hope).


samdphillips
2020-5-14 00:50:13

@greg that is what I was starting to try


samdphillips
2020-5-14 00:50:36

Just wondering if there was some good community knowledge on this


greg
2020-5-14 00:50:41

Maybe you all can point out more flaws and I can get a free code review. :smile:


greg
2020-5-14 00:52:06

In the discussion about generators, I was going to say (but it seemed probably OT) that I expected to use generators more when I learned Racket. I think why I haven’t, is I got comfortable using thread and channels and such. So most “concurrency” uses of generators, I end up doing that? idk if that makes sense.


samdphillips
2020-5-14 00:56:57

Here is read-message distilled down. In the actual code there is some error checking, etc. (define (read-message inp) (match (read-byte inp) [#x00 (define payload-size (read-byte inp)) (define payload (read-bytes payload-size inp)) (list payload)] [#x01 'failure]))


samdphillips
2020-5-14 01:04:04

(also in the real code there are about 6 more clauses in the match)


jaz
2020-5-14 01:15:50

Something like: (define (read-message-evt in) (define (read-payload-evt in) (replace-evt in (λ (_) (define size (read-byte in)) (handle-evt (read-bytes-evt size in) list)))) (replace-evt in (λ (_) (match (read-byte in) [#x00 (read-payload-evt in)] [#x01 (handle-evt always-evt (λ (_) 'failure))])))) Since an event that’s ready for synchronization can become un-ready, this isn’t strictly correct, I guess. If you were worried about that case, I guess you’d need to use read-bytes-evt to read a single byte for the initial and payload bytes. Maybe?


jaz
2020-5-14 01:18:19

In the code above, I’m assuming that after the input port becomes ready, the attempt to read a single byte on it will succeed without blocking. Which is generally true.


samdphillips
2020-5-14 01:20:51

In my case if the timeout happens the port is closed so partial reads are no big deal.


samdphillips
2020-5-14 01:22:31

@jaz Thanks that confirmed the direction I was thinking of going.


jaz
2020-5-14 04:26:50

I was just playing around with some syntax that would allow you to write this sort of thing in a more direct style. Like https://gist.github.com/97jaz/ec714dfe9b66b674bff53b629b28c9d6


agj_chile
2020-5-14 06:35:06

@agj_chile has joined the channel