Scala 3 — Book

# Write Your Own map Method

Language

Now that you’ve seen how to write your own higher-order functions, let’s take a quick look at a more real-world example.

Imagine for a moment that the `List` class doesn’t have its own `map` method, and you want to write your own. A good first step when creating functions is to accurately state the problem. Focusing only on a `List[Int]`, you state:

I want to write a `map` method that can be used to apply a function to each element in a `List[Int]` that it’s given, returning the transformed elements as a new list.

Given that statement, you start to write the method signature. First, you know that you want to accept a function as a parameter, and that function should transform an `Int` into some generic type `A`, so you write:

``````def map(f: (Int) => A)
``````

The syntax for using a generic type requires declaring that type symbol before the parameter list, so you add that:

``````def map[A](f: (Int) => A)
``````

Next, you know that `map` should also accept a `List[Int]`:

``````def map[A](f: (Int) => A, xs: List[Int])
``````

Finally, you also know that `map` returns a transformed `List` that contains elements of the generic type `A`:

``````def map[A](f: (Int) => A, xs: List[Int]): List[A] = ???
``````

That takes care of the method signature. Now all you have to do is write the method body. A `map` method applies the function it’s given to every element in the list it’s given to produce a new, transformed list. One way to do this is with a `for` expression:

``````for (x <- xs) yield f(x)
``````
``````for x <- xs yield f(x)
``````

`for` expressions often make code surprisingly simple, and for our purposes, that ends up being the entire method body.

Putting it together with the method signature, you now have a standalone `map` method that works with a `List[Int]`:

``````def map[A](f: (Int) => A, xs: List[Int]): List[A] =
for (x <- xs) yield f(x)
``````
``````def map[A](f: (Int) => A, xs: List[Int]): List[A] =
for x <- xs yield f(x)
``````

### Make it generic

As a bonus, notice that the `for` expression doesn’t do anything that depends on the type inside the `List` being `Int`. Therefore, you can replace `Int` in the type signature with the generic type parameter `B`:

``````def map[A, B](f: (B) => A, xs: List[B]): List[A] =
for (x <- xs) yield f(x)
``````
``````def map[A, B](f: (B) => A, xs: List[B]): List[A] =
for x <- xs yield f(x)
``````

Now you have a `map` method that works with any `List`.

These examples demonstrate that `map` works as desired:

``````def double(i : Int): Int = i * 2
map(double, List(1, 2, 3))            // List(2, 4, 6)

def strlen(s: String): Int = s.length
map(strlen, List("a", "bb", "ccc"))   // List(1, 2, 3)
``````

Now that you’ve seen how to write methods that accept functions as input parameters, let’s look at methods that return functions.
{"ft_lang_label":"__label__en","ft_lang_prob":0.8394062,"math_prob":0.9823746,"size":2602,"snap":"2023-40-2023-50","text_gpt3_token_len":704,"char_repetition_ratio":0.13818322,"word_repetition_ratio":0.14164905,"special_character_ratio":0.28324366,"punctuation_ratio":0.1418919,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.991982,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2023-09-26T13:12:56Z\",\"WARC-Record-ID\":\"<urn:uuid:5151abd2-a199-4be1-8f07-3444aeb2b549>\",\"Content-Length\":\"85319\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:284d46d5-4647-4fe0-9804-69f9029c27e9>\",\"WARC-Concurrent-To\":\"<urn:uuid:0669cef2-1e75-4495-8b80-07cab8388b18>\",\"WARC-IP-Address\":\"104.21.51.204\",\"WARC-Target-URI\":\"https://docs.scala-lang.org/scala3/book/fun-write-map-function.html\",\"WARC-Payload-Digest\":\"sha1:GM3TDLZFZEL47PMLOTW6CS2X7GWAYP22\",\"WARC-Block-Digest\":\"sha1:FCIQVCFAEBWQGCAGYVPCOK3H5TRRJ457\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2023/CC-MAIN-2023-40/CC-MAIN-2023-40_segments_1695233510208.72_warc_CC-MAIN-20230926111439-20230926141439-00323.warc.gz\"}"}