#lang scribble/manual @; To compile this: @; 1) Create a package development link: @; raco planet link cobbe bcond.plt 1 0 bcond @; 2) Create the package @; raco planet create bcond @; 3) Install the package @; raco planet fileinject cobbe bcond.plt 1 0 @(require (for-label racket) (for-label (planet cobbe/bcond:1/bcond)) (for-label syntax/parse) scribble/eval) @(define the-eval (make-base-eval)) @(the-eval '(require (planet cobbe/bcond:1/bcond))) @title{@bold{Bcond}: An Extended @racket[cond] Form} Version 1.0, November 2010 Richard Cobbe @defmodule[(planet cobbe/bcond:1/bcond)] This module defines a single form, @racket[bcond], that extends the built-in @racket[cond] form with the ability to specify (non-recursive) bindings among the @racket[cond] clauses, much like Haskell's @tt{do} construct allows @tt{let} bindings mixed in with the computations. @section{Definitions} @defform/subs[#:literals (cond begin) (bcond bcond-clause ...) ([bcond-clause [test-expr body-expr ...] [test-expr] [test-expr => proc-expr] [else body-expr ...] [let id expr] [let-values (id ...) expr]])]{ An extended conditional form, based on @racket[cond]. Evaluation of @racket[bcond] proceeds exactly as for @racket[cond], with the following exceptions: @specform[[else body-expr ...]]{ If execution reaches this clause, then the result of the @racket[bcond] expression is the result of @racket[(begin body-expr ...)], which is evaluated in tail-position with respect to the @racket[bcond] form. Unlike @racket[cond], however, this clause does not have to be the last clause in the form. (Although it is impossible for subsequent clauses to be evaluated, we deliberately allow this freedom to simplify the implementation of macros that expand into @racket[bcond].)} @specform[[let id expr]]{ This @racket[bcond-clause] binds @racket[id] to the value of @racket[expr] in all following @racket[bcond-clause]s. The right-hand side @racket[expr] is not evaluated unless evaluation falls through all preceding clauses. The expression @racket[expr] is not in tail position.} @specform[[let-values (id ...) expr]]{ This @racket[bcond-clause] evaluates @racket[expr], which must produce one value for each @racket[id], and then binds the @racket[id]s to the values of @racket[expr] in all following @racket[bcond-clause]s. As with @racket[let] clauses, @racket[expr] is not in tail position, and it is not evaluated unless all preceding clauses fall through.} } @examples[#:eval the-eval (define (my-filter f l) (bcond [(null? l) null] [let x (car l)] [(f x) (cons x (my-filter f (cdr l)))] [else (my-filter f (cdr l))])) (my-filter even? '(1 2 3 4 5)) ] In this example, @racket[bcond] allows us to bind @racket[x] to the first element of @racket[l] without having to split the conditional into multiple expressions. @section{Acknowledgments} Many thanks to Ryan Culpepper for developing @racket[syntax-parse] and helping troubleshoot problems with my first attempt at using it. @section{Copyright and License} This work is copyrighted and distributed under the terms of the Modified BSD License, included below. Copyright (c) 2010, Richard Cobbe. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @itemlist[ @item{Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.} @item{Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.} @item{The name of Richard Cobbe may not be used to endorse or promote products derived from this software without specific prior written permission.}] THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RICHARD COBBE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.