Why does Scheme need the special notion of procedure's location tag? - scheme

Why does Scheme need the special notion of procedure's location tag?
The standard says:
Each procedure created as the result of evaluating a lambda expression
is (conceptually) tagged with a storage location, in order to make
eqv? and eq? work on procedures
The eqv? procedure returns #t if:
obj1 and obj2 are procedures whose location tags are equal
Eq? and eqv? are guaranteed to have the same behavior on ... procedures ...
But at the same time:
Variables and objects such as pairs, vectors, and strings implicitly denote locations or sequences of locations
The eqv? procedure returns #t if:
obj1 and obj2 are pairs, vectors, or strings that denote the same locations in the store
Eq? and eqv? are guaranteed to have the same behavior on ... pairs ... and non-empty strings and vectors
Why not just apply "implicitly denote locations or sequences of locations" to procedures too?
I thought this concerned them as well
I don't see anything special about procedures in that matter

Pairs, vectors, and strings are mutable. Hence, the identity (or location) of such objects matter.
Procedures are immutable, so they can be copied or coalesced arbitrarily with no apparent difference in behaviour. In practice, that means that some optimising compilers can inline them, effectively making them "multiple copies". R6RS, in particular, says that for an expression like
(let ((p (lambda (x) x)))
(eqv? p p))
the result is not guaranteed to be true, since it could have been inlined as (eqv? (lambda (x) x) (lambda (x) x)).
R7RS's notion of location tags is to give assurance that that expression does indeed result in true, even if an implementation does inlining.

Treating procedures as values works in languages like ML where they are truly immutable. But in Scheme, procedures can actually be mutated, because their local variables can be. In effect, procedures are poor man's objects (though the case can also be made that OO-style objects are just poor man's procedures!) The location tag serves the same purpose as the object identity that distinguishes two pairs with identical cars and cdrs.
In particular, giving global procedures identity means that it's possible to ask directly whether a predicate we have been passed is specifically eq? or eqv? or equal?, which is not portably possible in R6RS (though possible in R6RS implementations in practice).

Related

The little schemer - semantic

I have just started reading The Little schemer. I have some problem understanding some words.
In page 27 it says,
The Law of Eq?
The primitive eq? takes two arguments. Each must be a non-numeric atom."
And a footnote says: In practice, some numbers may be arguments of eq?
I am using racket-minimal as my scheme interpreter. It evaluates (eq? 10 10) to #t.
There are many similar type of problems in TOYS chapter.
What did the author mean by that must(marked as bold) and the footnote?
It's traditional to embed some primitive data types such as low integers and characters in the pointer itself making those datatypes eq? even when the data came to be in the source at different times / points in source. However, numbers can be any size so even if number upto a certain implementation dependent size at some point they will be to big for the pointer. When you try (eq? 10000000000 10000000000) it might be #f on 32 bits systems and #t in 64 bit systems while (eqv? 10000000000 10000000000) is #t in any system.
Scheme's true identity predicate is eqv?. Eq? is an optimized version that is allowed to report #f instead of #t when applied to numbers, characters, or procedures. Most Scheme implementations of eq? do the right thing on small exact numbers (called "fixnums"), characters, and procedures, but fall down on larger numbers or numbers of other types.
So saying "MUST" means that you get only partly predictable results if you apply eq? to a number; the footnote means that in some cases (and this typically includes 10) you will get away with it. For details on what various Schemes actually do with fixnums, see FixnumInfo at the R7RS development site.

equal? and record-type

Suppose I have the following Scheme (R6RS) code:
(define-record-type typeA
(fields
(mutable A)))
and that I create two records:
(define X (make-typeA 123))
(define Y (make-typeA 123))
I can't understand why (equal? X Y) and (equal? (make-typeA 123) (make-typeA 123)) return #f.
I read the R6RS standard (section 11.5) but I didn't really understand it.
From R6RS:
The equal? predicate treats pairs and vectors as nodes with outgoing edges, uses string=? to compare strings, uses bytevector=? to compare bytevectors (see library chapter on “Bytevectors”), and uses eqv? to compare other nodes.
In other words, your use of equal? is really just doing the same thing as eqv? since that's how it's specified for records (see last line of above).
Chapter 6.1 has this to say about eqv? of records:
If obj1 and obj2 are both records of the same record type, and are the results of two separate calls to record constructors, then eqv? returns #f.
In your code, the two records are the results of two separate calls to the constructor. Hence they cannot be eqv?.
Some dialects of Scheme may allow you to use structural equality on records. For example, in Racket you can declare a record as #:transparent to get structural equality. I'm not sure you can get this behavior in standard Scheme.
I'm not really familiar with R6RS, but a quick google search suggests that
the key thing here is mutability:
If obj1 and obj2 are both records of the same record type, and are the
results of two separate calls to record constructors, then eqv?
returns #f.

