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])
the Racket package parendown (see
https://docs.racket-lang.org/parendown/index.html ) can reduce this a
lot:
(if (not #/ foo? x) #f
#/ begin
(define y (bar z))
(define z (jazz x y))
#/if (not #/ loopy? z) #f
#/ begin
(define a (yowza z))
#/if (not (string a)) (error 'ugh)
#/begin
(define b (bonkers a))
#/if (not (number? (hoop x b))) (error 'um)
(define ...)
)
Or, using let instead of define
(if (not #/ foo? x) #f
#/ let ((y (bar z)))
#/ let ((z (jazz x y)))
#/ if (not #/ loopy? z) #f
#/ let ((a (yowza z)))
#/ if (not (string a)) (error 'ugh)
#/ let ((b (bonkers a)))
#/ if (not (number? (hoop x b))) (error 'um)
#/ let ((...))
-- and presumably you wanted to do someting inside all there define's
)
Is this clearar?
There remain
* the ugly extra parentheses aroung each let-pair,
which is an unnecessary tradition once you use parendown,
and
* the 'not's after the 'if's.
which could be resolved with a three-argument check operator:
(check requirement errormessage stufftodoifok) -- essentially
an argument-reversed if.
but this is enough to eliminate the push off the right side of the page.
A heuristic when programming this way:
When a function takes several arguments, define it so that the
argument that is likely to be textually longer is at the end.
-- hendrik
>
> That's an awful lot of whitespace. We're getting dragged to the
> right. Pretty soon we're dealing with lines that have three dozen
> spaces at the front or more.
>
> At times, it can even get a bit silly just how deeply nested code
> can get. It can even degrade program comprehension for you &
> others. It can even impede your own coding by requiring you to
> scroll up to mentally re-construct the state you're in.
>
> This isn't necessarily a problem with Racket. I think it reflects
> of the inherent fussiness of some problems. And certainly, you
> can reformat the code differently to make the problem somewhat
> less severe.
>
> Nonetheless, I certainly have found myself envying those working
> in other languages where they can just bail out of a complicated
> computation by just returning a value. I mean, sure, I could
> raise an exception and bail out that way, right? It turns out
> there's a way: escape continuations. They permit a kind of
> C-style return-y programming in Racket. I've got an article (
>
https://click.convertkit-mail.com/92u52qdvngtnh535n9s9/3ohphkhq39xwevtr/aHR0cHM6Ly9saXNwLnNoL2VzY2FwZS1jb250aW51YXRpb25zLWZvci1mdXNzeS1jb2RlLw==
> ) up introducing escape continuations and give a simple
> real-world example from web programming.
>
> Happy hacking,
>
> Jesse
>
> Unsubscribe (
>
https://unsubscribe.convertkit-mail.com/92u52qdvngtnh535n9s9 ) |
> Update your profile (
>
https://preferences.convertkit-mail.com/92u52qdvngtnh535n9s9 ) |
> Moltkestrasse 3d, Mainz, RP 55118