Lesson notes
Thinking about functions
- You can think of functions as black boxes: a box takes a thing, does something, then spits some other thing out
- Some functions don't take anything (don't accept arguments), some don't do anything (their bodies are empty), some don't return any values.
- Our surfaceAreaCalculator takes one argument (radius), calculates the surface area and returns the result of that calculation.
- Functions can call other functions
- surfaceAreaCalculator can call the square function to get radius squared instead of manually multiplying radius by radius
- We create functions to make our lives easier:
- the code is easier to understand
- functions can be reused many times
Two functions together:
Functions calling themselves
- Functions can call themselves
-
Function definitions are descriptions of the boxes
- A real box is created when function is called
- If a function calls itself, a new identical box is created
- Number of ways to arrange n objects is n! (permutations)
- n! is defined like so: if n = 1, then n! = 1; if n > 0, then n! = n * (n-1)!
Recursion requirements
- A simple base case or a terminating scenario. When to stop, basically. In our example it was 1: we stop factorial calculation when we get to 1.
- A rule to move along the recursion, to go deeper. In our case, it was n * factorial(n-1).
Waiting for the multiplications
Nothing gets multiplied until we go all the way down, to the base case of factorial(1). Then we start going back up, one step at a time.
factorial(3);
3 * factorial(2);
3 * 2 * factorial(1);
3 * 2 * 1;
3 * 2;
6;
Sidenote
Note that 0! is 1, and the proper base case for n! is 0! In this lesson we omitted this case to make one less call and one less box to think about, since 1 * 1 is 1 anyway.
Just for fun
- There is a common joke among programmers: "In order to understand recursion, you have to understand recursion". Google seems to love this kind of joke. Try googling "recursion" and check out the suggestion at the top of the results page ;-)
- In order to understand recursion you must first understand recursion.
Recommended watching
Optional reading
Optional watching
Lesson transcript
We have a function surfaceAreaCalculator that accepts one argument — a radius — and returns a surface area of a corresponding sphere using a formula 4 * pi * r^2. Remember, we can think about functions as boxes: put a thing in the box, the box does something and spits out the result.
Some boxes don't accept anything, some — don't spit out anything, and some don't even do anything, but for now we're interested in boxes like surfaceAreaCalculator — accept something, calculate something, return the result.
We built this function in order to simplify our work. We have to calculate surface areas of different planets, and having this handy function means we don't have to remember and write down the formula over and over again.
Another reason is that now code is easier to understand. Compare this:
to this:
First one is much nicer and simpler, especially to someone who is new to this code. First one answers the "what" question, the second one answers the "how" question.
We can improve on this and make another function to calculate squares. Let's first take a look at how we might use it:
Instead of multiplying radius by radius, we call a square function and pass the radius. Obviously, the square function is nothing but "accept a number, return its square":
Let's trace the steps and see what happens when we run our program. We create a constant surfaceOfMars and tell it to store whatever value surfaceAreaCalculator function returns when it's called with 3390 as an argument.
3390 is known as radius inside the function. The function wants to multiply numbers and return, but it needs to know the last number, it has to call the square function and pass it the radius. square accepts one argument — it's the number 3390, in this case, and inside the square function it is known as n.
square wants to multiply n by n and return. Nothing stops it, so it does. We are back inside the surfaceAreaCalculator — it was literally waiting for the square function to finish. And now we have the result of calling square. It substitutes the call, so now it's possible to finish the multiplication and return.
The answer is returned and stored in the surfaceOfMars.
So, functions can call other functions. And a function doesn't know and doesn't care if it was called from inside another function. Maybe it was called from inside a function from inside another function from inside yet another function! It doesn't really matter as long as the computation comes back and finishes.
Let's try something else with functions calling functions. Say, you have three books on your shelf, and you want to know how many different ways to arrange them exists.
It turns out there are six ways to arrange 3 books. Four books — 24 ways. 13 books — almost as many ways as people on the planet. 25 books? More ways to arrange them than atoms in the universe.
In general, there are n! ways to arrange n books. Factorial means multiply all the numbers from 1 to n. So, 3! is 1 * 2 * 3. Let's write a factorial function:
Oh wait. We don't know what n is, that's the point. Hmm... How do they do it in math?
Oh, okay, so, they have two options: if n is 1, then factorial is 1, this is simple. But if n is not 1, then factorial is n * (n-1)!
Let's try this:
This might seem weird. We are calling a function from this function, but... it's the same function!
Is there something wrong? No, not really! The thing is, a function itself is not a box, it's a description of the box. When you call a function a box is created, and after it's done working it's destroyed. So, if you call the same function from itself, there's just another box created.
Let's trace it: we call factorial(3). 3 is not 1, so first condition is ignored. The function wants to multiply numbers and return the answer, but it can't — it needs to know the second number, so it calls factorial(3-1) or factorial(2).
A new identical factorial box is created, it accepts number 2, it's not 1, so it tries to multiply and return, but it can't — it needs to know the second number, so it calls factorial(1).
A new identical factorial box is created, it accepts number 1, and this box can return immediately — it returns 1.
1 comes back to the previous box, gets multiplied by 2 and the answer — 2 returns to the previous box, gets multiplied by 3 and the answer — 6 returns to the outside world and stored in the answer constant.
Phew!
This is called recursion: when something is described in terms of itself. When it comes to math or programming, recursion requires two things:
- A simple base case or a terminating scenario. When to stop, basically. In our example it was 1: we stop factorial calculation when we get to 1.
- A rule to move along the recursion, to go deeper. In our case, that was n * factorial(n-1).
Let's trace the steps once more, but from a different point of view. This is what happens step by step:
factorial(3);
3 * factorial(2);
3 * 2 * factorial(1);
3 * 2 * 1;
3 * 2;
6;
Nothing gets multiplied until we go all the way down, to the base case of factorial(1). And then we start going back up, one step at a time, one multiplication at a time.
Recursion is used widely, especially in functional programming — one of the styles of programming. And not only for math calculations, for all sorts of things! You'll see recursion all the time in this course and next ones, because it's extremely powerful and, I have to say, it's really cool.
It's your turn. Continue to the quiz and the exercise, and create your own recursive function. It might be a bit tricky, just remember: you need to describe two things — when to stop and how to go deeper. Good luck!
<!DOCTYPE html>
<html class="h-100" data-bs-theme="light" data-mantine-color-scheme="light" lang="en" prefix="og: https://ogp.me/ns#">
<head>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<link crossorigin="true" href="https://cdn.hexlet.io" rel="preconnect">
<meta content="aa2vrdtq64dub8knuf83lwywit311w" name="facebook-domain-verification">
<link href="/favicon.ico" rel="icon" sizes="any">
<link href="/favicon.svg" rel="icon" type="image/svg+xml">
<link href="/apple-touch-icon.png" rel="apple-touch-icon">
<link href="/manifest.webmanifest" rel="manifest">
<script>
//<![CDATA[
window.gon={};gon.ym_counter="25559621";gon.is_bot=true;gon.applications={};gon.current_user={"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false};gon.token="3kzV7hEHQ7Ksf1HsXT2VNpmSKv78DAPl38VRD6nr0EiNirjYMGx4Ust1rgTvo6L3lTikpTASGel9QJsc5DcPkw";gon.locale="en";gon.language="en";gon.theme="light";gon.rails_env="production";gon.mobile=false;gon.google={"analytics_key":"UA-1360700-51","optimize_key":"GTM-5QDVFPF"};gon.captcha={"google_v3_site_key":"6LenGbgZAAAAAM7HbrDbn5JlizCSzPcS767c9vaY","yandex_site_key":"ysc1_Vyob5ZPPUdPBsu0ykt8bVFdzsfpoVjQChLGl2b4g19647a89","verification_failed":null};gon.social_signin=false;gon.typoreporter_google_form_id="1FAIpQLScNwxM8rjQRRWqW5G6dn6-0NvLUblFemy7EvA9VsJ7Ov5wXqA";
//]]>
</script>
<meta charset="utf-8">
<title>Recursion: when a function calls itself | Programming fundamentals</title>
<meta name="description" content="Recursion: when a function calls itself / Programming fundamentals: Wrap your head around one very powerful and extremely important concept in programming — recursion.">
<link rel="canonical" href="https://hexlet.io/courses/intro_to_programming/lessons/recursion/theory_unit">
<meta name="robots" content="noarchive">
<meta property="og:title" content="Recursion: when a function calls itself">
<meta property="og:title" content="Programming fundamentals">
<meta property="og:description" content="Recursion: when a function calls itself / Programming fundamentals: Wrap your head around one very powerful and extremely important concept in programming — recursion.">
<meta property="og:url" content="https://hexlet.io/courses/intro_to_programming/lessons/recursion/theory_unit">
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="sHSF1wvInou_YcXlIDdME1-xZQyO12q373Gw7u9r2QDjsujhKqOla9hrOg2SqXvSUxvrV0LJcLtN9Hr9orcG2w" />
<script src="/vite/assets/inertia-CgrHVkgd.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/preload-helper-C1cfMHAs.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-0bhwJkNI.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ahoy-BXKrsWjp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/analytics-Du9ljYPK.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-V3hfk_CP.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/RootLayout-CUZzAr0T.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Surface-DbDKujDz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-B-jV56Ol.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-DOJkeu70.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-ClTF9s_T.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-mvvEXZQ8.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/index.esm-DATLpQdV.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Modal-BhY0AP_c.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Textarea-P1s4q94S.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/exports-BsSGGK2I.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-Bfba02I7.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-CYyKzrjQ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-SJZekO2j.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-bo78L81P.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-BhqaZ6vG.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-DlXMvSuQ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CFtMU8gd.js" as="script" crossorigin="anonymous">
<link rel="stylesheet" href="/vite/assets/application-BhDYOUva.css" />
<script src="/vite/assets/application-ZyVHkzwO.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/autocomplete-BokUl44d.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-mvvEXZQ8.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/createPopper-gQnwoPhY.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/js.cookie-CB1F2-VC.js" as="script" crossorigin="anonymous"><link rel="stylesheet" href="/vite/assets/application-BhDYOUva.css" media="screen" />
<!-- Google Tag Manager - deferred -->
<script>
// dataLayer stub сразу — пуши работают до загрузки скрипта
window.dataLayer = window.dataLayer || [];
// Сам скрипт — отложенно после load
window.addEventListener('load', function() {
setTimeout(function() {
dataLayer.push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
var j = document.createElement('script');
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=GTM-WK88TH';
document.head.appendChild(j);
}, 1500);
});
</script>
<!-- End Google Tag Manager -->
</head>
<body>
<!-- Google Tag Manager (noscript) -->
<noscript>
<iframe height="0" src="https://www.googletagmanager.com/ns.html?id=GTM-WK88TH" style="display:none;visibility:hidden" width="0"></iframe>
</noscript>
<!-- End Google Tag Manager (noscript) -->
<header class="sticky-top bg-body">
<nav class="navbar navbar-expand-lg">
<div class="container-xxl">
<a class="navbar-brand" href="/"><img alt="Hexlet logo" height="24" src="https://hexlet.io/vite/assets/logo_en_light-FS-yL6XB.svg" width="96">
</a><button aria-controls="collapsable" aria-expanded="false" aria-label="Menu" class="navbar-toggler border-0 mb-0 mt-1" data-bs-target="#collapsable" data-bs-toggle="collapse">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsable">
<ul class="navbar-nav mb-lg-0 mt-lg-1">
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
All courses
<span class="bi bi-chevron-down align-middle ms-1"></span>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item d-flex py-2" href="/courses"><div class="fw-bold me-auto">Everything</div>
<div class="text-muted">8</div>
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Popular categories</b>
</li>
<li>
<a class="dropdown-item py-2" href="/courses_backend-development">Backend Development
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_devops">DevOps
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_frontend-development">Frontend Development
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_testing">Testing
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Popular courses</b>
</li>
<li>
<a class="dropdown-item py-2" href="/programs/frontend">Frontend Developer
</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
About Hexlet
<span class="bi bi-chevron-down align-middle"></span>
</button>
<ul class="dropdown-menu bg-body">
<li>
<a class="dropdown-item py-2" href="/pages/about">About company
</a></li>
<li>
<a class="dropdown-item py-2" href="/blog">Blog
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/hse-research" role="button"><span class="translation_missing" title="translation missing: en.layouts.header.results">Results</span>
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://career.hexlet.io" role="button"><span class="translation_missing" title="translation missing: en.layouts.header.career">Career</span>
</span></li>
<li>
<a class="dropdown-item py-2" href="/testimonials">Testimonials
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://t.me/hexlet_help_bot" role="button"><span class="translation_missing" title="translation missing: en.layouts.header.support">Support</span>
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/referal-program/?promo_creative=priglasite-druzei&promo_name=referal-program&promo_position=promo_position&promo_start=010724&promo_type=link" role="button"><span class="translation_missing" title="translation missing: en.layouts.header.referal_program">Referal Program</span>
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/certificate" role="button"><span class="translation_missing" title="translation missing: en.layouts.header.certificates">Certificates</span>
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://hh.ru/employer/4307094" role="button"><span class="translation_missing" title="translation missing: en.layouts.header.vacancies">Vacancies</span>
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://b2b.hexlet.io" data-target="_blank" role="button"><span class="translation_missing" title="translation missing: en.layouts.header.teams">Teams</span>
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexly.ru/" data-target="_blank" role="button"><span class="translation_missing" title="translation missing: en.layouts.header.college">College</span>
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexlyschool.ru/" data-target="_blank" role="button"><span class="translation_missing" title="translation missing: en.layouts.header.private_school">Private School</span>
</span></li>
</ul>
</li>
</ul>
<ul class="navbar-nav flex-lg-row align-items-lg-center gap-2 ms-auto">
<li>
<a class="nav-link" aria-label="Switch theme" href="/theme/switch?new_theme=dark"><span aria-hidden="true" class="bi bi-moon"></span>
</a></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="/u/new" role="button"><span>Sign up</span>
</span></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="https://hexlet.io/session/new" role="button"><span>Sign in</span>
</span></li>
</ul>
</div>
</div>
</nav>
</header>
<div class="x-container-xxxl">
</div>
<main class="mb-6 min-vh-100 h-100">
<div id="app" data-page="{"component":"web/courses/lessons/theory_unit","props":{"errors":{},"locale":"en","language":"en","httpsHost":"https://hexlet.io","host":"hexlet.io","colorScheme":"light","auth":{"user":{"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false}},"cloudflareTurnstileSiteKey":"0x4AAAAAAA15KmeFXzd2H0Xo","vkIdClientId":"51586979","yandexIdClientId":null,"formAuthToken":"R0VyMJU4iFV_qMt9aekc2ZzHE8aqUYjBza_1HusSRVcUgx8GtFOztRiiNJXbdysYkG2dnWZPks1vKj8Nps6ajA","topics":[{"id":20437,"title":"Thank you for this course. I am slowly jamming all this information in my brain and it is slowly latching into empty pockets in my head. This is at least how I have felt in the last few weeks. The resources and videos on recursion are great. I feel like I understand the concept. And it seems \"math\" centric to use recursion to aid in a solution. Would you happen to have a real-world example of using recursion that would help someone like me who appreciates math when calculating a tip on a receipt but has not memorized the Fibonacci sequence by heart?","plain_title":"Thank you for this course. I am slowly jamming all this information in my brain and it is slowly latching into empty pockets in my head. This is at least how I have felt in the last few weeks. The resources and videos on recursion are great. I feel like I understand the concept. And it seems \"math\" centric to use recursion to aid in a solution. Would you happen to have a real-world example of using recursion that would help someone like me who appreciates math when calculating a tip on a receipt but has not memorized the Fibonacci sequence by heart? ","creator":{"public_name":"Adam Abundis","id":192365,"is_tutor":false},"comments":[{"creator":{"public_name":"Robert Kuznetsov","id":138381,"is_tutor":false},"id":102779,"body":"Your question is really interesting :)","topic_id":20437}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Recursion: when a function calls itself","entity_url":null,"active":true}},{"id":8505,"title":"Hi! \nThank you for such awesome lessons!\nThis task is very tough, however.\nEven after looking at the teacher's solution I didn't understand the last part, namely, why we need 'end' in it? \n\n**return** begin + sequenceSum(begin + 1, end); \n\nI don't see how it's used in the function: we don't use it for addition.\nCould you please explain? Thank you!","plain_title":"Hi! Thank you for such awesome lessons! This task is very tough, however. Even after looking at the teacher's solution I didn't understand the last part, namely, why we need 'end' in it? return begin + sequenceSum(begin + 1, end); I don't see how it's used in the function: we don't use it for addition. Could you please explain? Thank you! ","creator":{"public_name":"anna cole","id":138325,"is_tutor":false},"comments":[{"creator":{"public_name":"Анна Л.","id":101744,"is_tutor":false},"id":16763,"body":"Thank you! It helps a lot.\nI had this terminating concept at the back of my mind but simply didn't know how to put it in the code. \nNow I understand that it should be a part of the function, after a comma and in the brackets.\n\nThanks for the hard work building this learning platform, guys!","topic_id":8505},{"creator":{"public_name":"anna cole","id":138325,"is_tutor":false},"id":16788,"body":"Thank you! It helps a lot. I had this terminating concept at the back of my mind but simply didn't know how to put it in the code. Now I understand that it should be a part of the function, after a comma and in the brackets.\n\nThanks for the hard work building this learning platform, guys!","topic_id":8505},{"creator":{"public_name":"R. D.","id":3,"is_tutor":false},"id":16708,"body":"Hey Anna,\n\nglad you liked it!\n\nRemember the concept of a terminating scenario from the video lesson? Basically, it's a condition of when to end recursion. Without such condition, the recursion will be endless, infinite. The function will never stop calling itself and eventually, the program will run out of memory and crash.\n\nEven though `end` isn't used in any additions or calculations, it **is** used for the terminating condition: check out line 6 of the solution. It says: when the recursive process hits this point (i.e. when `begin` equals `end`), the program returns `begin` instead of making a recursive call. This will be the end of the series of the recursive calls.\n\nAnd while `begin` does not equal `end` (see line 9), the recursive call is made. And this new call is made with `begin + 1`. So, every new recursive step we increase the value of `begin` and pass it along, until we hit the point where `begin` is finally as big as `end`.\n\nDoes it make things clearer?","topic_id":8505}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Recursion: when a function calls itself","entity_url":null,"active":true}}],"lesson":{"exercise":{"id":1703,"slug":"intro_to_programming_recursive_process_exercise","name":null,"state":"active","kind":"exercise","language":"javascript","locale":"en","has_web_view":false,"has_test_view":false,"reviewable":true,"readme":"## sequenceSum.js\n\nUse recursion (and recursive process) to implement the `sequenceSum()` function, which calculates the sum of a sequence of integer numbers.\n\nThe sequence is described by two things:\n\n* `begin` - start of the sequence (first number in the sequence);\n* `end` - end of the sequence (upper limit)\n\nFor example: `begin = 2`, `end = 6` represents the following sequence: `2, 3, 4, 5, 6`.\n\nThe sum of such sequence is `20`.\n\n```javascript\nsequenceSum(2, 6); // 2 + 3 + 4 + 5 + 6 = 20\nsequenceSum(1, 5); // 1 + 2 + 3 + 4 + 5 = 15\nsequenceSum(-3, 2); // (-3) + (-2) + (-1) + 0 + 1 + 2 = -3\nsequenceSum(2, 1); // NaN, because begin is larger than end\n```\n\nYou can take a look inside `__tests__/sequenceSum.test.js` to find out all the possible arguments that we use to test your function.\n\n### Hints\n\n* If `begin > end`, then the sequence consists of no numbers, therefore it's empty. The function should return NaN since it's impossible to find a sum of an empty sequence.\n* The sum of a sequence where `begin === end` is equals to `begin`.\n","prepared_readme":"## sequenceSum.js\n\nUse recursion (and recursive process) to implement the `sequenceSum()` function, which calculates the sum of a sequence of integer numbers.\n\nThe sequence is described by two things:\n\n* `begin` - start of the sequence (first number in the sequence);\n* `end` - end of the sequence (upper limit)\n\nFor example: `begin = 2`, `end = 6` represents the following sequence: `2, 3, 4, 5, 6`.\n\nThe sum of such sequence is `20`.\n\n```javascript\nsequenceSum(2, 6); // 2 + 3 + 4 + 5 + 6 = 20\nsequenceSum(1, 5); // 1 + 2 + 3 + 4 + 5 = 15\nsequenceSum(-3, 2); // (-3) + (-2) + (-1) + 0 + 1 + 2 = -3\nsequenceSum(2, 1); // NaN, because begin is larger than end\n```\n\nYou can take a look inside `__tests__/sequenceSum.test.js` to find out all the possible arguments that we use to test your function.\n\n### Hints\n\n* If `begin > end`, then the sequence consists of no numbers, therefore it's empty. The function should return NaN since it's impossible to find a sum of an empty sequence.\n* The sum of a sequence where `begin === end` is equals to `begin`.\n","has_solution":true,"entity_name":"Recursion: when a function calls itself"},"units":[{"id":1711,"name":"theory","url":"/courses/intro_to_programming/lessons/recursion/theory_unit"},{"id":4670,"name":"quiz","url":"/courses/intro_to_programming/lessons/recursion/quiz_unit"},{"id":5986,"name":"exercise","url":"/courses/intro_to_programming/lessons/recursion/exercise_unit"}],"links":[],"ordered_units":[{"id":1711,"name":"theory","url":"/courses/intro_to_programming/lessons/recursion/theory_unit"},{"id":4670,"name":"quiz","url":"/courses/intro_to_programming/lessons/recursion/quiz_unit"},{"id":5986,"name":"exercise","url":"/courses/intro_to_programming/lessons/recursion/exercise_unit"}],"id":838,"slug":"recursion","state":"approved","name":"Recursion: when a function calls itself","course_order":180,"goal":"Wrap your head around one very powerful and extremely important concept in programming — recursion.","self_study":null,"theory_video_provider":"youtube","theory_video_uid":"vLhHyGTkjCs","theory":"## Lesson notes\n\n### Thinking about functions\n\n- You can think of functions as black boxes: a box takes a thing, does something, then spits some other thing out\n - Some functions don't take anything (don't accept arguments), some don't do anything (their bodies are empty), some don't return any values.\n - Our `surfaceAreaCalculator` takes one argument (radius), calculates the surface area and returns the result of that calculation.\n- Functions can call other functions\n- `surfaceAreaCalculator` can call the `square` function to get radius squared instead of manually multiplying radius by radius\n- We create functions to make our lives easier: \n - the code is easier to understand\n - functions can be reused many times\n\n```javascript\nconst surfaceOfMars = surfaceAreaCalculator(3390); // this is WHAT, it's easier to understand\nconst surfaceOfMars = 4 * 3.14 * 3390 * 3390; // this is HOW\n```\n\nTwo functions together:\n\n```javascript\nconst surfaceAreaCalculator = (radius) => {\n return 4 * 3.14 * square(radius);\n}\n\nconst square = (num) => {\n return num * num;\n}\n```\n\n### Functions calling themselves\n\n- Functions can call themselves\n - **Function definitions** are descriptions of the boxes\n - A real box is created when **function is called**\n - If a function calls itself, a new identical box is created\n- Number of ways to arrange n objects is n! ([permutations](https://en.wikipedia.org/wiki/Permutation))\n- n! is defined like so: if n = 1, then **n! = 1**; if n > 0, then **n! = n * (n-1)!**\n\n```javascript\nconst factorial = (n) => {\n if (n === 1) {\n return 1;\n }\n else {\n return n * factorial(n-1);\n }\n}\n\nconst answer = factorial(3);\n```\n\n### Recursion requirements\n\n1. A simple base case or a terminating scenario. When to stop, basically. In our example it was 1: we stop factorial calculation when we get to 1.\n2. A rule to move along the recursion, to go deeper. In our case, it was `n * factorial(n-1)`.\n\n### Waiting for the multiplications\n\nNothing gets multiplied until we go all the way down, to the base case of `factorial(1)`. Then we start going back up, one step at a time.\n\n```\nfactorial(3);\n3 * factorial(2);\n3 * 2 * factorial(1);\n3 * 2 * 1;\n3 * 2;\n6;\n```\n\n### Sidenote\n\nNote that 0! is 1, and the proper base case for n! is 0! In this lesson we omitted this case to make one less call and one less box to think about, since 1 * 1 is 1 anyway.\n\n### Just for fun\n\n1. There is a common joke among programmers: \"*In order to understand recursion, you have to understand recursion*\". Google seems to love this kind of joke. Try googling \"recursion\" and check out the suggestion at the top of the results page ;-)\n2. In order to understand recursion you must first understand recursion.\n\n## Recommended watching\n\n- [What on Earth is Recursion? - Computerphile](https://www.youtube.com/watch?v=Mv9NEXX1VHc)\n- [Recursion (Part 7 of Functional Programming in JavaScript) from Fun Fun Function](https://www.youtube.com/watch?v=k7-N8R0-KY4)\n\n## Optional reading\n\n- [Properties of recursive algorithms](https://www.khanacademy.org/computing/computer-science/algorithms/recursive-algorithms/a/properties-of-recursive-algorithms)\n\n## Optional watching\n\n- [Fibonacci Programming - Computerphile](https://www.youtube.com/watch?v=7t_pTlH9HwA)\n\n## Lesson transcript\n\nWe have a function `surfaceAreaCalculator` that accepts one argument — a radius — and returns a surface area of a corresponding sphere using a formula 4 * pi * r^2. Remember, we can think about functions as boxes: put a thing in the box, the box does something and spits out the result.\n\nSome boxes don't accept anything, some — don't spit out anything, and some don't even do anything, but for now we're interested in boxes like `surfaceAreaCalculator` — accept something, calculate something, return the result.\n\nWe built this function in order to simplify our work. We have to calculate surface areas of different planets, and having this handy function means we don't have to remember and write down the formula over and over again.\n\nAnother reason is that now code is easier to understand. Compare this:\n\n```javascript\nconst surfaceOfMars = surfaceAreaCalculator(3390);\n```\n\nto this:\n\n```javascript\nconst surfaceOfMars = 4 * 3.14 * 3390 * 3390;\n```\n\nFirst one is much nicer and simpler, especially to someone who is new to this code. First one answers the \"what\" question, the second one answers the \"how\" question.\n\nWe can improve on this and make another function to calculate squares. Let's first take a look at how we might use it:\n\n```javascript\nconst surfaceAreaCalculator = (radius) => {\n return 4 * 3.14 * square(radius);\n}\n```\n\nInstead of multiplying radius by radius, we call a square function and pass the radius. Obviously, the square function is nothing but \"accept a number, return its square\":\n\n```javascript\nconst square = (num) => {\n return num * num;\n}\n```\n\nLet's trace the steps and see what happens when we run our program. We create a constant `surfaceOfMars` and tell it to store whatever value `surfaceAreaCalculator` function returns when it's called with 3390 as an argument.\n\n3390 is known as `radius` inside the function. The function wants to multiply numbers and return, but it needs to know the last number, it has to call the `square` function and pass it the radius. `square` accepts one argument — it's the number 3390, in this case, and inside the `square` function it is known as `n`.\n\n`square` wants to multiply `n` by `n` and return. Nothing stops it, so it does. We are back inside the `surfaceAreaCalculator` — it was literally waiting for the `square function` to finish. And now we have the result of calling `square`. It substitutes the call, so now it's possible to finish the multiplication and return.\n\nThe answer is returned and stored in the `surfaceOfMars`.\n\nSo, functions can call other functions. And a function doesn't know and doesn't care if it was called from inside another function. Maybe it was called from inside a function from inside another function from inside yet another function! It doesn't really matter as long as the computation comes back and finishes.\n\nLet's try something else with functions calling functions. Say, you have three books on your shelf, and you want to know how many different ways to arrange them exists.\n\nIt turns out there are six ways to arrange 3 books. Four books — 24 ways. 13 books — almost as many ways as people on the planet. 25 books? More ways to arrange them than atoms in the universe.\n\nIn general, there are n! ways to arrange n books. Factorial means multiply all the numbers from 1 to n. So, 3! is 1 * 2 * 3. Let's write a factorial function:\n\n```javascript\nconst factorial = (n) => {\n return 1 * 2 * 3 * 4; // oh...\n}\n```\n\nOh wait. We don't know what `n` is, that's the point. Hmm... How do they do it in math?\n\nOh, okay, so, they have two options: if n is 1, then factorial is 1, this is simple. But if n is not 1, then factorial is n * (n-1)!\n\nLet's try this:\n\n```javascript\nconst factorial = (n) => {\n if (n === 1) {\n return 1;\n }\n else {\n return n * factorial(n-1);\n }\n}\n\nconst answer = factorial(3);\n```\n\nThis might seem weird. We are calling a function from this function, but... it's the same function!\n\nIs there something wrong? No, not really! The thing is, a function itself is not a box, it's a description of the box. When you call a function a box is created, and after it's done working it's destroyed. So, if you call the same function from itself, there's just another box created.\n\nLet's trace it: we call `factorial(3)`. 3 is not 1, so first condition is ignored. The function wants to multiply numbers and return the answer, but it can't — it needs to know the second number, so it calls `factorial(3-1)` or `factorial(2)`.\n\nA new identical `factorial` box is created, it accepts number 2, it's not 1, so it tries to multiply and return, but it can't — it needs to know the second number, so it calls `factorial(1)`.\n\nA new identical `factorial` box is created, it accepts number 1, and this box can return immediately — it returns 1.\n\n1 comes back to the previous box, gets multiplied by 2 and the answer — 2 returns to the previous box, gets multiplied by 3 and the answer — 6 returns to the outside world and stored in the `answer` constant.\n\nPhew!\n\nThis is called recursion: when something is described in terms of itself. When it comes to math or programming, recursion requires two things:\n\n1. A simple base case or a terminating scenario. When to stop, basically. In our example it was 1: we stop factorial calculation when we get to 1.\n2. A rule to move along the recursion, to go deeper. In our case, that was `n * factorial(n-1)`.\n\nLet's trace the steps once more, but from a different point of view. This is what happens step by step:\n\n```\nfactorial(3);\n3 * factorial(2);\n3 * 2 * factorial(1);\n3 * 2 * 1;\n3 * 2;\n6;\n```\n\nNothing gets multiplied until we go all the way down, to the base case of `factorial(1)`. And then we start going back up, one step at a time, one multiplication at a time.\n\nRecursion is used widely, especially in functional programming — one of the styles of programming. And not only for math calculations, for all sorts of things! You'll see recursion all the time in this course and next ones, because it's extremely powerful and, I have to say, it's really cool.\n\nIt's your turn. Continue to the quiz and the exercise, and create your own recursive function. It might be a bit tricky, just remember: you need to describe two things — when to stop and how to go deeper. Good luck!\n"},"lessonMember":null,"courseMember":null,"course":{"start_lesson":{"exercise":null,"units":[{"id":1662,"name":"theory","url":"/courses/intro_to_programming/lessons/intro/theory_unit"}],"links":[],"ordered_units":[{"id":1662,"name":"theory","url":"/courses/intro_to_programming/lessons/intro/theory_unit"}],"id":813,"slug":"intro","state":"approved","name":"What is a computer anyway?","course_order":110,"goal":"We'll ask and try to answer some simple but important questions: What is a computer anyway? Is it smart? Do computers speak programming languages?","self_study":null,"theory_video_provider":"youtube","theory_video_uid":"muFql8Z4sCg","theory":"Every lesson includes additional materials: illustrations, recommended articles and videos, some optional resources and the full video script.\n\nThese first lessons don't have many links yet, but we're gradually going deeper and deeper, so expect more stuff as you follow along.\n\n## Video script\n\nThis is Tota.\n\nHe is a caveman.\n\nOne day he was walking in the forest, and all of a sudden a large noisy sphere appeared out of nowhere, sparkling and blinking.\n\n\"Just like Terminator movie\", - would've said Tota if he had seen Terminator.\n\nThe sphere disappeared quickly, and left a smoking black box on the grass.\n\nTota was curious, he waited for the smoke to calm down and went ahead to explore the box.\n\nIt was a heavy thing with two buttons on the side, one with an X and one with an O on its face, a long hole and a lever.\n\nBeing a caveman, Tota tried to touch it, kick it, smell it and roll it around. The box was obviously not alive, but the buttons intrigued him.\n\nTota discovered an interesting thing: if he pushed X once and O once, then pulled the lever, then O would glow for a momemnt, then X would glow for a moment.\n\nDid I tell you that Tota was remarkably smart? Top of his cave.\n\nHe then decided to push the buttons in the same way as they glow: O, then X, then pulled the lever. The box answered again.\n\nTota repeated the new pattern. There was another answer. When Tota pushed the last pattern, the box beeped and a produced a ball of lightning, scaring Tota immensely and putting the tree in front of him on fire.\n\nSo, now Tota had this weapon of sorts. He killed many animals with it, and enjoyed many meals near a fire.\n\nSoon he discovered more patterns: one would create some noise he really hated, another would spit a long leaf with markings, and others would do nothing at all.\n\nOnce Tota found an even more advanced feature of this device. He wanted to make fire again, but instead of just pushing the lever once, he pushed and held it. When he released it moments later, no fire came out, but both X and O started blinking. He desperately pressed O and they stopped blinking. From then on, simple O and a lever push produced the fire, so much easier and faster than before!\n\nHe realized that he had trained this beast just like he trained a baby wolf one day.\n\nSo... what is this thing?\n\nOf course, Tota calls it Boomwoom, but we can clearly come up with something better. At first, one might think this is some sort of overly complicated weapon. But it does some other weird stuff, like music... and even printing. It's not like a home appliance, although, some washing machines are more complicated to operate.\n\nLet's start with the buttons. Seems like the machine \"understands\" certain combinations and doesn't understand others. We don't know the meaning of the buttons and combinations, so I want to call it \"code\", as in \"I have no idea what that is, but it probably means something\". Some codes work, some don't, just like in our speech some sounds mean something, and others don't. 'Language' seems like a good word for it. This machine understands certain language of codes.\n\nOkay, how do we call this machine then? Code-language-understander? \"Understand\" sounds important to us, but the key thing about the machine is not that it just understands, but does something as a result. It understands the code for \"fire flash\", and immediately produces the fire flash. So, it's more like... code-language-performer? It performs some actions.\n\nThe guy from the future who sent this thing to the stone age might call it differently, but we today would definitely call this machine a \"computer\". That's how we call machines that accept code and perform some actions.\n\nYou might think this is a terrible computer with some terrible code. Today we have these magical devices with awesome features and programming languages with easy to read codes like this:\n\nBy the way, you will be able to write and understand this easily by the end of the course.\n\nAnd yes, nowadays computers are different. But... not too different. We haven't yet explored this machine thoroughly enough, but trust me: fundamentally, they are the same. Just like this... is very different to this... both use the same principles and capable of the same thing, to different extent.\n\nSo, we can keep looking at that weird machine and understand something important about computer programming in general:\n\nFirst: Computer understands a particular, strict language. Random pushes don't do much, only certain combinations work. And one tiny mistake in a pattern breaks everything. And second: Computers are really stupid\n\nYou might think this last part is due to this particular computer being weird and underpowered, but I am really talking about computers in general. They are very powerful but very stupid. Make no mistake, all they do is perform whatever we tell them. No magic. But, of course, for Tota it's magic indeed, just like some modern devices are magic to us, unless we learn computer programming. Fortunately, this is exactly what we are going to do in this course.\n\n## Synopsis\n\n- Computer accepts code and performs actions\n- Computer understands certain language of codes:\n - Some codes work\n - Some codes don't work\n - There are strict rules about code\n- Unlike people computers are fundamentally not smart, they only do what we tell them to do. And we tell them to do stuff using code\n- All computers are fundamentally the same. Primitive, old, underpowered computer and modern laptop use the same principles and capable of the same thing, to different extent\n\n## Additional materials\n\n- [Inside your computer - Bettina Bair](https://www.youtube.com/watch?v=AkFi90lZmXA)\n- [Punch Card Programming - Computerphile](https://www.youtube.com/watch?v=KG2M4ttzBnY)\n- [The Future of Computer Intelligence Is Everything but Artificial](https://www.wired.com/2014/06/the-future-of-computer-intelligence-is-everything-but-artificial/)\n\n\n"},"id":135,"slug":"intro_to_programming","challenges_count":4,"name":"Programming fundamentals","allow_indexing":true,"state":"approved","course_state":"finished","pricing_type":"free","description":"What actually are computers? Do they speak programming languages? Is it hard to write your own programs? The answer to these, and many other questions, can be found in this course. We'll explore the nature of computers and code, and some fascinating ideas that allowed us to create modern computers, mobile phones, the internet and, you know, pretty much everything we rely on every day.","kind":"basic","updated_at":"2026-01-20T11:37:42.764Z","language":"javascript","duration_cache":67920,"skills":["Use basic language constructs: conditions, loops, functions, and others","Divide code into modules for reuse and no name conflicts","Understand key concepts for writing good code, such as code cleanliness and determinism"],"keywords":[],"lessons_count":16,"cover":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NTY3OSwicHVyIjoiYmxvYl9pZCJ9fQ==--2aca53c34d52f86032c605caceb0ccdd4a9b2fa8/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJwbmciLCJyZXNpemVfdG9fZmlsbCI6WzYwMCw0MDBdfSwicHVyIjoidmFyaWF0aW9uIn19--6067466c2912ca31a17eddee04b8cf2a38c6ad17/image.png"},"recommendedLandings":[],"lessonMemberUnit":null,"accessToLearnUnitExists":true,"accessToCourseExists":true},"url":"/courses/intro_to_programming/lessons/recursion/theory_unit","version":"1656487db0d1dd5f33634fe1070e57e55135cbeb","encryptHistory":false,"clearHistory":false}"><style data-mantine-styles="true">:root, :host{--mantine-font-family: Arial, sans-serif;--mantine-font-family-headings: Arial, sans-serif;--mantine-heading-font-weight: normal;--mantine-radius-default: 0rem;--mantine-primary-color-filled: var(--mantine-color-indigo-filled);--mantine-primary-color-filled-hover: var(--mantine-color-indigo-filled-hover);--mantine-primary-color-light: var(--mantine-color-indigo-light);--mantine-primary-color-light-hover: var(--mantine-color-indigo-light-hover);--mantine-primary-color-light-color: var(--mantine-color-indigo-light-color);--mantine-spacing-xxl: calc(4rem * var(--mantine-scale));--mantine-font-size-xs: 12px;--mantine-font-size-sm: 14px;--mantine-font-size-md: 16px;--mantine-font-size-lg: clamp(16.0000px, calc(15.2727px + 0.2273vw), 18.0000px);--mantine-font-size-xl: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-display-3: clamp(32.0000px, calc(26.1818px + 1.8182vw), 48.0000px);--mantine-font-size-display-2: clamp(36.0000px, calc(25.8182px + 3.1818vw), 64.0000px);--mantine-font-size-display-1: clamp(40.0000px, calc(25.4545px + 4.5455vw), 80.0000px);--mantine-font-size-h1: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-font-size-h2: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-font-size-h3: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-font-size-h4: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-font-size-h5: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-h6: 1rem;--mantine-primary-color-0: var(--mantine-color-indigo-0);--mantine-primary-color-1: var(--mantine-color-indigo-1);--mantine-primary-color-2: var(--mantine-color-indigo-2);--mantine-primary-color-3: var(--mantine-color-indigo-3);--mantine-primary-color-4: var(--mantine-color-indigo-4);--mantine-primary-color-5: var(--mantine-color-indigo-5);--mantine-primary-color-6: var(--mantine-color-indigo-6);--mantine-primary-color-7: var(--mantine-color-indigo-7);--mantine-primary-color-8: var(--mantine-color-indigo-8);--mantine-primary-color-9: var(--mantine-color-indigo-9);--mantine-color-red-0: #ffeaea;--mantine-color-red-1: #fed4d4;--mantine-color-red-2: #f4a7a8;--mantine-color-red-3: #ec7878;--mantine-color-red-4: #e55050;--mantine-color-red-5: #e03131;--mantine-color-red-6: #e02829;--mantine-color-red-7: #c71a1c;--mantine-color-red-8: #b21218;--mantine-color-red-9: #9c0411;--mantine-color-violet-0: #fce9ff;--mantine-color-violet-1: #f1cfff;--mantine-color-violet-2: #e09bff;--mantine-color-violet-3: #d16fff;--mantine-color-violet-4: #be37fe;--mantine-color-violet-5: #b51afe;--mantine-color-violet-6: #b009ff;--mantine-color-violet-7: #9b00e4;--mantine-color-violet-8: #8a00cc;--mantine-color-violet-9: #7800b3;--mantine-color-indigo-0: #edecff;--mantine-color-indigo-1: #d6d5fe;--mantine-color-indigo-2: #aaa9f4;--mantine-color-indigo-3: #7b79eb;--mantine-color-indigo-4: #5451e4;--mantine-color-indigo-5: #3b37e0;--mantine-color-indigo-6: #2d2adf;--mantine-color-indigo-7: #1f1ec7;--mantine-color-indigo-8: #1819b2;--mantine-color-indigo-9: #0c149e;--mantine-color-cyan-0: #dffdff;--mantine-color-cyan-1: #caf5ff;--mantine-color-cyan-2: #99e8ff;--mantine-color-cyan-3: #64daff;--mantine-color-cyan-4: #3ccffe;--mantine-color-cyan-5: #24c8fe;--mantine-color-cyan-6: #00c2ff;--mantine-color-cyan-7: #00ade4;--mantine-color-cyan-8: #009acd;--mantine-color-cyan-9: #0085b5;--mantine-color-green-0: #e9fdec;--mantine-color-green-1: #d7f6dc;--mantine-color-green-2: #b0eab9;--mantine-color-green-3: #86df94;--mantine-color-green-4: #62d574;--mantine-color-green-5: #4ccf5f;--mantine-color-green-6: #3fcc54;--mantine-color-green-7: #2fb344;--mantine-color-green-8: #25a03b;--mantine-color-green-9: #138a2e;--mantine-color-yellow-0: #fff7e2;--mantine-color-yellow-1: #ffeecd;--mantine-color-yellow-2: #ffdc9c;--mantine-color-yellow-3: #ffc966;--mantine-color-yellow-4: #feb93a;--mantine-color-yellow-5: #feae1e;--mantine-color-yellow-6: #ffa90f;--mantine-color-yellow-8: #ca8200;--mantine-color-yellow-9: #af7000;--mantine-h1-font-size: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-h1-font-weight: normal;--mantine-h2-font-size: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-h2-font-weight: normal;--mantine-h3-font-size: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-h3-font-weight: normal;--mantine-h4-font-size: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-h4-font-weight: normal;--mantine-h5-font-size: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-h5-font-weight: normal;--mantine-h6-font-size: 1rem;--mantine-h6-font-weight: normal;}
:root[data-mantine-color-scheme="dark"], :host([data-mantine-color-scheme="dark"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-dark-filled: var(--mantine-color-dark-5);--mantine-color-dark-filled-hover: var(--mantine-color-dark-6);--mantine-color-dark-light: rgba(105, 105, 105, 0.15);--mantine-color-dark-light-hover: rgba(105, 105, 105, 0.2);--mantine-color-dark-light-color: var(--mantine-color-dark-0);--mantine-color-dark-outline: var(--mantine-color-dark-1);--mantine-color-dark-outline-hover: rgba(184, 184, 184, 0.05);--mantine-color-gray-filled: var(--mantine-color-gray-5);--mantine-color-gray-filled-hover: var(--mantine-color-gray-6);--mantine-color-gray-light: rgba(222, 226, 230, 0.15);--mantine-color-gray-light-hover: rgba(222, 226, 230, 0.2);--mantine-color-gray-light-color: var(--mantine-color-gray-0);--mantine-color-gray-outline: var(--mantine-color-gray-1);--mantine-color-gray-outline-hover: rgba(241, 243, 245, 0.05);--mantine-color-red-filled: var(--mantine-color-red-5);--mantine-color-red-filled-hover: var(--mantine-color-red-6);--mantine-color-red-light: rgba(236, 120, 120, 0.15);--mantine-color-red-light-hover: rgba(236, 120, 120, 0.2);--mantine-color-red-light-color: var(--mantine-color-red-0);--mantine-color-red-outline: var(--mantine-color-red-1);--mantine-color-red-outline-hover: rgba(254, 212, 212, 0.05);--mantine-color-pink-filled: var(--mantine-color-pink-5);--mantine-color-pink-filled-hover: var(--mantine-color-pink-6);--mantine-color-pink-light: rgba(250, 162, 193, 0.15);--mantine-color-pink-light-hover: rgba(250, 162, 193, 0.2);--mantine-color-pink-light-color: var(--mantine-color-pink-0);--mantine-color-pink-outline: var(--mantine-color-pink-1);--mantine-color-pink-outline-hover: rgba(255, 222, 235, 0.05);--mantine-color-grape-filled: var(--mantine-color-grape-5);--mantine-color-grape-filled-hover: var(--mantine-color-grape-6);--mantine-color-grape-light: rgba(229, 153, 247, 0.15);--mantine-color-grape-light-hover: rgba(229, 153, 247, 0.2);--mantine-color-grape-light-color: var(--mantine-color-grape-0);--mantine-color-grape-outline: var(--mantine-color-grape-1);--mantine-color-grape-outline-hover: rgba(243, 217, 250, 0.05);--mantine-color-violet-filled: var(--mantine-color-violet-5);--mantine-color-violet-filled-hover: var(--mantine-color-violet-6);--mantine-color-violet-light: rgba(209, 111, 255, 0.15);--mantine-color-violet-light-hover: rgba(209, 111, 255, 0.2);--mantine-color-violet-light-color: var(--mantine-color-violet-0);--mantine-color-violet-outline: var(--mantine-color-violet-1);--mantine-color-violet-outline-hover: rgba(241, 207, 255, 0.05);--mantine-color-indigo-filled: var(--mantine-color-indigo-5);--mantine-color-indigo-filled-hover: var(--mantine-color-indigo-6);--mantine-color-indigo-light: rgba(123, 121, 235, 0.15);--mantine-color-indigo-light-hover: rgba(123, 121, 235, 0.2);--mantine-color-indigo-light-color: var(--mantine-color-indigo-0);--mantine-color-indigo-outline: var(--mantine-color-indigo-1);--mantine-color-indigo-outline-hover: rgba(214, 213, 254, 0.05);--mantine-color-blue-filled: var(--mantine-color-blue-5);--mantine-color-blue-filled-hover: var(--mantine-color-blue-6);--mantine-color-blue-light: rgba(116, 192, 252, 0.15);--mantine-color-blue-light-hover: rgba(116, 192, 252, 0.2);--mantine-color-blue-light-color: var(--mantine-color-blue-0);--mantine-color-blue-outline: var(--mantine-color-blue-1);--mantine-color-blue-outline-hover: rgba(208, 235, 255, 0.05);--mantine-color-cyan-filled: var(--mantine-color-cyan-5);--mantine-color-cyan-filled-hover: var(--mantine-color-cyan-6);--mantine-color-cyan-light: rgba(100, 218, 255, 0.15);--mantine-color-cyan-light-hover: rgba(100, 218, 255, 0.2);--mantine-color-cyan-light-color: var(--mantine-color-cyan-0);--mantine-color-cyan-outline: var(--mantine-color-cyan-1);--mantine-color-cyan-outline-hover: rgba(202, 245, 255, 0.05);--mantine-color-teal-filled: var(--mantine-color-teal-5);--mantine-color-teal-filled-hover: var(--mantine-color-teal-6);--mantine-color-teal-light: rgba(99, 230, 190, 0.15);--mantine-color-teal-light-hover: rgba(99, 230, 190, 0.2);--mantine-color-teal-light-color: var(--mantine-color-teal-0);--mantine-color-teal-outline: var(--mantine-color-teal-1);--mantine-color-teal-outline-hover: rgba(195, 250, 232, 0.05);--mantine-color-green-filled: var(--mantine-color-green-5);--mantine-color-green-filled-hover: var(--mantine-color-green-6);--mantine-color-green-light: rgba(134, 223, 148, 0.15);--mantine-color-green-light-hover: rgba(134, 223, 148, 0.2);--mantine-color-green-light-color: var(--mantine-color-green-0);--mantine-color-green-outline: var(--mantine-color-green-1);--mantine-color-green-outline-hover: rgba(215, 246, 220, 0.05);--mantine-color-lime-filled: var(--mantine-color-lime-5);--mantine-color-lime-filled-hover: var(--mantine-color-lime-6);--mantine-color-lime-light: rgba(192, 235, 117, 0.15);--mantine-color-lime-light-hover: rgba(192, 235, 117, 0.2);--mantine-color-lime-light-color: var(--mantine-color-lime-0);--mantine-color-lime-outline: var(--mantine-color-lime-1);--mantine-color-lime-outline-hover: rgba(233, 250, 200, 0.05);--mantine-color-yellow-filled: var(--mantine-color-yellow-5);--mantine-color-yellow-filled-hover: var(--mantine-color-yellow-6);--mantine-color-yellow-light: rgba(255, 201, 102, 0.15);--mantine-color-yellow-light-hover: rgba(255, 201, 102, 0.2);--mantine-color-yellow-light-color: var(--mantine-color-yellow-0);--mantine-color-yellow-outline: var(--mantine-color-yellow-1);--mantine-color-yellow-outline-hover: rgba(255, 238, 205, 0.05);--mantine-color-orange-filled: var(--mantine-color-orange-5);--mantine-color-orange-filled-hover: var(--mantine-color-orange-6);--mantine-color-orange-light: rgba(255, 192, 120, 0.15);--mantine-color-orange-light-hover: rgba(255, 192, 120, 0.2);--mantine-color-orange-light-color: var(--mantine-color-orange-0);--mantine-color-orange-outline: var(--mantine-color-orange-1);--mantine-color-orange-outline-hover: rgba(255, 232, 204, 0.05);--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-9) 0%, var(--mantine-color-cyan-7) 100%);--app-color-surface: #2e2e2e;}
:root[data-mantine-color-scheme="light"], :host([data-mantine-color-scheme="light"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-red-light: rgba(224, 40, 41, 0.1);--mantine-color-red-light-hover: rgba(224, 40, 41, 0.12);--mantine-color-red-outline-hover: rgba(224, 40, 41, 0.05);--mantine-color-violet-light: rgba(176, 9, 255, 0.1);--mantine-color-violet-light-hover: rgba(176, 9, 255, 0.12);--mantine-color-violet-outline-hover: rgba(176, 9, 255, 0.05);--mantine-color-indigo-light: rgba(45, 42, 223, 0.1);--mantine-color-indigo-light-hover: rgba(45, 42, 223, 0.12);--mantine-color-indigo-outline-hover: rgba(45, 42, 223, 0.05);--mantine-color-cyan-light: rgba(0, 194, 255, 0.1);--mantine-color-cyan-light-hover: rgba(0, 194, 255, 0.12);--mantine-color-cyan-outline-hover: rgba(0, 194, 255, 0.05);--mantine-color-green-light: rgba(63, 204, 84, 0.1);--mantine-color-green-light-hover: rgba(63, 204, 84, 0.12);--mantine-color-green-outline-hover: rgba(63, 204, 84, 0.05);--mantine-color-yellow-light: rgba(255, 169, 15, 0.1);--mantine-color-yellow-light-hover: rgba(255, 169, 15, 0.12);--mantine-color-yellow-outline-hover: rgba(255, 169, 15, 0.05);--app-color-surface: #f1f3f5;--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-5) 100%);}</style><style data-mantine-styles="classes">@media (max-width: 35.99375em) {.mantine-visible-from-xs {display: none !important;}}@media (min-width: 36em) {.mantine-hidden-from-xs {display: none !important;}}@media (max-width: 47.99375em) {.mantine-visible-from-sm {display: none !important;}}@media (min-width: 48em) {.mantine-hidden-from-sm {display: none !important;}}@media (max-width: 61.99375em) {.mantine-visible-from-md {display: none !important;}}@media (min-width: 62em) {.mantine-hidden-from-md {display: none !important;}}@media (max-width: 74.99375em) {.mantine-visible-from-lg {display: none !important;}}@media (min-width: 75em) {.mantine-hidden-from-lg {display: none !important;}}@media (max-width: 87.99375em) {.mantine-visible-from-xl {display: none !important;}}@media (min-width: 88em) {.mantine-hidden-from-xl {display: none !important;}}</style><div style="position:absolute;top:0rem" class=""></div><div style="max-width:var(--container-size-xl);height:100%;min-height:0rem" class=""><style data-mantine-styles="inline">.__m__-_R_5ub_{--grid-gutter:0rem;}</style><div style="height:100%;min-height:0rem" class="m_410352e9 mantine-Grid-root __m__-_R_5ub_"><div class="m_dee7bd2f mantine-Grid-inner" style="height:100%"><style data-mantine-styles="inline">.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:91.66666666666667%;--col-max-width:91.66666666666667%;}@media(min-width: 48em){.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:83.33333333333334%;--col-max-width:83.33333333333334%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem;display:flex" class="m_96bdd299 mantine-Grid-col __m__-_R_rdub_"><style data-mantine-styles="inline">.__m__-_R_6qrdub_{margin-top:0rem;padding-inline:var(--mantine-spacing-xs);width:100%;}@media(min-width: 48em){.__m__-_R_6qrdub_{margin-top:var(--mantine-spacing-xl);width:80%;}}@media(min-width: 62em){.__m__-_R_6qrdub_{padding-inline:var(--mantine-spacing-xl);}}</style><div style="margin-inline:auto;max-width:var(--mantine-breakpoint-xl)" class="__m__-_R_6qrdub_"><div style="color:var(--mantine-color-dimmed)" class="m_4451eb3a mantine-Center-root" data-inline="true"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;margin-inline-end:calc(0.125rem * var(--mantine-scale));color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-lock "><path d="M5 13a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v6a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-6"></path><path d="M11 16a1 1 0 1 0 2 0a1 1 0 0 0 -2 0"></path><path d="M8 11v-4a4 4 0 1 1 8 0v4"></path></svg></div><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Programming fundamentals</p></div><h1 style="--title-fw:var(--mantine-h1-font-weight);--title-lh:var(--mantine-h1-line-height);--title-fz:var(--mantine-h1-font-size);margin-bottom:var(--mantine-spacing-xl)" class="m_8a5d1357 mantine-Title-root" data-order="1">Theory: Recursion: when a function calls itself</h1><script type="application/ld+json">{"@context":"https://schema.org","@type":"LearningResource","name":"Recursion: when a function calls itself","inLanguage":"en","isPartOf":{"@type":"LearningResource","name":"Programming fundamentals"},"isAccessibleForFree":"False","hasPart":{"@type":"WebPageElement","isAccessibleForFree":"False","cssSelector":".paywalled"}}</script><div class=""><div style="--alert-color:var(--mantine-color-indigo-light-color);margin-bottom:var(--mantine-spacing-lg);font-size:var(--mantine-font-size-lg)" class="m_66836ed3 mantine-Alert-root" id="mantine-_R_remqrdub_" role="alert" aria-describedby="mantine-_R_remqrdub_-body" aria-labelledby="mantine-_R_remqrdub_-title"><div class="m_a5d60502 mantine-Alert-wrapper"><div class="m_667f2a6a mantine-Alert-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-rocket "><path d="M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3 -5a9 9 0 0 0 6 -8a3 3 0 0 0 -3 -3a9 9 0 0 0 -8 6a6 6 0 0 0 -5 3"></path><path d="M7 14a6 6 0 0 0 -3 6a6 6 0 0 0 6 -3"></path><path d="M14 9a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path></svg></div><div class="m_667c2793 mantine-Alert-body"><div class="m_6a03f287 mantine-Alert-title"><span id="mantine-_R_remqrdub_-title" class="m_698f4f23 mantine-Alert-label">Full access to materials</span></div><div id="mantine-_R_remqrdub_-body" class="m_7fa78076 mantine-Alert-message"><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:space-between;--group-wrap:wrap" class="m_4081bf90 mantine-Group-root"><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Sign up and get access to this and dozens of other courses</p><a style="--button-height:var(--button-height-xs);--button-padding-x:var(--button-padding-x-xs);--button-fz:var(--mantine-font-size-xs);--button-bg:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-hover:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-color:var(--mantine-color-white);--button-bd:none" class="mantine-focus-auto mantine-active m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root" data-variant="gradient" data-size="xs" href="/u/new"><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">Sign up</span></span></a></div></div></div></div></div><div style="margin-bottom:var(--mantine-spacing-xl)" class=""><div class="ratio ratio-16x9"><iframe width="100%" height="auto" src="//www.youtube.com/embed/vLhHyGTkjCs" loading="lazy" allowFullScreen="" title="video"></iframe></div></div><div class="paywalled m_d08caa0 mantine-Typography-root"><h2 id="heading-2-1">Lesson notes</h2>
<h3 id="heading-3-2">Thinking about functions</h3>
<ul>
<li>You can think of functions as black boxes: a box takes a thing, does something, then spits some other thing out
<ul>
<li>Some functions don't take anything (don't accept arguments), some don't do anything (their bodies are empty), some don't return any values.</li>
<li>Our <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">surfaceAreaCalculator</code> takes one argument (radius), calculates the surface area and returns the result of that calculation.</li>
</ul>
</li>
<li>Functions can call other functions</li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">surfaceAreaCalculator</code> can call the <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">square</code> function to get radius squared instead of manually multiplying radius by radius</li>
<li>We create functions to make our lives easier:
<ul>
<li>the code is easier to understand</li>
<li>functions can be reused many times</li>
</ul>
</li>
</ul>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const surfaceOfMars = surfaceAreaCalculator(3390); // this is WHAT, it's easier to understand
const surfaceOfMars = 4 * 3.14 * 3390 * 3390; // this is HOW</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Two functions together:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const surfaceAreaCalculator = (radius) => {
return 4 * 3.14 * square(radius);
}
const square = (num) => {
return num * num;
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<h3 id="heading-3-3">Functions calling themselves</h3>
<ul>
<li>Functions can call themselves
<ul>
<li><strong>Function definitions</strong> are descriptions of the boxes</li>
<li>A real box is created when <strong>function is called</strong></li>
<li>If a function calls itself, a new identical box is created</li>
</ul>
</li>
<li>Number of ways to arrange n objects is n! (<a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://en.wikipedia.org/wiki/Permutation" rel="noopener noreferrer" target="_blank">permutations</a>)</li>
<li>n! is defined like so: if n = 1, then <strong>n! = 1</strong>; if n > 0, then <strong>n! = n * (n-1)!</strong></li>
</ul>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const factorial = (n) => {
if (n === 1) {
return 1;
}
else {
return n * factorial(n-1);
}
}
const answer = factorial(3);</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<h3 id="heading-3-4">Recursion requirements</h3>
<ol>
<li>A simple base case or a terminating scenario. When to stop, basically. In our example it was 1: we stop factorial calculation when we get to 1.</li>
<li>A rule to move along the recursion, to go deeper. In our case, it was <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n * factorial(n-1)</code>.</li>
</ol>
<h3 id="heading-3-5">Waiting for the multiplications</h3>
<p>Nothing gets multiplied until we go all the way down, to the base case of <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial(1)</code>. Then we start going back up, one step at a time.</p>
<code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial(3);
3 * factorial(2);
3 * 2 * factorial(1);
3 * 2 * 1;
3 * 2;
6;</code>
<h3 id="heading-3-6">Sidenote</h3>
<p>Note that 0! is 1, and the proper base case for n! is 0! In this lesson we omitted this case to make one less call and one less box to think about, since 1 * 1 is 1 anyway.</p>
<h3 id="heading-3-7">Just for fun</h3>
<ol>
<li>There is a common joke among programmers: "<em>In order to understand recursion, you have to understand recursion</em>". Google seems to love this kind of joke. Try googling "recursion" and check out the suggestion at the top of the results page ;-)</li>
<li>In order to understand recursion you must first understand recursion.</li>
</ol>
<h2 id="heading-2-8">Recommended watching</h2>
<ul>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.youtube.com/watch?v=Mv9NEXX1VHc" rel="noopener noreferrer" target="_blank">What on Earth is Recursion? - Computerphile</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.youtube.com/watch?v=k7-N8R0-KY4" rel="noopener noreferrer" target="_blank">Recursion (Part 7 of Functional Programming in JavaScript) from Fun Fun Function</a></li>
</ul>
<h2 id="heading-2-9">Optional reading</h2>
<ul>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.khanacademy.org/computing/computer-science/algorithms/recursive-algorithms/a/properties-of-recursive-algorithms" rel="noopener noreferrer" target="_blank">Properties of recursive algorithms</a></li>
</ul>
<h2 id="heading-2-10">Optional watching</h2>
<ul>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.youtube.com/watch?v=7t_pTlH9HwA" rel="noopener noreferrer" target="_blank">Fibonacci Programming - Computerphile</a></li>
</ul>
<h2 id="heading-2-11">Lesson transcript</h2>
<p>We have a function <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">surfaceAreaCalculator</code> that accepts one argument — a radius — and returns a surface area of a corresponding sphere using a formula 4 * pi * r^2. Remember, we can think about functions as boxes: put a thing in the box, the box does something and spits out the result.</p>
<p>Some boxes don't accept anything, some — don't spit out anything, and some don't even do anything, but for now we're interested in boxes like <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">surfaceAreaCalculator</code> — accept something, calculate something, return the result.</p>
<p>We built this function in order to simplify our work. We have to calculate surface areas of different planets, and having this handy function means we don't have to remember and write down the formula over and over again.</p>
<p>Another reason is that now code is easier to understand. Compare this:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const surfaceOfMars = surfaceAreaCalculator(3390);</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>to this:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const surfaceOfMars = 4 * 3.14 * 3390 * 3390;</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>First one is much nicer and simpler, especially to someone who is new to this code. First one answers the "what" question, the second one answers the "how" question.</p>
<p>We can improve on this and make another function to calculate squares. Let's first take a look at how we might use it:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const surfaceAreaCalculator = (radius) => {
return 4 * 3.14 * square(radius);
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Instead of multiplying radius by radius, we call a square function and pass the radius. Obviously, the square function is nothing but "accept a number, return its square":</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const square = (num) => {
return num * num;
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Let's trace the steps and see what happens when we run our program. We create a constant <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">surfaceOfMars</code> and tell it to store whatever value <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">surfaceAreaCalculator</code> function returns when it's called with 3390 as an argument.</p>
<p>3390 is known as <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">radius</code> inside the function. The function wants to multiply numbers and return, but it needs to know the last number, it has to call the <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">square</code> function and pass it the radius. <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">square</code> accepts one argument — it's the number 3390, in this case, and inside the <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">square</code> function it is known as <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n</code>.</p>
<p><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">square</code> wants to multiply <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n</code> by <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n</code> and return. Nothing stops it, so it does. We are back inside the <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">surfaceAreaCalculator</code> — it was literally waiting for the <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">square function</code> to finish. And now we have the result of calling <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">square</code>. It substitutes the call, so now it's possible to finish the multiplication and return.</p>
<p>The answer is returned and stored in the <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">surfaceOfMars</code>.</p>
<p>So, functions can call other functions. And a function doesn't know and doesn't care if it was called from inside another function. Maybe it was called from inside a function from inside another function from inside yet another function! It doesn't really matter as long as the computation comes back and finishes.</p>
<p>Let's try something else with functions calling functions. Say, you have three books on your shelf, and you want to know how many different ways to arrange them exists.</p>
<p>It turns out there are six ways to arrange 3 books. Four books — 24 ways. 13 books — almost as many ways as people on the planet. 25 books? More ways to arrange them than atoms in the universe.</p>
<p>In general, there are n! ways to arrange n books. Factorial means multiply all the numbers from 1 to n. So, 3! is 1 * 2 * 3. Let's write a factorial function:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const factorial = (n) => {
return 1 * 2 * 3 * 4; // oh...
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Oh wait. We don't know what <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n</code> is, that's the point. Hmm... How do they do it in math?</p>
<p>Oh, okay, so, they have two options: if n is 1, then factorial is 1, this is simple. But if n is not 1, then factorial is n * (n-1)!</p>
<p>Let's try this:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const factorial = (n) => {
if (n === 1) {
return 1;
}
else {
return n * factorial(n-1);
}
}
const answer = factorial(3);</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>This might seem weird. We are calling a function from this function, but... it's the same function!</p>
<p>Is there something wrong? No, not really! The thing is, a function itself is not a box, it's a description of the box. When you call a function a box is created, and after it's done working it's destroyed. So, if you call the same function from itself, there's just another box created.</p>
<p>Let's trace it: we call <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial(3)</code>. 3 is not 1, so first condition is ignored. The function wants to multiply numbers and return the answer, but it can't — it needs to know the second number, so it calls <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial(3-1)</code> or <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial(2)</code>.</p>
<p>A new identical <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial</code> box is created, it accepts number 2, it's not 1, so it tries to multiply and return, but it can't — it needs to know the second number, so it calls <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial(1)</code>.</p>
<p>A new identical <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial</code> box is created, it accepts number 1, and this box can return immediately — it returns 1.</p>
<p>1 comes back to the previous box, gets multiplied by 2 and the answer — 2 returns to the previous box, gets multiplied by 3 and the answer — 6 returns to the outside world and stored in the <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">answer</code> constant.</p>
<p>Phew!</p>
<p>This is called recursion: when something is described in terms of itself. When it comes to math or programming, recursion requires two things:</p>
<ol>
<li>A simple base case or a terminating scenario. When to stop, basically. In our example it was 1: we stop factorial calculation when we get to 1.</li>
<li>A rule to move along the recursion, to go deeper. In our case, that was <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">n * factorial(n-1)</code>.</li>
</ol>
<p>Let's trace the steps once more, but from a different point of view. This is what happens step by step:</p>
<code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial(3);
3 * factorial(2);
3 * 2 * factorial(1);
3 * 2 * 1;
3 * 2;
6;</code>
<p>Nothing gets multiplied until we go all the way down, to the base case of <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">factorial(1)</code>. And then we start going back up, one step at a time, one multiplication at a time.</p>
<p>Recursion is used widely, especially in functional programming — one of the styles of programming. And not only for math calculations, for all sorts of things! You'll see recursion all the time in this course and next ones, because it's extremely powerful and, I have to say, it's really cool.</p>
<p>It's your turn. Continue to the quiz and the exercise, and create your own recursive function. It might be a bit tricky, just remember: you need to describe two things — when to stop and how to go deeper. Good luck!</p></div></div></div></div><style data-mantine-styles="inline">.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:8.333333333333334%;--col-max-width:8.333333333333334%;}@media(min-width: 48em){.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:16.666666666666668%;--col-max-width:16.666666666666668%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem" class="m_96bdd299 mantine-Grid-col __m__-_R_1bdub_"><div style="margin-inline:var(--mantine-spacing-xs)" class="mantine-visible-from-sm"><button style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-lg);text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" data-disabled="true" data-block="true" disabled="" type="button"><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label"><span style="margin-inline-end:var(--mantine-spacing-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Next</span>→</span></span></button><a style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Navigation</span><span class="m_57492dcc mantine-NavLink-description">Theory</span></div><span class="m_690090b5 mantine-NavLink-section" data-position="right"></span></a><div style="margin-block:var(--mantine-spacing-lg)" class="m_3eebeb36 mantine-Divider-root" data-orientation="horizontal" role="separator"></div><div style="margin-block:var(--mantine-spacing-lg)" class=""><div style="justify-content:space-between;margin-bottom:calc(0.1875rem * var(--mantine-scale));color:var(--mantine-color-dimmed);font-size:var(--mantine-font-size-xs)" class="m_8bffd616 mantine-Flex-root __m__-_R_qimrbdub_"><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Completed</p><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">0 / 16</p></div><div style="--progress-size:var(--progress-size-sm)" class="m_db6d6462 mantine-Progress-root" data-size="sm"><div style="--progress-section-size:0%;--progress-section-color:var(--mantine-color-gray-filled)" class="m_2242eb65 mantine-Progress-section" role="progressbar" aria-valuemax="100" aria-valuemin="0" aria-valuenow="0" aria-valuetext="0%"></div></div></div><button style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root" type="button"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Discussions (archive)</span><span class="m_57492dcc mantine-NavLink-description"></span></div></button><div style="--toc-bg:var(--mantine-color-blue-light);--toc-color:var(--mantine-color-blue-light-color);--toc-size:var(--mantine-font-size-sm);--toc-radius:var(--mantine-radius-sm);margin-top:var(--mantine-spacing-xl)" class="m_bcaa9990 mantine-TableOfContents-root" data-variant="light" data-size="sm"></div></div><div class="mantine-hidden-from-sm"><div style="--stack-gap:0rem;--stack-align:stretch;--stack-justify:flex-start" class="m_6d731127 mantine-Stack-root"><button style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-xs);padding:0rem;text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" data-disabled="true" data-block="true" disabled="" type="button"><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">→</span></span></button><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" data-disabled="true" type="button" disabled=""><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></span></button><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto mantine-active m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" type="button"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></span></button></div></div></div></div></div></div></div>
</main>
<footer class="bg-dark fw-light text-light px-3 py-5">
<div class="row small">
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 mb-3">About Hexlet</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/about">About us</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://help.hexlet.io/category/4316" data-target="_blank" role="button">Help</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" target="_blank" rel="noopener noreferrer" href="/map">Site Map</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 fw-normal mb-3">Learn</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_backend-development">Backend
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_devops">DevOps
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_frontend-development">Frontend
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_python">Python
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_testing">Testing
</a></li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5"><span class="translation_missing" title="translation missing: en.layouts.footer_content.popular_courses_for_beginners">Popular Courses For Beginners</span></div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/frontend">Frontend Developer</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5"><span class="translation_missing" title="translation missing: en.layouts.footer_content.popular_courses_for_advanced">Popular Courses For Advanced</span></div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/web-development-free">Fundamentals of Web Development</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-react-development">React</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/css-animation">CSS Animation</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/http-api">HTTP API</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/layout-designer-positioning">Position CSS</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/cli-basics">Command line basics</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/git-basics-free">Git fundamentals</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="row">
<div class="col-12 col-sm-4 col-md-2">
<div class="fs-4">
<ul class="list-unstyled d-flex">
<li class="me-3">
<a aria-label="Facebook" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://www.facebook.com/hexlethq"><span class="bi bi-facebook"></span>
</a></li>
<li class="me-3">
<a aria-label="Instagram" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://www.instagram.com/hello_hexlet/"><span class="bi bi-instagram"></span>
</a></li>
<li>
<a aria-label="Twitter" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://twitter.com/Hexlet_IO"><span class="bi bi-twitter-x"></span>
</a></li>
</ul>
</div>
<div class="mb-2 d-flex flex-column">
<a class="link-light text-decoration-none" rel="nofollow" href="mailto:support@hexlet.io">support@hexlet.io</a>
<a class="link-light text-decoration-none py-2" target="_blank" href="https://t.me/hexlet_help_bot">t.me/hexlet_help_bot</a>
</div>
<ul class="list-unstyled d-flex">
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 opacity-100 external-link" rel="nofollow" data-href="https://hexlet.io/locale/switch?new_locale=en" data-target="_self" role="button"><span class="my-auto">EN</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://ru.hexlet.io/locale/switch?new_locale=ru" data-target="_self" role="button"><span class="my-auto">RU</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://kz.hexlet.io/locale/switch?new_locale=kz" data-target="_self" role="button"><span class="my-auto">KZ</span>
</span></li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<ul class="list-unstyled fs-4">
<li class="mb-3">
<a class="link-light text-decoration-none" href="tel:%2B7%20717%20272%2076%2070">+7 717 272 76 70</a>
<span class="d-block opacity-50 small">free call</span>
</li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<ul class="list-unstyled small">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/legal">Legal</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/offer"><span class="translation_missing" title="translation missing: en.layouts.footer_content.offer">Offer</span></a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/contacts"><span class="translation_missing" title="translation missing: en.layouts.footer_content.contacts">Contacts</span></a>
</li>
</ul>
</div>
<div class="col-12 col-sm-12 col-md-4 small">
<div class="mb-2">
<div>TOO "Hexlet"</div>
<div>The Republic of Kazakhstan, Almaty</div>
<div>Auezova St., 14A</div>
<div>BIN 230340043714
</div>
</div>
</div>
</div>
</footer>
<div id="root-assistant-offcanvas"></div>
<script src="/vite/assets/assistant-CIOaBlj-.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-0bhwJkNI.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-V3hfk_CP.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/MarkdownBlock-DejNWqwz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-B-jV56Ol.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-DOJkeu70.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/shiki-DZwEN4Zo.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-ClTF9s_T.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-mvvEXZQ8.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-CJocDKTE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-DH3_MBnL.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-Cj65YiRw.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useIsomorphicEffect-Csl7vw8x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-DeAQqnBE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-CN66HKVH.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/classnames-DQgTDFJJ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-Bfba02I7.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/debounce-BcxwEZ7X.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/prop-types-DGBR76ns.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-CYyKzrjQ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-SJZekO2j.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-bo78L81P.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-BhqaZ6vG.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-DlXMvSuQ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CFtMU8gd.js" as="script" crossorigin="anonymous">
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015" integrity="sha512-ZpsOmlRQV6y907TI0dKBHq9Md29nnaEIPlkf84rnaERnq6zvWvPUqr2ft8M1aS28oN72PdrCzSjY4U6VaAw1EQ==" data-cf-beacon='{"version":"2024.11.0","token":"d11015b65d11429ea6b4a2ef37dd7e0b","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>