Removing last two elements from a list in Lisp - common-lisp

I need to remove the last two elements from a list in common list, but I can remove only one. What's the way?
(defun my-butlast (list)
(loop for l on list
while (rest l)
collect (first l)))

Simple: reverse, pop, pop, reverse ;-) 1
More efficiently, the following works too:
(let ((list '(a b c d)))
(loop
for x in list
for y in (cddr list)
collect x))
This can also be written, for some arbitrary L and N:
(mapcar #'values L (nthcdr N L))
It works because iteration over multiple lists is bounded by the shortest one. What matters here is the length of the second list (we don't care about its values), which is the length of the original list minus N, which must be a non-negative integer. Notice that NTHCDR conveniently works with sizes greater than the length of the list given in argument.
With the second example, I use the VALUES function as a generalized identity function; MAPCAR only uses the primary value of the computed values, so this works as desired.
The behavior is consistent with the actual BUTLAST2 function, which returns nil for N larger than the number of elements in the list. The actual BUTLAST function can also deal with improper (dotted) lists, but the above version cannot.
1. (alexandria:compose #'nreverse #'cddr #'reverse)
2. BUTLAST is specified as being equivalent to (ldiff list (last list n)). I completely forgot about the existence of LDIFF !

There's a function in the standard for this: butlast, or if you're willing to modify the input list, nbutlast.
butlast returns a copy of list from which the last n conses have been omitted. If n is not supplied, its value is 1. If there are fewer than n conses in list, nil is returned and, in the case of nbutlast, list is not modified.
nbutlast is like butlast, but nbutlast may modify list. It changes the cdr of the cons n+1 from the end of the list to nil.
Examples:
CL-USER> (butlast '(1 2 3 4 5) 2)
(1 2 3)
CL-USER> (nbutlast (list 6 7 8 9 10) 2)
(6 7 8)
The fact that you called your function my-butlast suggests that you might know about this function, but you didn't mention wanting to not use this function, so I assume it's still fair game. Wrapping it up is easy:
CL-USER> (defun my-butlast (list)
(butlast list 2))
MY-BUTLAST
CL-USER> (my-butlast (list 1 2 3 4))
(1 2)

Related

Inverting order of multiple values in Common Lisp

I've been thinking about the following problem. Suppose I'm dealing with a function returning multiple values, such as truncate. Is there a clever way to reverse the order of values that get returned? I'm talking about something more clever than e.g.
(multiple-value-bind (div rem) (truncate x y)
(values rem div))
I don't know how clever this is, but here's what you want:
(reverse (multiple-value-list (the-function-that-returns-multiple-values)))
multiple-value-list being the key, here.
To return these again as separate values, use values-list:
(values-list (reverse (multiple-value-list (the-function-that-returns-multiple-values))))
This whole page may be enlightening.
This problem can be solved more cleverly by writing a higher order function whose input is a function that returns some (values a b), and which returns a function which calls that function, but returns (values b a). In other words a value reversing combinator:
(defun val-rev (function)
(lambda (&rest args)
(multiple-value-bind (a b) (apply function args)
(values b a))))
Though inside the definition of this function we are doing the cumbersome thing you don't want (capturing the values with m-v-bind and reversing with values) this is encapsulated in the combinator and just an implementation detail. It's probably more efficient than consing up a value list and reversing it. Also, it specifically targets the first two values. If a function returns four values, A B C D, then reversing the multiple-value-list means that the first two return values will be C D. However, if we just bind the first two and reverse them, then we bet B A. Reversing the first two (or only two) values is clearly not the same as reversing all values.
Demo:
[1]> (truncate 17 3)
5 ;
2
[2]> (funcall (val-rev #'truncate) 17 3)
2 ;
5
Note that in a Lisp-1 dialect, the invocation loses the added noise of #' and funcall, reducing simply to: ((val-rev truncate) 17 3).
val-rev is kind of a dual of the flip higher order function which you see in some functional languages, which takes a binary function and returns a binary function which is that function, but with the arguments reversed.
To have it as clean/consistent as multiple-value-bind, you could define a macro such as this:
(defmacro reverse-multiple-value-bind (args f &rest body)
`(multiple-value-bind ,(reverse args)
,f
,#body))
Then you have
>> (multiple-value-bind (x y) (floor 3.7) (print x) (print y))
3
0.70000005
and
> (reverse-multiple-value-bind (x y) (floor 3.7) (print x) (print y))
0.70000005
3

How to create a multi-dimensional array in Common Lisp?

Is it possible to call make-array function with a list as parameter? For example:
(make-array '((length '("a" "b")) (length '("r" "8" "5"))))
return:
#<TYPE-ERROR expected-type: NUMBER datum: (LENGTH '(...
Even if I try to cast the result of length with the following command:
(coerce (length '(1)) 'number)
it works for one dimension array but not for two dimensions.
Is it possible to call make-array function with a list as parameter?
Yes, in fact you always have to pass it a list designator, but it has to be a list (or list designator) of integers. The list '((length '("a" "b")) (length '("r" "8" "5")))) has two lists as its elements, not integers. E.g., if you do (first '((length '("a" "b")) (length '("r" "8" "5"))))), you get (length '("a" "b")), not 2. You'd need to do (make-array (list (length …) (length …)) …) instead.
It's described pretty clearly in the documentation for make-array in the HyperSpec:
Function MAKE-ARRAY
Syntax:
make-array dimensions &key element-type initial-element initial-contents adjustable fill-pointer displaced-to
displaced-index-offset
=> new-array
Arguments and Values:
dimensions—a designator for a list of valid array dimensions.
E.g., (make-array '(2 2)) returns a 2 × 2 array. Or, if you need to dynamically compute the dimensions, just list them together. E.g., (make-array (list (length '(a b c)) (length '(d e)))) returns a 3 × 2 array.
Note that the argument is designator for a list. The glossary entry says:
list designator n. a designator for a list of objects; that is, an
object that denotes a list and that is one of: a non-nil atom
(denoting a singleton list whose element is that non-nil atom) or a
proper list (denoting itself).
That means that when you do (make-array 5), the 5 is actually acting as a designator for the list (5). You can really think of make-array always accepting a list as the first argument, but that in the case of a one-element list, you can just pass the single element instead, since it's unambiguous what you'd want.
Related
These are related, but not quite duplicates, since they are about how to create a list to pass to make-array, whereas this question is about whether a list can be passed to make-array.
How to make an array with size received as arguments in a function in LISP?
How to modify this "make-matrix" function?
Simple rule 1: if you quote it, it does not get evaluated.
This is data, not code: '((length '("a" "b")) (length '("r" "8" "5"))).
Why? Because it is quoted.
Simple rule 2: if you want to compute something, then write Lisp code, not literal data.
(list 1 2) -> (1 2)
(list (length '(a b c)) (length '(1 2 3 4))) -> (3 4)
Addressing an unanswered aspect of the subject of the question: much like Common Lisp lists, multidimensional arrays also have a literal representation, which can be convenient in some situations.
Lists
(list 'a 'b 'c)
;; is equivalent to
'(a b c)
A vector (single dimensional array) is represented as #[n](foo*) -- n,optional, being the number of elements and foo being the items in the vector, e.g.
(vector 1 2 3 4)
;; is equivalent to
#4(1 2 3 4)
;; or
#(1 2 3 4)
A 'proper' multidimensional array, i.e. an array larger than one dimension, is represented as: #nA<sequence> where n is the number of dimensions and <sequence> has a structure similar to a nested list, e.g.
(make-array '(2 3) :initial-contents '((a b c) (d e f)))
;; is equivalent to the following. Note, the 'inner most' array arrays must have the same number of objects, i.e. lisp won't auto-fill them with nil or anything else.
#2A((A B C) (D E F))
But you don't need to memorize that. Like many other forms, the Lisp reader accepts as input whatever it printed as output of make-array. (Given some caveats that I won't go into, or rather will leave as an exercise for the reader!)

Count amount of odd numbers in a sentence

I am fairly new to lisp and this is one of the practice problems.
First of all, this problem is from simply scheme. I am not sure how to answer this.
The purpose of this question is to write the function, count-odd that takes a sentence as its input and count how many odd digits are contained in it as shown below:
(count-odd'(234 556 4 10 97))
6
or
(count-odd '(24680 42 88))
0
If possible, how would you be able to do it, using higher order functions, or recursion or both - whatever gets the job done.
I'll give you a few pointers, not a full solution:
First of all, I see 2 distinct ways of doing this, recursion or higher order functions + recursion. For this case, I think straight recursion is easier to grok.
So we'll want a function which takes in a list and does stuff, so
(define count-odd
(lambda (ls) SOMETHING))
So this is recursive, so we'd want to split the list
(define count-odd
(lambda (ls)
(let ((head (car ls)) (rest (cdr ls)))
SOMETHING)))
Now this has a problem, it's an error for an empty list (eg (count-odd '())), but I'll let you figure out how to fix that. Hint, check out scheme's case expression, it makes it easy to check and deal with an empty list
Now something is our recursion so for something something like:
(+ (if (is-odd head) 1 0) (Figure out how many odds are in rest))
That should give you something to start on. If you have any specific questions later, feel free to post more questions.
Please take first into consideration the other answer guide so that you try to do it by yourself. The following is a different way of solving it. Here is a tested full solution:
(define (count-odd num_list)
(if (null? num_list)
0
(+ (num_odds (car num_list)) (count-odd (cdr num_list)))))
(define (num_odds number)
(if (zero? number)
0
(+ (if (odd? number) 1 0) (num_odds (quotient number 10)))))
Both procedures are recursive.
count-odd keeps getting the first element of a list and passing it to num_odds until there is no element left in the list (that is the base case, a null list).
num_odds gets the amount of odd digits of a number. To do so, always asks if the number is odd in which case it will add 1, otherwise 0. Then the number is divided by 10 to remove the least significant digit (which determines if the number is odd or even) and is passed as argument to a new call. The process repeats until the number is zero (base case).
Try to solve the problem by hand using only recursion before jumping to a higher-order solution; for that, I'd suggest to take a look at the other answers. After you have done that, aim for a practical solution using the tools at your disposal - I would divide the problem in two parts.
First, how to split a positive integer in a list of its digits; this is a recursive procedure over the input number. There are several ways to do this - by first converting the number to a string, or by using arithmetic operations to extract the digits, to name a few. I'll use the later, with a tail-recursive implementation:
(define (split-digits n)
(let loop ((n n)
(acc '()))
(if (< n 10)
(cons n acc)
(loop (quotient n 10)
(cons (remainder n 10) acc)))))
With this, we can solve the problem in terms of higher-order functions, the structure of the solution mirrors the mental process used to solve the problem by hand:
First, we iterate over all the numbers in the input list (using map)
Split each number in the digits that compose it (using split-digits)
Count how many of those digits are odd, this gives a partial solution for just one number (using count)
Add all the partial solutions in the list returned by map (using apply)
This is how it looks:
(define (count-odd lst)
(apply +
(map (lambda (x)
(count odd? (split-digits x)))
lst)))
Don't be confused if some of the other solutions look strange. Simply Scheme uses non-standard definitions for first and butfirst. Here is a solution, that I hope follows Simply Scheme friendly.
Here is one strategy to solve the problem:
turn the number into a list of digits
transform into a list of zero and ones (zero=even, one=odd)
add the numbers in the list
Example: 123 -> '(1 2 3) -> '(1 0 1) -> 2
(define (digit? x)
(<= 0 x 9))
(define (number->digits x)
(if (digit? x)
(list x)
(cons (remainder x 10)
(number->digits (quotient x 10)))))
(define (digit->zero/one d)
(if (even? d) 0 1))
(define (digits->zero/ones ds)
(map digit->zero/one ds))
(define (add-numbers xs)
(if (null? xs)
0
(+ (first xs)
(add-numbers (butfirst xs)))))
(define (count-odds x)
(add-numbers
(digits->zero/ones
(number->digits x))))
The above is untested, so you might need to fix a few typos.
I think this is a good way, too.
(define (count-odd sequence)
(length (filter odd? sequence)))
(define (odd? num)
(= (remainder num 2) 1))
(count-odd '(234 556 4 10 97))
Hope this will help~
The (length sequence) will return the sequence's length,
(filter proc sequence) will return a sequence that contains all the elements satisfy the proc.
And you can define a function called (odd? num)

Beginner Scheme: Procedures that return themselves

This is an example from the book I am reading:
1 (define (length items)
2 (define (length-iter a count)
3 (if (null? a)
4 count
5 (length-iter (cdr a)(+ 1 count))))
6 (length-iter items 0))
What I am not understanding is how can length-iter know about count? The first time this
procedure is called with a list, it will in turn define another procedure with two argumenets, I get that much. But how does it know that a is the list items? It hasnt reached line 6 yet, where items is passed to length-iter as the argument a. Somehow though it already knows this and is able to make the computation. Any help in clarifying this a bit is appreciated!
There are two parts in the length function:
Definition of the inner function length-iter;
Invocation of the inner function length-iter.
In the invocation, i.e., line 6, you pass the original items list to the inner function as an argument. This is where the inner function gets called. Previously, you are just defining the function, not calling it:
(length-iter items 0)
Thus, items will be bound to a, and 0 to count. You can think of the inner function as a separate function:
(define (length-iter a count)
(if (null? a)
count
(length-iter (cdr a)(+ 1 count))))
And then, think of your length function as if it just delegated all the work to the length-iter function:
(define (length items)
(length-iter items 0))
That's what's being done in your function. The difference, is that the length-iter function is only known to length.

What determines when a collection is created?

If I understand correctly Clojure can return lists (as in other Lisps) but also vectors and sets.
What I don't really get is why there's not always a collection that is returned.
For example if I take the following code:
(loop [x 128]
(when (> x 1)
(println x)
(recur (/ x 2))))
It does print 128 64 32 16 8 4 2. But that's only because println is called and println has the side-effect (?) of printing something.
So I tried replacing it with this (removing the println):
(loop [x 128]
(when (> x 1)
x
(recur (/ x 2))))
And I was expecting to get some collecting (supposedly a list), like this:
(128 64 32 16 8 4 2)
but instead I'm getting nil.
I don't understand which determines what creates a collection and what doesn't and how you switch from one to the other. Also, seen that Clojure somehow encourages a "functional" way of programming, aren't you supposed to nearly always return collections?
Why are so many functions that apparently do not return any collection? And what would be an idiomatic way to make these return collections?
For example, how would I solve the above problem by first constructing a collection and then iterating (?) in an idiomatic way other the resulting list/vector?
First I don't know how to transform the loop so that it produces something else than nil and then I tried the following:
(reduce println '(1 2 3))
But it prints "1 2nil 3nil" instead of the "1 2 3nil" I was expecting.
I realize this is basic stuff but I'm just starting and I'm obviously missing basic stuff here.
(P.S.: retag appropriately, I don't know which terms I should use here)
A few other comments have pointed out that when doesn't really work like if - but I don't think that's really your question.
The loop and recur forms create an iteration - like a for loop in other languages. In this case, when you are printing, it is indeed just for the side effects. If you want to return a sequence, then you'll need to build one:
(loop [x 128
acc []]
(if (< x 1)
acc
(recur (/ x 2)
(cons x acc))))
=> (1 2 4 8 16 32 64 128)
In this case, I replaced the spot where you were calling printf with a recur and a form that adds x to the front of that accumulator. In the case that x is less than 1, the code returns the accumulator - and thus a sequence. If you want to add to the end of the vector instead of the front, change it to conj:
(loop [x 128
acc []]
(if (< x 1)
acc
(recur (/ x 2)
(conj acc x))))
=> [128 64 32 16 8 4 2 1]
You were getting nil because that was the result of your expression -- what the final println returned.
Does all this make sense?
reduce is not quite the same thing -- it is used to reduce a list by repeatedly applying a binary function (a function that takes 2 arguments) to either an initial value and the first element of a sequence, or the first two elements of the sequence for the first iteration, then subsequent iterations are passed the result of the previous iteration and the next value from the sequence. Some examples may help:
(reduce + [1 2 3 4])
10
This executes the following:
(+ 1 2) => 3
(+ 3 3) => 6
(+ 6 4) => 10
Reduce will result in whatever the final result is from the binary function being executed -- in this case we're reducing the numbers in the sequence into the sum of all the elements.
You can also supply an initial value:
(reduce + 5 [1 2 3 4])
15
Which executes the following:
(+ 5 1) => 6
(+ 6 2) => 8
(+ 8 3) => 11
(+ 11 4) => 15
HTH,
Kyle
The generalized abstraction over collection is called a sequence in Clojure and many data structure implement this abstraction so that you can use all sequence related operations on those data structure without thinking about which data structure is being passed to your function(s).
As far as the sample code is concerned - the loop, recur is for recursion - so basically any problem that you want to solve using recursion can be solved using it, classic example being factorial. Although you can create a vector/list using loop - by using the accumulator as a vector and keep appending items to it and in the exist condition of recursion returning the accumulated vector - but you can use reductions and take-while functions to do so as shown below. This will return a lazy sequence.
Ex:
(take-while #(> % 1) (reductions (fn [s _] (/ s 2)) 128 (range)))

Resources