Here's my solution:

(define/guard (f x)
  (guard (foo? x) else
    #false)
  (define y (bar x))
  (define z (jazz x y))
  (guard (loopy? z) else
    #false)
  (define a (yowza z))
  (guard (string? a) else
    (error 'ugh))
  (define b (bonkers a))
  (guard (number? (hoop x b)) else
    (error 'um))
  (define ...))

It uses a `guard` macro I wrote and talked about in this thread 
<https://groups.google.com/g/racket-users/c/H-EppBmQ7oU>.
On Friday, October 1, 2021 at 12:53:25 PM UTC-7 [email protected] wrote:

> On Fri, Oct 01, 2021 at 02:32:52PM -0400, David Storrs wrote:
> > On Fri, Oct 1, 2021 at 11:58 AM Hendrik Boom <[email protected]> 
> wrote:
> > 
> > > On Fri, Oct 01, 2021 at 02:22:14PM +0000, Jesse Alama wrote:
> > > > Hello,
> > > >
> > > > Have you ever wished you could do a C-style return in the middle
> > > > of a block of Racket code? When you're in the heat of things with
> > > > a complicated problem where input values need a fair amount of
> > > > multi-stage extraction and validation, using cond quickly pulls
> > > > code to the right. My procedure is:
> > > >
> > > > * cond/case. In each branch:
> > > > * Define some new values safe in the knowledge of where you are
> > > > (extract) and perhaps check them, if necessasry (validate)
> > > > * Make sure you have an else branch.
> > > > * return to 1 and repeat as many times as necessary.
> > > >
> > > > The result:
> > > >
> > > > (cond [(foo? x)
> > > > (define y (bar x))
> > > > (define z (jazz x y))
> > > > (cond [(loopy? z)
> > > > (define a (yowza z))
> > > > (cond [(string? a)
> > > > (define b (bonkers a))
> > > > (cond [(number? (hoop x b))
> > > > (define ...)]
> > > > [else
> > > > (error 'um)])]
> > > > [else
> > > > (error 'ugh)])]
> > > > [else #f])]
> > > > [else #f])
> > >
> > >
> > I'm presuming that this code should either return #f, return a calculated
> > value, or raise an exception. If so, here's a version that runs in plain
> > racket that I find pretty easy to read. It has the advantage that the
> > 'return #f' parts aren't way far away from what causes them.
> > 
> > (with-handlers ([false? identity] ; return #f
> > [any/c raise]) ; re-raise everything else
> > (let* ([x (if (foo? x)
> > x
> > (raise #f))]
> > [z (jazz x (bar x))]
> > [a (if (loopy? z)
> > (yowza z)
> > (raise #f))]
> > [b (if (string? a)
> > (bonkers a)
> > (error 'ugh))])
> > (if (number? (hoop x b))
> > 'all-good
> > (error 'um))))
>
> Yes. But different semantics if bar, yowza, and bonkers have side effects.
> If they don't, they're quite equivalent.
>
> -- hendrik
>
> > 
> > If instead you want to return the exn that comes from error instead of
> > re-raising it then you can do that by removing the false? clause from the
> > with-handlers. NOTE: You should re-raise exn:break since otherwise the
> > user cannot ^C the program.
> > 
> > (with-handlers ([exn:break? raise]
> > [any/c identity])
> > ...put the let* code here...)
> > 
> > -- 
> > You received this message because you are subscribed to the Google 
> Groups "Racket Users" group.
> > To unsubscribe from this group and stop receiving emails from it, send 
> an email to [email protected].
> > To view this discussion on the web visit 
> https://groups.google.com/d/msgid/racket-users/CAE8gKodxas7jtze%2BttcFA%2BG0ATKUFZD3rhK%2B%3Dn2U1md1zQPJSg%40mail.gmail.com
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/262c0b9d-6d51-4e03-adcf-0efa3fb76f61n%40googlegroups.com.

Reply via email to