I made this macro for exactly for the same reason :)

https://gist.github.com/ruliana/80d7bb46225a22a3682711ca8bd11a1d

@JohnClements, I guess you have a point :) but I think David is mostly
talking about what we call "Guard Clauses" (
http://refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html),
good or bad, they are a tool for simplifying code. But I agree, don't
overdo it ^_^

Macro copied below for convenience (btw, sorry for the code, Racket is not
my main programming language... yet)


#lang racket (require racket/stxparam)
(provide return
define/guard)
(define-syntax-parameter return
(λ (stx)
(raise-syntax-error (syntax-e stx) "can only used inside \"define/guard\""
)))
(define-syntax-rule (define/guard (name args ...) body0 body ...)
(define (name args ...)
(let/cc ret
(syntax-parameterize ([return (make-rename-transformer #'ret)])
body0
body ...))))
(define/guard (test2 a b)
(when (> a b) (return 456))
(displayln "hehehe")
123)

Em ter, 22 de nov de 2016 às 05:24, <racket-users@googlegroups.com>
escreveu:

> racket-users@googlegroups.com
> <https://groups.google.com/forum/?utm_source=digest&utm_medium=email#!forum/racket-users/topics>
>  Google
> Groups
> <https://groups.google.com/forum/?utm_source=digest&utm_medium=email/#!overview>
> <https://groups.google.com/forum/?utm_source=digest&utm_medium=email/#!overview>
> Topic digest
> View all topics
> <https://groups.google.com/forum/?utm_source=digest&utm_medium=email#!forum/racket-users/topics>
>
>    - What is the Racket equivalent to 'return' for early exit?
>    <#m_-7182901911078251811_group_thread_0> - 10 Updates
>
> What is the Racket equivalent to 'return' for early exit?
> <http://groups.google.com/group/racket-users/t/111743b363e0afa8?utm_source=digest&utm_medium=email>
> David Storrs <david.sto...@gmail.com>: Nov 21 09:37AM -0800
>
> In Perl I would often write:
>
> sub do_something {
> return unless ( some necessary condition is met );
> ... do the thing ...
> }
>
> In Racket I could wrap the rest of the procedure in an (if), but that adds
> an unnecessary level of indentation and feels clunky. Is there a clean
> solution?
> David Storrs <david.sto...@gmail.com>: Nov 21 09:41AM -0800
>
> Edit: I know I could also use call/cc and invoke the continuation to
> escape, but that still adds another layer of indentation for something that
> in the normal case won't be called.
>
> It's not a big deal, but I was wondering about it.
>
> On Mon, Nov 21, 2016 at 9:37 AM, David Storrs <david.sto...@gmail.com>
> wrote:
>
> George Neuner <gneun...@comcast.net>: Nov 21 01:04PM -0500
>
> On 11/21/2016 12:41 PM, David Storrs wrote:
>
> > In Racket I could wrap the rest of the procedure in an (if), but
> > that adds an unnecessary level of indentation and feels clunky.
> > Is there a clean solution?
>
> In Racket, IF requires both alternatives be specified. What's wrong
> with WHEN or UNLESS?
>
> (define (do-something)
> (unless (some necessary condition is met)
> ... do the thing(s) ...)
> )
>
> George
> Leif Andersen <l...@leifandersen.net>: Nov 21 01:07PM -0500
>
> Honestly, I personally like to use let/ec for this. I know it's still using
> continuations, but it is much more lightweight, both syntactically and in
> terms of run-time costs.
>
> (define (do-something)
> (let/ec return
> (unless (some-condition)
> (return NO))
>
> (do-the-thing)))
>
> Although honestly, with this pattern, I find that errors work better here,
> as they return early, and you can decide how they get handled with a
> with-handlers.
>
> (define (do-something)
> (unless (some-condition)
> (error "NO"))
> (do-the-thing))
>
> (with-handlers ([exn:fail? (lambda (e) (displayln "I returned early"))])
> (do-something))
>
> But that is specifically because I prefer the workflow of catching errors,
> rather than always having to manually check the output of the function....
> (I'm looking at you C...)
>
> Hope that helps.
>
>
> ~Leif Andersen
>
> On Mon, Nov 21, 2016 at 12:41 PM, David Storrs <david.sto...@gmail.com>
> wrote:
>
> "John Clements" <cleme...@brinckerhoff.org>: Nov 21 01:30PM -0500
>
> > ... do the thing ...
> > }
>
> > In Racket I could wrap the rest of the procedure in an (if), but that
> adds an unnecessary level of indentation and feels clunky. Is there a clean
> solution?
>
> Playing the role of irritating ideologue, it’s … me!
>
> Yes, there’s let/ec, but my (limited) experience in industry suggests that
> reading functions that use ‘return’ liberally can be massively more
> difficult than one that uses ‘if’ or a related form. I would argue that the
> call/ec doesn’t actually make the code less clunky, it just hides the
> clunkiness, and makes the code harder to read, to boot. In the absence of
> return, you can generally easily deduce when control flow reaches a
> particular point (“we only get here if x is > 0 and the string is empty”).
> In the presence of return, this becomes “we only get here if x is > 0 and
> the string is empty and one of these 19 incomprehensible clauses didn’t
> trigger a return.”
>
> I do think that call/ec makes sense in some circumstances; for instance,
> if you want to bail out of a deeply nested call, and the intervening calls
> are to functions that someone else wrote. But generally, I try to bite the
> bullet and use the if (or cond), on the theory that when I come to read my
> own code next year I’ll have some idea what it’s doing.
>
> BTW: yes, my soapbox is huge. Huge!
>
> John
> "Norman Gray" <nor...@astro.gla.ac.uk>: Nov 21 06:33PM
>
> David, hello.
>
> On 21 Nov 2016, at 17:37, David Storrs wrote:
>
> > return unless ( some necessary condition is met );
> > ... do the thing ...
> > }
>
> One (not-really-an-)answer is that that's an intrinsically procedural
> way of thinking about the function, which is therefore 'un-schemey', and
> going against the grain. That seems a good answer if you attach a
> particular value to idiomatic code, less so otherwise.
>
> Another answer is to write something like
>
> (or (and (necessary-condition-not-met) 'early-return-value)
> ;; other guards?...
> (do-the-thing))
>
> If (necessary-condition-not-met) is true, then this expression will
> evaluate to 'early-return-value. That does add the extra level of
> indentation you didn't want, but it may look quite natural (or hideous),
> depending on the precise circumstances.
>
> A third answer is, as you mentioned, calling with call/cc. Calling
> explicitly with call/cc might indeed look untidy, but if this is
> something you're using in a couple of places, then it's possible to wrap
> it up prettily:
>
> (require racket/stxparam)
> (define-syntax-parameter check
> (lambda (stx)
> (raise-syntax-error (syntax-e stx) "can only be used inside
> do-something-while-checking")))
>
> (define-syntax-rule (do-something-while-checking form . forms)
> (call/cc (lambda (*bail-out)
> (define (check* ok?) ; ok? must be a thunk
> (or (ok?) (*bail-out 'early-return-value)))
> (syntax-parameterize ((check (make-rename-transformer
> #'check*)))
> form . forms))))
>
> (define (necessary-condition-met) #f)
> (do-something-while-checking
> (check necessary-condition-met)
> (printf "hello2~%"))
>
> All the best,
>
> Norman
>
>
> --
> Norman Gray : https://nxg.me.uk
> SUPA School of Physics and Astronomy, University of Glasgow, UK
> David Storrs <david.sto...@gmail.com>: Nov 21 10:35AM -0800
>
> Okay, that makes sense. Thanks, all.
>
> On Mon, Nov 21, 2016 at 10:07 AM, Leif Andersen <l...@leifandersen.net>
> wrote:
>
> David Storrs <david.sto...@gmail.com>: Nov 21 10:40AM -0800
>
> On Mon, Nov 21, 2016 at 10:30 AM, 'John Clements' via Racket Users <
>
> > Yes, there’s let/ec, but my (limited) experience in industry suggests
> that
> > reading functions that use ‘return’ liberally can be massively more
> > difficult than one that uses ‘if’ or a related form.
>
>
> I mostly agree with you. I've found that functions should have at most two
> return points: one at the top and one at the bottom. The one at the top
> is just for checking preconditions before you start doing real work, the
> one at the bottom is the happy path result.
>
>
> > BTW: yes, my soapbox is huge. Huge!
>
> I think you meant 'yuje'. Or perhaps 'bigly'? ;>
>
>
>
> "Norman Gray" <nor...@astro.gla.ac.uk>: Nov 21 06:47PM
>
> Greetings.
>
> On 21 Nov 2016, at 18:07, Leif Andersen wrote:
>
> > rather than always having to manually check the output of the
> > function....
> > (I'm looking at you C...)
>
> On reflection, I think this is a better answer than mine (and is
> probably what I'd do in fact).
>
> Apart from anything else, it means that (do-something) will only return
> the type of thing it's supposed to return, and not anything that needs
> checked. That would be still more important if you were using Typed
> Racket.
>
> All the best,
>
> Norman
>
>
> --
> Norman Gray : https://nxg.me.uk
> SUPA School of Physics and Astronomy, University of Glasgow, UK
> Matthew Butterick <m...@mbtype.com>: Nov 21 10:59AM -0800
>
> > return unless ( some necessary condition is met );
> > ... do the thing ...
> > }
>
>
>
> On Nov 21, 2016, at 10:07 AM, Leif Andersen <l...@leifandersen.net> wrote:
>
> > (do-the-thing))
>
> > (with-handlers ([exn:fail? (lambda (e) (displayln "I returned early"))])
> > (do-something))
>
>
> I agree with Leif. I've learned this pattern from studying well-written
> Racket code.
>
> As I understand it, the policy idea is that when a called function doesn't
> do what it was asked to do, then the caller of the function — not the
> called function — should get to decide how serious a problem it is. So
> `error` / `with-handlers` is the best idiom.
>
> I think of `return` as a way for a function to deliver its *expected
> result*, in the special circumstance where it has to bust out of a deeply
> nested block. IOW, `return` is not for error conditions.
> Back to top <#m_-7182901911078251811_digest_top>
> You received this digest because you're subscribed to updates for this
> group. You can change your settings on the group membership page
> <https://groups.google.com/forum/?utm_source=digest&utm_medium=email#!forum/racket-users/join>
> .
> To unsubscribe from this group and stop receiving emails from it send an
> email to racket-users+unsubscr...@googlegroups.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.
For more options, visit https://groups.google.com/d/optout.

Reply via email to