Re: [racket-users] Re: Escape continuations for fussy code

2021-10-20 Thread Ryan Kramer
 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  
> 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 
>> .
>> 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  
>>> wrote: 
>>> > 
>>> > > On Fri, Oct 01, 2021 at 02:22:14PM +, 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 

Re: [racket-users] Re: Escape continuations for fussy code

2021-10-03 Thread Laurent
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 
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
> .
> 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 
>> wrote:
>> >
>> > > On Fri, Oct 01, 2021 at 02:22:14PM +, 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+unsubscr...@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
> 
> .
>

-- 
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 

Re: [racket-users] Re: Escape continuations for fussy code

2021-10-02 Thread jackh...@gmail.com
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 
.
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  
> wrote:
> > 
> > > On Fri, Oct 01, 2021 at 02:22:14PM +, 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+unsubscr...@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.


Re: [racket-users] Re: Escape continuations for fussy code

2021-10-01 Thread Hendrik Boom
On Fri, Oct 01, 2021 at 02:32:52PM -0400, David Storrs wrote:
> On Fri, Oct 1, 2021 at 11:58 AM Hendrik Boom  wrote:
> 
> > On Fri, Oct 01, 2021 at 02:22:14PM +, 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+unsubscr...@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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/20211001195320.4wtga4tjwgo75jhz%40topoi.pooq.com.


Re: [racket-users] Re: Escape continuations for fussy code

2021-10-01 Thread David Storrs
On Fri, Oct 1, 2021 at 11:58 AM Hendrik Boom  wrote:

> On Fri, Oct 01, 2021 at 02:22:14PM +, 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

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+unsubscr...@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.