Null use in a small Scheme script - scheme

I'm just learning how to write in Scheme and hitting a road block with the use of Null. I have the script below from this video series...
https://www.youtube.com/watch?v=Qqext1NwmqM&index=2&list=PLgyU3jNA6VjRMB-LXXR9ZWcU3-GCzJPm0
Script...
(define (my-map fn lst)
(if (null? lst)
null
(cons (fn (car lst)) (my-map fn (cdr lst)))))
This is just redefining the map function in Scheme. It fails at the third line as "null: undefined. cannot reference undefined identifier" when I pass a function and a list.
I just copied what the video shows so not sure why it's failing. If I switch out null for '(), that works. Anyone know why?

It's quite possible that your Scheme interpreter doesn't have the null symbol bound to the '() value, as this is not required by the language specification. Either do this:
(define null '())
Or equivalently this, as you already guessed:
(define (my-map fn lst)
(if (null? lst)
'()
(cons (fn (car lst))
(my-map fn (cdr lst)))))
Notice that the latest Scheme report states that (null? obj) should return #t
if obj is the empty list, otherwise returns #f
So it's ok to define null as '().

Related

Racket Contract Violation (Max Recursion Function)

Learning some Scheme/Racket, so give me some leeway.
Currently trying to find the max value when given a list without using the built-in max() function.
Current Code:
#lang racket
(provide max-num)
(define (max-num lst)
(define (helper lst max)
(displayln lst)
(displayln max)
(displayln " ")
(when (null? max) ; first run
(helper (cdr lst) (car lst)))
(if (null? lst)
max ; then end
(if (> (car lst) max) ; else compare
(helper (cdr lst) (car lst)) ; then update max
(helper (cdr lst) max)))) ; else keep max
(if (null? lst)
#f ; then Error
(helper lst '())) ; else run helper
)
(max-num '())
(max-num '(1 5 2 4 3))
Output via DrRacket:
As far as I can tell, the displayln outputs tell me I am on the right track. However, it ends up with a contract violation real? error instead of returning the max value.
I'm guessing that the (if (null? lst)) doesn't want to return "max" at the end and instead pushes towards the else branch despite the list being empty. I've looked around and debugged for about an hour now to no avail. Any help would be greatly appreciated.
You have to know that when you do:
(when test
do-something)
do-something-else
It will always do-something-else regardless if test is true or not. SO what is happening is that the first round max is null? and it does (helper (cdr lst) (car lst))) and that returns the answer. Then it discard that answer and continue to the if with max being null? and it finally fails when it does (> (car lst) max) since a null? is not a number. The error message says it expected a real? but it got the initial value '().
So to hint you on your way you should have one expression in addition to the local definitions eg.
(if test1
result1
(if test2
result2
alternative2))
or
(cond (test1 result1)
(test2 result2)
(else alternative2))
And of course since you know the argument is not null? you could just call (helper (cdr lst) (car lst)) instead of passing the empty list and remove the when entirely. when and unless are for side effects and not really for good functional Scheme style.

Racket function passing empty list instead of actual list

I'm pretty new to racket and I'm trying to make a finite state machine for a project. here's what I have so far.
#lang racket
(define (test rules cs pass lst)
(if (eq? (length lst) 0)
(if (member cs pass)
(write 'passed)
(write 'failed))
(test rules (next rules cs (car lst)) (cdr lst))))
(define (next rules cs input)
(if (eq? cs (car (car rules)))
(if (eq? input (car(cdr(car rules))))
(car(cdr(cdr(car rules))))
((next (cdr rules) cs input)))
(next (cdr rules) cs input)))
then I input
(define rules '('(0 a 0) '(0 b 1) '(1 a 0) '(1 b 1)))
(define pass '(1))
(test rules 0 pass '(a b a b))
and for a reason that I cannot figure out, I get
this error on the next function. It acts as though rules is an empty list, which I'm pretty sure it's not. Anyway if anyone could tell me why it's doing that it would really help.
Thanks!
EDIT1
Thanks so much for the help guys. It's really helping. The code is working entirely until the end, but now it throws an error at the end of my code if I test multiple lists with testmany.
(define (testmany rules cs pass lst)(if (eq? (length lst) 0)
(write 'done)
((test rules cs pass (car lst))
(testmany rules cs pass (cdr lst)))))
(define (test rules cs pass lst) (if (eq? (length lst) 0)
(if (member cs pass)
(write 'accepted.....)
(write 'rejected.....))
(test rules (next rules cs (car lst)) pass (cdr lst))))
(define (next rules cs input) (if (eq? cs (car (car rules)))
(if (eq? input (car(cdr(car rules))))
(car(cdr(cdr(car rules))))
(next (cdr rules) cs input))
(next (cdr rules) cs input)))
The code doesn't seem to know when to stop the recursion of the testmany function. When the list is empty, it prints done, but then continues the next part as if the list still had elements, throwing this error. If anyone knows why it is throwing this error please let me know.
Thanks!
You forgot the begin:
(define (testmany rules cs pass lst) (if (eq? (length lst) 0)
(write 'done)
(begin
; ^^^^^ here
(test rules cs pass (car lst))
(testmany rules cs pass (cdr lst)))))
Without it, the return value of (test rules cs pass (car lst)) is attempted to be used as a function; but it is #<void>, the result of (write ....) form, which is the last one evaluated (more like, executed) by your test function.
By the way, #<void> is not an empty list; it's more like a non-value.
edit: the reason it does recurse to the end (without the begin) is that to apply a function foo in (foo val) to a value val, both expressions are evaluated first.
It is only after the evaluation of val, i.e. (testmany ...), finishes fully that the error is discovered that the value of foo, i.e. (test ...) expression, is not in fact a function, and can not be applied.

Scheme - How do I get each list in a list that's not made up of more lists

(define (walk-list lst fun) ;;walk-list(list, fun)
(if (not(null? lst)) ;;IF the list isn't NULL
(begin
(if (list? lst) ;;&& the list is actually a list , THEN{
(begin
(if (equal? (car lst) '()) ;;IF the first element in the list is empty
(fun lst) ;;THEN call the function on the list (funct is supose to get each word)
(if (not (null? lst)) ;;ELSE IF the first item isn't a list
(begin ;;{
(walk-list (car lst) fun) ;;walk-list((car lst),fun)
(walk-list (cdr lst) fun))))))))) ;;walk-list((cdr lst),fun)
(walk-list test-document display) ;;walk through the list with the given document
The will look something like this:
(define test-document '(
((h e l l o));;paragraph1
((t h i s)(i s)(t e s t));;paragraph2
))
I'm trying to get each individual word into the document have a function applied to it. Where is says (fun list). But the function is never called.
First off. begin is if you need to do more than one expression. The first expression then needs to have side effects or else it's just a waste of processing power.
Ie.
(begin
(display "hello") ; display is a side effect
(something-else))
When you don't have more than one expression begin isn't needed. if has 3 parts. They are:
(if predicate-expression ; turnas into something true or #f (the only false value)
consequent-expression ; when predicate-expression evalautes to anything but #f
alternative-expression) ; when predicate-expression evaluates to #f this is done
You should ident your code properly. Here is the code idented with DrRacket IDE, with reduncant begin removed and missing alternative-expressions added so you see where they return:
(define (walk-list lst fun) ;;walk-list(list, fun)
(if (not (null? lst)) ;;IF the list isn't NULL
(if (list? lst) ;; && the list is actually a list , THEN{
(if (equal? (car lst) '()) ;; IF the first element in the list is empty
(fun lst) ;; THEN call the function on the list (funct is supose to get each word)
(if (not (null? lst)) ;; ELSE IF the first item isn't a list
(begin ;; Here begin is needed
(walk-list (car lst) fun) ;; walk-list((car lst),fun)
(walk-list (cdr lst) fun)) ;; walk-list((cdr lst),fun)
'undfined-return-1)) ;; stop recursion, return undefined value
'undefined-return-2) ;; stop recursion, return undefined value
'undefined-return-3)) ;; stop recursion, return undefined value
So when does (fun lst) get called? Never! There is no () in any car in (((h e l l o))((t h i s) (i s) (t e s t))) and (equal? (car lst) '()) which is (null? (car lst)) will always be #f. Since we know (not (null? lst)) is #t so it will walk car and cdr where either 'undefined-return-2 or 'undefined-return-3 will be evaluated and the procedure stops when everything is visited and nothing processed.
You haven't shown what (walk-list test-document display) should have displayed but I make a wild guess that you want it for every element except pairs and null, thus I would have written this like this:
(accumulate-tree test-document display (lambda (a d) 'return) '())
accumulate-tree you'll find in this SICP handout. It demonstrates many uses for it as well. For completeness I'll supply it here:
(define (accumulate-tree tree term combiner null-value)
(cond ((null? tree) null-value)
((not (pair? tree)) (term tree))
(else (combiner
(accumulate-tree (car tree)
term
combiner
null-value)
(accumulate-tree (cdr tree)
term
combiner
null-value)))))
Judging from you code you are an Algol programmer learning your first Lisp. I advice you to look at the SICP videoes and book.

Scheme getting last element in list

Im trying to write a simple scheme function that returns the last element of a list. My function looks like it should work, but I managed to fail on something:
(define (last_element l)(
(cond (null? (cdr l)) (car l))
(last_element (cdr l))
))
(last_element '(1 2 3)) should return 3
DrRacket keeps on giving me the errors:
mcdr: contract violation
expected: mpair?
given: ()
Since (null? '()) is true, I don't get why this doesn't work.
This is a function I think I will need for a homework assignment (writing the function last-element is not the assignment), and the instructions say that I cannot use the built-in function reverse, so I can't just do (car (reverse l))
How do I fix this function?
Your syntax is totally wrong. You have an extra set of parentheses around the body of the function, not enough around the cond clauses, and your recursive case isn't even within the cond, so it gets done whether the test succeeds or fails. The following procedure should work:
(define (last_element l)
(cond ((null? (cdr l)) (car l))
(else (last_element (cdr l)))))
Just to add: in professional-level Racket, the last function is a part of the racket/list library.
you can retrieve the last element of a list by calling
(define (lastElem list) (car (reverse list)))
or, recursively using if built-in
(define (last list)
(if (zero? (length (cdr list)))
(car list)
(last (cdr list))))
You can also do it like this.First find the lenght of a list by cdring it down.Then use list-ref x which gives the x element of the list.
For example list-ref yourlistsname 0 gives the first element (basically car of the list.)And (list-ref
yourlistsname (- length 1)) gives the last element of the list.

How I can force scheme to return #f explicitly instead of just void?

(define every-aux
(lambda(status predicate lst)
(cond((null? lst) status)
((cond((equal? (predicate (car lst)) #t)
(set! status #t)
(every-aux status predicate (cdr lst)))
(else (set! status #f) status))))))
Above Procedure returns void if predicate does not match with every element in lst?
It does not have any problem is returning #t though if predicate matches every element of lst.
Changing the last line to
(else (set! status #f) status))))))
to
(else (set! status "#f") status))))))
returns "#f" so procedure is correct.
How I can force scheme to return #f explicitly instead of just void?
Your code is very messy:
You have a cond inside another, but cond is intended for multiple tests/results.
There is no reason to have that status modified -- Scheme uses call-by-value, so this is likely not doing whatever you think it does.
Specifically, there is no reason to use (else (set! status #f) status) -- you could just return #f directly.
The actual reason for your confusion is the weird cond nesting -- the second cond is actually used as a test, so if you make it (the inner cond) return #f, then the whole test of the outer cond is getting #f, which means that it (the outer cond) didn't get any true result, and resorts to returning an unspecified value (and if this is Racket, then that value is shown as #<void>). So if you flatten the two conds into one, your problem will go away.
Finally, if you're having problems at such a level, then you should consider using some textbook to familiarize yourself with the language. Specifically HtDP is intended to give you an easy path into getting familiar with the syntax.
#Eli Barzilay
After some I deliberation I could see the solution. Thanks for the pointers.
(define every?
(lambda (predicate list)
(if(null? list) "Empty List not allowed."
(every-aux? predicate list))))
(define every-aux?
(lambda (predicate lst)
(cond ((null? lst) #t)
((equal? (predicate (car lst)) #t) (every-aux? predicate (cdr lst)))
(else #f))))

Resources