Exploring Recursive Methods in JavaScript with Function Declarations

Recursion with function expressions raises many questions. There are two approaches to accomplishing this: one involves using a named function expression, while the other employs the arguments.callee method. However, it's important to note that the use of arguments.callee is now deprecated.

The real question lies in how to achieve recursion with function declaration. Is it possible to eliminate arguments.callee from this scenario without relying on the function name?

function fib(n){
   return n < 3 ? 1 : arguments.callee(n - 1) + arguments.callee(n - 2);
}

Answer №1

When it comes to function declarations, there is no inherent way to safely reference itself. If the function is renamed, using the previous name within the body would result in an error.

function fib_renamed(n){
   return n < 3 ? 1 : fib(n - 1) + fib(n - 2);
// used to be correct ^^^          ^^^
}

console.log(fib(8));

Additionally, arguments.callee throws an error in strict mode:

function fib(n){
  "use strict";
   return n < 3 ? 1 : arguments.callee(n - 1) + arguments.callee(n - 2);
}

console.log(fib(8));

Nevertheless, any recursive function can be customized to be name-agnostic with the Y combinator (also known as the fixed-point combinator). This allows a function to call itself without requiring a formal name. In certain languages, this might not be feasible, but in JavaScript, it can be achieved. Utilizing the Y/fixed-point combinator eliminates the need for self-references.

The function must be modified to accept one parameter representing itself and then returns a function that uses this parameter for recursive calls. Here's a simplified example using arrow functions:

//original
const fib = n => n < 3 ? 1 : fib(n - 1) + fib(n - 2);

//updated
const updated = fib => 
             n => n < 3 ? 1 : fib(n - 1) + fib(n - 2);

With traditional function declarations, the process would look like this:

//original
function fib(n){
   return n < 3 ? 1 : fib(n - 1) + fib(n - 2);
}

//updated
function updated(fib) {
  return function (n){
    return n < 3 ? 1 : fib(n - 1) + fib(n - 2);
  }
}

The implementation of the Y combinator itself is:

