How do I find the number of lower case letters in Scheme Racket? - scheme

I'm trying to find the number of lower/upper case letters in a string, but there is a problem with my code:
(define case
(lambda (list)
(if(char-lower-case? (car list))
(case (cdr list))
(+ 1 (case (cdr list)))
)
))
(case (string->list "ScheMe"))
How can I solve this problem?

In your function you have two problems:
case is a predefined operator in racket/scheme
You don't test for an empty list.
Moreover, you use the parameter list, which is a primitive operator and should not be used as variable name.
Here is a working function:
(define (case1 lst)
(cond ((null? lst) 0)
((char-lower-case? (car lst)) (case1 (cdr lst)))
(else (+ 1 (case1 (cdr lst))))))
(case1 (string->list "ScheMe"))

Your code lacks a base case. (case '()) should evaluate to 0 but you get an error since you are doing car and cdr on nil.
Other things that might be wrong:
Your title indicates that you want to count lowercase letters but you increase for every uppercase.
list and case are names from the standard library. For R5RS it means undefined behaviour and for R6RS and later it means the library bindings would be unavailable. In #!racket (I guess you use this language since you tagged racket) it works as R6RS.

Related

In Scheme, does `or` and `and` short circuit?

Do and and or short circuit in Scheme?
The following are two implementation of lat? (list of atoms). One uses cond … else and the other uses or and and. I was wondering if they are equivalent and the answer to that hinges on whether or and and have short circuit evaluation in Scheme.
(define lat?
(lambda (l)
(cond
((null? l) #t)
((atom? (car l)) (lat? (cdr l)))
(else #f))))
uses cond and else
(define lat?
(lambda (l)
(or (null? l)
(and (atom? (car l))
(lat? (cdr l))))))
uses or and and
I think or short-circuits. Why? I know (car ()) and (cdr ()) each produce Error: Attempt to apply…. If or didn’t short-circuit, then (lat? ()) would eventually evaluate (car ()) and produce the error. However, (lat? ()) does not produce the error, therefore (via Modus Tollens) or short-circuits. Is this correct? And does and short-circuit?
Yes, they both short-circuit per r6rs specification (didn't find html version of r7rs online but here a link to the pdf version of r7rs specification, see section 4.2):
If there are no <test>s, #t is returned. Otherwise, the expressions are evaluated from left to right until a <test> returns #f or the last <test> is reached. In the former case, the and expression returns #f without evaluating the remaining expressions. In the latter case, the last expression is evaluated and its values are returned.
and & or is subsequently defined in terms of test.

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.)

I have got this code to remove the last element of a list. How can i change this to remove a set word regardless of its location?

#lang racket
(define (remove-last lst)
(if (null? (cdr lst))
'()
(cons (car lst) (remove-last (cdr lst)))))
(remove-last '(Help Me Please))
This then prints out:
(Help Me)
How can I change this? For example if I wanted to remove me.
Like this, for example:
(define (remove-words lst words)
(cond
((null? lst)
'())
((member (car lst) words)
(remove-words (cdr lst) words))
(else
(cons (car lst) (remove-words (cdr lst) words)))))
then
> (remove-words '(Help Me Please) '(Me Help Not))
'(Please)
You can also use the procedures for sets:
(define (remove-words lst words)
(set-subtract lst words))
Please note that you are working with symbols here, not strings.
You can also solve the problem using filter-not and member together:
(define (remove-words lst words)
(filter-not (lambda (x) (member x words) lst))
If you want to cut down on the wordiness of that anonymous function, the tools most suited to that are curry and cut (with the latter needing a (require srfi/26) to use).
Currying a function turns it into a new function that accepts one argument, then returns another function that accepts one more argument, then again, then again, and so on until it has all the arguments it needs to call the original function. A curried version of remove-words would be called as ((remove-words lst) words) instead, and you could make it from our current implementation with (curry remove-words). This requires that the arguments be supplied in left to right order, which doesn't work for member. There's another form curryr that goes right-to-left, but because member takes an optional third argument it won't work.
You could use cut (from srfi 26) then, which lets you pick which arguments of a function you want to "lock-in" and which you want the new function to accept. (cut member <> words)creates a new function (lambda (arg) (member arg words)) and (cut * <> <> 8) creates (lambda (arg1 arg2) (* arg1 arg2 8)). So with this, remove-words looks like:
(require srfi/26)
(define (remove-words lst words)
(filter-not (cut member <> words) lst))
Although going with set-subtract is still probably the best solution since you should avoid reinventing the wheel as much as possible (unless you're trying to learn more about wheels). Nonetheless, it's very useful to have a firm grip on the general functions provided by Racket that make your life easier.

Find whether element in list integer?

I was wondering, how do you check if every element in a list is an integer or not? I can check the first element by using (integer? (car list), but if I do (integer? (cdr list), it always returns false (#f) because the whole of the last part of the list is not an integer as a group.
In this case let's say list is defined as.
(define list '(1 2 5 4 5 3))
(define get-integers
(lambda (x)
(if (null? x)
"All elements of list are integers"
(if (integer? (car x))
(get-integers (cdr x))
"Not all elements are an integer"))))
Practical Schemes provide functions for doing tests across whole sequences. An application of the andmap function, for example, would be appropriate. Racket provides a for/and to do something similar. If you really needed to write out the loop by hand, you'll be using recursion.
What you need to do is test each element in the list to see if it satisfies a condition (being an integer, in this case). When you evaluate (integer? (car list)) on a list of integers, you're checking if the first element in the list is an integer, and that's fine. But the expression (integer? (cdr list)) tests if a list is an integer (because cdr returns a list), and that won't work - you need to test the next element in the list, and the next, and so on until the list is empty.
There are several ways to do the above, the most straightforward would be to recur on the list testing each element in turn, returning false if a non-integer element was found or true if all the list was consumed without finding a non-integer element, like this:
(define (all-integers? lst)
(cond ((null? lst) #t)
((not (integer? (car lst))) #f)
(else (all-integers? (cdr lst)))))
A more practical approach would be to use a built-in procedure, like this:
(andmap integer? lst)
andmap will check if all the elements in lst evaluate to true for the given predicate. For example:
(andmap integer? '(1 2 3))
> #t
(andmap integer? '(1 "x" 3))
> #f
SRFI-1 uses the terms every and any rather than andmap and ormap. match can also be used:
(define list-of-integers?
(lambda (lst)
(match lst
(((? number?) ..1) #t)
(_ #f))))

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