Is it possible to do so? Let's say I want to get the last element of a list, I would create a variable i = 0, and increment it until it equals to length. Any idea? An example would be greatly appreciated.
Thanks,
There are several ways to declare a variable; the cleanest one is let:
(let ((x some-expr))
; code block that uses x
But you don't need this to get the last element of a list. Just use recursion:
(define (last xs)
(if (null? (cdr xs))
(car xs)
(last (cdr xs))))
Note: if you want, you can use a variable to cache cdr's result:
(define (last xs)
(let ((tail (cdr xs)))
(if (null? tail)
(car xs)
(last tail))))
Yes, it's possible to define local variables in scheme, either using let or define inside a function. Using set!, it's also possible to reassign a variable like you imagine.
That being said, you should probably not solve your problem this way. In Scheme it's generally good practice to avoid set! when you don't need to (and in this case you definitely don't need to). Further iterating over a list using indices is usually a bad idea as scheme's lists are linked lists and as such random access O(n) (making the last function as you want to implement it O(n^2)).
So a simple recursive implementation without indices would be more idiomatic and faster than what you're planning to do and as such preferable.
Related
In The Little Schemer (4th Ed.) it is claimed that a list for which null? is false contains at least one atom, or so I understand from my reading of the text.
This doesn't make sense to me, since (atom '()) is false, and we can stick those into a list to make it non-null:
> (null? '(()))
#f
So my question is, is this a mistake in my reading, or a matter of definitions? Since it's not in the errata I assume such a well-studied book wouldn't have a mistake like this.
If we considered (()) to be the same as (() . ()) or even (cons '() '()) and then considered cons an atom then I could see how you can get there, but I don't think that's what's going on.
(this was tested in Racket 7.0, with the definition of atom? given in the book, i.e.
(define atom?
(lambda (x)
(and (not (pair? x)) (not (null? x)))))
I know this doesn't cover funny Racket features, but should be sufficient here.)
lat is assumed to be a list of atoms at that point in the book.
If it's not empty, by definition it contains some atoms in it.
It's not about Lisp, it's about the book's presentation.
I think lat indicates list of atoms. Thus if lat is not null?, then it needs to contain at least one atom.
There is a procedure called lat? defined as such:
(define lat?
(lambda (l)
(cond
((null? l) #t)
((atom? (car l))
(lat? (cdr l)))
(else #f))))
(lat? '(()) ; ==> #f so by definition '(()) is not a lat and thus the statement does not apply to that list.
A list can contain any type of elements, including empty and other lists, both which are not atoms. lat is a restricted to a flat list with only atomic elements.
As a concept an “atom” is something that can not be broken into smaller parts. A number 42 is an atom, a list (42 43) is not an atom since it contains two smaller parts (namely the numbers 42 and 43). Since an empty list does not contain any smaller parts, it is by this logic an atom.
Now let’s attempt to implement an atom? predicate, that determines whether it’s input is an atom.
(define (atom? x)
(cond
[(number? x) #t]
[(symbol? x) #t]
[(char? x) #t]
...
[else #f]))
Here the ... needs to be replaced with a test for every atomic data type supported by the implementation. This can potentially be a long list. In order to avoid this, we can try to be clever:
(define (atom? x)
(not (list? x)))
This will correctly return false for non-empty lists, and true for numbers, characters etc. However it will return false for the empty list.
Since it is up to the authors of the book to define the term “atom” (the word does not appear in the language standard) they might have opted for the above simple definition.
Note that the definition as non-list is misleading when the language contains other compound data structures such as vectors and structures. If I recall correctly the only compound data structure discussed in the book is lists.
I need to write a basic scheme procedure that can find the median of a list and another for the mean.
This is what I've come up with so far:
Mean:
(define (mean lst)
(if (null? lst) ()
(+ 1 (car lst) (mean (cdr lst))))
I know I need to divide my the length somewhere but not sure how to do so. My thought process for this is to add each element to the stack of the list and then divide my the length of the list?
Median:
I'm not sure where to start for median.I know I need to determine if the list has an odd number of elements or even, so to do that I've come up with
(define (median lst)
(if (integer? (/ (length lst) 2) ;which is the one for even
I don't know if I need another procedure to get me to the middle of the list?
The median procedure was already discussed here.
Calculating the mean is simple, just add all the elements and divide by the length of the list, the only special case to take care of is when the list is empty (because that will lead to a division by zero: the length is zero!), return an appropriate value indicating this.
By now you should definitely know how to add all the elements in a list, check with your instructor in case of doubts, but it's a basic operation, it shouldn't be a problem.
I am having trouble writing a function that will move the first element to the end of the list every time it is called. I have tried using a combination of reverse and cdr to cut off the elements at either end, but cannot figure out how to add the elements to the correct end. Any help would be appreciated. Thanks!
Correct outcomes:
(first_to_last '(1 2 3))
(2 3 1)
(first-to-last (first-to-last '(1 2 3)))
(3 1 2)
I think you're over-doing the reversing, personally.
What we want is a list consisting of cdr x with car x appended to the end. The one trick here is that car x isn't a list, so we want to convert it to a list before appending it:
(define (first-to-last x) (append (cdr x) (list (car x))))
If you wanted to stick to the fundamentals, cons is the really fundamental way to put things together into lists, but it would be a bit more work. You'd basically end up defining something essentially identical to append in terms of cons. That's pretty easy but kind of pointless, given that append already exists.
Edit: I guess if you want to use reverse for some reason or other, you could do something like this:
(define (first-to-last x) (reverse (cons (car x) (reverse (cdr x)))))
It's a bit longer and strikes me as kind of clumsy, but it ought to work anyway.
I'm working on an assignment involving Racket and I was hoping somebody could lead me into the right direction.
I must calculate the norm of a list without recursion or using a loop and without defining any helper functions.
Is this possible? The only thing that comes to mind is to somehow use the built-in map functions
(define (norm lst)
(apply + (map square lst)))
In Scheme, the function (map fn list0 [list1 .. listN]) comes with the restriction that the lists must have the same number of elements. Coming from Python, I'm missing the freedom of Python list comprehensions, which look a lot like map above, but without this restriction.
I'm tempted to implement an alternative "my-map", which allows for lists of differing size, iterating through the first N elements of all lists, where N is the length of the shortest list.
For example, let num be 10 and lst be (1 2 3). With my-map, I hope to write expressions like:
(my-map + (circular-list num) lst)))
And get:
(11 12 13)
I have an easier time reading this than the more conventional
(map + (lambda (arg) (+ num arg)) lst)
or
(map + (make-list (length lst) num) lst)
Two questions:
As a Scheme newbie, am I overlooked important reasons for the restriction on `map`?
Does something like `my-map` already exist in Scheme or in the SRFIs? I did take a look at srfi-42, but either it's not what I'm looking for, or it was, and it wasn't obvious.
First, note that map does allow empty lists, but of course if there's one empty list then all of them should be empty.
Second, have a look at the srfi-1 version of map -- it is specifically different from the R5RS version as follows:
This procedure is extended from its R5RS specification to allow the arguments to be of unequal length; it terminates when the shortest list runs out.
Third, most Scheme programmers would very much prefer
(map (lambda (arg) (+ num arg)) lst)
My guess is that Scheme is different from Python in a way that makes lambda expressions become more and more readable as you get used to the language.
And finally, there are some implementations that come with some form of a list comprehension. For example, in Racket you can write:
(for/list ([arg lst]) (+ num arg))