Scheme function to remove first element
write a scheme function that remo开发者_运维知识库ve the first top level occurrence of a given item from a list of items. eg given list (a b c) item b, result list (a c)
plz help me
Think what are you trying to accomplish.
You have a list of stuff and you are trying to remove a certain element.
example: trying to remove b
(a a a a b a a b a ...)
anything before first b should be kept and anything after it also..
so we have to spit out from our function:
a a a a + a a b a ...
if we were to reduce this to operating with recursion:
at any point looking through the list you can:
1. inspect element at front of the list and give it out to the result
and recursively inspect the rest of the list
2. stop if you found your element and
give out the rest of the list as you've accomplished your task
Not sure what you want, but first start it simply with an index, this is pretty much how you have to 'think' with Scheme, first start with 'What if it were the first element?', the answer then is of course that it should be the rest of the list. And then 'Well, what if it's not the first', then the answer is 'It should cons the first up to the result of the same procedure applied to the rest.', that's all the info Scheme needs in this, and many cases really.
(define (slice-out lst k)
(if (<= k 0) (cdr lst) ; if we want to remove the first (0) element, surely the result is simply the tail of the list?
(cons (car lst) ; if it's higher than 0, we just cons the first element...
(slice-out (cdr lst) (- k 1))))) ; to the result of the same method applied to the tail but with one lower k.
> (slice-out '(a b c d e) 2)
===>(a b d e)
This function returns an error if the list is too short for the index.
However, if you want to slice out by some equality to another object, this example suffices, we now no longer slice it out of we reach 0, but if it's identical to a search example:
(define (slice-out-by-equality lst search)
(if (equal? (car lst) search) (cdr lst)
(cons (car lst)
(slice-out-by-equality (cdr lst) search))))
> (slice-out-by-equality '(a b c d e) 'c)
===> (a b d e)
Using the very same principles, This one however returns an error if the item isn't found.
Point is that scheme has many flavours of equality comparisons, so, what we actually want is this:
(define (make-slice-out comparison)
(lambda (lst search)
(let loop ((lst lst))
(cond
((null? lst) '())
((comparison (car lst) search) (cdr lst))
(else (cons (car lst) (loop (cdr lst))))))))
This example shows what Scheme is all about, not sure if you're known with it, but we've used a closure here, this function actually takes as argument any binary comparison function and then evaluate to the function you want, it's also sanitized, it doesn't make an error any more if it's not found, it returns it simply returns the old list because if it reaches the end of the list, with nothing removed yet, it just conses it up to () again.
> ((make-slice-out =) '(1 2 3 6 3) 6)
===> (1 2 3 3); we just made an anonymous function here.
But remembering our original function, we can now define it simply like this, when supplying the predicate 'equal?' our new function actually evaluates to our old function (with the important asset that it's now sanitized):
(define slice-out-by-equality (make-slice-out equal?))
And, there's more binary comparison, how about this more exotic example:
(define slice-out-less-than (make-slice-out <))
We made a function this way that slices out the first element that is strictly less than our search term, thus this works:
> (slice-out-less-than '(573 284 238 174 92 47) 100)
====> (573 284 238 174 47)
Even though 47 is also less than 100, 92 is the first of those that is.
There are those function car and cdr that allow You to take parts of the list. Function append allows You to joint two lists into one. I think they might come handy. Also check out the cons function and make sure You understand what a list actually is and what does it have to do with pairs.
You can proceed as follows for example. Take Your list, cut the first element out and check what it is. If it's the one to be removed discard it. If it's not the element to be removed, process the rest of the list and then append that element back at the beginning.
Something like this (if it is a homework):
(define (remove-first-occurence some-list find-symbol accum)
(cond
[(empty? some-list) accum]
[else (cond
[(= (first some-list) find-symbol) (cons accum (rest some-list))]
[else (remove-first-occurence (rest some-list) find-symbol (cons (first some-list) accum))]
)]))
(remove-first-occurence '(1 2 3 4 3) 3 empty)
(define (remove-first-occurence list element accum)
(cond
((null? list) accum)
(else
(cond((= (car list) element) (cons accum (cdr list)))
(else(remove-first-occurence (cdr list) element(cons (car list) accum)))
)
)
)
)
(remove-first-occurence '(1 2 3) 2 '())
perl2scheme -s \ 'use strict; sub remove_first { \ grep { $_ ne $_[0] || $first++ } @{ $_[1] }; } \ print join(",",remove_first("b", ("a","b","c"));'
The trivial remaining task of implementing perl2scheme is left as an excercize for the reader.
精彩评论