notjack
2019-10-4 16:48:03

@aymano.osman do you use syntax-parse? I find that helps me write simpler and more correct macros a lot


samdphillips
2019-10-4 16:49:52

Yes syntax-parse eliminates a huge source of bugs in destructuring input syntax.


notjack
2019-10-4 16:57:32

The syntax-rules, syntax-case, and define-syntax-rule forms really ought to have their reference docs updated to suggest using syntax-parse instead.


notjack
2019-10-4 16:57:56

mental todo list note


samdphillips
2019-10-4 17:26:45

Have the portions of the Guide about macros been rewritten for syntax-parse ?



heymatthewoden
2019-10-4 20:20:43

So, real new to racket (and lisp in general), with probably less than ten hours under my belt. I started with beautifulracket, but paused to learn a little more about syntax and structure.

So now I’m going through https://github.com/zyrolasting/racket-koans to do just that. Working through https://github.com/zyrolasting/racket-koans/blob/master/koans/procedures.rkt#L74 - I’ve found myself a little stuck on how to write the contract for this. Here’s my contract for my-joiner so far: (define/contract (my-join delimiter . numbers) (case-> [-> integer? #:rest (listof integer?) string?] [-> string? #:rest (listof integer?) string?]) ... based on the tests, I’ll be given an arbitrary number of parameters, so I can use a rest-id to separate a possible delimiter, then handle mapping/joining based on that first parameter. The example suggests that I need case->, but I just don’t think I understand how to use it here. What I’ve got matches based on the number of arguments, it seems. Not the types of values.

If someone can give me a nudge in the right direction (either on contracts, or maybe just my approach to the problem), that’d be amazing.


shu--hung
2019-10-4 20:43:11

Contracts are not types. Checking the number of arguments is the right approach imo


heymatthewoden
2019-10-4 20:43:48

yeah, just read through case-lambda. I think I’ve been conflating contracts and pattern matching.


shu--hung
2019-10-4 20:43:57

but you have to actually distinguish the cases for different # of arguments in the contract


shu--hung
2019-10-4 20:44:26

in the code you pasted, the two cases overlapped


heymatthewoden
2019-10-4 20:49:37

Gotcha. So in the contract, if I wanted to allow the first argument to be an integer, string, or char, I could do: [-> (first-or/c integer? string? char?) #:rest (listof integer?) string?] (I mean, maybe there’s a better contract, but that’s the gist?)


shu--hung
2019-10-4 20:50:24

yes, but this contract let (my-join #\space) passes without raising an error


shu--hung
2019-10-4 20:50:59

I would try to split the cases into: - A contract for 1 argument - A contract for 2 or more arguments


heymatthewoden
2019-10-4 20:51:00

ah, sure - I’d want a case-> that handles a single arg, and expects a number.


shu--hung
2019-10-4 20:51:08

right


shu--hung
2019-10-4 20:51:43

so this turns into: - (-> ? ?result) - (-> ? ? #:rest ?rest ?result)


shu--hung
2019-10-4 20:51:53

and the two are combined via case->


heymatthewoden
2019-10-4 20:52:13

cool.


heymatthewoden
2019-10-4 20:52:25

Thanks a bunch, this clears a lot up!


shu--hung
2019-10-4 20:56:39

Also for the first argument you can use or/c