Reputation: 519
I am supposed to develop a data representation of:
<exp> = <var> | (lambda (<var>) <exp>) | (<exp> <exp>)
the subset contains 3 expressions. Variables, function of one argument, and function application.
My question is, how am I supposed to create data representation of the above if lambda
are functions without names? This doesn't make sense. Well at least to me.
Upvotes: 1
Views: 91
Reputation: 48745
I won't go into making data structures here since Joshua has done that already, but talk about functions in general.
No functions need a name. Some names points to function objects (procedures, closures).
So you have (lambda (x) x)
. In an interpreter lambda
is a special form and it turns the form into a procedure
(closure). An representation after evaluation might be (procedure (x) <env> x)
where env
is the current environment. Evaluating ((lambda (x) x) y)
will evaluate the operator, which evaluates to (procedure (x) <env> x)
and the evaluator will identify that as a procedure so it will evaluate the argument before applying x
in the closures environment with the variable bindings.
How does functions with names make more sense?
With a named eg. (define identity (lambda (x) x)
The same mechanism is used to create the procedure, but the special form define creates a binding to the result so that identity
is bound to (procedure (x) <env> x)
in the environment. When you do (identity q)
it will evaluate identity
first as a part of the default case where you have an application so that the interpreter gets (procedure (x) <env> x)
and when it analyses that it knows to evaluate the argument before application.
And this is just interpreted code. In a compiled one the differences would be a lot smaller and it's a possibility that it would have turned into the exact same compiled code since the name is just for programmers to abstract complexity into easily solvable parts.
Upvotes: 1
Reputation: 85873
This sounds like an exercise in rolling your own datatypes. Here's one way you could represent, create, access, and test for the structures. I've represented:
<var>
by a list (var [name])
where [name]
is whatever the name of the variable is (it could be a string, a symbol, a number, or anything else that you want to be the name of a variable);(lambda [var] [exp])
where [var]
and[exp]
are variable and expression objects; and (application [exp1] [exp2])
where [exp1]
and [exp2]
are expression objects.It's important to notice that we're just using the data structures that Scheme has already provided us. This means that it would be possible, for instance, to access the name of a variable v
by using (cadr v)
instead of (var-name v)
, but we really should prefer the latter. It allows us, for instance, to change the underlying representation later, and as long as var-name
is updated accordingly, all the code using var-name
will continue to work.
(define (make-var name)
(list 'var name))
(define (var? thing)
(and (pair? thing)
(eq? 'var (car thing))))
(define (var-name var)
(cadr var))
(define (make-function var expression)
(list 'lambda var expression))
(define (function? thing)
(and (pair? thing)
(eq? 'lambda (car thing))))
(define (function-var function)
(cadr function))
(define (function-exp function)
(caddr function))
(define (make-application expression1 expression2)
(list 'application expression1 expression2))
(define (application? thing)
(and (pair? thing)
(eq? 'application (car thing))))
(define (application-applicand application)
(cadr application))
(define (application-argument application)
(caddr application))
(define (expression? thing)
(or (var? thing)
(function? thing)
(application? thing)))
Upvotes: 1