true and false null values in lisp vs scheme - scheme

I want to use the function in a scheme program im writing however im unsure ho to translate the T & Nil values within the function. Can nil essentially be written as '() in scheme?
(define (listword (lambda (word)
(cond
((isvowel (car word)) (novowel word))
(T (novowel word NIL))))))

To avoid confusion I'll take Common Lisp as an exemplar of a 'traditional' Lisp and call it 'Lisp' below, as opposed to Scheme: Scheme is also a Lisp of course but I want to have to type less.
Both Lisp and Scheme use the common convention that there is a single distinguished false object with everything else being true. In the construction of lists, both Lisp and Scheme also need to have a special distinguished 'empty list' element which is also unique. Lisp then chooses to pun, making the empty list and false be the same object: Scheme does not, and treats them as distinct. Additionally, Lisp provides a name for the empty list object, while Scheme does not, and Scheme also does not treat the empty list object as self-evaluating while Lisp does. Both languages provide a canonical true object as well, but again Lisp provides a name for it while Scheme doesn't. In both languages the true and false objects are self-evaluating.
So.
(Common) Lisp:
all objects are true except for the empty list, () -- (if () 1 2) evaluates to 2;
the empty list is self-evaluating -- (eq '() ()) is true;
the empty list is unique -- (eq () ()) and (eq () '()) are both true, as is (eq () (cdr (list 1))) for instance;
the empty list has a name, NIL -- (eq nil ()) & so on;
there is a canonical true object whose name is T and whose value is T;
while it is perhaps disputed, I think it is better to use NIL when you want to talk about false and () when you want to talk about the empty list.
Scheme:
all objects are true except for the special false object which is #f -- (if #f 1 2) evaluates to 2 while (if x 1 2) evaluates to 1 for x having any value not eq? to #f;
#f is self-evaluating --(eq? #f '#f) is true;
#f is unique;
#f has no special name in the sense that there is no symbol whose value it is (this is probably not the right terminology in Scheme);
there is a canonical true object, #t, although all objects are true other than #f;
there is a unique empty list object, () -- this object is not the same as #f, is not self-evaluating and does not have a name, so (eq? #f '()) is false, but (eq? '() '()) is true, as is (eq? '() (cdr (list 1))), while (if '() 1 2) evaluates to 1 and (eq? () 1) is an error.
Disclaimer: my knowledge of CL is better than my knowledge of Scheme.

In Common Lisp nil/'nil/()/'() represents the same value nil and it is both the empty list and the one false value. In Scheme they are two different values, '() for the empty list and #f as the false value. When translating Common Lisp one needs to determine if the value represents a false value or an empty list. In some cases you will have the empty list being used as a boolean and thus you would need to do (not (null? v)) where CL just does v. The reason for this is that only #f is false in Scheme and thus the empty list is a true value. (if '() #t #f) ; ==> #t
In Common Lisp t can be replaced by #t, but in Scheme there are special symbols in some forms like else in cond that is the idiomatic way to do the alternative term.

I guess you're translating some Common Lisp code to Scheme. In Scheme, the T at the end of a cond expression can be replaced by true, but the idiomatic way is to use an else. And NIL is just the empty list '(), sometimes aliased as null.
Also, be careful with how you define a procedure, you wrote an incorrect opening parenthesis in the first line - the correct way is:
(define listword
(lambda (word)
...))
Or equivalently (and perhaps more idiomatic):
(define (listword word)
...)

Related

Nil is not the empty list?

I am learning Scheme and am using an online interpreter from repl.it. I am having some trouble understanding why this returns #f:
(eq? '() 'nil) ; ==> #f
In LISP 1.5 nil, 'nil, '() and () evaluates to nil. The reader translated () and nil into the same singleton empty list and it is self evaluating so that the quote is optional. nil is also the only false value and all other values are truthy. The very first Scheme implementation was hosted by a commercial Lisp compatible with 1.5 and much of the host were used transparently in the first Scheme. Common Lisp is a descendant of 1.5 and still works like this, but Scheme has had changes from report to report and these are the rules from R5RS and later:
The empty list is '(). It's quoted and evaluates to (). It is not self evaluating so () is invalid Scheme code. 'nil evalutes to nil which is a symbol and not the empty list. In Scheme the only false value is #f and thus the empty list is truthy.
In code:
'() ; ==> ()
'(1 . (2 . ()) ; ==> (1 2)
() ; ==> ERROR: Illegal empty application (not allowed)
(eq? '() 'nil) ; ==> #f (empty list and nil are different values)
(if '() #t #f) ; ==> #t (empty list is truthy)

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.

How do I use and/or instead of if/cond?

I'm new to Scheme programming and I've gotten this task that I just can't find out how to work correctly. I'm supposed to define a procedure with one parameter (a number). If the number is positive I want 1 to be returned, -1 if the number is negative and 0 if it is 0, using only and/or. If and cond is not allowed. I only get #t or #f returned, but you see that's not what I want. Any help or pointers is appreciated
You can solve your problem if you look at the following equivalence, valid when every expj has a value different from #f:
(cond (test1 exp1) (or (and test1 exp1)
(test2 exp2) (and test2 exp2)
... ≡ ...
(testn expn) (and testn expn)
(else expn+1)) expn+1)
Since the function that gets the sign of a number can simply be written in this way:
(define (sign x)
(cond ((> x 0) +1)
((< x 0) -1)
(else 0)))
after applying the above equivalence, since every result is an integer, different from #f, this function becomes equal to the solution proposed also in another answer:
(define (sign x)
(or (and (> x 0) +1)
(and (< x 0) -1)
0))
So, which is the reason of the above equivalence? It depends on the fact that and evaluates its arguments in turn; as soon as one of them is #f, it stops by returning #f, otherwise returns its last argument (and this explains the single branches (and testj expj)); while or evaluates its arguments in turn; as soon as one of them is not #f, it stops by returning it, otherwise returns its last argument (and this explains the chain (or (and ...) (and ...) ... expn+1)).
(define test
(lambda (n)
(or (and (< n 0) -1)
(and (= n 0) 0)
1)))
Part of the trick is understanding that and, if everything evaluates to true, will return the last item it evaluated, while or will return the first thing that successfully evaluates to true. The other part is realizing that everything except for #f is considered "true."
The transformation of and is seen in the report but to not include the actual macros it's basically this:
; only one argument
(and a) ; ===>
a
; one of more
(and a b ...) ; ==>
(if a
(and b ...)
#f)
All arguments must be evaluate to a positive value and the last value is the result, else #f. It short circuits so when something is #f the rest of the expressions are never evaluated.
For or is like this:
(or a) ; ==>
a
(or a b ...) ; ==>
(let ((a-value a))
(if a-value
a-value
(or b ...)))
The first argument that does not evaluate to #f gets returned. If all values are #f the last #f will be the result.
Thus if you want:
(if a b c) ; ==>
(let ((tmpa a))
(or (and atmpa b)
(and (not atmpa) c)) ; not part only important if b can be #f
I use let to prevent evaluating the same expression several times. eg. if you had one that printed something like (begin (display "hello") #f) or it's an expensive calculation then it's necessary or else you can just substitute the variable with the expression. eg. the last would become:
(or (and a b)
(and (not a) c))
That transformed back with no temporary variables become:
(if (if a b #f)
(if a b #f)
(if (not a) c #f))
If b is #f value, then the result is #f because of the last if. Thus everytime a is true b is the result. Everytime it's false, c is the answer. Thus
(if a b c)
So imagine you want to return the first true value in a list.
(define (first-true lst)
(and (not (null? lst))
(car lst)
(first-true (cdr lst))))

Best way to check if a list is not null?

In Common Lisp, if I wanted to check whether a list was not null, I could simply use the list itself as the condition, since all non-nil lists are considered as true. However, I find that in Scheme, doing the same will make Scheme think that I am trying to call a function. Is there a better way to check whether or not a list is null in Scheme than to define another function that does (not (null? x))?
In Scheme, everything that's not #f is truthy, so '() is considered #t in if statements.
Thus,
(if '() "true" "false") => "true"
(not '()) => #f
Using (not (null? x)) is the most straightforward way of checking if a list is not null: it describes exactly what you want, and in corner cases where you're given something that's not a list, it will give you different behavior:
(if (not (null? #t)) "true" "false") => "true"
(if (not #t) "true" "false") => "false"
If you know that it's a list, you can use (pair? x), since every list is either a pair or '().

Adding arguments to list causes error

I tried an example where we need to pass a list as arguments and if condition succeeds I want to add result to a new list.
Here's the code:
(define get-description
(lambda (codeValue newList)
(cond
((= (car codeValue) 1) (cons "A" newlist))
((= (car codeValue) 2)(cons "B" newlist))
((= (car codeValue) 3) "C")
(else "Negative numbers are not valid"))))
I pass this as the function call:
(get-description (list 1 2 3) (list))
I get output:
(cons "A" empty)
Output should just show: (A)
I am using DrRacket for writing my programs and have chosen language mode as: Beginning Student.
Why do I get cons and A with "" and empty in my newlist?
Please don't use "Beginning Student" as a language type in Racket. That's a subset specially made for the HtDP book. The languages "racket", "r5rs", "pretty big", are more like real Schemes and should all work for The Little Schemer.
In your arguments list, you have (codeValue newList), but in the program body you refer to newlist. All of the Schemes that I've used are case-sensitive. Changing your newList to newlist made your program run perfectly fine on Chez Scheme and Guile too.
Edit: To clarify, "A" is a string. Scheme also has the additional data type of symbol, which is just a name and nothing else (and is probably what you want here). You probably want to (cons 'A newlist) rather than (cons "A" newlist) if you're expecting (A).
Other Schemes would print just ("A"). Such output is clearly an idiosyncrasy of the Racket language.
As for why the A is in quotation marks, that's because it's a string object, and that's simply how string objects are printed. But if you were to DISPLAY such an object, you'd get the A by its lonesome.

Resources