I guess I'll pile on too. My approach was `let++` which I rename to `let*` 
because (I think) it is backwards compatible. The pattern for early exit is 
`#:break (when test-expr result-expr)` so the previous example would look 
like this:

(let* (#:break (when (not (foo? x))
                 #f)
       [y (bar x)]
       [z (jazz x y)]
       #:break (when (not (loopy? z))
                 #f)
       [a (yowza z)]
       #:break (when (not (string? a))
                 'ugh)
       [b (bonkers a)]
       #:break (when (not (number? (hoop x b)))
                 'um))
  (list x y z a b))

In practice, this allowed me to rewrite a lot of functions that were highly 
nested into a single let++ form.

The other feature of let++ is that it also supports let-values. (Having to 
nest "let, then let-values, then let again" was another reason my code 
would get too indented for my taste.)

Implementation: https://github.com/default-kramer/fission-flare/blob/
master/src/util/let%2B%2B.rkt
Example: https://github.com/default-kramer/fission-flare/blob/
d6e71353dbd53e0d00d71e0e7911caca6455c4db/src/core/state.rkt#L266


On Sunday, October 3, 2021 at 9:45:28 AM UTC-5 laurent...@gmail.com wrote:

> Oh well, since everyone is at it, here's my version that no-one asked for. 
> It's similar to parendown, but uses a more standard (but also specific) 
> macro `cond/else` from 
> https://github.com/Metaxal/bazaar/blob/master/cond-else.rkt :
>
> (*cond/else*
>  [(*not* (foo? x)) #f]
>  #:else
>
>  (*define* y (bar x))
>  (*define* z (jazz x y))
>  #:cond
>  [(*not* (loopy? z)) #f]
>  #:else
>  (*define* a (yowza z))
>  #:cond
>  [(*not* (string? a))
>   (error 'ugh)]
>  #:else
>  (*define* b (bonkers a))
>  #:cond
>  [(number? (hoop x b))
>   (*define* ...)]
>  #:else
>  (*error* 'um))
>
> I find the different coloration of the keywords helpful to parse the code 
> too.
>
> Now waiting for more original solutions to this problem :-)
>
>
> On Sat, Oct 2, 2021 at 9:09 PM jackh...@gmail.com <jackh...@gmail.com> 
> wrote:
>
>> 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 hen...@topoi.pooq.com 
>> 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 <hen...@topoi.pooq.com> 
>>> 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 racket-users...@googlegroups.com. 
>>> > 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 racket-users...@googlegroups.com.
>>
> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/racket-users/262c0b9d-6d51-4e03-adcf-0efa3fb76f61n%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/racket-users/262c0b9d-6d51-4e03-adcf-0efa3fb76f61n%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>

-- 
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 racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/d550bbe5-39f6-48f6-9c16-01e7683eb816n%40googlegroups.com.

Reply via email to