In a Clojure book, I found a map function with 3 args:
(Map vector (iterate inc 0) coll)
What is the vector doing? How is it that this function accepts 3 args instead of the standard 2?
The map function accepts a variable number of arguments. The required first argument is a function, and then you can pass any number of collections after. When more than one collection is passed, the corresponding element from each collection will be passed as an argument to the function (e.g. if you pass one collection, the function will receive one argument, and if you pass three collections, it will receive three arguments).
As for vector, it does the same thing the vector function usually does — make a vector out of its arguments. For example, (vector 1 100 1000) gives [1 100 1000]. In this case, its arguments will be the nth elements of two collections:
An infinite sequence of integers starting at zero
Whatever is in coll
In effect, this transforms each item in coll into a vector containing the item's index followed by the item. So if coll is [a b c], for example, it will give you ([0 a] [1 b] [2 c]).
Related
as a lisp newbie i'm stuck with a general problem: I want to query data, generate a sum over it and want to calculate further with this results.
For example i sum up 33 77 and want to divide the result:
(defun sum (L)
(reduce '+ L))
(/ 999 (sum '(33 77)))
Without the divison i receive the correct sum. When i'm trying to proceed further, i get an error that a numerical function was given an argument.
A type-of query (type-of '(sum '(33 77))) says it's CONS
What's the correct handling for results for further calculation?
(type-of '(sum '(33 77)))
The evaluation of the above consists first in evaluating '(sum '(33 77)), and call function type-of with the result of the evaluation.
'(sum '(33 77)) is the same as (quote (sum (quote (33 77)))), except that the apostrophe is a reader syntax ' that turns what follows, say x, into (quote x).
The quote form is self-evaluating, meaning the value it evaluates to is the exact value that was quoted, here (sum '(33 77)).
That value is data representing code: it literally is a list, built at read-time, that contains the symbol sum followed by another element, a list whose first element is quote that is followed by another list containing 33 and 77, literal numbers.
Since the value of your expression is a list, and since lists are built by chaining cons-cells, it is normal that type-of returns cons.
If you remove one level of quotes:
(type-of (sum '(33 77)))
Then the evaluation of (sum '(33 77)) follows the normal evaluation of function calls, by first evaluating the argument, '(33 77), a literal list, and calling sum with it. Your function returns the sum, 110, and this is the value that is given when calling type-of. In that case, you should obtain a numerical type.
I am trying to print the size of a list created from below power set function
fun add x ys = x :: ys;
fun powerset ([]) = [[]]
| powerset (x::xr) = powerset xr # map (add x) (powerset xr) ;
val it = [[],[3],[2],[2,3],[1],[1,3],[1,2],[1,2,3]] : int list list;
I have the list size function
fun size xs = (foldr op+ 0 o map (fn x => 1)) xs;
I couldnt able to merge these two functions and get the result like
I need something like this:
[(0,[]),(1,[3]),(1,[2]),(2,[2,3]),(1,[1]),(2,[1,3]),(2,[1,2]),(3,[1,2,3])]
Could anyone please help me with this?
You can get the length of a list using the built-in List.length.
You seem to forget to mention that you have the constraint that you can only use higher-order functions. (I am guessing you have this constraint because others these days are asking how to write powerset functions with this constraint, and using foldr to count, like you do, seems a little constructed.)
Your example indicates that you are trying to count each list in a list of lists, and not just the length of one list. For that you'd want to map the counting function across your list of lists. But that'd just give you a list of lengths, and your desired output seems to be a list of tuples containing both the length and the actual list.
Here are some hints:
You might as well use foldl rather than foldr since addition is associative.
You don't need to first map (fn x => 1) - this adds an unnecessary iteration of the list. You're probably doing this because folding seems complicated and you only just managed to write foldr op+ 0. This is symptomatic of not having understood the first argument of fold.
Try, instead of op+, to write the fold expression using an anonymous function:
fun size L = foldl (fn (x, acc) => ...) 0 L
Compare this to op+ which, if written like an anonymous function, would look like:
fn (x, y) => x + y
Folding with op+ carries some very implicit uses of the + operator: You want to discard one operand (since not its value but its presence counts) and use the other one as an accumulating variable (which is better understood by calling it acc rather than y).
If you're unsure what I mean about accumulating variable, consider this recursive version of size:
fun size L =
let fun sizeHelper ([], acc) = acc
| sizeHelper (x::xs, acc) = sizeHelper (xs, 1+acc)
in sizeHelper (L, 0) end
Its helper function has an extra argument for carrying a result through recursive calls. This makes the function tail-recursive, and folding is one generalisation of this technique; the second argument to fold's helper function (given as an argument) is the accumulating variable. (The first argument to fold's helper function is a single argument rather than a list, unlike the explicitly recursive version of size above.)
Given your size function (aka List.length), you're only a third of the way, since
size [[],[3],[2],[2,3],[1],[1,3],[1,2],[1,2,3]]
gives you 8 and not [(0,[]),(1,[3]),(1,[2]),(2,[2,3]),...)]
So you need to write another function that (a) applies size to each element, which would give you [0,1,1,2,...], and (b) somehow combine that with the input list [[],[3],[2],[2,3],...]. You could do that either in two steps using zip/map, or in one step using only foldr.
Try and write a foldr expression that does nothing to an input list L:
foldr (fn (x, acc) => ...) [] L
(Like with op+, doing op:: instead of writing an anonymous function would be cheating.)
Then think of each x as a list.
I am trying to append one list to an end of another list. The usual :: operator gives me the following error:
This expression has type char list
but an expression was expected of type char
in the statement
`(createList 0 5 'a')::['c';'d';'e';'f';'g']`
(* the following createList expression returns the list ['a';'a';'a';'a';'a'] *)
When I use # operator, it appends the list fine; so, my question is what is the difference between # and ::? is it just # is used between two lists while :: used between list and non-list types?
# concatenates two lists (type 'a list -> 'a list -> 'a list), while :: takes an element of a certain type and "prepends" it before a list containing elements of exactly the same type (i.e. :: has type 'a -> 'a list -> 'a list).
You can basically simulate a::b by [a]#b.
Note that # requires OCaml to traverse the first list given to find the last argument of the first list. This takes O(n) time where n is the number of elements in the first list. ::, on the other hand, requires O(1) time.
Regarding your example (createList 0 5 'a')::['c';'d';'e';'f';'g']:
(createList 0 5 'a') creates a list holding 'a's, i.e. we have type char list, and ['c';'d';'e';'f';'g'] is also of type char list. Thus, you can only use # to concatenate them (see above), and :: makes no sense (see type signature of :: above).
# is to concatenates two lists.
:: is to add an element to the head of a list
Define a function that, given a list L, an object x, and a positive
integer k, returns a copy of L with x inserted at the k-th position.
For example, if L is [a1, a2, a3] and k=2, then [a1, x, a2, a3] is
returned. If the length of L is less than k, insert at the end. For
this kind of problems, you are supposed not to use, for example, the
length function. Think about how the function computes the length. No
'if-then-else' or any auxiliary function.
I've figured out how to make a function to find the length of a list
fun mylength ([]) = 0
| mylength (x::xs) = 1+ mylength(xs)
But, as the questions states, I can't use this as an auxiliary function in the insert function. Also, i'm lost as to how to go about the insert function? Any help or guidance would be appreciated!
Here's how to do this. Each recursive call you pass to the function tail of the list and (k - 1) - position of the new element in the tail of the list. When the list is empty, you construct a single-element list (which was given to you); when k is 0, you append your element to what's left from the list. On the way back, you append all heads of the list that you unwrapped before.
fun kinsert [] x k = [x]
| kinsert ls x 0 = x::ls
| kinsert (l::ls) x k = l::(kinsert ls x (k - 1))
I used a 0-indexed list; if you want 1-indexed, just replace 0 with 1.
As you can see, it's almost the same as your mylength function. The difference is that there are two base cases for recursion and your operation on the way back is not +, but ::.
Edit
You can call it like this
kinsert [1,2,3,4,5,6] 10 3;
It has 3 arguments; unlike your length function, it does not wrap arguments in a tuple.
Here's how I'd approach it. The following assumes that the list item starts from zero.
fun mylength (lst,obj,pos) =
case (lst,obj,pos) of
([],ob,po)=>[ob]
| (xs::ys,ob,0) => ob::lst
| (xs::ys,ob,po) => xs::mylength(ys,obj,pos-1)
We want to find the largest value in a given nonempty list of integers. Then we have to compare elements in the list. Since data
values are given as a sequence, we can do comparisons from the
beginning or from the end of the list. Define in both ways. a)
comparison from the beginning b) comparison from the end (How can we
do this when data values are in a list?) No auxiliary functions.
I've been playing around a lot with recursive functions, but can't seem to figure out how to compare two values in the list.
fun listCompare [] = 0
| listCompare [x] = x
| listCompare (x::xs) = listCompare(xs)
This will break the list down to the last element, but how do I start comparing and composing the list back up?
You could compare the first two elements of a given list and keep the larger element in the list and drop the other. Once the list has only one element, then you have the maximum. In functional pseudocode for a) it looks roughly like so:
lmax [] = error "empty list"
lmax [x] = x
lmax (x::y::xs) =
if x > y then lmax (x::xs)
else lmax (y::xs)
For b) you could reverse the list first.
This is what the foldl (or foldr) function in the SML list library is for :
foldl : ((`a * `b) -> `b) -> `b -> `a list -> `b
You can simply add an anonymous function to compare the current element against the accumulator :
fun lMax l =
foldl (fn (x,y) => if x > y then x else y) (nth l 0) l
The nth function simply takes the int list : l and an int : 0 to return the first element in the list. As lists in SML are written recursively as : h :: t, retrieving the first element is an O(1) operation, and using the foldl function greatly increases the elegance of code. The whole point of having a functional language is to define abstractions to pass around anonymous functions as higher-order functions and re-use the abstract type definitions with concrete functions.