Syntax and variables in Scheme - scheme

obviously, this code should fail :
(define or 5)
but I was wondering why does this code fail to run :
(define apply
(lambda (x y f)
(f x y)
)
)
(apply #f #t or)
(or #f #t), would work as expected.
I'm not defining any new variable with a saved name, only passing the function or as an argument.
and (apply 1 2 +) on the other hand works...

or is a special form. It isn't a function. So it can not be passed like that as an argument. Rather than (apply #f #t or), you must use:
(apply #f #t (lambda (a b) (or a b)))
(define or 5) does not fail. It shadows the or special form. Some implementations may not allow redefinition either within a module or of given symbols. So when asking about Scheme it is important to specific the implementation.
This is because special forms can only occur in the first position. Special forms are implemented as macro expansions. For example: (or a b) => (let ((v a)) (if v v b))

When you want to redefine special forms you need to use thunks, otherwise the arguments get evaluated, while the arguments of the special forms are evaluated in the order imposed inside the special form.
Instead, to get the same behavior as the semantics of the special forms you can force and delay the argument evaluation by using thunks. For example,
(define (or-sp-form a b) (if (a) 'ok (b)))
and call such a function like
(or-sp-form (lambda () false) (lambda () true))
Defining a special form like that, it can now be passed as argument to other functions like
(f or-sp-form)
and take care inside f to pass delayed arguments to or-sp-form.

Related

"set-elts: contract violation. expected: set? , given: x" in Scheme

Friend gave me this problem to solve as a way for me to learn Scheme:
E ::= (λ V E) | (E E) | V with V=variable and write a Scheme function freeVariables which takes the free variables. For example:
Input = (freeVariables '(λ f (λ x (f ((t g) g)))))
Output = (t g)
However I have the code complete as shown below with logic done. But this is what happens when I add an input:
Input = (freeVariables'(λ f (λ x (f ((t g) g)))))
Output = set-elts: contract violation
expected: set?
given: x
What exactly is wrong with the code I have created? What does the output above mean? And are there any possible fixes? Everything is below Code, logic behind it and debugger.
#lang scheme
(require data/set)
(define (freeVariables exp)
(cond [(null? exp) '()]
[(symbol? exp) (list exp)]
[(eq? (car exp) 'λ)
(let ((variables (cadr exp))
(body (caddr exp)))
(set-difference (freeVariables body) variables))]
[else (apply append (map freeVariables exp))]))
So the logic would work is this:
If exp is null = return empty list
If exp is a variable = return a list containing the variable
-If the first element of exp is the symbol λ, then exp represents a lambda term. Then bind the variables in the lambda term to variables and the body of the lambda term to body, and we return the difference between the free variables in the body and the variables in the lambda term with usage of set-difference to remove bound variables from free variables in body.
Else exp must be a function application and append the results.
Debugger:
Thank you and kind regards
Input = (freeVariables'(λ f (λ x (f ((t g) g)))))
Output = set-elts: contract violation
expected: set?
given: x
The grammar in the question only allows for (λ x ...) λ-expressions, with just one parameter.
This means you have a variable x, not a list of variables, to handle.
Thus, write
(let ((var (cadr exp)) ; singular
....
to get that variable, and if you need to have a list of symbols to pass to set-difference, you need to create that list, using (list var) instead of your variables.
The error message indicates that a "contract" has been violated, i.e. a piece of code's expectations about one of its argument's type have not been met.
Specifically it says that a function set-elts, apparently called somehow by set-difference, expects one of its arguments to answer to the predicate set?, but it does not.
It also indicates x as the culprit, which is just a symbol inside your test expression. In your case, set? probably means lists, i.e. (list 'x) could pass the muster. If not, try (list->seteq (list var)).
Another problem with your code is its use of append, which breaks the abstraction. Use set-union instead.

What Scheme special forms must the hygienic macro expander know about?

syntax-rules in Scheme are "hygienic" and "referentially transparent" and must preserve Scheme's lexical scoping. From my understanding, this means that during the macro expansion phase, the expander would need to know about lambda and define.
The expander needs to know about lambda.
Suppose we have this code:
(define x 1)
((lambda (x) x) 2)
If the expander did not know about the lambda special form, it would consider the two xs in (lambda (x) x) to be bound to the x in (define x 1), which is incorrect.
The expander needs to know about define, so that it knows where (i.e. in which scope) a particular identifier is defined. In addition, suppose we have this code:
(define n 1)
(define f (lambda (x y) (+ x y)))
(define lambda f)
(lambda n n)
In order to correctly determine that both n in (lambda n n) refer to (define n 1), the expander has to understand that (define lambda f) has changed the meaning of lambda (and therefore the expander has to stop using special rules for handling lmabda in this scope).
What other special forms does the macro expander need to know about? Does it need to know about set!?
The examples seem to be about lexical scoping, not macro expansion.
(define x 1)
((lambda (x) x) 2)
The binding of x in the second line shadows that in the first.
Similarly in the second example (define lambda f) binds lambda
in the region following the define; there is no macro expansion.
The identifier lambda can be used as a keyword in a syntactic extension (macro);
lexical scoping applies normally, there are no special rules:
> (let-syntax ([lambda (syntax-rules ()
[(lambda arg) ((lambda (x) (+ 1 x)) arg)])])
(lambda 2))
3
>
But:
> (letrec-syntax ([lambda (syntax-rules ()
[(lambda arg) ((lambda (x) (+ 1 x)) arg)])])
(lambda 2))
Exception: invalid syntax (lambda (x) (+ 1 x))
>

How do I get a function's name as a symbol?

I am trying to define a function func->symbol that takes a function and returns its name as a symbol. For example:
(define (pythagoras a b)
(sqrt (+ (* a a) (* b b))))
;; #1
(func->symbol pythagoras) ; Returns: 'pythagoras
;; #2
(func->symbol (if #t pythagoras sqrt)) ; Returns: 'pythagoras
;; #3
(let ((f (if #t pythagoras sqrt)))
(func->symbol f)) ; Returns: 'pythagoras
;; #4
(let ((f (if #t pythagoras sqrt)))
(let ((g f))
(func->symbol g))) ; Returns: 'pythagoras
This is a follow-up question on How do I get a definition's name as a symbol? which only deals with case #1. For case #1, a simple macro def->symbol is sufficient:
(define-syntax def->symbol
(syntax-rules ()
((_ def) 'def)))
However, this macro definition does not pass cases #2, #3, #4. Is it possible to define func->symbol, or is Scheme not expressive enough for this?
In Racket, in many cases, you can get a function's name using object-name. But it is probably a bad idea to rely on this result for anything other than debugging.
Perhaps it's worth an answer which shows why this is not possible in any language with first-class functions.
I'll define what I mean by a language having first-class functions (there are varying definitions).
Functions can be passed as arguments to other functions, and returned as values from them.
Functions can be stored in variables and other data structures.
There are anonymous functions, or function literals.
Scheme clearly has first-class functions in this sense. Now consider this code:
(define a #f)
(define b #f)
(let ((f (lambda (x)
(+ x 1))))
(set! a f)
(set! b f))
Let's imagine there is a function-name function, which, given a function, returns its name. What should (function-name a) return?
Well, the answer is that there's simply no useful value it can return (in Racket, (object-name a) returns f, but that's clearly exposing implementation details which might be useful for debugging but would be very misleading as a return value for a function-name procedure.
This is why such a procedure can't exist in general in a language with first-class functions: the function which maps from names to values is many-to-one and thus has no inverse.
Here is an example of the sort of disgusting hack you could do to make this 'work' and also why it's horrible. The following is Racket-specific code:
(define-syntax define/naming
;; Define something in such a way that, if it's a procedure,
;; it gets the right name. This is a horrid hack.
(syntax-rules ()
[(_ (p arg ...) form ...)
(define (p arg ...) form ...)]
[(_ name val)
(define name (let ([p val])
(if (procedure? p)
(procedure-rename p 'name)
p)))]))
And now, given
(define/naming a
(let ([c 0])
(thunk
(begin0
c
(set! c (+ c 1))))))
(define/naming b a)
Then:
> (object-name a)
'a
> (object-name b)
'b
> (eqv? a b)
#f
> (a)
0
> (b)
1
> (a)
2
So a and b have the 'right' names, but because of that they are necessarily not the same object, which I think is semantically wrong: if I see (define a b) then I want (eqv? a b) to be true, I think. But a and b do capture the same lexical state, so that works, at least.

Taking the 'and' of a list by folding in Scheme

In the book Structure and Interpretation of Computer Programs
by H. Abelson and G. J. Sussman with J. Sussman,
the accumulation or fold-right is introduced in Section 2.2.3 as follows:
(define (accumulate op initial sequence)
(if (null? sequence)
initial
(op (car sequence)
(accumulate op initial (cdr sequence)))))
I tried to use this to take the and of a list of Boolean variables, by writing:
(accumulate and
true
(list true true false))
However, this gave me the error and: bad syntax in DrRacket (with #lang sicp),
and I had to do this instead:
(accumulate (lambda (x y) (and x y))
true
(list true true false))
Why? I believe it has something to do with how and is a special form,
but I don't understand Scheme enough to say.
Perhaps I'm just missing some obvious mistake...
You answered your own question: and is a special form (not a normal procedure!) with special evaluation rules, and accumulate expects a normal procedure, so you need to wrap it inside a procedure.
To see why and is a special form, consider these examples that demonstrate that and requires special evaluation rules (unlike procedures), because it short-circuits whenever it finds a false value:
; division by zero never gets executed
(and #f (/ 1 0))
=> #f
; division by zero gets executed during procedure invocation
((lambda (x y) (and x y)) #f (/ 1 0))
=> /: division by zero

Are self evaluating identifier ignored by quote?

I know that when you type for example in a repl 'a, it will output a without evaluating it and internally, in my case, it expend to (##core#quote a) in Chicken-scheme.
I know that numbers and strings are special in a way that they are self-evaluating symbols. I guess that for that reason, the quote doesn't seem to have any effect on them.
For example:
(+ '1 '2 '3)
> 6
(+ (quote 1) (quote 2) (quote 3))
> 6
(string-append '"hello " '"world")
>"hello world"
But doing the following
''1
(quote 1) => (#core#quote '1) => (#core#quote (#core#quote 1))
If we do that:
(car ''a)
> quote
Which confirms what I tought. Then if we do the following we should find 1 as expected.
(cadr ''1)
> 1
Am I right that quoted self evaluating identifiers are ignored at evaluation time? Because if I do
(define a '1)
a
It doesn't print '1 but 1.
What you should try to do here is to understand how evaluation works by writing a very simple evaluator. For example (and this is pseudocode!):
(define (self-evaluating? form)
;; This might not be exactly right, might be missing one type or two,
;; but you get the idea.
(or (null? form)
(number? form)
(boolean? form)
(string? form)
(vector? form)
(character? form)))
(define (eval form env)
(cond ((self-evaluating? form)
;; Self-evaluating forms evaluate to themselves.
form)
((symbol? form)
;; A symbol is evaluating by looking it up in the environment.
;; Note that this is pseudocode, and lookup-in-environment is not
;; a standard function...
(lookup-in-environment form env))
((list? form)
(eval-combination form env))))
(define (eval-combination form env)
(case (car form)
((quote)
;; A quote special form is evaluated simply by returning the
;; argument to quote.
(second form))
((define)
;; We evaluate a definition by evaluating the body in the current
;; environment, and setting the variable to the result in that
;; environment.
;;
;; Note again that this is pseudocode, and set-in-environment! is
;; not a standard function...
(set-in-environment! env (second form) (eval (third form) env)))
;; Other special forms
...
;; Default rule: evaluate all the subexpressions in the current
;; environment; the first one should be a procedure, which we then
;; apply to the list of values of the succeeding ones.
(else
(apply (eval (car form) env)
(map (lambda (arg) (eval arg env)) (cdr form)))))))
By tracing the execution of that code by hand for a few examples (and you can ignore the env parameter for your case), you should be able to see what's going on. The key thing to note about an evaluator like this is that it's very orthogonal: for each type of form there is a separate rule on how to evaluate it, and the rules don't know about each other. It's all driven by this logic:
Is the form an atom or a combination (list)?
If the form is an atom, is it self-evaluating or is it a symbol?
If the form is a combination, is it a special form or a procedure application? The only thing we look at to decide this is the form's car.
You're right. Evaluating (quote <object>) returns that object. Evaluating a self-evaluating object also returns that object.
You're thinking of it backwards. It's not that quote is ignored when the object is self-evaluating, it's that self-evaluating objects effectively quote themselves.
Syntactic keywords define their own evaluation rules. For example:
(define <identifier> <inititailizer>)
does not evaluate <identifier> but does evaluate <initializer>. The syntactic keyword quote does not evaluate its argument but when quote itself is evaluated it returns its argument. So if you write:
(define a '1)
the '1 is evaluated which evaluates the quote syntax to the number 1.
Note that self-evaluating expressions are defined in R7RS as:
⟨self-evaluating⟩ −→ ⟨boolean⟩ | ⟨number⟩ | ⟨vector⟩
| ⟨character⟩ | ⟨string⟩ | ⟨byte vector⟩

Resources