Skip to content
4 changes: 4 additions & 0 deletions concepts/map/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"blurb": "The map function applies a given function to each element of one or more collections.",
"authors": ["JaumeAmoresDS"]
}
49 changes: 49 additions & 0 deletions concepts/map/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Introduction

In its most basic form, the higher-order function `map` accepts two arguments: a function `f` and a collection `coll`.

Given `f` and `coll`, `map` applies `f` to each element of `coll`, returning a list of the results in the same order.

```clojure
(map inc [1 2 3]) ; => (2 3 4)
```

The previous example applies the function `inc` to each element of the vector and returns the result as the list `(2 3 4)`.

Let's see another example where we greet someone with the message "Welcome":

```clojure
(defn say-welcome
[name]
(str "Welcome " name "!"))

(map say-welcome ["Chris" "Jane" "Peter"]) ; => ("Welcome Chris!" "Welcome Jane!" "Welcome Peter!")
```

## Returning a lazy sequence

Previously we provided a simplified explanation of how `map` operates.

In reality, `map` does not return a list but a *lazy* sequence.

This essentially means that the elements of the resulting sequence are not generated until they are actually needed.

In other words, the function `f` passed to `map` is not applied until the elements of the resulting sequence are requested, for example, by printing them or retrieving their values.

This is advantageous when `f` is computationally expensive and only some elements are actually needed.

## Multiple collections

`map` allows multiple collections to be passed as input.

If the number of collections passed is `n`, the function `f` will receive `n` arguments, one from each collection.

The result is a sequence where the i-th element is obtained by applying `f` to the `n` elements at position i from each collection.

```clojure
(def coll_a [a1 a2])
(def coll_b [b1 b2])
(def coll_c [c1 c2])
(map f coll_a coll_b coll_c) ; => ((f a1 b1 c1) (f a2 b2 c2))
```

49 changes: 49 additions & 0 deletions concepts/map/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Introduction

In its most basic form, the higher-order function `map` accepts two arguments: a function `f` and a collection `coll`.

Given `f` and `coll`, `map` applies `f` to each element of `coll`, returning a list of the results in the same order.

```clojure
(map inc [1 2 3]) ; => (2 3 4)
```

The previous example applies the function `inc` to each element of the vector and returns the result as the list `(2 3 4)`.

Let's see another example where we greet someone with the message "Welcome":

```clojure
(defn say-welcome
[name]
(str "Welcome " name "!"))

(map say-welcome ["Chris" "Jane" "Peter"]) ; => ("Welcome Chris!" "Welcome Jane!" "Welcome Peter!")
```

## Returning a lazy sequence

Previously we provided a simplified explanation of how `map` operates.

In reality, `map` does not return a list but a *lazy* sequence.

This essentially means that the elements of the resulting sequence are not generated until they are actually needed.

In other words, the function `f` passed to `map` is not applied until the elements of the resulting sequence are requested, for example, by printing them or retrieving their values.

This is advantageous when `f` is computationally expensive and only some elements are actually needed.

## Multiple collections

`map` allows multiple collections to be passed as input.

If the number of collections passed is `n`, the function `f` will receive `n` arguments, one from each collection.

The result is a sequence where the i-th element is obtained by applying `f` to the `n` elements at position i from each collection.

```clojure
(def coll_a [a1 a2])
(def coll_b [b1 b2])
(def coll_c [c1 c2])
(map f coll_a coll_b coll_c) ; => ((f a1 b1 c1) (f a2 b2 c2))
```

6 changes: 6 additions & 0 deletions concepts/map/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"url": "https://clojuredocs.org/clojure.core/map",
"description": "ClojureDocs: map"
}
]
4 changes: 4 additions & 0 deletions concepts/reduce/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"blurb": "The reduce function combines all elements of a collection into a single value by applying a function cumulatively",
"authors": ["JaumeAmoresDS"]
}
99 changes: 99 additions & 0 deletions concepts/reduce/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Introduction

The higher-order funcion `reduce` accepts either two or three arguments.

Let's see each one in turn.

## Reduce with three arguments

When called with three arguments, `(reduce f val coll)` runs sequentially as follows:

- First, it applies the function `f` to `val` and the first element `x_1` of the collection `coll`: `(f val x_1)`.
- Then, it applies the function `f` to its own result and the second element `x_2` of the collection `coll`: `(f (f val x_1) x_2)`.
- Then again, it applies `f` to its previous result and the third element of `coll`.

And so on until all the elements of `coll` are used.

Let's see a typical example using `+` as our function:

```clojure
(reduce + 100 [1 2 3 4])
;=> (+ 100 1)
;=> (+ 101 2)
;=> (+ 103 3)
;=> (+ 106 4)
;=> 110
```

## Reduce with two arguments

When called with two arguments, `(reduce f coll)` runs sequentially as follows:

- First, it applies the function `f` to the two first elements `x_1` and `x_2` of the collection `coll`.
- Then, it applies `f` to its own result and the third element `x_3` of `coll`.
- Then again to its own result and the fourth element of `coll`.

And so on until all the elements of `coll` are used:

```clojure
(reduce + [1 2 3 4])
;=> (+ 1 2)
;=> (+ 3 3)
;=> (+ 6 4)
;=> 10
```

In all these cases, the function `f` must accept either two arguments or a variable number of arguments as happens in the previous case with function `+`.

Let's see an example with a user-defined function:

```clojure
(defn include-if-even
[coll x]
(if (= (mod x 2) 0)
(conj coll x)
coll))
```

In the previous example, the function `include-if-even`:

- Accepts two arguments: a collection `coll` and a number `x`.
- It then checks if `x` module 2 is 0, in which case `x` is an even number.
- If that's the case, it includes this number into the collection `coll` and returns this collection.
- Otherwise, it returns the original collection.