Scheme Infix to Postfix

Let me establish that this is part of a class assignment, so I'm definitely not looking for a complete code answer. Essentially we need to write a converter in Scheme that takes a list representing a mathematical equation in infix format and then output a list with the equation in postfix format.
We've been provided with the algorithm to do so, simple enough. The issue is that there is a restriction against using any of the available imperative language features. I can't figure out how to do this in a purely functional manner. This is our fist introduction to functional programming in my program.
I know I'm going to be using recursion to iterate over the list of items in the infix expression like such.
(define (itp ifExpr)
(
; do some processing using cond statement
(itp (cdr ifExpr))
))
I have all of the processing implemented (at least as best I can without knowing how to do the rest) but the algorithm I'm using to implement this requires that operators be pushed onto a stack and used later. My question is how do I implement a stack in this function that is available to all of the recursive calls as well?
(Updated in response to the OP's comment; see the new section below the original answer.)
Use a list for the stack and make it one of the loop variables. E.g.
(let loop ((stack (list))
... ; other loop variables here,
; like e.g. what remains of the infix expression
)
... ; loop body
)
Then whenever you want to change what's on the stack at the next iteration, well, basically just do so.
(loop (cons 'foo stack) ...)
Also note that if you need to make a bunch of "updates" in sequence, you can often model that with a let* form. This doesn't really work with vectors in Scheme (though it does work with Clojure's persistent vectors, if you care to look into them), but it does with scalar values and lists, as well as SRFI 40/41 streams.
In response to your comment about loops being ruled out as an "imperative" feature:
(let loop ((foo foo-val)
(bar bar-val))
(do-stuff))
is syntactic sugar for
(letrec ((loop (lambda (foo bar) (do-stuff))))
(loop foo-val bar-val))
letrec then expands to a form of let which is likely to use something equivalent to a set! or local define internally, but is considered perfectly functional. You are free to use some other symbol in place of loop, by the way. Also, this kind of let is called 'named let' (or sometimes 'tagged').
You will likely remember that the basic form of let:
(let ((foo foo-val)
(bar bar-val))
(do-stuff))
is also syntactic sugar over a clever use of lambda:
((lambda (foo bar) (do-stuff)) foo-val bar-val)
so it all boils down to procedure application, as is usual in Scheme.
Named let makes self-recursion prettier, that's all; and as I'm sure you already know, (self-) recursion with tail calls is the way to go when modelling iterative computational processes in a functional way.
Clearly this particular "loopy" construct lends itself pretty well to imperative programming too -- just use set! or data structure mutators in the loop's body if that's what you want to do -- but if you stay away from destructive function calls, there's nothing inherently imperative about looping through recursion or the tagged let itself at all. In fact, looping through recursion is one of the most basic techniques in functional programming and the whole point of this kind of homework would have to be teaching precisely that... :-)
If you really feel uncertain about whether it's ok to use it (or whether it will be clear enough that you understand the pattern involved if you just use a named let), then you could just desugar it as explained above (possibly using a local define rather than letrec).
I'm not sure I understand this all correctly, but what's wrong with this simpler solution:
First:
You test if your argument is indeed a list:
If yes: Append the the MAP of the function over the tail (map postfixer (cdr lst)) to the a list containing only the head. The Map just applies the postfixer again to each sequential element of the tail.
If not, just return the argument unchanged.
Three lines of Scheme in my implementation, translates:
(postfixer '(= 7 (/ (+ 10 4) 2)))
To:
(7 ((10 4 +) 2 /) =)
The recursion via map needs no looping, not even tail looping, no mutation and shows the functional style by applying map. Unless I'm totally misunderstanding your point here, I don't see the need for all that complexity above.
Edit: Oh, now I read, infix, not prefix, to postfix. Well, the same general idea applies except taking the second element and not the first.

Append! in Scheme?

I'm learning R5RS Scheme at the moment (from PocketScheme) and I find that I could use a function that is built into some variants of Scheme but not all: Append!
In other words - destructively changing a list.
I am not so much interested in the actual code as an answer as much as understanding the process by which one could pass a list as a function (or a vector or string) and then mutate it.
example:
(define (append! lst var)
(cons (lst var))
)
When I use the approach as above, I have to do something like (define list (append! foo (bar)) which I would like something more generic.
Mutation, though allowed, is strongly discouraged in Scheme. PLT even went so far as to remove set-car! and set-cdr! (though they "replaced" them with set-mcar! and set-mcdr!). However, a spec for append! appeared in SRFI-1. This append! is a little different than yours. In the SRFI, the implementation may, but is not required to modify the cons cells to append the lists.
If you want to have an append! that is guaranteed to change the structure of the list that's being appended to, you'll probably have to write it yourself. It's not hard:
(define (my-append! a b)
(if (null? (cdr a))
(set-cdr! a b)
(my-append! (cdr a) b)))
To keep the definition simple, there is no error checking here, but it's clear that you will need to pass in a list of length at least 1 as a, and (preferably) a list (of any length) as b. The reason a must be at least length 1 is because you can't set-cdr! on an empty list.
Since you're interested in how this works, I'll see if I can explain. Basically, what we want to do is go down the list a until we get to the last cons pair, which is (<last element> . null). So we first see if a is already the last element in the list by checking for null in the cdr. If it is, we use set-cdr! to set it to the list we're appending, and we're done. If not, we have to call my-append! on the cdr of a. Each time we do this we get closer to the end of a. Since this is a mutation operation, we're not going to return anything, so we don't need to worry about forming our modified list as the return value.
Better late than never for putting in a couple 2-3 cents on this topic...
(1) There's nothing wrong with using the destructive procedures in Scheme while there is a single reference to the stucture being modified. So for example, building a large list efficiently, piecemeal via a single reference - and when complete, making that (now presumably not-to-be-modified) list known and referred to from various referents.
(2) I think APPEND! should behave like APPEND, only (potentially) destructively. And so APPEND! should expect any number of lists as arguments. Each list but the last would presumably be SET-CDR!'d to the next.
(3) The above definition of APPEND! is essentially NCONC from Mac Lisp and Common Lisp. (And other lisps).

What does it mean to 'hash cons'?

When to use it and why?
My question comes from the sentence: "hash cons with some classes and compare their instances with reference equality"
From Odersky, Spoon and Venners (2007), Programming in Scala, Artima Press, p. 243:
You hash cons instances of a class by caching all instances you have created in a weak collection. Then, any time you want a new instance of the class, you first check the cache. If the cache already has an element equal to the one you are about to create, you can reuse the existing instance. As a result of this arrangement, any two instances that are equal with equals() are also equal with reference equality.
Putting everyone's answers together:
ACL2 (A Computational Logic for Applicative Common Lisp) is a software system consisting of a programming language, an extensible theory in a first-order logic, and a mechanical theorem prover.
-- Wiki ACL2
In computer programming, cons (pronounced /ˈkɒnz/ or /ˈkɒns/) is a fundamental function in most dialects of the Lisp programming language. cons constructs (hence the name) memory objects which hold two values or pointers to values. These objects are referred to as (cons) cells, conses, or (cons) pairs. In Lisp jargon, the expression "to cons x onto y" means to construct a new object with (cons x y). The resulting pair has a left half, referred to as the car (the first element), and a right half (the second element), referred to as the cdr.
-- Wiki Cons
Logically, hons is merely another name for cons, i.e., the following is an ACL2 theorem:
(equal (hons x y) (cons x y))
Hons generally runs slower than cons because in creating a hons, an attempt is made to see whether a hons already exists with the same car and cdr. This involves search and the use of hash-tables.
-- http://www.cs.utexas.edu/~moore/acl2/current/HONS.html
Given your question:
hash cons with some classes and compare their instances with reference equality
It appears that hash cons is the process of hashing a LISP constructor to determine if an object already exists via equality comparison.
http://en.wikipedia.org/wiki/Hash_cons now redirects.
It is cons with hashing to allow eq (reference) comparison instead of a deep one. This is more efficient for memory (because identical objects are stored as references), and is of course faster if comparison is a common operation.
http://www.cs.utexas.edu/~moore/acl2/current/HONS.html describes an implementation for Lisp.

Resources