Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add while / break #40

Merged
merged 2 commits into from
Oct 27, 2021
Merged

add while / break #40

merged 2 commits into from
Oct 27, 2021

Conversation

bennn
Copy link
Member

@bennn bennn commented Oct 11, 2021

@countvajhula
Copy link
Contributor

Thanks for putting this together!

I rephrased the description to be more beginner-friendly (feel free to tweak it or let me know if you want me to change something):

@defmodule[syntax-parse-example/while-break/while-break]{}

@defform[(while test body ...+)]{

  @examples[#:eval while-break-eval
    (define x 5)

    (while (> x 0)
      (displayln x)
      (set! x (sub1 x)))

    (set! x 5)

    (while #t
      (displayln x)
      (set! x (sub1 x))
      (unless (> x 0)
        (break)))
  ]

  A simple while loop familiar from many programming languages, this macro works by using a @seclink["Named_let" #:doc '(lib "scribblings/guide/guide.scrbl")]{named let} to provide the looping, and an @tech/reference{escape continuation} to provide the ability to @racket[break] out of the loop.

  In typical implementations, @racket[break] is a statement that allows you to leave the while loop at any time, but it is also a special kind of statement in that you can only use it within the body of the while loop. To ensure this behavior, the macro defines @racket[break] as a @seclink["stxparam" #:doc '(lib "scribblings/reference/reference.scrbl")]{syntax parameter}, which in a nutshell is a way to define syntax with default behavior outside the macro body (in our case, simply reporting a syntax error) and special behavior within the macro body. This parameter is then used as a label for the continuation so that it may be used to exit the loop.
}

@defform[(break value ...)]{
  This is an alias for the continuation recorded at the start of the loop. Invoking it calls the continuation with the provided value (if any) which becomes the value of the entire @racket[while] expression. It may only appear within a @racket[while] form, and is a syntax error outside of one.
}

@racketfile{while-break.rkt}

In Racket, most expressions evaluate to a specific value (or many values), reflecting the functional style of programming which discourages side effects such as mutating the value of a variable. A while loop inherently encourages side effects since it typically has no return value (and of course, must mutate a variable if the loop is to terminate!). Yet, in the present implementation, the while expression can evaluate to a specific value when one is explicitly returned via @racket[break]. Could the implementation be modified to return a value even in the case of a normal exit? For instance, we could have it return the value of the final expression executed in the course of looping. As an exercise, see if you can make the while loop a little more "functional" by allowing it to always return a value.

Also, I noticed that the github issues link here is broken, looks like it needs to be issues rather than issue.

Finally, I'm wondering if it might be easier to go through these examples if they were on individual pages linked from the main index page. It may be less intimidating.

Otherwise LGTM 👍

@bennn
Copy link
Member Author

bennn commented Oct 12, 2021

Thanks! The new description is great.

Thanks also for reporting the broken link. I pushed a fix to master.

Everything's on one page to make searching easier. This way, people can ctrl-f to find all the examples that use syntax-parameterize etc. without having to click through a bunch of pages. I know it looks unfriendly, but I think this way is more useful.

@countvajhula
Copy link
Contributor

Ah, yeah that's probably one of my main difficulties with Racket docs in general - ie. the lack of full text (incl. within collection) search, which would make relying on Ctrl-f unnecessary. Another alternative here could be to have several TOCs indexing the macros. Like "Examples by Name", and "Examples by Topics Covered."

In any case, this looks good to me, and thank you for organizing this 😄

@bennn bennn merged commit cd8d8d1 into master Oct 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants