strange behavior of sort in racket - sorting

I have the following defined:
(struct type (parent dirty) #:mutable #:transparent)
(define types (make-hash))
(define (add-key predicate parent)
(begin
(hash-ref! types parent (type empty #t)) ;;if the parent doesn't exist, is created with no parent.
(let([node (hash-ref types predicate #f)])
(if(or (boolean? node) ;;the node is not on the list
(not(equal? (type-parent node) parent))) ;;the node has a different parent
(hash-set! types predicate (type parent #t))
(printf "nothing to do\n")
))))
(define (ancestor? predicate1 predicate2)
(let ([node (hash-ref types predicate2 #f)])
(cond [(false? node)(error "following predicate is not in types: " predicate2)]
[(empty? (type-parent node)) #f]
[(equal? (type-parent node) predicate1) #t]
[else (ancestor? predicate1 (type-parent node))])))
It seems to work great, and I can do stuff like:
> (ancestor? integer? even?)
#t
> (ancestor? list? even?)
#f
> (ancestor? integer? odd?)
#t
>
I only seem to have an issue with sort as (sort '(integer? odd? number? list? even?) ancestor?)
throws the following error: following predicate is not in types: integer?
which is, of course, defined in my implementation. The thing is that I am sure that the key-value pair exists, i can manipulate it, i can manually run every line of code of ancestor... I'am really puzzled to what could be causing this... Any idea?

I took your code as-is and dropped it in a file.
Added a trace line for ancestor?: either add a first line with (displayln `(ancestor? ,predicate1 ,predicate2)) or add (trace ancestor?) (after a (require racket/trace)).
This shows the offending call that is broken in your code: (ancestor? 'odd? 'integer?) leads to that exact error.
(I have no idea what your code is doing: the idea is that it's easy to derive the problem mechanically.)

Related

What is Classifier and Transformer in MIT Scheme?

In the following scheme code, accumulate does right-fold. When I tried to run using mit scheme. I ran into following error:
Transformer may not be used as an expression: #[classifier-item 13]
Classifier may not be used as an expression: #[classifier-item 12]
I google searched but didn't find useful information. Is it related a macro?
; This function is copied from SICP chapter 2
(define (accumulate op initial sequence)
(if (null? sequence)
initial
(op (car sequence)
(accumulate op initial (cdr sequence)))))
; works as expected
(accumulate
(lambda (x y) (or x y)) ; replace or with and also works
#f
'(#t #f #t #f #f)
))
; does not work
; error: Classifier may not be used as an expression: #[classifier-item 12]
(accumulate
or
#f
'(#t #f #t #f #f)
))
; does not work
; error: Transformer may not be used as an expression: #[classifier-item 13]
(accumulate
and
#f
'(#t #f #t #f #f)
))
Macros can be passed around in some languages, but not in Scheme and Common Lisp. The reason is that macros should be able to be expanded ahead of time. eg.
(define (cmp a b)
(cond ((< a b) -1)
((> a b) 1)
(else 0)))
Now a compiling Scheme will expand each node recursively replacing it with the expansion until it is no change:
(define (cmp a b)
(if (< a b)
(begin -1)
(cond ((> a b) 1)
(else 0))))
(define (cmp a b)
(if (< a b)
-1
(cond ((> a b) 1)
(else 0))))
(define (cmp a b)
(if (< a b)
-1
(if (> a b)
(begin 1)
(cond (else 0)))))
(define (cmp a b)
(if (< a b)
-1
(if (> a b)
1
(cond (else 0)))))
; end result
(define (cmp a b)
(if (< a b)
-1
(if (> a b)
1
0)))
From this point of cond doesn't need to exist in the underlying language at all since you'll never ever use it, but how would this have to be implemented to work:
(define (test syntax a b)
(syntax a b))
(test or #f #t)
For this to work the underlying language needs to know what or is even after expansion since syntax would need to be bound to or and then the transformation can happen. But when the code runs the macro expansion has already happened and in most implementations you would see something indicating that or is an unbound variable. It seems like MIT Scheme has added error checking for top level syntax syntax that will fire an error if you don't override it. Eg. if you add this you will not see any problems whatsoever:
(define (or a b) (if a a b))
(define (and a b) (if a b #f))
Now after those lines any reference to and and or are not the syntax, but these procedures. There are no reserved words in Scheme so if you do something crazy, like defining define you just cannot use it for the rest f that scope:
(define define display) ; defiens define as a top level variable
(define define) ; prints the representation of the function display
(define test 10) ; fail since test is an undefined variable so it cannot be displayed.
I created a interpreted lisp with macros that actually could be passed, but it isn't very useful and the chances of optimization is greatly reduced.
Yes it's related to the macros / special forms like and and or.
You can make it work simply by wrapping them as lambdas, (accumulate (lambda (a b) (or a b)) ...) -- the results will be correct but of course there won't be any short-circuiting then. The op is a function and functions receive their arguments already evaluated.
Either hide the arguments behind lambdas ((lambda () ...)) and evaluate them manually as needed, or define specific versions each for each macro op, like
(define (accumulate-or initial sequence)
(if (null? sequence)
initial
(or (car sequence)
(accumulate-or initial (cdr sequence)))))
Here sequence will still be evaluated in full before the call to accumulate-or, but at least the accumulate-or won't be working through it even after the result is already known.
If sequence contains some results of heavy computations which you want to avoid in case they aren't needed, look into using "lazy sequences" for that.

Need a hint on a homework question which asks to add numbers in a list in a particular way

This is a homework question
The function takes in a list as the parameter, which may contain as many layers as sublists as needed For example, '(a (1 b 3)) or '((a 3 5) (b (3 1) 4)). The output has the same list structure of the input (meaning that sublists are maintained), but the car of each list is the sum of all numbers in the list. And all other non-numeric values are discarded. As an example output, consider '((a 3 5) (b (3 1) 4)), the output should be '(16 (8) (8 (4))). Also, only use basic scheme instructions/operations such as + - * /, car, cdr, cons, append, null?, number?, if/else, cond, etc.. Cannot Use a helper method.
So far this is the code I have, which sometimes partially does the job. But I'm having a really hard time figuring out how to get the sum from the sublists to add up at one spot at the car of the outmost list.
(define partialsums*
(lambda (lis)
(cond
[(null? lis) '(0)]
[(list? (car lis)) (cons (partialsums* (car lis)) (if (not (null? (cdr lis))) (partialsums* (cdr lis)) '()))]
[(number? (car lis)) (cons (+ (car lis) (car (partialsums* (cdr lis)))) '())]
[else (cons (+ 0 (car (partialsums* (cdr lis)))) '())])))
I've already spent several hours on this but couldn't quite grasp how to correctly approach the problem, probably because this is my first week using scheme :(. Any help is appreciated.
Also, I cannot use a helper method. Everything needs to be done inside one function in a recursive style. letrec is not allowed either.
To make life easy, you should model the data. Since there are no types, we can do this informally.
What is the structure of the input?
We can model it like "Data Definitions" from How to Design Programs. Read the "Intertwined Data" section because our data definition is similar to that of an S-expression.
; A NestedElem is one of:
; - Atom
; - NestedList
; An Atom is one of:
; - Number
; - Symbol
; A NestedList is one of
; - '()
; - (cons NestedElem NestedList)
We can define an atom? predicate to help us differentiate between clauses of the kinds of data in our program.
; Any -> Boolean
; is `a` an atom?
(define atom?
(lambda (a)
(or (number? a)
(symbol? a))))
The structure of the program should match the structure of the Data.
So we define a "template" on our data. It distinguished and destructs each data into clauses. It further de-structures the rhs of a clause.
; NestedElem -> ...
(define nested-elem-template
(lambda (ne)
(cond
[(atom? ne) ...]
[else ...])))
; Atom -> ...
(define atom-template
(lambda (atom)
(cond [(number? atom) ...]
[(symbol? atom) ...])))
; NestedList -> ...
(define nested-list-template
(lambda (nl)
(cond [(null? nl) ...]
[else (... (car nl)... (cdr nl))])))
We definitely know more about the data. (car nl) in the nested-list-template is of type NestedElem. Therefore we can fill up some ...s with calls to templates that deal with that kind of data. In the same vein, we can wrap recursive calls around expressions of a datatype we know of.
; NestedElem -> ...
(define nested-elem-template
(lambda (ne)
(cond
[(atom? ne) (atom-template ne)]
[else (nested-list-template ne)])))
; Atom -> ...
(define atom-template
(lambda (atom)
(cond [(number? atom) ...]
[(symbol? atom) ...])))
; NestedList -> ...
(define nested-list-template
(lambda (nl)
(cond [(null? nl) ...]
[else (... (nested-elem-template (car nl))
... (nested-list-template (cdr nl)))])))
Now we can "fill in the blanks".
We can "filter", "map", and "fold" over this data structure. All those can be defined using the template as a scaffold.
Note 1: Your HW asks you to do multiple tasks:
remove the symbols
sum up the numbers
cons the sum onto every list
Don't try to do everything in a single function. Delegate into multiple helper functions/traversals.
Note 2: I did not model the output type. It's the same as input type except that Symbol is no longer an atom.

Can someone explain equality to me in scheme/racket?

So I stumbled across this today and it has me puzzled.
(define (x) '(1))
(eq? (x) (x)) ;=> #t
(eq? '(1) '(1)) ;=> #f
(define (y) (list 1))
(eq? (y) (y)) ;=> #f
(eq? (list 1) (list 1)) ;=> #f
Can anyone explain what's happening here ?
When compiled this program
(define (x) '(1))
(eq? (x) (x))
(eq? '(1) '(1))
is compiled into (something like):
(define datum1 '(1))
(define datum2 '(1))
(define datum3 '(1))
(define (x) datum1)
(eq? (x) (x))
(eq? datum2 datum3)
Therefore (x) will always return the object stored in datum1.
The expressions (eq? '(1) '(1)) on the other hand will
find out that datum2 and datum3 does not store the same object.
Note: There is a choice for the compiler writer. Many Scheme implementation will compile the above program to:
(define datum1 '(1))
(define (x) datum1)
(eq? (x) (x))
(eq? datum1 datum1)
and then the result will be true in both cases.
Note: The documentation of quote doesn't explicitly state whether multiple occurrences of '(1) in a program will produce the same value or not. Therefore this behavior might change in the future. [Although I believe the current behavior is a deliberate choice]
eq? checks if the objects are the same (think "if the pointer refers to the same address in memory").
In the first case you're working with literals created at compile time. Comparing (and modifying) literals is generally undefined behaviour. Here it looks like procedure x returns the same literal every time, but in the second expression it looks like the 2 literals are not the same. As I said, undefined behaviour.
In the second case you're not working with literals but list creates a new list at execution time. So each call to y or list creates a fresh list.
uselpa's answer is correct.† I wanted to expand on what a quoted datum is, a little further, though.
As you know, all Scheme programs are internally read in as a syntax tree. In Racket, in particular, you use the read-syntax procedure to do it:
> (define stx (with-input-from-string "(foo bar)" read-syntax))
> stx
#<syntax::1 (foo bar)>
You can convert a syntax tree to a datum using syntax->datum:
> (syntax->datum stx)
'(foo bar)
quote is a special form, and what it does is return the quoted portion of the syntax tree as a datum. This is why, for many Scheme implementations, your x procedure returns the same object each time: it's returning the same portion of the syntax tree as a datum. (This is an implementation detail, and Scheme implementations are not required to have this behaviour, but it helps explain why you see what you see.)
And as uselpa's answer says, list creates a fresh list each time, if the list is non-empty. That's why the result of two separate non-empty invocations of list will always be distinct when compared with eq?.
(In Scheme, the empty list is required to be represented as a singleton object. So (eq? '() '()) is guaranteed to be true, as is (eq? (list) '()), (eq? (cdr (list 'foo)) (list)), etc.)
† I would not use the phrasing "undefined behaviour" for comparing literals because that's easily confused with the C and C++ meaning of UB, which is nasal demons, and although the result of comparing literals may not be what you expect, it would not cause your program to crash, etc. Modifying literals is nasal demons, of course.

All: A Function Returning True if and only if All Elements of a List are True

I am looking for a built-in function in Racket that will return True iff all the items in a list are true.
I tried:
(define (all lst)
(when
(equal? lst '())
#t)
(if (not (car lst))
#f
(all (cdr lst))))
Giving error:
car: contract violation
expected: pair?
given: '()
A couple of testcases:
(all '(#t #f #t)) ; #f
(all '(#t #t #t)) ; #t
Could you please either fix it or point me to the built-in function?
(I googled, but got no meaningful result)
You've already accepted another answer that explains a nice way to do this, but I think it's worth pointing out what was wrong in your attempt, because it was actually very close. The problem is that true from the when block is completely ignored. It doesn't cause the function to return. So even when you have the empty list, you evaluate the when, and then keep on going into the other part where you call car and cdr with the same empty list:
(define (all lst)
(when ; The whole (when ...) expression
(equal? lst '()) ; is evaluated, and then its result
#t) ; is ignored.
(if (not (car lst))
#f
(all (cdr lst))))
A very quick solution would be to change it to:
(define (all lst)
(if (equal? lst '())
#t
(if (not (car lst))
#f
(all (cdr lst)))))
At that point, you can simplify a little bit by using boolean operators rather than returning true and false explicitly, and clean up a little bit by using empty?, as noted in the other answer:
(define (all lst)
(or (empty? lst)
(and (car lst)
(all (cdr lst)))))
You were actually very close at the start.
If you're looking for a builtin solution, you'll probably want to take a look at andmap, which applies a predicate over an entire list and ands the results together.
You could use this to implement all very simply.
(define (all lst)
(andmap identity lst))
By using identity from racket/function, all will just use the values in the list as-is. Instead of using identity explicitly, you could also use values, which is just the identity function on single values, so it's a somewhat common idiom in Racket.
There are two kinds of lists: empty ones and pairs.
Therefore we have the following structure:
(define (all xs)
(cond
[(empty? xs) ...]
[(pair? xs) ...]
[else (error 'all "expected a list, got: " xs)]))
Since all elements in the empty list are true, we get:
(define (all xs)
(cond
[(empty? xs) #t]
[(pair? xs) ...]
[else (error 'all "expected a list, got: " xs)]))
If a list begins with a pair, then all elements of the list are true,
if both the first element of the list and the rest of the elements of the list are true:
(define (all xs)
(cond
[(empty? xs) #t]
[(pair? xs) (and (first xs) (all (rest xs)))]
[else (error 'all "expected a list, got: " xs)]))
Note that part of the problem in your program is the use of when.
The result of
(when #t
'foo)
'bar
is 'bar. The construct when is only useful if you are using side effects (such as caused by set! and friends).
All is a higher order folding function. Scheme refers to these as "reductions" and reduce is available in SRFI-1
In Gauche Scheme:
(use srfi-1)
(define (all list-of-x)
(reduce (lambda (x y)
(and x y))
#t
list-of-x))
Will return #f or a value that evaluates to true. For example:
gosh> (all '(1 2 3))
1
If that's OK, then we're done. Otherwise we can always get #t with:
(use srfi-1)
(define (all-2 list-of-x)
(if (reduce (lambda (x y)
(and x y))
#t
list-of-x)
#t
#f))
And then wind up with:
gosh> (all '(1 2 3))
#t

Scheme returning wrong type to apply for list input

I am trying to write a program which will add numbers in a list. However, when I give the input as a list, Scheme does not give me an output.
My code is the following:
(define (sumlist lst)
(cond ( (pair? lst) (+ (car lst) (sumlist(cdr lst))) )))
Why does this happen? I am giving input properly, i.e, I am quoting the list.
I am giving input as follows:
(sumlist '(1 2 3))
EDIT:
I changed the question slightly. The list was not quoted in pair? 'lst and that is why I was getting an error.
Now, I am not getting an error. However, I am not getting any output either.
EDIT2:
I unquoted the list in pair? lst. However, now it is giving me the following error: Wrong type in arg2 #
I have updated the code accordingly.
Your function application syntax is wrong. Function application is always prefix in Scheme, i.e. car(lst) should be (car lst), etc.
Also, (pair? 'lst) is wrong, since you should not be quoting the argument. That will test if the symbol lst is a pair, which is obviously always false.
You need a base case for when you don't want to recurse—when you receive the empty list—which should return 0.
Putting all these together, and you should have this:
(define (sumlist lst)
(if (pair? lst)
(+ (car lst) (sumlist (cdr lst)))
0))
(I also changed cond to if since cond is unnecessary in this case.)

Resources