Understanding symbols in Scheme - scheme

I am having a hard time understanding symbols in Scheme. The following confuses me:
1 ]=> (symbol? 'x)
; Value: #t
1 ]=> (symbol? '('x))
; Value: #f
I thought I understood why the first one is a symbol, but then why is '('x)) not? Can someone please explain why?
For what it's worth, I am running MIT/GNU Scheme.

In scheme '... is a shorthand for (quote ...).
Thus 'x is shorthand for (quote x).
And '(1 2 3) is shorthand (quote (1 2 3)).
When a quote expression is evaluated, the quoted values is not evaluated as an expression, but simply returned.
In (quote x) what is quoted is the symbol x. So (quote x) evaluates to the symbol x.
In (quote (1 2 3)) the quoted value is a list. It evaluates to (1 2 3).
In your slightly more complicated example, you have
'('x) which is shorthand for (quote ((quote x))).
This evaluates to the list ((quote x)). Which in most Schemes are
printed as ('x).

'('x) is a list, not a symbol. Symbols in Scheme are alphanumeric, like variables and keywords. So 'a is a symbol, and so is 'supercalafragalistic, but '(1 2 3) is a list of numbers.
I'm not sure exactly what's throwing you off, but it's probably the '. ' can be used to make symbols, but also to make lists, and other things too. Not everything that starts with ' is a symbol.

Related

Quoting numerical constants in Chez Scheme

I am curious as to why Chez Scheme does not treat numbers as symbols. Whether they are in a list or are quoted alone, number? returns true, meaning that it was not made into a symbol. Is there a practical reason for this?
Chez Scheme Version 9.5.4
Copyright 1984-2020 Cisco Systems, Inc.
> (number? (car '(1 2 3 4 5)))
#t
> (symbol? (car '(1 2 3 4 5)))
#f
> (define symbolic-num '5)
> (number? symbolic-num)
#t
> (symbol? symbolic-num)
#f
>
This is not specific to Chez, but is standard behaviour; see e.g. R5RS:
The rules for writing a symbol are exactly the same as the rules for writing an identifier [6.3.3 Symbols]
So a numeric literal can't be a symbol, because it's not an identifier.
Now, 'e is shorthand for (quote e), and
(quote <datum>) evaluates to <datum>. [4.1.2 Literal expressions]
That is, (quote 1) - '1 - evaluates to 1, which is an integer, and (quote a) - 'a - evaluates to a, which is a symbol.
Numerical constants, string constants, character constants, and boolean constants evaluate ``to themselves''; they need not be quoted. [4.1.2 Literal expressions]
This gets a bit confusing because REPLs print some things in the "shorthand-quoted" form, but that's just an output convention.
Note that (display 'a) will show a, not 'a.

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 = +

Why does '(1 2 3) evaluate to a list en Lisp (Scheme)?

The quote (') is used to introduce a pre-evaluated value, so (quote x) results in the symbol x and not what the symbol evalutes to.
Numbers, Booleans, characters and strings are self-evaluating in Scheme, so quoting them doesn't matter.
But why does (quote (1 2 3)) or (quote ()) answers #t to the predicate list?.
Should't the result be a "pre-evaluated" value? But in this case (1 2 3) has actually been evaluated to (list 1 2 3)?
Thank you.
pre-evaluated value
I'm not sure where you got that term from. I've never used it. It's not "pre-evaluated", it's unevaluated.
This is really all works from the fact Lisp (and Scheme) is Homoiconic: the structure of the program really uses lists and atoms underneath.
quote is the dual to eval: (eval (list '+ '1 '2 '3)) (and since a quoted number is just the number, (eval (list '+ 1 2 3)) does it as well) is the opposite of (quote '(+ 1 2 3)).
An evaluated list is a call, so an unevaluated call is a list.
Should't the result be a "pre-evaluated" value? But in this case (1 2 3) has actually been evaluated to (list? 1 2 3)?
You're missing some parentheses here! You get (list? '(1 2 3)) (or (list? (quote (1 2 3)). That is, (list? (list 1 2 3)). Which is true.
You can check the opposite with (eval (list '+ 1 2 3)): you get 6.
Note: Some values just evaluate to themselves (like numbers or functions. You can throw eval at it as many times as you want, and it won't change a thing: (eval (eval (eval 1))) is just 1.)
(quote (+ 1 2 3)) = '(+ 1 2 3) = (list '+ '1 '2 '3) = (list '+ 1 2 3) (numbers are self-evaluating, i.e. evaluating to self).
(eval '(+ 1 2 3)) = (+ 1 2 3) = 6. And (eval '(1 2 3)) = (1 2 3) = error.
The first identity is just syntactical. The central identity here is the second one, '(+ 1 2 3) = (list '+ '1 '2 '3). It holds because everything is evaluated in Lisp, but before that, it must be read. Which means, converted from textual source code to actual data structures.
Since ( ... ) parentheses denote lists, reading ( ... ) forms creates lists. Then, evaluating the quoted form just returns that form as is (i.e. non-evaluated). The token + gets read as a symbol +; the literals 1, 2, 3 get read as numbers 1, 2, 3. So the end result is the same as the result of evaluating the form (list '+ '1 '2 '3).
And of course all this still applies without the + inside, as well.
The quote introduces an unevaluated value, not pre-evaluated, whatever that means.
When the expression (quote X) is treated as a form to be evaluated, it simply evaluates to X itself. X is not treated as a form to be evaluated to a value, but rather the resulting value is the syntax X itself.
Quote is a way of the program expressing, "I want to use a piece of my own syntax as a value". And that's precisely what a "literal" is in computer science: a piece of program text reflected back into the program as a run-time value.
In Lisp, atoms other than symbols denote themselves when evaluated. The syntax 3 evaluates to the integer 3. They are the same thing: Lisp syntax is a data structure, and in that data structure, an integer literal 3 is already represented by the object that it denotes.
Thus, under evaluation, there is no difference between (quote 3) and just 3. "Give me the syntax 3 itself" and "give me the value of the syntax 3" are the same: just 3.
Under (quote (1 2 3)), the syntax being quoted is (1 2 3). That syntax is the list object that it looks like; quote just regurgitates it. If were to evaluate the (1 2 3) form, it would be an error: it looks like 1 is being used as an operator or function, with arguments 2 and 3. When quote is itself evaluated, it suppresses this evaluation and just yields the (1 2 3) as-is.
Because the (1 2 3) is a piece of the program syntax, however, there is a restriction in the language that this list may not be modified. An operation like (inc (car (quote (1 2 3)))) which tries to change the list to (2 2 3) invokes undefined behavior. Essentially, the program is trying to modify its own syntax; if for a moment we disregard the additional complexity that Lisp is a compiled language, this is de facto self-modifying code.

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