Early short circuit return circuit?

I am trying to figure out how I can do an “early return” in a circuit without using a top-level if or cond type construct.

 (define (win b) (let* ((test (first (first b))) (result (every (lambda (i) (= (list-ref (list-ref bi) i) test)) (enumerate (length b))))) (when (and (not (= test 0)) result) test)) 0) 

For example, in the above code, I want win return test if the when condition is met, otherwise it returns 0. However, what happens is that the procedure will always return 0, regardless of the result of the when condition.

The reason I structure my code this way is because in this procedure I need to perform numerous complex checks (several blocks similar to let* in the example), and putting everything in a large cond will be very cumbersome.

+4
source share
4 answers

Here's how to use call / cc to build return yourself.

 (define (example x) (call/cc (lambda (return) (when (< x 0) (return #f)) ; more code, including possible more calls to return 0))) 

Some circuits define a macro called let / cc that lets you throw off some lambda noise:

 (define (example x) (let/cc return (when (< x 0) (return #f)) 0)) 

Of course, if your scheme does not allow it, let / cc be trivial to write.


This works because call / cc saves the point at which it was called as a continuation. It passes this continuation to its function argument. When a function calls this continuation, Scheme discards any call stack it has created so far and continues from the end of the / cc call. Of course, if a function never calls a continuation, then it just returns normally.

The continuations do not get truly intelligent until you start returning them from this function or maybe save them in the global data structure and call them later. Otherwise, they are similar to any structured-goto language expressions (while / for / break / return / continue / exceptions / conditions).


I don’t know what your complete code looks like, but it might be better to go with cond and decompose complex checks into separate functions. The need for return and let* usually a symptom of overly peremptory code. However, the call / cc method should now work with your code.

+7
source

One way would be to use recursion instead of a loop, then an early exit would be achieved, not recursive.

+1
source

You can use the "continue with call" support to simulate a return. Here is an example on wikipedia . This function is called call-with-current-continuation , although there is often an alias call / cc that is exactly the same. There's also a slightly cleaner example here

Note. This is a fairly advanced method of programming the Scheme and may bend a little at first ... !!!!

0
source

In this case, you do not need it when you want to use if, although not at the top level.

 (define (win b) (let* ((test (first (first b))) (result (every (lambda (i) (= (list-ref (list-ref bi) i) test)) (enumerate (length b))))) (if (and (not (= test 0)) result) test 0))) 

The reason he always returned zero is whether the body of the one when it is executed, its result will be dumped to the floor. You see that lambda, implicit in the form of define functions, also creates an implicit start block, therefore

 (define foo (lambda (b) (begin (let ...) 0))) 

and getting started is that it returns the result of the last form inside, discarding all intermediate results on the floor. These intermediate results suggest side effects. You are not using any of this, which is fine (!), But you have to be careful to have only one form (the result of which you really want) inside the function definition.

Grem

0
source

Source: https://habr.com/ru/post/1303956/


All Articles