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 [email protected] 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 [email protected] <[email protected]> 
> 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 [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
>>  
>> <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 [email protected].
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