views:

135

answers:

5

Working with DrScheme (language-- Pretty Big). Trying to pass the result of an expression to a variable that can later be used in another expression. Here is a simplified version of the problem:

Definitions window:

(define (tot a b c) (+ a b c))

(define (tot2) (+ (tot a b c) 1))

Interpreter window

> (tot 5 6 7)

18

> (tot2)

.   . reference to undefined identifier: a

The result I want, of course, is 19. It would be easy to have DrScheme do all the algebra at once, but I need to have it solve the first expression, then solve the second expression based on the result of the first.

+4  A: 

Is this what you are looking for?

(define (tot a b c) (+ a b c))
(define (tot2 a b c) (+ (tot a b c) 1))

Then

(tot2 5 6 7)

should result in 19.


If you want tot2 assigned to the integer value rather than to a function,

(define (tot a b c) (+ a b c))
(define tot2 (+ (tot 5 6 7) 1))

assigns the result of the expression (+ (tot 5 6 7) 1) to the name tot2

ecounysis
With the solution you suggest, it's now telling me that tot2 is an undefined identifier when i provide values for either function. If I can't directly refer to those variables in the context of tot2, is there a way to roll the result of the (tot a b c) function into another variable and using that instead? Thanks for bearing with me by the way--I've been programming for exactly three days.
Steve
Did you call tot2 with three arguments? For example, (tot2 5 6 7) should result in 19.
ecounysis
@Steve: It's hard to say what's wrong now. Perhaps update your question to show your second attempt. Ecounysis' code shouldn't give the error you say you're getting.
Chuck
When I posted last night I must not have understood what ecounysis was aiming at. I see it now, but it's not the behavior I was looking for. My fault for not being clear enough.
Steve
+2  A: 

You're imagining a "persistence" that isn't there, though it's probably plausible, given prior experience with math.

That is: if I'm solving a math problem, and I say that x equals 5, well then x should stay equal to five for the remainder of the problem; until I erase the board, for instance.

So, can you write a programming language like this? Yes! In fact, I could write a small macro in DrScheme for you that produced exactly the behavior you appear to be looking for: it would set up a global table of variables so that every variable binding caused an update to this single table of variables.

BUT! All of the programmers I surveyed (one) (okay, it was me) agreed that this would be a very bad idea.

To see why, imagine that I have a large program that contains several variables called 'a'. Then, any time someone in part A of the program calls a function with a variable named 'a', then part B of the program will suddenly change its behavior. This will make it nearly impossible to reason about the behavior of larger programs.

More generally, this is the problem with "state" and "mutation".

For this reason, you cannot refer to variables other than the ones that are "in scope". That is, those variables whose binding form (in this case a 'define') encloses the reference.

John Clements
John, Ecounysis.Thanks for the explanation of why my approach wasn't working. The problem makes more sense now.I'm looking for this behavior because I'm rewriting a small program that includes 5 different functions. The program works, but only if the user enters values in this form: (+(tot 1 2 3)(tot2 5 7 8)). I would like a 6th function that totals the result of the first 5 without forcing the user to enter all the values at once.I guess what I should do is forget about re-assigning variables and learn to create a table that stores the result of each function.Sound reasonable?
Steve
I'm still not convinced, but perhaps it's because I don't fully understand your example.I definitely agree that you shouldn't have to provide a given argument more than once, but I'm not sure I see why you'd have to.Currently, my best guess is that you're trying to see *both* the results of the individual calls, *and* their sums. If I'm correct, then you might want to write something like this:grr, stupid character limit. Can't fit pasted code.cf. next comment.
John Clements
<pre>#lang scheme(define (tot1 a b c) (+ a b c))(define (tot2 a b c) (* a b c));; tots-and-sum : number number number number number number -> (list/c number number number);; return a list containing the result of calling tot1, the result of calling tot2, and their sum.(define (tots-and-sum g h i j k l) (let ([r1 (tot1 g h i)] [r2 (tot2 j k l)]) (list r1 r2 (+ r1 r2))))</pre>
John Clements
Oh, for heaven's sake. Well, I see you can't do that.
John Clements
I don't want to provide an argument more than once-- I simply want to define 5e functions and then have another function at the end that adds up the results of those functions with the arguments previously entered. But since a new definition is required to create the final function, when I refer to the previous 5 functions in the 6th the variables for each are undefined and the final calculation fails. It may be that I simply don't know enough to ask a good question, and more study is required. Thanks.
Steve
To summarize: you want functions to "remember" their last result. My apparently unhelpful comment is simply that--in its most straightforward form--what you want is definitely possible, but is a bad idea. :)
John Clements
+3  A: 

Scheme is lexically scoped: so a, b, and c will only exist for the dynamic extent of tot.

The dynamic extent of a procedure call is the period between when the call is initiated and when it returns (via gnu).

grettke
A: 

Based on your comments on John's answer, I think what you want is just to assign the result of each function call to a variable (either one variable for each or stick them all in a list) and then add those results together.

Chuck
A: 

After reading through everyone's comments, I realized that I was confusing two issues: having the interpreter evaluate an expression with variables, and actually supplying values for those variables. Because of this confusion, the questions I asked did not make sense. Here's a simplified version of the solution. As you can see, it is embarrassingly simple-- I just used "read" to have the user enter the values.

(define a (read))
(define b (read))
(define c (read))
(define d (read))
(define ee (read))
(define f (read))
(define tot (+ a b c))
(define tot2 (+ d ee f))
(define grandtotal (+ tot tot2))
(display grandtotal)

I used this approach with the actual program and now have a nice little application that totals my hours worked for the week. Thanks everyone for your patient assistance.

Steve