{"size": 2677, "ext": "scrbl", "max_stars_repo_path": "pyret-for/pyret-for.scrbl", "max_stars_repo_name": "bennn/syntax-parse-example", "max_stars_repo_stars_event_min_datetime": "2017-05-18T22:15:56.000Z", "max_stars_repo_stars_event_max_datetime": "2021-09-17T13:13:05.000Z", "max_issues_repo_path": "pyret-for/pyret-for.scrbl", "max_issues_repo_name": "bennn/syntax-parse-example", "max_issues_repo_issues_event_min_datetime": "2017-05-18T22:54:53.000Z", "max_issues_repo_issues_event_max_datetime": "2021-10-19T02:58:50.000Z", "max_forks_repo_path": "pyret-for/pyret-for.scrbl", "max_forks_repo_name": "bennn/syntax-parse-example", "max_forks_repo_forks_event_min_datetime": "2017-05-19T14:27:57.000Z", "max_forks_repo_forks_event_max_datetime": "2022-03-30T09:36:54.000Z"}
{"max_stars_count": 22, "max_issues_count": 20, "max_forks_count": 6, "avg_line_length": 35.2236842105, "max_line_length": 156, "alphanum_fraction": 0.6197235712}
#lang syntax-parse-example
@require[
  (for-label racket/base syntax/parse syntax-parse-example/pyret-for/pyret-for)]

@(define pyret-for-eval
   (make-base-eval '(require racket/math racket/list racket/string syntax-parse-example/pyret-for/pyret-for)))

@title{@tt{pyret-for}}
@stxbee2021["sorawee" 11]

@; =============================================================================

@defmodule[syntax-parse-example/pyret-for/pyret-for]{}

@defform[(pyret-for fn-expr ([pattern arg] ...) expr ...+)]{
  Many common higher-order functions consume a function value as the first
  argument, and @racket[_n] more arguments after that, where the function value
  accepts @racket[_n] arguments, which corresponds to the arguments in the call
  in some way.
  Examples include: @racket[map], @racket[filter] (only one argument),
  @racket[andmap], @racket[ormap].
  (@racket[foldl] and @racket[foldr] have arguments in a wrong order, so they
  don't quite work.)

  @examples[#:label @elem{Example without @racket[pyret-for]:} #:eval pyret-for-eval
    (define things     '(("pen") ("pineapple") ("apple") ("pen")))
    (define quantities '(1       2             3         5))

    (andmap (λ (thing quantity)
              (or (string-contains? (first thing) "apple")
                  (odd? quantity)))
            things
            quantities)

  ]

  The problem is that:

  @itemlist[
    @item{
      It is difficult for readers to relate formal arguments of the function
      value to the actual arguments of the call.
    }
    @item{
      There is a lot of rightward drift.
    }]

  @examples[#:label @elem{Example with @racket[pyret-for]:} #:eval pyret-for-eval
    (define things     '(("pen") ("pineapple") ("apple") ("pen")))
    (define quantities '(1       2             3         5))

    (pyret-for andmap ([thing things] [quantity quantities])
      (or (string-contains? (first thing) "apple")
          (odd? quantity)))
  ]

  The @racket[pyret-for] syntax, based on @hyperlink["https://www.pyret.org/docs/latest/Expressions.html#%28part._s~3afor-expr%29" @elem{Pyret's @tt{for}}],
  can be used to invoke this kind of higher-order function.

  @racket[pyret-for] additionally improves upon Pyret's for by allowing
  arbitrary match pattern.

  @examples[#:label @elem{Example with @racket[pyret-for] and match:} #:eval pyret-for-eval
    (define things     '(("pen") ("pineapple") ("apple") ("pen")))
    (define quantities '(1       2             3         5))

    (pyret-for andmap ([(list thing) things] [quantity quantities])
      (or (string-contains? thing "apple")
          (odd? quantity)))]

  Implementation:

  @racketfile{pyret-for.rkt}

}
