What is the “return” in scheme?

2019-07-22 13:35发布

I am trying to translate some python code to scheme.

def test(x):
    if x > 1:
        do something
    if x > 10:
        return
    if x == 4: 
        do something
test(11)

I did not find the "return" in scheme. I want to quit from the test function when x >10. How can I simulate the "return" in scheme? (I am using guile) Thanks

标签: scheme
5条回答
聊天终结者
2楼-- · 2019-07-22 13:49

In Scheme there isn't an explicit return keyword - it's a lot simpler than that, the value of the last expression in a sequence of expressions is the one that gets returned. For example, your Python code will translate to this, and notice that the (> x 10) case had to be moved to the bottom, so if it's true it can exit the function immediately with a #f value.

(define (test x)
  (if (> x 1)
      (do-something))
  (if (= x 4)
      (do-something))
  (if (> x 10)
      #f))

(test 11)
=> #f

In fact, after reordering the conditions we can remove the last one, but beware: an unspecified value will be returned if x is not 4, according to Guile's documentation - in other words, you should always return a value in each case, and an if expression should have both consequent and alternative parts.

(define (test x)
  (if (> x 1)
      (do-something))
  (if (= x 4)
      (do-something)))

(test 11)
=> unspecified

And by the way, I believe the logic in the Python code is a bit off. The first condition will always be evaluated whenever a value of x greater than 1 is passed, but if it is less than or equal to 1 the returned value in Python will be None and in Scheme is unspecified. Also the original function isn't explicitly returning a value - in Python this means that None will be returned, in Scheme the returned value will be either (do-something) if x happens to be 4, or unspecified in any other case.

查看更多
倾城 Initia
3楼-- · 2019-07-22 13:57

You may use call/cc

(define (test x) (call/cc (lambda (k)
                          (if x 
                             (k x)
                             (k))
                          (display "never displayed"))))
> (test 3)

3
> (test #f)

> 

You can return no value using (k).

Read about Continuations.

查看更多
做个烂人
4楼-- · 2019-07-22 13:58

As others have said, the last expression's value in a function is its return value, so you just have to arrange for exclusive execution pathways in your code, to achieve this effect.

(if <test> <consequent> <alternative>) is the basic branching operation in Scheme:

(define (test x)
    (if (> x 1)      
        (do_something)
        #f)
    (if (> x 10)
        #f                ; return #f
        ;; else:
        (if (= x 4)
           (do_something)
           ;; else:
           #f)))

(test 11)

Or we could use cond to avoid the needlessly nested structure in the code:

(define (test x)
    (if (> x 1)
        (do_something)
        #f)
    (cond
       ( (> x 10)  #f)
       ( (= x 4)   (do_something))
       ( else      #f)))
查看更多
在下西门庆
5楼-- · 2019-07-22 14:01

In Racket the most literal translation is:

#lang racket    
(define (test x)
  (let/ec return
    (when (> x 1)
      (do-something))
    (when (> x 10)
      (return 42))
    (when (= x 4)
      (do-something))))

(define (do-something)
  (display "!"))
(test 11)

The let/ec is short for let/escape-continuation. Look up the equivalent control structure in the manual for your Scheme implementation of choice.

The example displays one ! and then returns 42.

查看更多
Ridiculous、
6楼-- · 2019-07-22 14:01

The implicit return of Scheme can be illustrated by comparing how you can implement a simple function, such as square, in Python and scheme.

In Python:

def square(x):
   return x*x;

In Scheme:

(define (square x)
  (* x x))
查看更多
登录 后发表回答