ianwlarson
2017-8-11 22:51:52

@ianwlarson has joined the channel


ianwlarson
2017-8-11 22:53:03

Hello, is there any way to use the return value from a yield statement?


ianwlarson
2017-8-11 22:54:49

I’m trying to make a generator that can change its state when passed values, but doesn’t necessarily need to be passed values


lexi.lambda
2017-8-11 22:56:16

@ianwlarson the docs for yield show an example of using the return value from a yield expression. is there something else you’re asking about? http://docs.racket-lang.org/reference/Generators.html#%28def._%28%28lib._racket%2Fgenerator..rkt%29._yield%29%29


ianwlarson
2017-8-11 22:57:37

ianwlarson
2017-8-11 22:57:50

The problem is it that it demands you use the value


lexi.lambda
2017-8-11 22:57:58

ah, you might want to look at call-with-values.


ianwlarson
2017-8-11 22:57:59

if you try to NOT use a value, it has arity error


lexi.lambda
2017-8-11 22:58:19

the issue here is the same as the error produced by this code: (define x (values 1 2))


lexi.lambda
2017-8-11 22:59:14

essentially, yield returns a varying number of values depend on the number of arguments passed to the generator. call-with-values can handle an arbitrary number of values, whereas define/define-values/let/let-values only handle a statically-known number of values.


lexi.lambda
2017-8-11 23:00:26

you can, for example, write (call-with-values (lambda () (yield 2)) list), and the values passed to the generator will be collected into a list.


ianwlarson
2017-8-11 23:01:22

I feel like I need a phd to use this language


lexi.lambda
2017-8-11 23:03:24

there’s a values->list form provided by various utility libraries, perhaps that would be more palatable?


ianwlarson
2017-8-11 23:03:45

call with values works pretty well


ianwlarson
2017-8-11 23:03:51

because then I don’t have to unpack the list


ianwlarson
2017-8-11 23:04:28

I can use a case-lambda with ([() ()’] [(x) ( do something with the value)])


ianwlarson
2017-8-11 23:05:22

I’m probably misusing this language


ianwlarson
2017-8-11 23:06:01

Too used to procedural languages


ianwlarson
2017-8-11 23:06:53

I think it would be cool if yield returned void when nothing is passed to the generator


lexi.lambda
2017-8-11 23:07:49

that would make the zero-args case impossible to distinguish from passing a single argument, which is #<void>.


lexi.lambda
2017-8-11 23:08:08

and it also wouldn’t help at all distinguish between other numbers of arguments.


lexi.lambda
2017-8-11 23:08:58

I think a more pleasant interface would probably be to just produce a list, not multiple values, but some people find multi-valued return “elegant”. I will not comment on that. :)


ianwlarson
2017-8-12 02:40:51

Does having a let in a named loop have some undesirable interaction over define?


ianwlarson
2017-8-12 03:06:49

ianwlarson
2017-8-12 03:07:18

Does the 2nd let cause massive memory growth? If a define was used instead, would it be different?


lexi.lambda
2017-8-12 03:09:56

@ianwlarson after expansion, there is no difference between internal definitions and an equivalent letrec. in that code, loop is called in tail position, so there is no memory cost to the recursion.


ianwlarson
2017-8-12 03:12:05

so its like


ianwlarson
2017-8-12 03:12:16

internally converted to a let* or a letrec


ianwlarson
2017-8-12 03:12:48

not converted but in the actual implementation it’s equivalent


lexi.lambda
2017-8-12 03:13:35

no, it actually is converted; my phrasing was a little misleading. see the grammar for fully-expanded programs: http://docs.racket-lang.org/reference/syntax-model.html#%28part._fully-expanded%29


lexi.lambda
2017-8-12 03:14:28

most notably, define-values and define-syntaxes are only general-top-level-forms. neither appears in the grammar for expr.


ianwlarson
2017-8-12 03:15:52

I feel like I need a PHD to use this language


lexi.lambda
2017-8-12 03:18:40

to be fair, if you ask a low-level question, you will get a low-level answer. :)


ianwlarson
2017-8-12 03:21:03

and I’m thankful for it


ianwlarson
2017-8-12 03:21:06

I just can’t understand it


lexi.lambda
2017-8-12 03:26:22

well, “non-top-level definitions get turned into letrec internally” is probably a good enough, simpler explanation.


ianwlarson
2017-8-12 03:26:38

“A reference to a local binding in a fully expanded program has a scope set that matches its binding identifier exactly. ”


ianwlarson
2017-8-12 03:26:45

this was a line in the thing you linked me


ianwlarson
2017-8-12 03:27:03

which I believe answers what I asked


ianwlarson
2017-8-12 03:27:21

:sweat_smile: