How do I append a list recursively in common lisp? - lisp

(defun foo (in i out)
(if (>= i 0)
(progn
(append (list (intern (string (elt in i)))) out)
(print output)
(foo in (- i 1) out )
)
(out)
)
)
(print (foo "abcd" (- (length "abcd") 1) (list)))
I am trying to return this string as (a b c d). But it does return nil as output. What do I do wrong here? Thanks

I don’t know what this has to do with appending. I think your desired output is also weird and you shouldn’t do what you’re doing. The right object for a character is a character not a symbol. Nevertheless, a good way to get the list (a b c d) is as follows:
CL-USER> '(a b c d)
Interning symbols at runtime is weird so maybe you would like this:
(defconstant +alphabet+ #(a b c d e f g h i j k l m n o p q r s t u v w x y z))
(defun foo (seq)
(map 'list
(lambda (char)
(let ((index (- (char-code char) (char-code #\a))))
(if (< -1 index (length +alphabet+))
(svref +alphabet+ index)
(error "not in alphabet: ~c" char))))
seq))

You have just some minor mistakes. First, we need to get rid of output and (output); these bear no relation to the code. It seems you were working with a variable called output and then renamed it to out without fixing all the code. Moreover, (output) is a function call; it expects a function called output to exist.
Secondly, the result of append must be captured somehow; in the progn you're just discarding it. Here is a working version:
(defun foo (in i out)
(if (>= i 0)
(foo in (1- i) (cons (intern (string (elt in i))) out))
out))
Note also that instead of your (append (list X) Y), I'm using the more efficient and idiomatic (cons X Y). The result of this cons operation has to be passed to foo. The out argument is our accumulator that is threaded through the tail recursion; it holds how much of the list we have so far.
I.e. we can't have (progn <make-new-list> (foo ... <old-list>)); that just creates the new list and throws it away, and then just passes the old list to the recursive call. Since the old list initially comes as nil, we just keep passing along this nil and when the index hits zero, that's what pops out. We need (foo .... <make-new-list>), which is what I've done.
Tests:
[1]> (foo "" -1 nil)
NIL
[2]> (foo "a" 0 nil)
(|a|)
[3]> (foo "ab" 1 nil)
(|a| |b|)
[4]> (foo "abcd" 3 nil)
(|a| |b| |c| |d|)
[5]> (foo "abcd" 3 '(x y z))
(|a| |b| |c| |d| X Y Z)
Lastly, if you want the (|a| |b| |c| |d|) symbols to appear as (a b c d), you have to fiddle withreadtable-case.
Of course:
[6]> (foo "ABCD" 3 nil)
(A B C D)

Related

A list with their position via for loop in racket

(define ( addposition x )
(cond
[(empty? x) "empty list"]
[#t (for/list ([i x])
(list i (add1 (index-of x i))))]
))
(addposition (list 'a 'b 'c ))
it returns me '((a 1) (b 2) (c 3)), but I need the list like '(a 1 b 2 c 3)
As a bare minimum to get what you want you can throw that nested list to a (flatten) call:
> (flatten '((a 1) (b 2) (c 3)))
'(a 1 b 2 c 3)
But overall the idea to build mini lists with index-of and then flattening it is not the most performant. Nor will it be correct if your list contains duplicate values.
If we keep our own record of the next index, and using recursion instead of the otherwise handy for/list structure, we can build our list this way:
(define (add-positions xs [ind 0])
(if (null? xs)
xs
(append (list (first xs) ind)
(add-positions (rest xs) (add1 ind))
)))
(add-positions '(a b c d))
;=> '(a 0 b 1 c 2 d 3)
This can be expressed pretty naturally using map and flatten:
;;; Using map and flatten:
(define (list-pos xs (start 0))
(flatten (map (lambda (x y) (list x y))
xs
(range start (+ start (length xs))))))
Here map creates a list of lists, each containing one value from the input list and one value from a range list starting from start, and flatten flattens the result.
This seems more natural to me than the equivalent using for/list, but tastes may differ:
;;; Using for/list:
(define (list-pos xs (start 0))
(flatten (for/list ((x xs)
(p (range start (+ start (length xs)))))
(list x p))))
There are a lot of ways that you could write this, but I would avoid using append in loops. This is an expensive function, and calling append repeatedly in a loop is just creating unnecessary overhead. You could do this:
;;; Using Racket default arguments and add1:
(define (list-pos xs (pos 0))
(if (null? xs)
xs
(cons (car xs)
(cons pos (list-pos (cdr xs) (add1 pos))))))
Here the first element of the list and a position counter are added onto the front of the result with every recursive call. This isn't tail recursive, so you might want to add an accumulator:
;;; Tail-recursive version using inner define:
(define (list-pos xs (start 0))
(define (loop xs pos acc)
(if (null? xs)
(reverse acc)
(loop (cdr xs)
(add1 pos)
(cons pos
(cons (car xs) acc)))))
(loop xs start '()))
Because the intermediate results are collected in an accumulator, reverse is needed to get the final result in the right order.
You could (and I would) replace the inner define with a named let. Named let should work in Racket or Scheme; here is a Scheme version. Note that Scheme does not have default arguments, so an optional argument is used for start:
;;; Tail-recursive Scheme version using named let:
(define (list-pos xs . start)
(let loop ((xs xs)
(pos (if (null? start) 0 (car start)))
(acc '()))
(if (null? xs)
(reverse acc)
(loop (cdr xs)
(add1 pos)
(cons pos
(cons (car xs) acc))))))
All of the above versions have the same behavior:
list-pos.rkt> (list-pos '(a b c))
'(a 0 b 1 c 2)
list-pos.rkt> (list-pos '(a b c) 1)
'(a 1 b 2 c 3)
Here is a simple solution using for/fold
(define (addposition l)
(for/fold ([accum empty]) ([elem l])
(append accum elem)))
I love the for loops in Racket 😌
Note: As pointed out by ad absurdum, append is expensive here. So we can simply reverse first and then use cons to accumulate
(define (addposition l)
(for/fold ([accum empty]) ([elem (reverse l)])
(cons (first elem) (cons (second elem) accum))))
As others have pointed out, you can start by making a list of lists. Let's use a list comprehension:
> (for/list ([x '(a b c)]
[pos (in-naturals 1)])
(list x pos))
'((a 1) (b 2) (c 3))
Here, we iterate in parallel over two sets of data:
The list '(a b c)
The stream (in-naturals 1), which produces 1, 2, 3, ....
We combine them into lists with list, giving this structure:
'((a 1) (b 2) (c 3))
This is called "zipping", and using list comprehensions is a convenient way to do it in Racket.
Next, we want to flatten our list, so it ends up looking like this:
'(a 1 b 2 c 3)
However, you shouldn't use flatten for this, as it flattens not just the outermost list, but any sub-lists as well. Imagine if we had data like this, with a nested list in the middle:
> (flatten
(for/list ([x '(a (b c d) e)]
[pos (in-naturals 1)])
(list x pos)))
'(a 1 b c d 2 e 3)
The nested list structure got clobbered! We don't want that. Unless we have a good reason, we should preserve the internal structure of each element in the list we're given. We'll do this by using append* instead, which flattens only the outermost list:
> (append*
(for/list ([x '(a (b c d) e)]
[pos (in-naturals 1)])
(list x pos)))
'(a 1 (b c d) 2 e 3)
Now that we've got it working, let's put it into a function:
> (define (addposition xs)
(append*
(for/list ([x xs]
[pos (in-naturals 1)])
(list x pos))))
> (addposition '(a b c))
'(a 1 b 2 c 3)
> (addposition '(a (b c d) e))
'(a 1 (b c d) 2 e 3)
Looks good!

Is it possible to have a 2 dimension array as a result type from a map in CLisp?

is it possible in C-Lisp to collect the results of a map into an array with 2 dimensions? how would I reference this array in the function?
I've tried things like,
(map 'Array'(3 3) #'somefunction sequence)
or
(map '(simple-array T (3 3)) #'somefunction sequence)
and was not successful.
Of course the sequence i'm starting from have the same number of total elements of the result array i wish to obtain
A good way to do this is to use displaced arrays and map-into. Here's an over-simple example:
(defun map-array (f a &rest make-array-kws &key &allow-other-keys)
;; Map F over A, which can be any array, returning a new array with
;; the same shape as A. Keyword arguments get passwd to MAKE-ARRAY
;; of the result array. This may not handle things like fill
;; pointers well or at all.
(let ((r (apply #'make-array (array-dimensions a)
make-array-kws)))
(map-into
(make-array (array-total-size r)
:element-type (array-element-type r)
:displaced-to r)
f
(make-array (array-total-size a)
:element-type (array-element-type a)
:displaced-to a))
r))
No. According to the hyperspec (http://www.lispworks.com/documentation/lw50/CLHS/Body/f_map.htm#map), the result type specifier has to be a sequence type. Multi-dimensional arrays are not sequence types. Of course, you could write a function to do what you want, but it cannot be directly accomplished with the map function.
Here's how you might make your own:
(defun map-to-array (fn sequence w h &optional (type t))
(assert (<= (length sequence) (* w h)) (w h) "Result array too small.")
(let ((result (make-array (list w h)
:element-type type))
(x -1)
(y 0))
(map nil
(lambda (e)
(incf x)
(when (= x w)
(setf x 0)
(incf y))
(setf (aref result x y)
(funcall fn e)))
sequence)
result))

Lisp - if statements various actions

This is my lisp code.
(DEFUN F (A B)
(SETF C (* 4 A))
(SETF D (* 2 (EXPT B 3)))
(SETF RES (+ C D))
(IF (AND (TYPEP A 'INTEGER) (TYPEP B 'INTEGER))
(list 'Final 'value '= res)
'(YOUR INPUTS ARE NOT NUMBERS)))
For example, (f 5 9) works well.
But (f 'w 'q) doesn't work with the following error message:
(ERROR TYPE-ERROR DATUM W EXPECTED-TYPE NUMBER FORMAT-CONTROL
~#<~s' is not of the expected type~s'~:#> FORMAT-ARGUMENTS
(W NUMBER))
Error: W' is not of the expected typeNUMBER'
I want to make if A,B is integer calculate 4A+2B^3.
Else if at least one is not an integer print error message.
I try to the code shown above.
But how can I make this error handling using if statements?
First, you should use LET or LET* to define local variables.
(defun f (a b)
(let* ((c (* 4 a)) ; You need LET* instead of LET because
(d (* 2 (expt b 3))) ; RES depends on the previous variables.
(res (+ c d)))
(if (and (typep a 'integer) (typep b 'integer))
(list 'final 'value '= res)
'(your inputs are not numbers))))
The actual problem is that you're doing the calculations before you check that the arguments are integers. You should move the calculation inside the IF.
(defun f (a b)
(if (and (integerp a) (integerp b))
(let* ((c (* 4 a))
(d (* 2 (expt b 3)))
(res (+ c d)))
(list 'final 'value '= res))
'(your inputs are not numbers)))
Returning lists like that is kind of strange. If you intend them as output for the user, you should instead print the messages and return the actual result.
(defun f (a b)
(if (and (integerp a) (integerp b))
(let ((result (+ (* 4 a)
(* 2 (expt b 3)))))
(format t "Final value = ~a~%" result)
result) ; Return RESULT or
(format t "Your inputs are not integers.~%"))) ; NIL from FORMAT.
In most cases you should signal an error if the arguments are not correct type. Printing output from a function that does the calculation is usually a bad idea.
(defun f (a b)
(check-type a integer "an integer")
(check-type b integer "an integer")
(+ (* 4 a)
(* 2 (expt b 3))))
(defun main (a b)
(handler-case
(format t "Final value = ~a~%" (f a b))
;; CHECK-TYPE signals a TYPE-ERROR if the type is not correct.
(type-error () (warn "Your inputs are not integers."))))
(main 12 1)
; Final value = 50
;=> NIL
(main 12 'x)
; WARNING: Your inputs are not integers.
;=> NIL
Common Lisp condition system also allows you to use restarts to fix errors. CHECK-TYPE establishes a restart named STORE-VALUE, which you can invoke to supply a correct value for the place. In this case it probably doesn't make sense, but you could do something like use 1 as a default.
(defun main (a b)
(handler-bind ((type-error (lambda (e)
(store-value 1 e))))
(format t "Final value = ~a~%" (f a b))))
(main 12 1)
; Final value = 50
;=> NIL
(main 12 'x)
; Final value = 50
;=> NIL
Notice that conditions/error handlers do add some overhead, so for performance critical functions you might not want to use them and instead check your arguments before calling the function.
(declaim (ftype (function (integer integer) integer) f))
(defun f (a b)
(declare (optimize (speed 3) (safety 0) (debug 0)))
(+ (* 4 a)
(* 2 (expt b 3))))
(defun main (a b)
(if (and (integerp a)
(integerp b))
(format t "Final value = ~a~%" (f a b))
(warn "Your inputs are not integers.")))

Difference between '(()) and (cons null null)

I am confused about the difference between '(()) and (cons null null) in scheme.
The code below show that b and c are completely the same thing.
(define (dup2 x)
(let ((d '(())))
(set-car! d (car x))
(set-cdr! d (cdr x))
d))
(define a '(1 2))
(define b (dup2 a))
(define c (dup2 a))
(set-car! b 2)
> c ;; --> (2 2)
However, when I used dup instead of dup2:
(define (dup x)
(let ((d (cons null null)))
(set-car! d (car x))
(set-cdr! d (cdr x))
d))
(define a '(1 2))
(define b (dup a))
(define c (dup a))
(set-car! b 2)
> c ;; --> (1 2)
Variable b and c are different. I have done some experiments, but I haven't understand yet.
The value of d in the first implementation is literal data, and is modified with undefined consequences. To highlight what's happening, consider the following code:
(define (incorrect-list-null-and-x x)
(let ((l '(()))) ; a list of the form (() . ())
(set-cdr! l (cons x (cdr l))) ; (cdr l) is (), so (cons x (cdr l)) should be (x . ()) == (x), right?
; and now l should be (() . (x . ())) == (() x), right?
l))
The expected result is that (incorrect-list-null-and-x n) should return a list of the form (() n), and it does the first time, but successive calls are still accessing the same data:
(incorrect-list-null-and-x 1) ;=> (() 1)
(incorrect-list-null-and-x 2) ;=> (() 2 1)
(incorrect-list-null-and-x 3) ;=> (() 3 2 1)
(incorrect-list-null-and-x 4) ;=> (() 4 3 2 1)
The same problem manifests itself a bit differently in your dup2. Every value returned from dup2 is actually the same pair:
(let* ((x (dup2 (cons 1 2)))
(y (dup2 (cons 3 4))))
(display x)
(display y))
outputs:
(3 . 4)(3 . 4)
because the call (dup2 (cons 3 4)) modifies the same structure that was previously returned by (dup2 (cons 1 2)).
Data literals, like '(()), are meant to be read-only, and modifying it using set-car! or set-cdr! has undefined behaviour. For predictable behaviour, use the (cons '() '()) version if you want to use set-car! or set-cdr! on it.
In particular, cons creates a new cons cell, whereas a data literal usually won't.
Still, for the purposes of implementing dup, why are you using set-car! and set-cdr! anyway? Just use cons directly:
(define (dup x)
(cons (car x) (cdr x)))
In your first code snippet you use (d '(())) which ends up binding a literal to d. You then modify the literal which is generally undefined. In your second code snippet you use (d (cons null null)) which binds d to a newly created 'cons cell' which you then modify. There is no problem modifying that.
Note: you've not defined null. Perhaps you meant '()?

Shouldn't this function return the list back with all elements in it?

(defun r (list)
(let ((o ()))
(dolist (x list o)
(cons o x))))
(r (list 1 2 3))
It does not. it returns nil
You need to change o somewhere. PUSH for example has the desired side-effect. CONS does not.
(defun r (list)
(let ((o ()))
(dolist (x list o)
(push x o))))
> (r (list 1 2 3))
(3 2 1)
Your dolist block returns the final value of variable o. Your variable o is assigned nil initially, and then doesn't ever change.
You might want to use push instead of cons inside the loop.
A list is nothing more than a linked list of cons cells, ending in a nil value.
For example (1 2 3) is equivalent to (cons 1 (cons 2 (cons 3 nil)))
Your code by design is wrong, because what you are trying to construct being with nil, the empty list, and then you're trying to cons to it other elements. A corrected version of what you are trying to do would be
(defun r (list)
(let ((o ()))
(dolist (el list o)
(setf o (cons el o))))
Are you trying to do something like this?
(defun r(list)
(let ((o ()))
(dolist (x list)
(setf o (cons o x)))
o))
(r (list 1 2 3))
(((NIL . 1) . 2) . 3)
If so, note the following:
dolist assigns x from list: (dolist (x list) ...
o must be set: (setf o (...
o has to be "returned"