This question already has an answer here:
Using car and cdr
(1 answer)
Closed 2 years ago.
When I do a cons on two atoms, I am getting a . in between.
1]=>(cons 'one 'two)
;Value 1: (one . two)
Why I am getting the . operator. Does it have any meaning?
I am using mit-scheme.
I have seen this stackoverflow link but not clear.
UPDATE:
The definition of cons in Little Schemer states that,
cons takes two arguments, the first one is any S-expression and the second one is any list.
The dot is just the way Scheme displays a cons cell when the cdr part is not itself a cons cell or the empty list. The dot is not an operator in this case, for example:
(cons 1 2)
=> '(1 . 2) ; a cons pair, a.k.a. a cons cell
(cons 1 (cons 2 3))
=> '(1 2 . 3) ; not a proper list, it doesn't end in '()
If the cdr part is a cons cell or the empty list '(), then we have a list:
(cons 1 '())
=> '(1) ; a proper list, ends in '()
(cons 1 (cons 2 '()))
=> '(1 2) ; a proper list, ends in '()
The definition in The Little Schemer is a simplification, in reality cons can take any type of value for each one of its arguments. By convention if the second argument is a list it'll be considered a list and displayed as such, otherwise it's a plain old cons cell and the dot is there to remind you of this.
The procedure cons creates a "cons cell" pointing to the two arguments provided.
A cons cell is a pair of pointers and a list is a single cons cell or a series of cons cells whose second pointer points to another cons cell, and the second pointer of the last cell points to another object .
Note: I use the word "object" for simplicity not in the programming sense.
In a proper list the second pointer of the last cons cell points to an empty list.
In an improper list the second pointer of the last cons cell points to an object that is not an empty list.
Note2: an "empty list" () is a unique value in scheme and is different from a list, In common lisp it is equal to nil, Nil does not exist in scheme.
+-----+-----+
| | |
| | |
+--+--+--+--+
| |
| |
v v
obj obj
A cons cell
+-----+-----+ +-----+-----+ +-----+-----+
| | +---->+ | +---->+ | |
| | | | | | | | |
+--+--+-----+ +--+--+-----+ +--+--+--+--+
| | | |
| | | |
v v v v
0 1 2 3
(0 1 2 . 3) -> (0 . (1 . (2 . 3)))
An improper list
+-----+-----+ +-----+-----+ +-----+-----+
| | +---->+ | +---->+ | +----> ()/nil
| | | | | | | | |
+--+--+-----+ +--+--+-----+ +--+--+-----+
| | |
| | |
v v v
0 1 2
(0 1 2) -> (0 . (1 . (2 . () )
A proper list
The dot (when seen in the repl) is used to signify that the final pointer of the list points to an object that is not an empty list and it is therefore an improper list.
This is my understanding at least from common lisp though I am sure it translates to most other lisps (I think Clojure is different (if you consider it a lisp that is)).
Wikipedia page on cons.
~
The little Schemer is lying. cons can take any type as its first and second argument. You can always create a pair with quoted structures like '(1 . 8).
There is no data structure specifically to make lists so Scheme has a trick. They define a list as either the empty list or a cons that has a list as its cdr. Thus '(1 . (2 . (3 . ()))) is a list and if you evaluate it Scheme repl will print (1 2 3) back. If you evaluate '(1 2 3) the reader will turn the input code into '(1 . (2 . (3 . ()))) before the Scheme interpreter gets to evaluate it. A list that ends with '() is called a proper list since it has no dots between the last two elements. eg. '(1 . (2 . (3 . 4))) ; ==> (1 2 3 . 4)
If you give the second argument a proper list is the result always a proper list and you'll not see any dots.
This Prolog code returns:
?- [a,b,c,d] = [a|[b,c,d]].
true
and this one
?- [X,Y] = [a|[b,c,d]].
returns false.
I am not totally grasping why [X, Y] is false. Trace is not helpful here. I would expect the following assignment to hold
X = a
Y = [b,c,d]
and the statement be true.
What does | do besides splitting on head and tail?
A list in Prolog is implemented as a linked list of functors. If you write a list like [a, b, c, d]. it looks in reality like:
+-------+
| (|)/2 |
+---+---+ +-------+
| o | o---->| (|)/2 |
+-|-+---+ +---+---+ +-------+
v | o | o---->| (|)/2 |
a +-|-+---+ +---+---+ +-------+
v | o | o---->| (|)/2 |
b +-|-+---+ +---+---+
v | o | o----> []
c +-|-+---+
v
d
or in Prolog notation [a | [b | c | [d | [] ] ] ]. The comma-separated list is syntactical sugar: if you write [a, b, c, d], the Prolog interpreter converts it to a representation as above.
Since [b, c, d] is equal to:
[ b | [ c | [ d | [] ] ] ]
and thus [ a | [b, c, d] ] is thus equal to
[a | [b | c | [d | [] ] ] ]
But the list [X, Y] is just equal to
[X, Y] == [ X | [ Y | [] ] ]
or in a structural way:
+-------+
| (|)/2 |
+---+---+ +-------+
| o | o---->| (|)/2 |
+-|-+---+ +---+---+
v | o | o----> []
X +-|-+---+
v
Y
If we then match it with [a | [b | c | [d | [] ] ] ] this means the "outer" shell can be matched, so X = a, but then Y = b, and [] = [ c | [ d | [] ] ]. The last part does not match, and thus it returns false. The X and Y are thus not the problem. The problem is that [] is a constant, and it does not match with the functor that represents [ c | [d] ].
If we would for example unify [ X | Y ] == [a, b, c, d] we get:
?- [ X | Y ] = [a, b, c, d].
X = a,
Y = [b, c, d].
So to conclude, one can say that | itself "does" nothing. It is a functor, just like f(1, 2). In Lisp they used cons [wiki] for this, and nil for the empty list. So [1, 4, 2, 5] looks in Lisp like cons 1 (cons 4 (cons 2 (cons 5 nil))), or in Prolog it would look like cons(1, cons(4, cons(2, cons(5, nil)))). It is only a bit cumbersome to write. In fact the comma separated notation is more the "magic" part. Prolog just performs unification for lists, just like it does for other functors and constants.
I want to create a list of Fibonacci numbers.
I want to call fib x and it should give me a list till the xth element.
How do I achieve that.
I would calculate fib numbers like this:
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
How do I put the result in a list to call the list till the element I need?
A compact definition (that scales linear) is the following:
fib :: Num n => [n]
fib = 0 : nxt
where nxt = 1 : zipWith (+) fib nxt
fibN :: Num n => Int -> [n]
fibN = flip take fib
What we here do is constructing a list fib that is "cons" of 0 and nxt (the rest of the lists). nxt is defined in the where clause as a "cons" of 1 and and the result of zipWith (+) fib nxt. The zipWith elementwise adds the elements of fib and nxt together, since nxt is always one element "ahead" of fib, we thus add the two last elements together. We then take the first n elements in the fibN function.
So we obtain a list like:
fib nxt
| |
v v
+-------+ +-------+ +-------------+
| (:) | ,->| (:) | ,->| zipWith |
+---+---+ | +---+---+ | +-----+---+---+
| 0 | o---' | 1 | o---' | (+) | o | o |
+---+---+ +---+---+ +-----+-|-+-|-+
^ ^ | |
| `------------------|---'
`-------------------------------'
In case we thus evaluate up to the third element, this means that we call zipWith, and this will produce the sum of the head of fib and nxt and advance both points, like:
fib nxt
| |
v v
+-------+ +-------+ +-------+ +-------------+
| (:) | ,->| (:) | ,->| (:) | ,->| zipWith |
+---+---+ | +---+---+ | +---+---+ | +-----+---+---+
| 0 | o---' | 1 | o---' | 1 | o---' | (+) | o | o |
+---+---+ +---+---+ +---+---+ +-----+-|-+-|-+
^ ^ | |
| `------------------|---'
`-------------------------------'
and so on.
Not a fast way (because your function runs in exponential time), but using your function fib
nfibs :: Int -> [Integer]
nfibs n = take n (map fib [0..])
I am currently about to implement a multi-way tree in c++, but I am still not sure about what exactly they are. I have read a few documentations, but I am still confused because of the lack of pictures or visualization provided.
Lets say I want a 3 way tree, according to online web notes it means each node can have at most 3-1 = 2 elements and each node can have at most 3 children. Below I have drawn some trees that I am not sure if they are 3-way trees, can someone please verify I am understanding this correctly? Thank you!
Also, if I have a 2 way tree, does that mean I have a binary tree as well? O.o?
My understanding of a multi-way tree is the number of subtrees that can be traversed from a single node.
+---+
| D |
+---+
^
|
|
+---+ +------+ +---+
| A | <-- | Root | --> | B |
+---+ +------+ +---+
|
|
V
+---+
| C |
+---+
The diagram above shows a multi-way tree because the root has more than 1 child.
Usually 2 children per node (except leaf nodes) indicates binary trees.
There are many different kinds of binary trees.
See also B-Tree and B*Trees.
Edit 1:
Another view:
+------------------------+
| Root +
+------------------------+
| | | |
V V V V
+---+ +---+ +---+ +---+
| A | | B | | C | | D |
+---+ +---+ +---+ +---+
I know that xs !! n gives me nth element in a list, but I don't know how to edit nth element in that list. Can you tell me how can I edit nth element in a list or give a hint at least?
For example how can I make the second element 'a' an 'e' in this: ['s','t','a','c','k']?
Changing the nth element
A common operation in many languages is to assign to an indexed position in an array. In python you might:
>>> a = [1,2,3,4,5]
>>> a[3] = 9
>>> a
[1, 2, 3, 9, 5]
The
lens package gives this functionality with the (.~) operator. Though unlike in python the original list is not mutated, rather a new list is returned.
> let a = [1,2,3,4,5]
> a & element 3 .~ 9
[1,2,3,9,5]
> a
[1,2,3,4,5]
element 3 .~ 9 is just a function and the (&) operator, part of the
lens package, is just reverse function application. Here it is with more common function application.
> (element 3 .~ 9) [1,2,3,4,5]
[1,2,3,9,5]
Assignment again works perfectly fine with arbitrary nesting of Traversables.
> [[1,2,3],[4,5,6]] & element 0 . element 1 .~ 9
[[1,9,3],[4,5,6]]
or
> set (element 3) 9 [1,2,3,4,5,6,7]
Or if you want to effect multiple elements you can use:
> over (elements (>3)) (const 99) [1,2,3,4,5,6,7]
> [1,2,3,4,99,99,99]
Working with types other then lists
This is not just limited to lists however, it will work with any datatype that is an instance of the Traversable typeclass.
Take for example the same technique works on trees form the standard
containers package.
> import Data.Tree
> :{
let
tree = Node 1 [
Node 2 [Node 4[], Node 5 []]
, Node 3 [Node 6 [], Node 7 []]
]
:}
> putStrLn . drawTree . fmap show $ tree
1
|
+- 2
| |
| +- 4
| |
| `- 5
|
`- 3
|
+- 6
|
`- 7
> putStrLn . drawTree . fmap show $ tree & element 1 .~ 99
1
|
+- 99
| |
| +- 4
| |
| `- 5
|
`- 3
|
+- 6
|
`- 7
> putStrLn . drawTree . fmap show $ tree & element 3 .~ 99
1
|
+- 2
| |
| +- 4
| |
| `- 99
|
`- 3
|
+- 6
|
`- 7
> putStrLn . drawTree . fmap show $ over (elements (>3)) (const 99) tree
1
|
+- 2
| |
| +- 4
| |
| `- 5
|
`- 99
|
+- 99
|
`- 99
Because Haskell is a functional language, you cannot 'edit' elements in lists, because everything is immutable. Instead, you can create a new list with something like:
take n xs ++ [newElement] ++ drop (n + 1) xs
However, it is not recommended in Haskell. For some more information you can see this post: Haskell replace element in list
You can't edit the nth element of a list, values are immutable. You have to create a new list. But due to the immutability, it can share the part after the changed element with the original list.
So if you want to apply a transformation to the nth element of a list (and have the parts before and after identical), you have three parts
the front of the list before the element in question, say front
the element in question, say element
the back of the list after the element in question, say back.
Then you'd assemble the parts
front ++ transform element : back
so it remains to get a hold on the interesting parts in a nice way.
splitAt :: Int -> [a] -> ([a],[a])
does that, splitAt idx list gives back the first part of the list, before the index idx as the first component of the pair, and the rest as the second, so
changeNthElement :: Int -> (a -> a) -> [a] -> [a]
changeNthElement idx transform list
| idx < 0 = list
| otherwise = case spliAt idx list of
(front, element:back) -> front ++ transform element : back
_ -> list -- if the list doesn't have an element at index idx
(Note: I have started counting elements at 0, if you want to start counting at 1, you need to adjust and use idx-1.)
I' surprised the following method was not yet mentioned, so I will add it for further reference:
replace index elem = map (\(index', elem') -> if index' == index then elem else elem') . zip [0..]
> replace 2 'e' "stack"
"steck"
It handle the casse of out of range index.
> replace (-1) 'z' "abc"
"abc"
> replace 0 'z' "abc"
"zbc"
> replace 2 'z' "abc"
"abz"
> replace 3 'z' "abc"
"abc"
It is not slower than the splitAt method ( O(2N) ).
There is also the possibility of writing a simple recursive solution.
The basic idea is that, in order to substitute element #5 in a list, you just have to substitute element #4 in the tail of that list.
Using the notations from the answer of #DanielFisher, this gives the following code:
changeNthElement :: Int -> (a -> a) -> [a] -> [a]
changeNthElement n fn [] = [] -- nothing to change
changeNthElement n fn (x:xs)
| (n < 0) = x:xs -- no change for a negative index
| (n == 0) = (fn x) : xs -- easy case
| otherwise = x : (changeNthElement (n-1) fn xs) -- recursion
If the new value does not depend on the old one, one can specialize the above function:
setNthElement :: Int -> a -> [a] -> [a]
setNthElement n v xs = changeNthElement n (const v) xs
Testing:
$ ghci
GHCi, version 8.8.4: https://www.haskell.org/ghc/ :? for help
...
λ>
λ> :load q15530511.hs
[1 of 1] Compiling Main ( q15530511.hs, interpreted )
Ok, one module loaded.
λ>
λ> xs = replicate 10 7
λ>
λ> xs
[7,7,7,7,7,7,7,7,7,7]
λ>
λ> changeNthElement 3 (+2) xs
[7,7,7,9,7,7,7,7,7,7]
λ>
λ> setNthElement 2 42 xs
[7,7,42,7,7,7,7,7,7,7]
λ>