I saw a question which asked about a contract of a method in a pet language known as let.The language is not important but does contract means that
things that the method takes as an argument and its value after evaluating?
(define extend-env*
(lambda (syms vals old-env)
(if (null? syms)
old-env
(extended-env-record
(car syms)
(car vals)
(extend-env* (cdr syms)
(cdr vals)
old-env)))))
So in here the method takes a symbol a value and an environment and I think it produces a new environment.
Does that mean contract for this method is Identifier(Variable),Value,Environment = Environment ?
Your functions starts like this:
(lambda (syms vals old-env) ...)
Here sym stand for symbol and thus syms stands for a list of syms aka a list of symbols. In the same manner vals stands for a list of values. Finally old-env is an environment.
This covers the input to the function. To confirm that syms is supposed to be a list of symbols, look at how syms is used in the body. We see thee uses: (null? syms), (car syms), and, (cdr syms). This means we guess correctly.
To see type of the output, look for the expression(s) that produce return values.
The simplest is old-env which is an environment. If the function always returns the same type of value, we have determined that the output is an environment. It best to check that the other return expressions also return environments though.
To sum up: the contract seen from Racket is:
extend-env* : list-of-symbols list-of-values environment -> environment
Now in your program the symbols represent identifiers, so you could also write:
extend-env* : list-of-identifiers list-of-values environment -> environment
if you document that identifiers are represented as symbols.
Related
Is there normal "set" function (not special form) in Scheme language or some way to implement it?
I'd like to write code something like:
(map (lambda (var)
(set var 0))
'(a b c))
which could assign a value (here it is '0') to variables from list (here they are 'a', 'b' and 'c').
No. And to see why there isn't consider something like this:
(define (mutant var val)
(let ((x 1))
(set var val)
x))
Now, what should (mutant 'x 3) return? If it should return 3, then:
set can't be a function since it needs access to the lexical environment of mutant;
any kind of reasonable compilation of this function is not possible.
If you want set to be a function then catastrophe follows. Consider this definition:
(define (mutant-horror f)
(let ([x 3])
(f)
x))
Now, you would think that this can be optimised to this:
(define (mutant-horror f)
(f)
3)
But it can't. Because you might call it like this:
(mutant-horror (λ () (set 'x 3)))
or, more generally, you might call it with a function which, somewhere eventually in some function called indirectly from it might end up saying (set 'x 3).
This means that no binding can ever be optimised at all, which is a disaster. It's also at least very close to meaning lexical scope is not possible: if as well as set, a function called get exists, which retrieves the binding of a symbol, then you have, essentially, dynamic scope. That in turn makes things like tail-call elimination at least difficult and probably impossible (in fact set probably does this on its own).
Reasons like this are why even very old Lisps, where things like set did exist and did superficially work, actually made special exemptions for compiled code, where set didn't work (see for instance the Lisp 1.5 programmer's manual (PDF link), appendix D. This divergence between the semantics of compiled and interpreted code is one of the things that later Lisps and Lisp-related languages such as CL and Scheme did away with.
If instead you want something like Common Lisp's semantics, where the equivalent thing
(defun mutant (var val)
(let ((x 1))
(set var val)
x))
Would return 1 (unless x was a globally (see below) special variable, in which case it might return something else) and as a side-effect modify the value cell of whatever symbol was named by var (which might be x), then, well, Scheme has no notion of that at all, and that's a good thing on the whole.
Note that a modified version of the function will also work for locally special variables:
(defun mutant/local-special (a b)
(let ((x 1))
(declare (special x))
(set a b)
x))
But in this case you always know there's a special binding happening because you can always see the declaration.
When you write something like
(map (lambda (var)
(set var 0))
'(a b c))
my first thought was that you try to accumulate unordered sets of the form ( (a 0) (b 0) (c 0) ).
You cannot implement your own setter for any of the internal data structures that are provided by the language as this would mean to write a scheme function to modify some data structures that is implemented in C. For the data structures implemented in C you need to provide setters written in C -- supposing the lower language is C.
If you want to implement your own setter you either
-- check how the data structure in implmented, and if it's implemented in scheme you will undestand how to modify it
-- define your own data structure using already existing data structures and define setters for it.
A setter that mutates the data structure contains a ! at the end of its name, such as set!, append!, etc.
A function call just evaluates a series of instructions in an extended environment, the environment in particular is that of definition extended with its function parameters, this is prety much the case in any language...
If you do this:
(define (my-set var val)
(set! var val))
you will bind the value of val to var, but only within the scope of the current call on my-set. The reason you cannot write such function has to do with the nature of scheme itself, var is a pointer to whatever you pass in the function, but set! will make this pointer point to something else (still within the scope of my-set). my-set could work if we had some sort of mechanism of using actual pointers, as some low lever languages allow. But scheme does not...
Note that scheme goes very well with the functional programming style as well as recursion, so if you have a need for a function as you described, you are probably "doing something wrong"... :)
You can, however, do this:
(define my-list (list 1 2 3))
(define (my-set a-list a-value)
(set-car! my-list a-value))
> (my-set my-list 4)
> my-list
(4 2 3)
this works since a-list is a pointer to a cons-cell, set-car! will modify the contents of a cons-cell, but not affect the pointer to which.
To start off, this is homework. It isn't my intention to get a complete solution, but I am stuck with how to interpret this problem.
We're basically making an interpreter from a lexer and parser for a language that we have created in class.
Specifically, what I am stuck on is using Scheme/Drracket to implement creating a sequence using the parser that calls the method "make-seq" that can be defined by the following rules:
(make-seq (e)) = e
(make-seq (e1 e2 ... en)) = (make-let '*temp* e1 (make-seq (e2 ... en)))
Where make-let is defined as:
(define (make-let var exp1 exp2)
(list 'let var exp1 exp2))
I've implemented the make-seq method below:
(define (make-seq e)
(if (null? (cdr e))
e
(make-let '*temp* (car e) (make-seq (cdr e)))))
but I am not sure how to represent the 'temp in the rules above. I am fairly certain that I should not have the symbol 'temp actually in the implementation, but I'm not sure what I should be doing there instead.
Could anyone give me pointers as to how I should move forward with this?
Thanks!
Using *temp won't be a problem unless the program it's interpreting also has *test:
(let ((*temp 10))
(seq
expression1
(* *temp *temp))) ; end up using the result from the previous element in the sequence
To fix this you can introduce variables that are ok for the interpreter but not possible to create in code. I've often used symbols and lists where the first element is a special value. Your make-seq creates that instead and your interpreter needs to treat those as symbols too. Usually the interpreter uses eq? so basically every structure created as a list with a tag will be unique for that expansion making each nesting *temp not even bother the other ones created earlier.
I want to create a function that can determine the definition of an arbitrary function in scheme. If we call such a function "definition", it would work as such:
(define (triple x) (* 3 x))
(definition triple) would return "(triple x) (* 3 x)".
There would be some implementation problems (such as with n-arity), but I'm concerned mostly with whether or not the definition of individual functions are easily retrievable in Scheme.
As a continuation, is there a way to create a function that can determine the parameters of an arbitrary function? Such that:
(parameters +) returns (number number) or something similar.
These questions both fall under the question of how functions are stored in Scheme - I found some sources which claimed that function definitions are stored with the function name, but I couldn't find out how exactly they were stored.
If this is impossible - is there a language where function definitions are easily retrievable?
There is nothing like that in Scheme. Individual implementations might have that, though.
In Common Lisp there is the standard function function-lambda-expression, which might be able to retrieve source code - depending on the implementation.
Example in LispWorks (reformatted to improve readability here):
CL-USER 65 > (defun triple (x) (* 3 x))
TRIPLE
CL-USER 66 > (function-lambda-expression #'triple)
(LAMBDA (X)
(DECLARE (SYSTEM::SOURCE-LEVEL #<EQ Hash Table{0} 42201D392B>))
(DECLARE (LAMBDA-NAME TRIPLE))
(* 3 X))
NIL
TRIPLE
SBCL:
* (defun triple (x) (* 3 x))
TRIPLE
* (function-lambda-expression #'triple)
(SB-INT:NAMED-LAMBDA TRIPLE
(X)
(BLOCK TRIPLE (* 3 X)))
NIL
TRIPLE
As you can see it returns three values: the code, whether it is a closure and the name of the function.
I have see the following code... The first call of (next-num) returns 1, and the second returns 2.
(define next-num
(let ((num 0))
(lambda () (set! num (+ num 1)) num)))
(next-num) ; 1
(next-num) ; 2
What I can not understand is... num is created by let inside next-num, it is kind of a local variable... How does scheme know that each time next-num is called, the value of num is not erased by let ((num 0)); How does scheme know that it is always the same num that we modify whenever next-num is called?
It seems that num is both local and static... How can we define a local variable, but not static?
This is "lexical closure" and you're right that num, the "closed-over variable" is similar to a static variable, in C for example: it's only visible to code within the let form (its "lexical scope"), but it persists across the whole program run, rather than being re-initialized with each call to the function.
I think the part you're confused on is this: "num is created by let inside next-num, it is kind of a local variable". This isn't true because the let block isn't part of the next-num function: it's actually an expression which creates and returns the function which is then bound to next-num. (This is very different, e.g., from C, where functions can only be created at compile-time and by defining them at top-level. In Scheme, functions are values like integers or lists, which any expression can return).
Here's another way to write (almost) the same thing which makes it clearer that the define is just associating next-num to the value of a function-returning expression:
(define next-num #f) ; dummy value
(let ((num 0))
(set! next-num
(lambda () (set! num (+ num 1)) num)))
It's important to note the difference between
(define (some-var args ...) expression expression ...)
which makes some-var a function which executes all the expressions when called, and
(define some-var expression)
which binds some-var to the value of expression, evaluated then and there. Strictly speaking, the former version is unnecessary, because it's equivalent to
(define some-var
(lambda (args ...) expression expression ...))
Your code is almost the same as this, with the addition of the lexically scoped variable, num, around the lambda form.
Finally, here's a key difference between closed-over variables and static variables, which makes closures much more powerful. If you had written the following instead:
(define make-next-num
(lambda (num)
(lambda () (set! num (+ num 1)) num)))
then each call to make-next-num would create an anonymous function with a new, distinct num variable, which is private to that function:
(define f (make-next-num 7))
(define g (make-next-num 2))
(f) ; => 8
(g) ; => 3
(f) ; => 9
This is a really cool and powerful trick which accounts for a lot of the power of languages with lexical closures.
Edited to add: You ask how Scheme "knows" which num to modify when next-num is called. In outline, if not in implementation, this is actually pretty simple. Every expression in Scheme is evaluated in the context of an environment (a lookup table) of variable bindings, which are associations of names to places which can hold values. Each evaluation of a let form or a function call creates a new environment by extending the current environment with new bindings. To arrange to have lambda forms behave as closures, the implementation represents them as a structure consisting of the function itself plus the environment in which it was defined. Calls to that function are then evaluated by extending the binding environment in which the function was defined -- not the environment in which it was called.
Older Lisps (including Emacs Lisp until recently) had lambda, but not lexical scope, so although you could create anonymous functions, calls to them would be evaluated in the calling environment rather than the definition environment, and so there were no closures. I believe Scheme was the first language to get this right. Sussman and Steele's original Lambda Papers on the implementation of Scheme make great mind-expanding reading for anyone who wants to understand scoping, among many other things.
For example,
I want to check if an element is in a list. The algorithm is straightforward, let's do it in C++
bool element_of( const std::vector<int>& lst, int elem ) {
for( int i( 0 ), ie = lst.size(); i < ie; ++i )
if( elem == lst[i] )
return true;
return false;
}
Since Scheme don't let me use single if statement, I can't do something similar to the C++ code above. Then I came up with a temporary variable, namely result. result will have initial value of #f, next I recursively call the function to check the next item in the list i.e. cdr lst ... So my question is, does the variable which created with let restore its initial value each time it enters a new function call or its value stays the same until the last call?
On the other hand, using fold, my solution was,
(define (element-of x lst)
(fold (lambda (elem result)
(if (eq? elem x) (or result #t) result))
#f
lst))
Thanks,
Each Let call creates a new set of variables in the environment that the main body of the Let is being evaluted in. The Let syntax is a "syntactic sugar" for a lambda being evaluated with arguments passed to it that have been evaluted. For instance
(let ((a (func object))
(b (func object2)))
(cons a b))
is the same as writing
((lambda (a b) (cons a b)) (func object) (func object2))
So you can see that in the Let syntax, the arguments are first evaluated, and then the body is evaluated, and the definitions of a and b are utilized in the local environment scope. So if you recursively call Let, each time you enter the body of the Let call, you are evaluating the body in a new environment (because the body is inside a newly defined lambda), and the definition of the arguments defined in the local Let scope will be different (they are actually new variables in a nested environment setup by the new lambda, not simply variables that have been mutated or "re-defined" like you would find in a C++ loop).
Another way of saying this is that you're variables will be like the local scope variables in a C++ recursive function ... for each function's stack-frame, the locally scoped variables will have their own definition, and their own memory location ... they are not mutated variables like you might see in a loop that re-uses the same memory variables in the local scope.
Hope this helps,
Jason
let always reinitialises variables; it's evident, since you must always provide new binding values. e.g.,
(let ((a 42))
...)
Inside the ..., a starts out as 42, always. It doesn't "retain" values from previous invocations.
By the way, I think you meant to write (or result (equal? elem x)) rather than (if (eq? elem x) (or result #t) result). :-)
(or result (equal? elem x)) translates to the following C++ code:
return result || elem == x;
(assuming that the == operator has been overloaded to perform what equal? does, of course.) The benefit of this is that if result is already true, no further comparisons are performed.