We can then apply `reduce` to collect all the even numbers from a given collection as follows:

```clojure
(reduce include-if-even [] [1 2 3 4])
;=> (include-if-even [] 1)
;=> (include-if-even [] 2)
;=> (include-if-even [2] 3)
;=> (include-if-even [2] 4)
;=> [2 4]
```

Note that in the previous example we must necessarily pass three arguments to `reduce`: our function `include-if-even`, an initial collection `[]`, and a collection of numbers like `[1 2 3 4]`.

The initial collection `[]` is necessary due to the fact that `include-if-even` needs it as its first argument.

## Especial cases

Especial cases arise when we use an empty collection or a collection with only one item:

- If we apply `reduce` to an empty collection, `(reduce f val coll)` returns `(f val)`, and `(reduce f coll)` returns the result of applying `f` with no arguments.
- In this case, the function `f` must be able to use no arguments.
- If we apply `reduce` to a collection with only one item, `(reduce f val coll)` returns `(f val x_1)`, i.e., the result of applying `f` to `val` and the first element `x_1` of `coll`.
- If used with only two arguments, `(f coll)` returns the only element found in `coll`, and `f` is not called.

## Using collections of functions

`reduce` accepts any type of collection, including one that contains functions.

In that case, we will typically use three arguments `(reduce f val coll)`:

- The function `f` applies the first function `g_1` from the collection to `val`
- Then applies the second function `g_2` to the result of the previous application, `(f (f val g_1) g_2)`

And so on until all the functions are applied.

99 changes: 99 additions & 0 deletions concepts/reduce/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Introduction

The higher-order funcion `reduce` accepts either two or three arguments.

Let's see each one in turn.

## Reduce with three arguments

When called with three arguments, `(reduce f val coll)` runs sequentially as follows:

- First, it applies the function `f` to `val` and the first element `x_1` of the collection `coll`: `(f val x_1)`.
- Then, it applies the function `f` to its own result and the second element `x_2` of the collection `coll`: `(f (f val x_1) x_2)`.
- Then again, it applies `f` to its previous result and the third element of `coll`.

And so on until all the elements of `coll` are used.

Let's see a typical example using `+` as our function:

```clojure
(reduce + 100 [1 2 3 4])
;=> (+ 100 1)
;=> (+ 101 2)
;=> (+ 103 3)
;=> (+ 106 4)
;=> 110
```

## Reduce with two arguments

When called with two arguments, `(reduce f coll)` runs sequentially as follows:

- First, it applies the function `f` to the two first elements `x_1` and `x_2` of the collection `coll`.
- Then, it applies `f` to its own result and the third element `x_3` of `coll`.
- Then again to its own result and the fourth element of `coll`.

And so on until all the elements of `coll` are used:

```clojure
(reduce + [1 2 3 4])
;=> (+ 1 2)
;=> (+ 3 3)
;=> (+ 6 4)
;=> 10
```

In all these cases, the function `f` must accept either two arguments or a variable number of arguments as happens in the previous case with function `+`.

Let's see an example with a user-defined function:

```clojure
(defn include-if-even
[coll x]
(if (= (mod x 2) 0)
(conj coll x)
coll))
```

In the previous example, the function `include-if-even`:

- Accepts two arguments: a collection `coll` and a number `x`.
- It then checks if `x` module 2 is 0, in which case `x` is an even number.
- If that's the case, it includes this number into the collection `coll` and returns this collection.
- Otherwise, it returns the original collection.

We can then apply `reduce` to collect all the even numbers from a given collection as follows:

```clojure
(reduce include-if-even [] [1 2 3 4])
;=> (include-if-even [] 1)
;=> (include-if-even [] 2)
;=> (include-if-even [2] 3)
;=> (include-if-even [2] 4)
;=> [2 4]
```

Note that in the previous example we must necessarily pass three arguments to `reduce`: our function `include-if-even`, an initial collection `[]`, and a collection of numbers like `[1 2 3 4]`.

The initial collection `[]` is necessary due to the fact that `include-if-even` needs it as its first argument.

## Especial cases

Especial cases arise when we use an empty collection or a collection with only one item:

- If we apply `reduce` to an empty collection, `(reduce f val coll)` returns `(f val)`, and `(reduce f coll)` returns the result of applying `f` with no arguments.
- In this case, the function `f` must be able to use no arguments.
- If we apply `reduce` to a collection with only one item, `(reduce f val coll)` returns `(f val x_1)`, i.e., the result of applying `f` to `val` and the first element `x_1` of `coll`.
- If used with only two arguments, `(f coll)` returns the only element found in `coll`, and `f` is not called.

## Using collections of functions

`reduce` accepts any type of collection, including one that contains functions.

In that case, we will typically use three arguments `(reduce f val coll)`:

- The function `f` applies the first function `g_1` from the collection to `val`
- Then applies the second function `g_2` to the result of the previous application, `(f (f val g_1) g_2)`

And so on until all the functions are applied.

6 changes: 6 additions & 0 deletions concepts/reduce/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"url": "https://clojuredocs.org/clojure.core/reduce",
"description": "ClojureDocs: reduce"
}
]
10 changes: 10 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,16 @@
"uuid": "9d9d7cf1-8504-4f7b-b2a0-1b3b638dc0d9",
"slug": "functions-generating-functions",
"name": "Functions generating functions"
},
{
"uuid": "2369e86f-6921-49b6-807d-b1bdf9e37cd2",
"slug": "map",
"name": "map"
},
{
"uuid": "1fcc926b-4e79-4377-874f-41626e59b87b",
"slug": "reduce",
"name": "reduce"
}
],
"key_features": [
Expand Down