{"id":19188927,"url":"https://github.com/kelvins/functional-programming-in-scala","last_synced_at":"2026-06-17T03:31:45.178Z","repository":{"id":84557951,"uuid":"486280353","full_name":"kelvins/functional-programming-in-scala","owner":"kelvins","description":"Functional Programming in Scala","archived":false,"fork":false,"pushed_at":"2022-05-22T00:46:13.000Z","size":190,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-23T03:42:34.400Z","etag":null,"topics":["functional-programming","scala"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kelvins.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-27T16:59:55.000Z","updated_at":"2023-03-05T07:13:59.000Z","dependencies_parsed_at":"2023-03-12T23:36:57.235Z","dependency_job_id":null,"html_url":"https://github.com/kelvins/functional-programming-in-scala","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kelvins/functional-programming-in-scala","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kelvins%2Ffunctional-programming-in-scala","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kelvins%2Ffunctional-programming-in-scala/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kelvins%2Ffunctional-programming-in-scala/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kelvins%2Ffunctional-programming-in-scala/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kelvins","download_url":"https://codeload.github.com/kelvins/functional-programming-in-scala/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kelvins%2Ffunctional-programming-in-scala/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34433085,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-17T02:00:05.408Z","response_time":127,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functional-programming","scala"],"created_at":"2024-11-09T11:26:43.808Z","updated_at":"2026-06-17T03:31:45.162Z","avatar_url":"https://github.com/kelvins.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003cimg height=25 src=\"https://cdn.jsdelivr.net/gh/devicons/devicon/icons/scala/scala-original.svg\" /\u003e Functional Programming in Scala\n\nThis document aims to present a simple but useful introduction to the core concepts of functional programming with examples in Scala.\nAlthough the examples are written in Scala, most of the concepts presented here are general to the functional programming paradigm and can be easily applied to other languages.\n\nIf you have any doubts or suggestions about the content, feel free to contribute opening an issue or a pull request.\n\n\u003e This document was created as a personal effort for studying Scala and functional programming and will likely have updates over time.\n\n## Topics\n\n- [Introduction](#introduction)\n- [Immutability](#immutability)\n- [Pure Functions](#pure-functions)\n- [Higher-order Functions](#higher-order-functions)\n- [Currying](#currying)\n- [Anonymous Functions](#anonymous-functions)\n- [Map-Filter-Reduce](#map-filter-reduce)\n- [Recursion](#recursion)\n- [Tail Recursion](#tail-recursion)\n- [Companion Objects](#companion-objects)\n- [Substitution Model](#substitution-model)\n- [Where to go next](#where-to-go-next)\n- [References](#references)\n\n## Introduction\n\nLike many other modern programming languages, Scala is a multi-paradigm language which supports concurrent, functional, imperative and object-oriented paradigms. Despite that, it is important to note that this document will focus only on the functional paradigm.\n\nScala is designed to express common programming patterns in a concise, elegant, and type-safe way. Furthermore, Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and it supports currying. Scala’s case classes and its built-in support for pattern matching provide the functionality of algebraic types, which are used in many functional languages. Also, singleton objects provide a convenient way to group functions that aren’t members of a class.\n\nIn the following sections you're going to find some practical examples about these functional programming concepts. Note that the examples can be reproduced in the Scala REPL.\n\n## Immutability\n\nIn simple words, an immutable object is an object which cannot be modified after its creation.\n\nAs well as the other topics presented here, immutability is one of the core concepts in functional programming. Unlike other languages like Java, where you need to use the `final` keyword to make something immutable, in Scala we can simply use the keyword `val` instead of `var`, for example:\n\n```scala\nscala\u003e var y: Int = 10\nvar y: Int = 10\n\nscala\u003e y = 5\ny: Int = 5\n\nscala\u003e val x: Int = 10\nval x: Int = 10\n\nscala\u003e x = 5\n-- [E052] Type Error: ----------------------------------------------------------\n1 |x = 5\n  |^^^^^\n  |Reassignment to val x\n\nlonger explanation available when compiling with `-explain`\n1 error found\n```\n\nNote that Scala throws a `Type Error` when trying to re-assign the `x` value.\n\nAlso, by default function parameters are immutable objects:\n\n```scala\nscala\u003e def addOne(x: Int): Int = x = x + 1\n-- [E052] Type Error: ----------------------------------------------------------\n1 |def addOne(x: Int): Int = x = x + 1\n  |                          ^^^^^^^^^\n  |                          Reassignment to val x\n\nlonger explanation available when compiling with `-explain`\n1 error found\n```\n\nFuthermore, Scala splits the collections hierarchy into \"immutable\" and \"mutable\" data structures. By default, Scala automatically puts the immutable data structures (such as Map and Set) into your default environment, so if you create a new Map or Set, you'll automatically get an immutable structure.\n\n### Key Points\n\n- By default Scala uses immutable objects (e.g. collections like Map and Set).\n- Make your \"variables\" immutable, unless there’s a good reason not to.\n\n## Pure Functions\n\nAccording to the [Wikipedia](https://en.wikipedia.org/wiki/Pure_function) and many other authors, pure functions are functions that have the following properties:\n\n- The function **return value will always be the same**: no matter how many times you call the function, it should always return the same value or values for the same input parameters.\n- The function **has no side effects**: the function should not interact with the external world (I/O, databases, external APIs, etc). For this assumption to make sense, the function should always have a return value.\n\nBased on the assumptions above, a pure function is a computational analogue of a mathematical function.\n\nAlso, since pure functions are deterministic, they are often easier to test and even understand.\n\nHere is a simple example of a **pure function** that sum `x` and `y`:\n\n```scala\nscala\u003e def sum(x: Int, y: Int): Int = x + y\ndef sum(x: Int, y: Int): Int\n\nscala\u003e sum(10, 5)\nval res0: Int = 15\n\nscala\u003e sum(10, 5)\nval res1: Int = 15\n```\n\nAs you can see, the return value (output) depends only on the function parameters (input values).\n\nNow, here is an example of an **impure function**:\n\n```scala\nscala\u003e var y: Int = 5\nvar y: Int = 5\n\nscala\u003e def sum(x: Int): Int = x + y\ndef sum(x: Int): Int\n\nscala\u003e sum(10)\nval res0: Int = 15\n\nscala\u003e y = 10\n// mutated y\n\nscala\u003e sum(10)\nval res1: Int = 20\n```\n\nAs you can see, the `sum` function now depends on the `y` variable, which is in the outer scope. If you change the value of `y` it will affect the result of the `sum` function. So, even when calling the function with the same parameters it will return a different result.\n\nAnother example of an **impure function** can be seen in the following snippet:\n\n```scala\nscala\u003e def sum(x: Int, y: Int): Int = x + y + scala.util.Random.nextInt(10)\ndef sum(x: Int, y: Int): Int\n\nscala\u003e sum(10, 5)\nval res0: Int = 17\n\nscala\u003e sum(10, 5)\nval res1: Int = 19\n```\n\nIn the example above the `sum` function is using a random function to generate an integer value and adding it to the sum. So, even when we call the function with the same parameters it will return a different result.\n\n### Impure Functions are Needed\n\nEven understanding the importance of pure functions, when stopping to think about it, it's practically impossible to create a useful application without reading or writing to the \"outside world\". So, here's the following recommendation from the Scala documentation:\n\n\u003e Write the core of your application using pure functions, and then write an impure “wrapper” around that core to interact with the outside world.\n\n### Key Points\n\n- A pure function is a function that depends only on its declared inputs to produce its output.\n- A pure function does not read or modify values from the \"outside world\".\n- Real-world applications consist of a combination of pure and impure functions.\n\n## Higher-order Functions\n\nIn short, higher-order functions are functions that can take other functions as arguments and/or return functions. All other functions are first-order functions. \n\nHigher-order functions, also known as HOF, can be found in many programming languages and are not specifc to the functional programming paradigm, however they make functional programming much easier as it is possible to combine several functions to accomplish a task.\n\nHere is an example of a higher-order function `calculate` that takes a function `func` as argument and uses it to do the calculation:\n\n```scala\nscala\u003e def sum(x: Int, y: Int): Int = x + y\ndef sum(x: Int, y: Int): Int\n\nscala\u003e def mult(x: Int, y: Int): Int = x * y\ndef mult(x: Int, y: Int): Int\n\nscala\u003e def calculate(func: (Int, Int) =\u003e Int, x: Int, y: Int): Int = func(x, y)\ndef calculate(func: (Int, Int) =\u003e Int, x: Int, y: Int): Int\n\nscala\u003e calculate(sum, 2, 3)\nval res0: Int = 5\n\nscala\u003e calculate(mult, 2, 3)\nval res1: Int = 6\n```\n\nIt is also possible to return functions, for example:\n\n```scala\nscala\u003e def sum(x: Int, y: Int): Int = x + y\ndef sum(x: Int, y: Int): Int\n\nscala\u003e def mult(x: Int, y: Int): Int = x * y\ndef mult(x: Int, y: Int): Int\n\nscala\u003e def getFunction(functionName: String): (Int, Int) =\u003e Int = functionName match {\n     |   case \"sum\"  =\u003e sum\n     |   case \"mult\" =\u003e mult\n     |   case _      =\u003e throw new Exception(\"Invalid function name\")\n     | }\ndef getFunction(functionName: String): (Int, Int) =\u003e Int\n\nscala\u003e val calculate: (Int, Int) =\u003e Int = getFunction(\"sum\")\nval calculate: (Int, Int) =\u003e Int = $Lambda$1087/0x000000080100b5d0@439f2d87\n\nscala\u003e calculate(2, 3)\nval res0: Int = 5\n```\n\nAs you will see later, some built-in functions like `.map()` and `.filter()` are great examples of higher-order functions.\n\n### Key Points\n\n- Higher-order functions can take one or more functions as arguments and/or return a function.\n- Higher-order functions are used everywhere in functional programming.\n\n## Currying\n\nCurrying is a technique of converting a function that takes multiple arguments into a sequence of functions that each takes a single argument. For example, a function `x=f(a, b)` would become two functions `y=g(a)` and `x=y(b)`, or called in sequence `x=g(a)(b)`.\n\nIn functional programming languages it provides a way of automatically managing how arguments are passed to functions, for example:\n\n```scala\nscala\u003e def add(x: Int)(y: Int): Int = x + y\ndef add(x: Int)(y: Int): Int\n\nscala\u003e val add10: Int =\u003e Int = add(10)\nval add10: Int =\u003e Int = Lambda$1390/37235503@236b4a44\n\nscala\u003e add10(15)\nval res0: Int = 25\n```\n\nNote that it could also be represented as a closure:\n\n```scala\nscala\u003e def add(x: Int): (Int) =\u003e Int = {\n     |   def innerFunction(y: Int): Int = x + y\n     |   innerFunction\n     | }\ndef add(x: Int): Int =\u003e Int\n\nscala\u003e val add10: Int =\u003e Int = add(10)\nval add10: Int =\u003e Int = $Lambda$1078/0x000000080100add8@536b71b4\n\nscala\u003e add10(15)\nval res0: Int = 25\n```\n\nBut using the currying syntax is much easier.\n\n### Key Points\n\n- Currying is a technique of converting a function that takes multiple arguments into a sequence of functions that each takes a single argument.\n- Currying is very useful when you need to apply some initial values to many other values/objects.\n\n## Anonymous Functions\n\nAn anonymous function (also known as lambda function) is a function definition that is not bound to an identifier. Anonymous functions are often used as arguments being passed to higher-order functions or used as a return value from higher-order functions that needs to return a function. If the function is only used once, or a limited number of times, an anonymous function may be syntactically lighter than using a named function.\n\n```scala\nscala\u003e val data: List[Int] = List(1, 2, 3)\nval data: List[Int] = List(1, 2, 3)\n\nscala\u003e def double(x: Int): Int = x * 2\ndef double(x: Int): Int\n\nscala\u003e data.map(double) // map using named function\nval res0: List[Int] = List(2, 4, 6)\n\nscala\u003e data.map(x =\u003e x * 2) // map using anonymous function\nval res1: List[Int] = List(2, 4, 6)\n\nscala\u003e data.map(_ * 2) // map using anonymous function (concise version)\nval res2: List[Int] = List(2, 4, 6)\n```\n\n## Map-Filter-Reduce\n\nThe functions `.map()`, `.filter()` and `.reduce()` are well know functions and are used in many programming languages, but in functional programming they are even more important since it avoids loops and modifying values from the outer scope. It is important to note that these functions always return a new object.\n\n### Map\n\nThe `.map()` function basically applies a function, passed as argument, to each value of a sequence of values, for example:\n\n```scala\nscala\u003e val data: List[Int] = List(1, 2, 3, 4, 5)\nval data: List[Int] = List(1, 2, 3, 4, 5)\n\nscala\u003e def double(x: Int): Int = x * 2\ndef double(x: Int): Int\n\nscala\u003e data.map(double)\nval res0: List[Int] = List(2, 4, 6, 8, 10)\n\nscala\u003e data.map(_ * 2) // using anonymous functions\nval res1: List[Int] = List(2, 4, 6, 8, 10)\n\nscala\u003e data\nval res2: List[Int] = List(1, 2, 3, 4, 5)\n```\n\nIn the example above it applies the `double` function to each element of the list and returns a new list object (as you can see in the last line, the original data was not modified).\n\nCombining currying with map:\n\n```scala\nscala\u003e val data: List[Int] = List(1, 2, 3, 4, 5)\nval data: List[Int] = List(1, 2, 3, 4, 5)\n\nscala\u003e def add(x: Int)(y: Int): Int = x + y\ndef add(x: Int)(y: Int): Int\n\nscala\u003e data.map(add(3))\nval res0: List[Int] = List(4, 5, 6, 7, 8)\n```\n\n### Filter\n\nThe `.filter()` function basically applies a function that returns a boolean, and is passed as argument, to each value of a sequence of values, for example:\n\n```scala\nscala\u003e val data: List[Int] = List(1, 2, 3, 4, 5)\nval data: List[Int] = List(1, 2, 3, 4, 5)\n\nscala\u003e data.filter(_ \u003e 3)\nval res0: List[Int] = List(4, 5)\n```\n\nAs you can see the final result is a new list containing the objects that had a `true` assert when passing by the filter function (in this case, only values higher than 3).\n\n### Reduce\n\nThe `.reduce()` function basically applies a function to each value and keeps an \"accumulator\" so it is used to reduce multiple values to a single one, for example:\n\n```scala\nscala\u003e val data: List[Int] = List(1, 2, 3, 4, 5)\nval data: List[Int] = List(1, 2, 3, 4, 5)\n\nscala\u003e def sum(acc: Int, value: Int): Int = {\n     |   println(s\"acc: $acc, value: $value\")\n     |   acc + value\n     | }\ndef sum(acc: Int, value: Int): Int\n\nscala\u003e data.reduce(sum)\nacc: 1, value: 2\nacc: 3, value: 3\nacc: 6, value: 4\nacc: 10, value: 5\nval res0: Int = 15\n\nscala\u003e data.reduce(_ + _)\nval res1: Int = 15\n```\n\n### Mixing them all\n\n```scala\nscala\u003e val data: List[Int] = List(1, 2, 3, 4, 5)\nval data: List[Int] = List(1, 2, 3, 4, 5)\n\nscala\u003e data.map(_ * 2).filter(_ \u003e 5).reduce(_ + _)\nval res0: Int = 24\n```\n\n### Key Points\n\n- Map, filter and reduce are always applied to every single value of a sequence.\n- Map, filter and reduce are not hard to understand and can make your life much easier.\n- Map, filter and reduce are used everywhere in functional programming.\n\n## Recursion\n\nRecursion is a well known topic in computer science but it is not broadly used in object-oriented programming. On the other hand, in functional programming you can't just write a loop to update a value, which is immutable, but you can use a recursive function to simulate the same behavior.\n\nScala already provides several built-in functions to perform operations on data structures, for example to sum all values in a sequence:\n\n```scala\nscala\u003e val data: Seq[Int] = Seq(1, 2, 3, 4)\nval data: Seq[Int] = List(1, 2, 3, 4)\n\nscala\u003e data.sum\nval res0: Int = 10\n```\n\nBut if you need to do something specific, which doesn't have any built-in function provided, you can write your own recursive function, for example:\n\n```scala\nscala\u003e def sum(data: Seq[Int]): Int = data match {\n     |   case Nil =\u003e 0\n     |   case head :: tail =\u003e head + sum(tail)\n     | }\ndef sum(data: Seq[Int]): Int\n\nscala\u003e val data: Seq[Int] = Seq(1, 2, 3, 4)\nval data: Seq[Int] = List(1, 2, 3, 4)\n\nscala\u003e sum(data)\nval res0: Int = 10\n```\n\n## Tail Recursion\n\n[This](https://stackoverflow.com/a/33930/4946821) great StackOverflow answer explains that in traditional recursion, the typical model is that you perform your recursive calls first, and then you take the return value of the recursive call and calculate the result. In this manner, you don't get the result of your calculation until you have returned from every recursive call.\n\nIn tail recursion, you perform your calculations first, and then you execute the recursive call, passing the results of your current step to the next recursive step. Basically, the return value of any given recursive step is the same as the return value of the next recursive call.\n\nThe consequence of this is that once you are ready to perform your next recursive step, you don't need the current stack frame anymore. This allows for some optimization. It will simply reuse the current stack frame for the next recursive step\n\nThe following example shows a function that, at first glance, looks like a tail recursive function but it is not because the last action multiplies a value of the current step with the recursive call:\n\n```scala\nscala\u003e def factorial(n: Int): Int = {\n     |   if (n \u003c= 1) 1\n     |   else n * factorial(n - 1)\n     | }\ndef factorial(n: Int): Int\n\nscala\u003e factorial(5)\nval res0: Int = 120\n```\n\nNow, the following exaple calculates the Greatest Common Divisor (GCD) using the tail recursion technique:\n\n```scala\nscala\u003e def gcd(a: Int, b: Int): Int = {\n     |   if (b == 0) a\n     |   else gcd(b, a % b)\n     | }\ndef gcd(a: Int, b: Int): Int\n\nscala\u003e gcd(21, 14)\nval res0: Int = 7\n```\n\nScala has an annotation called `tailrec` that helps in identifying functions that uses tail recursion, for example:\n\n```scala\nscala\u003e import scala.annotation.tailrec\nimport scala.annotation.tailrec\n\nscala\u003e @tailrec\n     | def gcd(a: Int, b: Int): Int = {\n     |   if (b == 0) a\n     |   else gcd(b, a % b)\n     | }\ndef gcd(a: Int, b: Int): Int\n\nscala\u003e gcd(21, 14)\nval res0: Int = 7\n```\n\nIf the `tailrec` is used in a function that does not implement the tail recursion it will raise an error:\n\n```scala\nscala\u003e import scala.annotation.tailrec\nimport scala.annotation.tailrec\n\nscala\u003e @tailrec\n     | def factorial(n: Int): Int = {\n     |   if (n \u003c= 1) 1\n     |   else n * factorial(n - 1)\n     | }\n         else n * factorial(n - 1)\n                ^\nOn line 4: error: could not optimize @tailrec annotated method factorial: it contains a recursive call not in tail position\n```\n\n:warning: `tailrec` is just a check for the programmer to verify if the function will in fact be optimized. If the function already implement the tail recurssion (without `tailrec`) it will be automatically optimized in compilation time.\n\n## Companion Objects\n\nThe _companion object_ concept is not exactly related to functional programming but is broadly used in Scala code.\n\nA companion object in Scala is an `object` that is declared in the same file as a `class`, and has the same name as the class, for example:\n\n```scala\nclass Settings {\n  def showPath() = println(Settings.path)\n}\n\nobject Settings {\n  private val path = \"tmp/settings.json\"\n}\n```\n\nAnd it is possible to use it as follows:\n\n```scala\nscala\u003e new Settings().showPath()\ntmp/settings.json\n```\n\nBesides that, companion objects have several benefits like:\n- Companion objects can access each other's private members.\n- Create new instances of a class without using the `new` keyword.\n- Create multiple \"constructors\" (actually factory methods) for a class.\n- Allows the creation of an `unapply` method.\n- Allows the creation of functions that acts like \"static methods\".\n\nMore details about companion objects can be found in the [Scala Book page](https://docs.scala-lang.org/overviews/scala-book/companion-objects.html).\n\n## Substitution Model\n\nScala uses the principle of substitution model to evaluate expressions. The idea is that all evaluation reduce an expression to a value so, for example, variable names are replaced by the values they are bound to. The expressions are evaluated in the same way we would evaluate a mathematical expression, for example:\n\n```scala\nscala\u003e def x = 5\nscala\u003e def y = 10\nscala\u003e (3 * x) + (2 * y)\n```\n\n```\n-\u003e (3 * 5) + (2 * y)\n-\u003e 15 + (2 * 10)\n-\u003e 15 + 20\n-\u003e 35\n```\n\nFunctions are evaluated in the same way as expressions, for example:\n\n```scala\nscala\u003e def square(x: Double) = x * x\nscala\u003e square(2 + 3)\n```\n\n```\n-\u003e square(5)\n-\u003e 5 * 5\n-\u003e 25\n```\n\nBut in function evaluation there are two strategies called `call-by-name` and `call-by-value`. Here is an example of how both work:\n\n```scala\nscala\u003e def square(x: Double) = x * x\nscala\u003e def sumOfSquares(x: Int, y: Int) = square(x) + square(y)\n```\n\n- `call-by-value`: evaluates every function argument only once thus it avoids the repeated evaluation of arguments.\n\n```\n-\u003e sumOfSquares(2, 2 + 3)\n-\u003e sumOfSquares(2, 5)\n-\u003e square(2) + square(5)\n-\u003e 2 * 2 + 5 * 5\n-\u003e 4 + 25\n-\u003e 29\n```\n\n- `call-by-name`: avoids evaluation of parameters if it is not used in the function body.\n\n```\n-\u003e sumOfSquares(2, 2 + 3)\n-\u003e square(2) + square(2 + 3)\n-\u003e 2 * 2 + square(2 + 3)\n-\u003e 4 + (2 + 3) * (2 + 3)\n-\u003e 4 + 5 * (2 + 3)\n-\u003e 4 + 5 * 5\n-\u003e 4 + 25\n-\u003e 29\n```\n\nAs you can see, `call-by-value` is more efficient then `call-by-name` so Scala uses `call-by-value` as the default evaluation strategy, however you can force it to use the `call-by-name` strategy using the follwing syntax `=\u003e`, for example:\n\n```scala\nscala\u003e def loop: Int = loop\nscala\u003e def test(x: Int, y: =\u003e Int) = x\nscala\u003e test(1, loop) // infinite loop\n```\n\nThe above example uses `call-by-value` and enter the infinite loop.\n\nNow the same example using `call-by-name`:\n\n```scala\nscala\u003e def loop: Int = loop\nscala\u003e def test(x: Int, y: =\u003e Int) = x\nscala\u003e test(1, loop)\nval res0: Int = 1\n```\n\nAs you can see it evaluates only the `x` value which is being used inside the function and returns it.\n\nMore details about Scala substitution model can be found in [this article](http://bkpathak.github.io/scala-substitution-model#:~:text=Scala%20model%20of%20expression%20evaluation,does%20not%20need%20further%20evaluation.).\n\n### Key Points\n\n- Scala uses the `call-by-value` strategy by default.\n- It is important to understand the difference between `call-by-name` and `call-by-value` but in most cases you don't need to worry about it.\n\n## Where to go next\n\nIf you are completely new to Scala, I really recommend the [Scala Book](https://alvinalexander.com/scala/scala-book-free/), it is a relatively short book and covers the most important topics related to the language.\n\nAnother great source of knowledge for beginners is the Udemy course \"[Scala at Light Speed](https://www.udemy.com/course/fast-scala/)\", which is a quick course (~2h) that will give you an overview about the language and its syntax.\n\nLast but not least, [Functional Programming: Simplified](https://www.amazon.com.br/dp/B076J7CJKY/ref=dp-kindle-redirect?_encoding=UTF8\u0026btkr=1) is another excellent book that covers many topics related to functional programming with examples in Scala.\n\n## References\n\n- [So You Want to be a Functional Programmer](https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-1-1f15e387e536) (Charles Scalfani)\n- [Scala Book](https://alvinalexander.com/scala/scala-book-free/) (Alvin Alexander, et al.)\n- [Scala Documentation](https://docs.scala-lang.org/)\n- [Anonymous Functions](https://en.wikipedia.org/wiki/Anonymous_function)\n- [Scala Substitution Model](http://bkpathak.github.io/scala-substitution-model#:~:text=Scala%20model%20of%20expression%20evaluation,does%20not%20need%20further%20evaluation.) (Bijay Pathak)\n- [Scala at Light Speed](https://www.udemy.com/course/fast-scala/) (Rock the JVM)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkelvins%2Ffunctional-programming-in-scala","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkelvins%2Ffunctional-programming-in-scala","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkelvins%2Ffunctional-programming-in-scala/lists"}