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? - scheme

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

Related

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

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.

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.

Scheme evaluation order standard

I've got a program I'm writing for a class to substitute the left-most occurrence of a variable with a new variable. (It actually allows you to provide an equivalence relation yourself, as well). The thing is, in Chez Scheme 8.2, this substitutes the right-most occurrence, if the left most is inside a list. We use a server running some version of scheme (I'm not sure which version), and on the server it substitutes, correctly, the left-most occurrence. Below is the code:
(define subst-leftmost
(lambda (new old ls proc)
(let ([keep-going? #t])
(letrec ([helper
(lambda (ls)
(cond [(null? ls) ls]
[(or (pair? (car ls)) (null? (car ls)))
(cons (helper (car ls)) (helper (cdr ls)))]
[(and keep-going? (proc old (car ls)))
(set! keep-going? #f) (cons new (cdr ls))]
[else (cons (car ls) (helper (cdr ls)))]))]) (helper ls))))
This is called like so: (subst-leftmost 'x 'a '(d b c (a) b a) eq?) which should produce the output (d b c (x) b a), and does on the server. In Chez scheme, however, it produces (d b c (a) b x). I think the difference is due to the line
[(or (pair? (car ls)) (null? (car ls)))
(cons (helper (car ls)) (helper (cdr ls)))]
evaluating the helper of the car and the helper of the cdr in a not-set order.
My question is this: Which version of scheme is following the standard, and how can I modify my code so that it works correctly in both versions?
(I've already talked to my professor about this. He's going to address the class about it on Monday, once he can think about it some, but I'm curious. I also already got the full points for the assignment, so don't worry about the ethics of helping me, in that regard.)
There isn't any, sorry. Here's the relevant legalese. Use LETs or LET* if you need to evaluate sub-expressions in a particular order.
Scheme guarantees no specific order (as Cirno has said). If your code has no side-effects, this doesn't matter.
However, your code is side-effecting (because of the set! to an outside variable), so, you have some choices:
Use Racket (which is committed to using left-to-right order, last time I talked to a Racket dev)
Structure your code to remove side-effects, so that your helper function doesn't change any variable or state outside it
Use appropriate lets to ensure the ordering you need (as Cirno suggested); in particular, change (cons (helper (car ls)) (helper (cdr ls))) to:
(let ((depth-first (helper (car ls))))
(cons depth-first (helper (cdr ls))))

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

the difference between if and cond?

i'm learning sicp now and do the ex2.23
i have wrirten the following code:
(define (for-each proc items)
(if (null? items)
#t
((proc (car items))
(for-each proc (cdr items)))))
but when running, cause error: procedure application: expected procedure, given: #; arguments were: ()
i think i know the reason: I call the for-each function recursively, every called for-each wanted to return value
but when i have modified the code:
(define (for-each proc items)
(cond ((null? items) #t)
(else (proc (car items)) (for-each proc (cdr items)))))
it runs well. I don't understand, why? in cond, does every called for-each no need to return value?
i used DrScheme, and choose language SICP
i'm not a native speaker of english, so if there is sth which isn't described clearly, pls tell me
but when running, cause error: procedure application: expected > procedure, given: #; arguments were: ()
i think i know the reason: I call the for-each function recursively, > every called for-each wanted to return value
No, it is because in the alternative clause of if you have the combination ((proc (car items)) (for-each proc (cdr items))). You intended to evaluate the two combinations (proc (car items)) and (for-each proc (cdr items)) sequentially, and to that end you thought putting them in another pair of parentheses would work. But in actuality, what you have specified is that the result of (proc (car items)) is a procedure to be applied to the argument which is the return value of (for-each proc (cdr items)). This is not the case, and you get an error. The key point being that parentheses in Lisp are not for grouping, but have a definite significance.
The problem is that if can only have a single combination in that position, whereas you want to have two in a row. On the other hand, cond does not suffer such a restriction; you can put as long a sequence of individual combinations in the consequent part of a cond clause as your heart desires. This state of affairs is simply how the language is defined to work.
You can just as well use cond in these situations, but if you still want to use if there are some options for stuffing multiple combinations into one. E. g. you can create a lambda procedure whose body is the two combinations and immediately fire it off:
(define (for-each proc items)
(if (null? items)
#t
((lambda ()
(proc (car items))
(for-each proc (cdr items)) )) ))
Or you can use begin which is actually meant to be used for such a purpose:
(define (for-each proc items)
(if (null? items)
#t
(begin
(proc (car items))
(for-each proc (cdr items)) ) ))

Resources