What is the return statement in Scheme?
Asked Answered
H

7

5

I am trying to translate this Python program to Scheme:

def test(x):
    if x > 1:
        print('foo')
    if x > 10:
        return
    if x == 4: 
        print('bar')


test(1)
test(2)   # prints 'foo'
test(4)   # prints 'foo\nbar'
test(11)  # prints 'foo'

What is the return statement in Scheme?

Hussey answered 27/4, 2014 at 19:24 Comment(3)
So in your example do something does something that result in a side effect? Perhaps if you said what the function was suppose to do we could make a more idiomatic Scheme version for you to look at. The answers so far try to mimic you code and is pretty bad Scheme.Precatory
@Maggyero Don't edit 8-year-old questions with what you think the OP might have meant.Altimetry
@Altimetry It is not correct Python code and Sylwester asked if do something has a side effect (which of course it has), so I addressed both issues and added an answer as the only simple and correct answer was in Adam Rosenfield’s comment.Canescent
P
5

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.

Pickle answered 27/4, 2014 at 19:36 Comment(4)
This isn't really a faithful translation of the python code, which would have performed the actions for part 1 and 2.Balaam
@Balaam you're right, I updated my answer with a direct translationUnpaged
A more faithful translation would be (define (test x) (if (> x 1) (do-something)) (if (not (> x 10)) (if (= x 4) (do-something)))), since if (x) return; {block} is equivalent to if (!x) {block}.Disabled
@amalloy: Well, you could use call/cc here for an escape continuation :)Natatorial
C
4

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.

Coburg answered 28/4, 2014 at 9:0 Comment(1)
It is a Scheme question, not a Racket question. How difficult is it to replace let/ec with call/cc to help the OP directly?Lilah
P
2

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))
Puncture answered 28/4, 2014 at 4:50 Comment(0)
K
1

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)))
Kaplan answered 29/4, 2014 at 18:29 Comment(0)
S
0

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.

Subjectivism answered 9/3, 2015 at 5:6 Comment(0)
F
0

I meet same question as you asked when I tried to implement a "tile" function to duplicate a list for multiple times. The idea is 1) create a variable to store the temporary result; 2) use "append" function in a for-loop; 3) return the temporary result.

The solution seems easy, as follows:

(define (tile ls n) 
    (define r (list ))
    (do ((i 0 (+  i 1)))
        ((> i (- n 1)))
        (begin
            (set! r (append r ls))
        )
    )
    r
)

actually a sole variable name itself will let the whole function return the value of this variable. This is because the Scheme always returns the last executed statement as the value of this function.

Foliose answered 11/4, 2020 at 10:20 Comment(0)
W
0

There is no return statement in Scheme. The body of a procedure is a sequence of expressions and the return value is the value of the last expression. So here is an equivalent Scheme program:

(define (test x)
  (if (> x 1)
    (display "foo\n"))
  (if (not (> x 10))
    (if (= x 4)
      (display "bar\n"))))


(test 1)
(test 2)   ; prints "foo"
(test 4)   ; prints "foo\nbar"
(test 11)  ; prints "foo"

You can simplify it to this program:

(define (test x)
  (if (> x 1)
    (display "foo\n"))
  (if (= x 4)
    (display "bar\n"))))
Wench answered 26/10, 2022 at 14:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.