I want to create following list in Lisp.
((lambda(x) (cons x x)) (cons'A 'B))
creates this list, but
((lambda(x y) (cons x y)) (cons'A 'B) (cons 'A 'B))
and
(cons (cons 'A 'B) (cons 'A 'B))
do not create the list.
My challenge is why!? How does the first command create this list and the others do not? Any detail?
Every time (cons 'A 'B) is called, a fresh cons cell is created, so your second two expressions create two "similar" (equal but not eql) objects (A . B),
You want to create a cons of A and B:
(cons 'A 'B)
Then you want to refer to it twice from another cons. So if x is a reference to this existing cons, you want
(cons x x)
Wrapping up, we get
(let ((x (cons 'A 'B)) (cons x x))
or equivalently
((lambda (x) (cons x x)) (cons 'A 'B))
If you do (cons 'A 'B) twice you create two cells:
AB
AB
and the cons of those will contain one link to the first, and another to the second.
(Using a lambda to refer to them is a pointless obfuscation; the point of the example with the lambda form is that you use x twice. The form
((lambda (x y) (cons x y)) (cons 'A 'B) (cons 'A 'B))
is just a very tedious way to write
(cons (cons 'A 'B) (cons 'A 'B))
whereas in the original example there is -- pointedly -- only one instance of (cons 'A 'B) which you want to be able to refer to twice.)
The purpose of this exercise is to illustrate the difference between "surface" equivalence and identity. Two lists which contain the same values are still two different lists, whereas two references to the same list are identical. As #sde hints, this makes a difference for understanding comparisons; the prototypical example is that equal is true for distinct lists containing the same values (as well as identical lists, of course), whereas eql is only true if its arguments are in fact identical (i.e. they refer to the same object).
Related
Tasked with adding a to end of (b c) to make (b c a)
So far when I try
(print (cons 'a '(b c)))
I get (a b c)
but when I do
(print (cons '(b c) 'a))
I get ((b c) . a)
All the other similar questions on Stack seem to be more complicated than this problem so I was wondering if there was an easy fix.
A list is a chain of pairs. The elements are the cars of each pair, the cdr is a reference to the next pair in the chain, or an empty list for the last pair in the chain.
When you use (cons 'a '(b c)) you create a new pair in front of the existing list (b c), so the result is still a list.
But when you use (cons '(b c) 'a), you're creating a pair whose cdr is the symbol a, not a list. And the last pair in the list (b c) still has its cdr pointing to the empty list.
You need to copy the first list, and when you get to the end, you have to make the cdr point to a list containing a. You can do this with a recursive procedure.
(define (list-append old-list new-el)
(if (null? old-list)
(list new-el)
(cons (car old-list)
(list-append (cdr old-list) new-el))))
(list-append '(b c) 'a)
The logic is:
If we try to append to an empty list, just return a list containing the new element
Otherwise, append the new element to the tail of the original list with the recursive call, and then put the first element in front of that (using the (cons new-element old-list) method that you showed in your first example).
I am trying to make the function remove-member, where I have a list of strings and I give one of the members of the string (i.e. "A") to the function, and it removes that member and returns the rest of the list without that member. At the moment I have created tests and started my function, but I am lost beyond that. I know recursion functions include the first member of the list and the rest of it, but how would I remove the first member of a string?
(define str (list->string (list 'A 'B 'C)))
(check-expect (remove-occurrences "A") (list 'B 'C))
(check-expect (remvove-occurrences '()) (list 'A 'B 'C))
(define (remove-occurrences r)
(cond
[(empty? r) str]
[(??? r)]))
To remove a single element from a list:
Is the list empty? If it is, we're done and the result is the empty list.
OK, it's not empty. Is the first element of the list the same as the element you want to remove? If it is then the result is the rest of the list.
OK, it's not empty, and the first element didn't match. So the answer is a list consisting of a cons of the first element and the result of removing the element from the rest of the list. Which you now know how to do.
Alternatively, to remove all occurrences of an element from a list:
Is the list empty? If it is, we're done and the result is the empty list.
OK, it's not empty. Is the first element of the list the same as the element you want to remove? If it is then the result is the the result of removing all occurrences of the element from rest of the list, which you know how do to now.
OK, it's not empty, and the first element didn't match. So the answer is a list consisting of a cons of the first element and the result of removing the element from the rest of the list. Which you now know how to do.
How these functions differ:
> (remove-one '(a b b c) 'b)
'(a b c)
> (remove-all '(a b b c) 'b)
'(a c)
Let's follow the data type.
This way we get the mundane tasks taken care of automatically for us, and get to focus our creative mental abilities on more interesting, less common aspects of our problem:
(define (list-p ad)
(cond
((null? ad) ; follow
#t)
((pair? ad)
(let ((a (car ad)) ; the
(d (cdr ad))) ; type!
(list-p d)))
(else #f)))
We can see this predicate as a constructor of Boolean values. Creating a list following the same example aka skeleton code is also easy:
(define (list-l ad)
(cond
((null? ad) ; return proper
(list)) ; type here, and
((pair? ad)
(let ((a (car ad))
(d (cdr ad)))
(list-l d))) ; here
(else #f)))
We've just followed the type's skeleton code, mended it in the few appropriate places, and got ourselves a working code which creates values of the proper type, all by itself!
But does it create any interesting value, fully using the supplied argument? Evidently, not. For that we must mend the recursive call:
(define (list-copy ad)
(cond
((null? ad)
(list))
((pair? ad)
(let ((a (car ad))
(d (cdr ad)))
(cons ... ; here
(list-copy d))
))
(else #f)))
Now you get to tweak this further, consing the first element of a pair conditionally, as required by your problem.
(note: null? could be called empty? in your dialect).
I mean what advantages does list has on other data structures which make it almost inevitable in functional languages?
"There is no spoon."
What if I told you there is no such thing as strings? There exists only lists of single characters.
Then what if I told you there is no such thing as a list? There exists only pairs.
; construct a pair of a and b
(cons 'a 'b) ; => ('a 'b)
; get the first element of the pair
(first (cons 'a 'b)) ; => 'a
; get the second element of the pair
(second (cons 'a 'b)) ; => 'b
; create a "list"
(define x (cons 'a (cons 'b (cons 'c (cons 'd (cons 'e null))))))
; => ('a ('b ('c ('d ('e ())))))
; get the third element in the "list", x
(first (second (second x)))
; => 'c
Now what if I told you there is no such thing as pairs? There exists only lambdas.
(define (cons x y)
(λ (f) (f x y)))
(define (first p)
(p (λ (x y) x)))
(define (second p)
(p (λ (x y) y)))
Of course this is just one possible implementation. But it's important to realize that it's all just an illusion.
Data abstraction is truly magical. Good languages allow you to invent any structure you wish to work with and define any constructors/selectors that make it useful to work with your structure. Some languages just offer more syntactic sugar than others.
Lists are common because, as programmers, we often deal with ordered collections of things. Other common types are Sets and Maps. Just don't fool yourself into thinking it's anything super special ^,^
Functional languages prefer immutability so, when it comes to data structures, functional languages prefer persistent data structures. In brief, persistent data structures are data structures where we can continue to access any previous version of the structure as well as the current version. We do not mutate the existing data structure, we simply use the existing data structure as a basis to create a new one.
This can be done for any data structure simply by copying. For instance, consider some pseudo-F#:
let array1 = [| 1, 2, 3, 4, 5 |]
let array2 = append 6 array1 // [| 1, 2, 3, 4, 5, 6 |]
To implement the append function, we'd have to create a new array of n+1 size and populate it with a copy of array1 and the element to be appended.
Note how this isn't very efficient, every append requires both n copies and allocating memory for the entire structure.
Consider instead we define some type:
type List<'a> =
|Empty
|Cons of 'a * List<'a>
Using the Cons case, we can construct new lists from an old list and a single element.
Consider we now have a list of 1 million elements:
let list1 = [1..1000000]
let list2 = Cons (0, list1) // [0..1000000]
In this case, list2 simply refers to list1, no copying is required. Hence, prepending to the start of the list is an O(1) operation and the memory footprint only grows linearly with each element despite the data persistence.
There are many other persistent data structures, Binary Trees are often used to make immutable Sets and Dictionaries. Finger Trees can be the basis of structures like Deques and Priority queues.
So, in short, lists are widely used in functional languages because they are a simple, efficient, persistent data structure.
This is #7 of of 99 Lisp problems: transform a list, possibly holding lists as elements into a `flat' list by replacing each list with its elements (recursively). I have tried several solutions, e.g from #2680864 or from here. They all work, but I run into a problem if I am flattening a list containing a quoted element. E.g.:
> '(a 'b c)
(A 'B C)
> '(a (quote b) c)
(A 'B C)
> (flatten '(a 'b c))
(A QUOTE B C)
In the latter case I would like to get:
(A 'B C)
It seems that the internal representation of ' gets in the way for this task! SBCL, CLISP, ECL, ... they all behave the same way.
Quoted elements in a list? That usually does not make sense. Why would you have it quoted?
(a b c) is a list of three symbols. Why would you quote elements in the list? like in (a 'b c)? Why? What would be the purpose of the quote?
In Common Lisp ' is a readmacro which expands 'a into (QUOTE A). Since this is a normal list, a typical flatten operation will collect the symbols QUOTE and A into the flat list. This is because a flatten function typicall checks whether something is an atom or not. If you don't want this, your flatten function needs to check if something is an atom or a two-element list with QUOTE as its first symbol.
But as I said above, the default usage is just to flatten symbols, since quoted symbols are usually not useful inside a list. You need to extend the flatten function otherwise.
For example:
(defun flatten (l &key (test #'atom))
(cond ((null l) nil)
((funcall test l) (list l))
(t (loop for a in l nconc (flatten a :test test)))))
CL-USER > (flatten '(a (('b) c) ('d) )
:test (lambda (item)
(or (atom item)
(and (eq (first item) 'quote)
(null (cddr item))))))
(A (QUOTE B) C (QUOTE D))
Why does this series of clojure commands return false and not true? What is the difference between the result of statement 1 "C" and 2 "(quote C)"?
; SLIME 2009-03-04
user> ('A 'B 'C)
C
user> (last '('A 'B 'C))
(quote C)
user> (= ('A 'B 'C) (last '('A 'B 'C)))
false
This question is somewhat similar to How does clojure's syntax-quote work?
In Clojure (and other Lisps) the ' is a shortcut for the form (quote ...). So when Clojure sees this:
('A 'B 'C)
which is "translated" by the reader into:
((quote A) (quote B) (quote C))
Each of those quote forms evaluates to a symbol, so (quote A) evaluates to the symbol named A. In Clojure, symbols are functions and can be applied, so ((quote A) (quote B) (quote C)) is actually a function call. From the docs:
"Symbols, just like Keywords, implement IFn for invoke() of one argument (a map) with an optional second argument (a default value). For example ('mysym my-hash-map :none) means the same as (get my-hash-map 'mysym :none)."
So what happens is that C is the default value and that's why it's returned.
Meanwhile, this
'('A 'B 'C)
is translated by the reader into
(quote ((quote A) (quote B) (quote C)))
Which is actually a list of three elements, each of which is a list of two elements, the symbol quote and another symbol (in this case A, B, C).
So, (last '('A 'B 'C)) is actually (quote C). That's the difference between those two results, C is the symbol with the name C while (quote C) is a list of two elements.
You can confirm this:
user=> (class ('A 'B 'C))
clojure.lang.Symbol
user=> (class (last '('A 'B 'C)))
clojure.lang.PersistentList
user=>
Hope that's clear!
('x 'y) is very unusual, for just this reason. Usually you want '(x y), which is a list of the literal symbols x and y. If you quote TWICE with '('x 'y), you get a list with (quote x) instead: the literal symbol quote, followed by the literal symbol x.