const Y  = f => (g => g (g)) (g => f (x => g (g) (x));

(from "Common combinators in JavaScript" by Avaq on GitHub)

To use the Y combinator:

const Y = f => (g => g (g)) (g => f (x => g (g) (x)));

function updated(fib) {
  return function (n){
    return n < 3 ? 1 : fib(n - 1) + fib(n - 2);
  }
}

console.log(Y(updated)(8));

const fib_new = Y(updated);
console.log(fib_new(8));

Answer №2

The U combinator

By passing a function to itself as an argument, a function can recur using its parameter instead of its name! The function given to U should have at least one parameter that binds to the function (itself).

const U = f => f(f)
  
U(a => console.log(a))

// Output:
// a => console.log(a)

  1. f is assigned to a => console.log(a) and U calls f(f)
  2. when f runs, it logs its only parameter a to the console
  3. as we know, a is f
  4. ie, f knows itself through a, without arguments.callee or a name

Here's a minimal, terminating program -

const U = f => f(f)

const countDown = recur => x =>
  x == 0
    ? "blast off!"
    : x + ", " + U(recur)(x - 1)
    
const ans =
  U(countDown)(10)
  
console.log(ans)
// 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, blast off!

It works in cases where arguments.callee or the function's name would be referenced more than once. Take the classic fib example -

const U = f => f(f)

const fib = recur => x =>
  x < 2
    ? x
    : U(recur)(x - 1) + U(recur)(x - 2)

const ans =
  U(fib)(10)
  
console.log(ans) // 55

By using currying, you can easily construct functions with multiple parameters -

const U = f => f(f)

const range = recur => min => max =>
  min == max
    ? []
    : [min, ...U(recur)(min + 1)(max)]
    
const fold = recur => init => f => xs =>
  xs.length == 0
    ? init
    : U(recur)(f(init,xs[0]))(f)(xs.slice(1))

const add = (x, y) =>
  x + y

const numbers =
  U(range)(7)(14)
  
const sum =
  U(fold)(0)(add)(numbers)
  
console.log(numbers, sum)
// [7, 8, 9, 10, 11, 12, 13]
// 70

U is the primordial essence from which the more sophisticated Y combinator is derived. Refer to this related Q&A for further details.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When utilizing a third-party library in conjunction with Vuetify, the V-menu may have a tendency to automatically close right after

Incorporating cytoscape into a vuetify SPA has been successful for the most part. The graph renders within a v-card-element, and I can navigate to a different page using the vue router when clicking a note in the graph. However, when attempting to replace ...

Obtaining a JSON object from a URL through 'GET' request using $resource in AngularJS

Just starting out with AngularJS and struggling to understand web services as well. My current task involves fetching a JSON object from the following URL: To retrieve the JSON object, I need to access: I am completely lost on how to proceed... Any assis ...

What sets canvas and webgl renderer apart in the world of three.js?

Attempting to showcase a sphere using three.js, but encountering issues when rendering with canvasRenderer due to the appearance of grey lines on the sphere. View the code here: http://jsfiddle.net/jzpSJ/ See the screenshot here: However, when rendering ...

Passing arguments to the callback function in React: a comprehensive guide

Within my react component, I have a collection of elements that I want to make clickable. When clicked, I trigger an external function and pass the item ID as an argument: render () { return ( <ul> {this.props.items.map(item => ( ...

Generating a JavaScript variable linked to a Rails Active Record relationship

I'm trying to implement an active record association in the DOM, but I'm encountering some difficulties. Here is my editor class: .editing .row .col-sm-3 .col-sm-8 .text-left #font-20 .title-font . ...

Checking Whether a Value Entered in an Input Field Exists in an Array Using jQuery

Can someone help me with checking if a specific value is in my array? I want to achieve something like that, any suggestions on how to do it? if(jQuery.inArray($('#ValueInputTitle').val, variableValueInput) !== -1) { console.log("is in arr ...

The client side script "/socket.io/socket.io.js" was not located, therefore the Express-generator project was used instead

I have been working on integrating the "chat-example" from Socket.IO's official website into an Express-generator generated project while keeping the structure of the project intact. I have made minimal changes to the code to fit it into the existing ...

Utilize React and Jest to handle errors by either mocking window values or resolving them

When my app attempts to inject environmental variables at runtime for docker using the window object, I encounter errors in my tests. The code snippet below shows the configuration: url config: declare const window: Window & typeof globalThis & ...

I'm looking to create a Slider component using @material-ui/core that has a track divided into two sections with distinct colors for the left and right sides. How

When the slider ranges from -10 to 0, I want it to display in red. For values between 0 and +10, I would like it to be shown in green. Is there a way to implement this color change using the <Slider /> component from @material-ui/core? ...

Developing a Javascript object using Typescript

Trying my hand at crafting a TypeScript object from JavaScript. The specific JavaScript object I'm attempting to construct can be found here: https://cdnjs.cloudflare.com/ajax/libs/chess.js/0.10.2/chess.js In the provided JavaScript example, the obj ...

Tips for passing a function as a prop to a component in React

I'm struggling with passing a function to the OnChange event in my component that generates input fields in a form. No matter what I try, I keep getting an error. import { FormGroup, FloatingLabel, FormControl } from "react-bootstrap"; con ...

I am no longer able to connect to mySQL using node js

I recently upgraded my node version, and now I'm facing issues accessing my database through my application. I have tried various solutions such as: - Changing the route to 127.0.0.1. - Adding my port number 3306. - Including socketPath: '/Applic ...

Right-click context menu not working properly with Internet Explorer

Seeking assistance with extracting the URL and title of a website using JavaScript. The script is stored in a .HTM file accessed through the registry editor at file://C:\Users\lala\script.htm Below is the script: <script type="text/java ...

Insert items into a frozen map

I'm dealing with an immutable map and iterating through an array to create objects that I want to place inside the map. What would be the correct approach to achieve this? Below is my current code snippet: let arrayOfNames = ['John', ' ...

Performing mathematical calculations with numerical values

This piece of code was created as a component of a calculator project for learning purposes. It functions correctly for the most part. However, I noticed that the addition operation seems to concatenate the two numbers together instead of actually adding ...

Information sent by the Firefox TCP socket using the socket.send() method cannot be retrieved until the socket is closed

I am experiencing an issue while trying to send data from Firefox to a Java desktop application. My Java class functions as a server, and the Firefox script acts as a client. When I test it using another Java class called client.java, the data is successfu ...

What are the steps to encapsulate an Android app within a React Native component, effectively creating a complete view?

I'm currently working on integrating my existing android native app into a React Native application with react-navigation. I'm trying to figure out how I can wrap the android app in a component and call it within the StackNavigator like this: co ...

Build a customizable digital clock script with Javascript/jQuery that displays the time in 24-hour format

Currently seeking a 24-hour format digital clock script in JavaScript/jQuery that also includes the date. The unique feature of this clock is that it will display images as its numbers and date, making for a visually appealing design. Additionally, I wou ...

Is it possible to ensure that an event will always be true in the console without having prior knowledge of the props by utilizing an external framework?

Within my input field, there is a calendar that opens when clicked, as it is part of a library. However, I am facing an issue where I am unable to change the styles of the calendar and inspect them through the console. The scenario unfolds as follows: Cl ...

Issue with nextjs not returning the updated object correctly

I'm currently developing a nextjs app that incorporates authentication. There are two key functions that I execute on each page load. The first function checks for the existence of jwt cookies and then calls another function to validate the tokens if ...