@@ -1081,25 +1081,40 @@ different.
10811081
10821082A flipped version of @racket[=<<].}
10831083
1084- @defform[#:literals [<-]
1084+ @defform[#:literals [<- let letrec ]
10851085 (do do-clause ... monadic-expr)
10861086 #:grammar
1087- ([do-clause [binding-id <- monadic-expr]
1088- monadic-expr])]{
1087+ ([do-clause monadic-do-clause
1088+ pure-do-clause]
1089+ [monadic-do-clause [binding-id <- monadic-expr]
1090+ monadic-expr]
1091+ [pure-do-clause (let binding-pair ... )
1092+ (letrec binding-pair ... )])]{
10891093
10901094A convenient, imperative-style shorthand for a sequence of monadic expressions chained together with
10911095@racket[>>=]. Each @racket[do-clause] corresponds to a single use of @racket[>>=], and each
10921096@racket[monadic-expr] must have a type with the shape @racket[(_m _a)], where @racket[_m] is a
10931097@racket[t:Monad].
10941098
1095- Any use of @racket[do ] with a single subform expands to the subform: @racket[(do _expr)] is equivalent
1096- to @racket[_expr]. Each @racket[do-clause] introduces a use of @racket[>>=], with the result
1097- potentially bound to a @racket[binding-id]. That is, @racket[(do [_x <- _m] _more ...+)] expands to
1098- @racket[{_ma >>= (λ [_x] (do _more ... ))}], and @racket[(do _m _more ...+)] expands to
1099- @racket[{_ma >>= (λ [_ ] (do _more ... ))}].
1100-
1101- This is often much more readable than writing the uses of @racket[>>=] out by hand, especially when
1102- the result of each action must be give a name.
1099+ The @racket[do ] form is desugared using the following rules:
1100+
1101+ @itemlist[
1102+ #:style 'ordered
1103+ @item{Any use of @racket[do ] with a single subform expands to the subform—@racket[(do _expr)] is
1104+ equivalent to @racket[_expr].}
1105+ @item{Each @racket[monadic-do-clause] introduces a use of @racket[>>=], with the result potentially
1106+ bound to a @racket[binding-id]. That is, @racket[(do [_x <- _m] _more ...+)] expands to
1107+ @racket[{_ma >>= (λ [_x] (do _more ... ))}], and @racket[(do _m _more ...+)] expands to
1108+ @racket[{_ma >>= (λ [_ ] (do _more ... ))}].}
1109+ @item{Each @racket[pure-do-clause] produces a local binding form @emph{without} any uses of
1110+ @racket[>>=], which is useful to create local bindings that are not monadic.
1111+ @racket[(do (let binding-pair ... ) _more ...+)] expands to
1112+ @racket[(let (binding-pair ... ) (do _more ... ))], and
1113+ @racket[(do (letrec binding-pair ... ) _more ...+)] expands to
1114+ @racket[(letrec (binding-pair ... ) (do _more ... ))].}]
1115+
1116+ Using @racket[do ] is often much more readable than writing the uses of @racket[>>=] out by hand,
1117+ especially when it is helpful to give the result of each action a name.
11031118
11041119@(hackett-examples
11051120 (do [xs <- (tail {1 :: 2 :: 3 :: 4 :: Nil})]
@@ -1109,7 +1124,21 @@ the result of each action must be give a name.
11091124 (do [xs <- (tail {1 :: 2 :: 3 :: Nil})]
11101125 [ys <- (tail xs)]
11111126 [zs <- (tail ys)]
1112- (head zs)))}
1127+ (head zs))
1128+ (eval:alts
1129+ (do (let [x 1 ]
1130+ [y 2 ])
1131+ (println {"x is " ++ (show x)})
1132+ (println {"y is " ++ (show y)})
1133+ (let [z {x + y}])
1134+ (println {"x + y is " ++ (show z)}))
1135+ (unsafe-run-io!
1136+ (do (let [x 1 ]
1137+ [y 2 ])
1138+ (println {"x is " ++ (show x)})
1139+ (println {"y is " ++ (show y)})
1140+ (let [z {x + y}])
1141+ (println {"x + y is " ++ (show z)})))))}
11131142
11141143@defthing[ap (t:forall [m a b] (t:Monad m) t:=> {(m {a t:-> b}) t:-> (m a) t:-> (m b)})]{
11151144
0 commit comments