2

I need to implement a function that takes one or more expressions and executes those expressions in order.

This is what I have so far:

(define (foo exp0 exp1 ) exp0 exp1)
  • Can you reproduce the question as it appears in the textbook? What you're describing isn't a function, but rather a macto. What you have so far is a function that takes two _values_ as arguments, and then returns the second of them. – Joshua Taylor Oct 09 '13 at 18:30
  • OK, so it is talking about implementing an operator/operation, not a function. I just wanted to be sure of that. I see this is your first question on StackOverflow. You should be able to edit your question, and adding this kind of clarification is a good example of why what functionality exists. I'll edit it in for now, but in the future, feel free to update your question with clarification; it's easier to find, and not everyone reads the comments. – Joshua Taylor Oct 09 '13 at 18:44
  • Why did you remove the question that I edited in (which you previously posted in a comment)? It added necessarily clarification. For instance, as stated, this is impossible; you can't define a _function_ that will do this. The quoted question, however, makes it clear that you're after an operator that you can define with `define-syntax-rule`, as [uselpa's answer](http://stackoverflow.com/a/19280458/1281433) explains. – Joshua Taylor Oct 09 '13 at 19:30

3 Answers3

1

Assuming you have the following expression

(sequence form1 form2 form3)

and you want the forms to be evaluated in order, then you can't pass them to a function as Josuha explained. The easiest transformation would be to change the above to

((lambda () form1 form2 form3))

since the forms in a lambda expression are executed sequentially and the result is the value of the last form. Since this transformation has to be done at the source code level, you have to use a macro such as:

(define-syntax-rule (sequence form1 form2 ...)
  ((lambda () form1 form2 ...)))

which will transform an expression such as

(sequence (display "a") (display "b") (display "c"))

into

((lambda () (display "a") (display "b") (display "c")))

which will execute the forms in sequence.

uselpa
  • 18,732
  • 2
  • 34
  • 52
  • This won't work as evaluation order of a form is unndefined.eg. ikarus would display "c" first and it's ok according the spec. – Sylwester Oct 09 '13 at 19:09
  • @Sylwester How could you write a procedure if the forms were evaluated at random? – uselpa Oct 09 '13 at 19:11
  • @Sylwester I agree with uselpa. I sort of overengineered the problem in my answer, since I was thinking about getting _function arguments_ evaluated in left to right order. The body of a function must be evaluated in top to bottom order, though. Otherwise, something like `(lambda (x) (display x) (set! x 10))` could _either_ print `10` or the original value of `x`. – Joshua Taylor Oct 09 '13 at 19:26
  • My mistake. I though the `display` forms were arguments but as it's in a lambda body it has explicit begin and the most efficient way of doing it. – Sylwester Oct 09 '13 at 20:58
0

Scheme doesn't specify any particular argument evaluation order. This means that if you have a display-and-return function:

(define (display-and-return x)
  (display x)
  x)

and you then call, for instance,

(list (display-and-return 1) (display-and-return 2))

you're guaranteed to get the result (1 2), but you could see the output produced by display as either 12 or 21. However, Scheme does specify that the arguments to a function will be evaluated before the body of the function is evaluated. So, you could sequence two expressions by making them arguments to functions:

((lambda (val1)
   ((lambda (val2)
      (list val1 val2))
    (display-and-return 2)))
 (display-and-return 1))

In general, you could use a transformation like this to turn (seq exp1 exp2 ... expm expn) into

((lambda (val1)
   ((lambda (val2)
      ...
        ((lambda (valm)
           expn)        ; or ((lambda (valn) valn) expn)
         expm) ... )
    exp2))
 exp1)

You can define that sort of transformation using define-syntax-rule.

Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • @user1025948 [uselpa's answer](http://stackoverflow.com/a/19280458/1281433) is better than this one. Because I started by pointing out that function arguments can be evaluated in any order, I continued by showing how you could make arguments to a function be evaluated in left to right fashion (so the innermost body would be a call to the function with the variables). This isn't necessary just for sequencing, though. As uselpa pointed out, you can just make the forms be the body of a lambda expression. – Joshua Taylor Oct 09 '13 at 19:28
  • This would work in one of the HtDP languages which requires only one form in the lambda body. – Sylwester Oct 09 '13 at 21:06
  • @Sylwester In fact, this would be a way of implementing lambda functions that could accept multiple forms in their body (just use throwaway variables in the lambda arglists that don't appear in the body). (In fact, that's the approach I took when implementing a λ-calculus interpreter not too long ago…) – Joshua Taylor Oct 09 '13 at 21:09
-1

You need something that takes 'one or more expressions' and then evaluates them and returns the last one. This could be defined with:

(define (sequence exp1 . exps)
  (car (reverse (cons exp1 exps))))       ; (if (null? exps) exp1 ...)

You would then invoke it as:

> (sequence (+ 1 2) (* 1 2) 17)
17

Using define-syntax stuff isn't needed as standard function application will 'execute those expressions in order'

If you need the order to be guaranteed as left-to-right, then you'll need:

(define-syntax sequence
  (syntax-rules ()
    ((sequence exp exps ...)
     (begin exp expos ...))))

but if you can't use begin, but can use lambda, then:

(define-syntax sequence
  (syntax-rules ()
    ((sequence exp exps ...)
     ((lambda () exp exps ...)))))
GoZoner
  • 67,920
  • 20
  • 95
  • 145