Are self evaluating identifier ignored by quote? - scheme

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⟩

Related

How to define a function in scm scheme that tests if its parameter is a macro?

For example, assuming 'match is a macro and 'car isn't:
> (macro? 'match)
#t
> (macro? 'car)
#f
Most schemes have no such macro? function. To distinguish normal functions from macros you can use procedure? from RnRS:
> (procedure? car)
#t
The problem is that you cannot name the keyword using Scheme syntax:
> (procedure? let)
Exception: invalid syntax let
So you have to use a symbol, like 'let, to refer to it. Given that eval needs to be able to tell keywords apart from other identifiers, you can try something like this:
(define keyword?
(lambda (symbol)
(guard (x [else (syntax-violation? x)])
(eval symbol)
#f)))
(keyword? 'let) ⇒ #t
(keyword? 'car) ⇒ #f
(keyword? 'does-not-exist) ⇒ #f
But this is certainly a rather big hammer. And this single-argument form of eval is a Chez Scheme extension, supplying (interaction-environment) as the default environment. It is also not completely safe because this hangs:
(let-syntax ([foo (lambda (x) (raise "oops"))])
(keyword? 'foo))

Define a macro that returns the operator of an expression in Scheme?

I'm looking for functionality like this:
(op (+ 1 2))
; +
I can’t for the life of me seem to figure out how to do this using define-macro. Any help?
Thanks,
Edit:
It's especially confusing cause I can do:
(car '(+ 1 2))
; +
But if I do:
(define-macro (op expr)
(car expr))
(op '(+ 1 2))
It doesn't work.
OP has defined the macro op as if it were a function, but Lisp macros do not work this way. The macro form is evaluated to produce a new form which substitutes for the original macro call, yet the macro arguments are passed into the macro body unevaluated. This means that within the macro body of op, car operates not on the data (+ 1 2), but rather on the data (quote (+ 1 2)).
The goal of the macro op is not to evaluate (car expr), but to produce the form (car expr) (where expr is replaced by the value of the macro argument), which is then evaluated in the REPL after the macro expansion has taken place. One could do this either using list:
(define-macro (opl expr)
(list 'car expr))
or using quasiquotation:
(define-macro (opq expr)
`(car ,expr))
Here, the backquote introduces a template for a list, and the comma causes the symbol expr to be evaluated to its value ((quote (+ 1 2))), and the result inserted into the list. A simple quoted list, e.g. '(car expr) would evaluate to the list (car expr), where expr is just the symbol expr. With quasiquotation, ,expr evaluates to the value of the argument provided in a macro call, e.g. `(car ,expr) --> (car '(+ 1 2)). Note that (list 'car expr) produces the same form when expr is '(+ 1 2), as with (opl '(+ 1 2))
This define-macro syntax is almost identical to the traditional defmacro syntax of Common Lisp, the difference there being that with defmacro the name of the macro goes before a list of formal parameters, e.g. (defmacro op (expr) ;...). define-macro is not available in Standard Scheme, but some Scheme implementations do support it. Guile Scheme supports both defmacro and define-macro. Both of the above macro solutions work in Guile:
scheme#(guile-user)> (opl '(+ 1 2))
$2 = +
scheme#(guile-user)> (opq '(+ 1 2))
$3 = +

Syntax and variables in 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.

what is apostrophe type in scheme

I have condition that uses the member function:
(cond ((member '1' (some-function)) (display #t)) (else (display #f)))
it works fine but i still couldn't find the answers to:
1)what is the type of '1'?
2)i have the next expression
(lambda(x)(= x 1))
how can I convert to the same type of '1'?
Notice that the cond expression is not doing what you think. What's really happening is this:
(cond ((member '1 '(some-function))
(display #t))
(else
(display #f)))
In other words: the number 1 is being quoted and the expression '(some-function) is being interpreted as a single-element list with the symbol some-function as its only member. Regarding the first question, this expression:
'1'
… is invalid in Scheme - try typing it in the evaluation window, nothing will happen: the first quote applies to the number 1, and the second quote is expecting further input, so anything that's written after it will get quoted. FYI double quotes mean a string, as in many other languages: "1". But a single quote indicates a quoted expression, that evaluates to itself:
'1
=> 1
And it's just shorthand for this:
(quote 1)
=> 1
Which in the above expression is unnecessary, a number already evaluates to itself:
1
=> 1
Now, about the second question, it doesn't make sense because '1' is not a type, as explained above.
'x is the same as (quote x). Scheme won't evaluate the argument so it's basically how you do constant values. It's not a single quote around rather you have two elements in the list quoted in your example like this:
(cond ((member '1 '(some-function)) (display #t)) (else (display #f)))
You never need to quote a number since it's always evaluated to itself. '1 is the same as just 1

Issues with evaluating expressions from user input

I'm trying to make a recursive definition that reads and execute user expressions, such as (3 + 5). Everything is working, except of one problem with the arithmetic symbol.
I managed to replicate the error in a simpler example:
(define v '(1 + 3))
((cadr v) 2 4)
The (cadr v) is the + symbol, but for some reason the procedure can't be executed on the two arguments that followed. Am I missing something?
I think that's because
(cadr v)
returns '+ not + (literal + not a + function).
You need to evaluate it before applying it to arguments.
This should work:
((eval (cadr v)) 2 4)
^evaluates the '+ to +
edit
This worked in racket in interactive mode.
I'm not really sure what's the difference, but made it work in r5rs mode in racket (a script):
#lang r5rs
;required by r5rs
(define user-initial-environment (scheme-report-environment 5))
(define v '(1 + 2))
;eval expects a quoted expression
;(it seems that if it's a function it has to have arguments too)
;and evaluation environment.
((eval (cadr v) user-initial-environment) 2 4)
As others have pointed out, the problem is that the list you've constructed contains the symbol plus, rather than the function plus.
At its heart, this is the same reason that '(a b) returns a list of two symbols, rather than signalling an unbound identifier error; the quote starts a term in a "data language" where legal identifiers are interpreted as symbols, rather than as variable references.
The question, of course, is what you should do about it. Some here have suggested using 'eval'; this is probably a bad idea, for reasons that I think Matthew Flatt captures elegantly in his blog post on the topic.
Instead, you should probably write a simple mapping function. Here's the way I'd write it. If you use my code in an assignment, be sure to credit me :).
#lang racket
;; a mapping from symbols to operators
(define operator-hash
(hash '+ +
'- -
'* *))
;; ... and whatever other operators you want.
;; example of using it:
(hash-ref operator-hash '+) ;; ==> +
Try this:
(define v '(1 + 3))
(let ((operator (eval (cadr v)))
(operand1 (car v))
(operand2 (caddr v)))
(apply operator (list operand1 operand2)))
You can do it this way with eval in Guile:
(define (infix-eval v)
(eval (list (cadr v)(car v)(caddr v))
(interaction-environment)))
> (infix-eval '(1 + 2))
3
Rather than using interaction-environment, you could supply another environment for evaluation, where you could also define some other symbols not found in standard Scheme, so that expressions like (7 % 3) and (2 ^ 6) would also work.

Resources