Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

have a function in Scheme return value (or do something else) and call itself

Tags:

scheme

I would like to have two expressions evaluated in function body. How would I go about it?

Given the following:

(define (f)
  ((+ 2 2) (+ 4 4)))

I would like both to have 2+2 and 4 + 4 evaluated (obviously the above doesn't work).

Basically, if I understand it correctly, in a spot where I can get a single thing done, I would like to have two things done. For example instead of calling just one function as a consequent in the if expression, I'd like to call two functions. Or ideally return a value and have the function call itself.

I am not sure if this makes sense but conceptually having such a mechanism seems plausible.

like image 915
dreamwalker Avatar asked Feb 27 '26 20:02

dreamwalker


1 Answers

The body of a procedure evaluates from top-to-bottom, no matter how many expressions are at the beginning, only the value of the last one is returned. For instance, if we write this:

(define (f)
  (+ 2 2)  ; evaluates to 4, but we don't do anything with it, so it's lost
  (+ 4 4)) ; evaluates to 8, this is the returned value

... When we call (f) the returned value is 8, the first expression's value is lost. Perhaps you meant to say, that you want multiple values returned? this is possible depending on the interpreter, for instance in Racket:

(define (f)
  (values (+ 2 2) (+ 4 4)))

(f)
=> 4
   8

Now (f) returns two values, if we are going to use them, we need special forms to "capture" the multiple returned values. In this example, I'll use let-values:

(let-values (((x y) (f))) ; 4 is bound to x, 8 is bound to y
  (+ x y))
=> 12

Another interpretation of your question, regarding the use of an if expression: if you need to write more than one expression inside an if, then you have to pack all the expressions inside a begin form (by the way: the body of a procedure is implicitly inside a begin).

But again, even tough all the expressions are executed in sequence, only the value of the last one is returned as a result - so all the expressions in the middle should be executed only for the effect, not for the value. For example:

(if (= 1 1)    ; condition is true
    (begin     ; execute a sequence of expressions
      (+ 2 2)  ; evaluates to 4, but the value is lost
      (+ 4 4)) ; evaluates to 8, this is the returned value
    (begin
      (+ 1 1)
      (+ 3 3)))
=> 8

Of course, in the above example it'd be simpler to just use a cond, which has an implicit begin. This is equivalent to the previous snippet:

(cond
  ((= 1 1)   ; condition is true, implicit `begin`
   (+ 2 2)   ; evaluates to 4, but the value is lost
   (+ 4 4))  ; evaluates to 8, this is the returned value
  (else
   (+ 1 1)
   (+ 3 3)))
=> 8
like image 123
Óscar López Avatar answered Mar 01 '26 11:03

Óscar López