0
votes

I'm trying to do a really basic problem in clojure and having some trouble wrapping my head around how vectors/lists work.

First off when I am defining the arguments of a function that has a vector as an argument, how do you represent that as an argument.

Would you just have it as a single variable say

(defn example [avector] (This is where the function goes) )

Or do you have to list each element of a vector or list beforehand?

(defn example [vectorpart1 vectorpart2 vectorpart3 vectorpart4 ] (This is where the function goes) )

Also, in terms of vectors and lists, does anyone know of commands that allow you to figure out the length of a vector or get the first/last/or nth element?

3
The question title seems to be at odds with the subsequent text.Thumbnail

3 Answers

2
votes

Your first example defines a function that takes a single argument, regardless of type. If you pass a vector then that argument will be set to a vector.

(example [1 2 3 4]) ;; (= avector [1 2 3 4])

Your second example defines a function which takes four arguments. You need to pass four separate values for calls to this function to be valid.

(example [1] [2] [3] [4])
;; (= vectorpart1 [1])
;; (= vectorpart2 [2])
;; (= vectorpart3 [3])
;; (= vectorpart4 [4])

It sounds like you might be thinking about the destructuring syntax, which allows you to destructure values directly from an argument vector.

(defn example [[a b c d]]
  ())

The literal vector syntax in the argument definition describes a mapping between the items in the first argument and symbols available in the function scope.

(example [1 2 3 4])
;; (= a 1)
;; (= b 2)
;; (= c 3)
;; (= d 4)

The other function that also sits in this space is apply. Apply takes a list or vector of arguments and calls a function with them in-place.

(defn example [a b c]
  (assert (= a 1))
  (assert (= b 2))
  (assert (= c 3)))

If we call this function with one vector, you'll get an arity exception.

(example [1 2 3])
;; ArityException Wrong number of args (1) passed ...

Instead we can use apply to pass the vector as arguments.

(apply example [1 2 3])
;; no errors!

You'll find all the methods you need to work with vectors in the Clojure docs.

If you want to remove a specific element, simply take the elements before it and the elements after it, then join them together.

(def v [1 2 3])
(concat (subvec v 0 1) (subvec v 2))
2
votes

To remove the element at index n from vector v:

(defn remove-indexed [v n]
  (into (subvec v 0 n) (subvec v (inc n))))

For example,

(remove-indexed (vec (range 10)) 5)
;[0 1 2 3 4 6 7 8 9]

Lots can go wrong:

  1. v might not be a vector.
  2. n might not be a whole number.
  3. n might be out of range for v (we require (contains? v n).

Clojure detects all these errors at run time. A statically typed language would detect 1 and 2 but not 3 at compile time.

0
votes

The short answer is that your first example is correct. You don't want to have to name every piece of your vector because you will commonly work with vectors of indeterminate length. If you want to do something with that vector where you need its parts to be assigned, you can do so by destructuring.

The slightly longer answer is that the list of parameters sent into any clojure defn already is a vector. Notice that the parameter list uses [] to wrap its list of args. This is because in Clojure code and data are the same thing. From this article...

Lisps are homoiconic, meaning code written in the language is encoded as data structures that the language has tools to manipulate.

This might be more than you're looking for but it's an important related concept.

Here'a a quick example to get you going... Pass a vector (of strings in this case) to a functions and it returns the vector. If you map over it however, it passes the contents of the vector to the function in succession.

user=> (def params ["bar" "baz"])
#'user/params
user=> (defn foo [params] (println params))
#'user/foo
user=> (foo params)
[bar baz]
nil
user=> (map foo params)
bar
baz
(nil nil)

Additionally, look at the Clojure cheatsheet to find more about things you can do with vectors (and everything else in Clojure).