How can you achieve the same functionality as running multiple instance methods in functional programming using JavaScript?

Let's consider a scenario where we have a JS class with Typescript defined as follows:

type Command = 'F' | 'B' // Forwards, Backwards

class Car {
  private x: number
  private y: number

  constructor(x: number, y: number) {
    this.x = x
    this.y = y
  }

  private reportPosition() {
    return `(${this.x}, ${this.y})`
  }

  private move(command: Command) {
    if (command === 'F') this.y++
    if (command === 'B') this.y--
  }

  execute(command: Command) {
    this.move(command)
    return this.reportPosition()
  }
}

Upon instantiation of a Car object and invoking the execute method, two main actions take place:

  • The internal state of the instance (x, y) gets updated.
  • The function execute returns a string.

Now, there is an attempt to refactor the above code in a more functional programming (FP) manner. However, one obstacle faced is how to handle the execute function effectively. The revised approach involves:

type Command = 'F' | 'B'

type Car = {
  x: number
  y: number
}

function createCar(x: number, y: number): Car {
  return { x, y }
}

function reportPosition(car: Car) {
  return `$({car.x}, ${car.y})`
}

function move(car: Car, command: Command) {
  if (command === 'F') return createCar(car.x + 1, car.y)
  if (command === 'B') return createCar(car.x - 1, car.y)
  return car
}


function execute(car: Car, command: Command) {
  const newCar = move(car, command)
  const msg = reportPosition(newCar)
  
  return [newCar, msg]
}

A few questions arise from this transition:

  1. Given that execute appears to be performing multiple tasks concurrently, there is uncertainty around returning two values from it within the function. Is this practice acceptable in the realm of functional programming? or should each individual function (move, reportPosition) be called separately?

  2. If the move function had additional logic to determine whether the car crashed after moving, would it also necessitate returning both a new car instance and a boolean value indicating a crash outcome?

  3. Moreover, introducing the createCar function inside the pure function move raises concerns regarding purity. How can this be rectified effectively? One potential solution could involve passing the createCar function as an argument to the move function?

Your insights are appreciated!

Answer №1

  1. Engaging in multiple tasks simultaneously does not necessarily negate functional programming principles (I believe what you mean by "valid" is pure functional programming). The purity of a function in functional programming lies in the fact that its output is solely determined by its inputs and nothing else. It also refrains from altering any external state or variables (known as "free variables" or global variables, which are variables not defined in the input parameters). The actions conducted in execute can be easily translated into a functional programming language like Haskell:
execute :: Car -> Command -> (Car, String)
execute car cmd = let newCar = move car cmd in (newCar, reportPosition newCar)
  1. If move needed to provide additional information, it could be incorporated into the return type while still maintaining purity. However, if considering a scenario where "if the car crashed" signifies an error state, this would typically be represented using a sum type (Maybe or Either in Haskell). For instance, utilizing Maybe: data Maybe a = Just a | Nothing, returning Nothing for a crash and Just position otherwise ensures that users of the move function can validate that no errors occurred.

  2. There should be no restriction on calling createCar within move. Both functions, move and createCar, do not modify any external state/variables and simply utilize the provided inputs in their outputs.

Reiterating my point from the initial post, many concepts from Haskell mentioned above (such as Maybe) have equivalents in libraries for JavaScript/TypeScript. Specifically, for TypeScript, resources like https://github.com/gcanti/fp-ts exist. Occasionally, it may be confusing due to varying names referring to the same concept in different libraries. For example, some libraries may use Option instead of Maybe.

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

Issue: Headers cannot be modified after being sent to the client - Node.js with Express and TypeScript

Greetings. I'm encountering the "Cannot set headers after they are sent to the client" error when trying to use res.redirect. This specific section of the code is triggered by a verification email. Everything works smoothly until the redirect step, w ...

Having an issue with the pop state function not functioning correctly

I am facing an issue with my images where clicking on a specific image changes the URL to that ID. However, I can only go back once and then the same URL is repeated every time I press the back button. Additionally, the forward button does not work at all. ...

Steps for navigating to a different page by clicking on a gridview row

Currently, I am utilizing a grid view on my webpage. My specific request is that upon clicking on any row within the grid, it should redirect to a separate page where all the details of the selected row will be displayed. Appreciate your assistance! ...

Encountering TypeScript errors when utilizing it to type-check JavaScript code that includes React components

My JavaScript code uses TypeScript for type checking with docstring type annotations. Everything was working fine until I introduced React into the mix. When I write my components as classes, like this: export default class MyComponent extends React.Compo ...

A guide on organizing JSX elements based on JSON data

What I Aim to Achieve: I am looking to display a list of elements using the .map method, and then arrange them in descending order based on their date. Despite attempting to use .sort and .filter before rendering the elements, I have not been successful. ...

How can I fix the issue with the Google Maps info window button not transferring the value in JavaScript

I have integrated Google Maps to display details. When I click on the marker icon, an info window opens up. I have included some values in the info window, but when I click on it, the value is not being passed. How can I resolve this issue? When I click ...

Undefined is the value assigned to Javascript Dot Notation

When using dot notation to access objects with a '.', I am encountering an issue that I cannot seem to figure out. The success function in my jQuery $.ajax function looks like this: success: function(data){ console.log('data = ' + da ...

Encountering a "type" property error with the cordova network plugin due to undefined value

During the development of my Android application using Cordova and Ionic framework, I encountered an issue with the network plugin from this source (https://github.com/apache/cordova-plugin-network-information). After the device ready alert triggers, I re ...

The transition() function in Angular 2.1.0 is malfunctioning

I am struggling to implement animations in my Angular 2 application. I attempted to use an example I found online and did some research, but unfortunately, I have not been successful. Can anyone please assist me? import {Component, trigger, state, anima ...

The reset function is malfunctioning on the meteor entity

Currently, I am going through an angular-meteor tutorial that can be found here I seem to be facing some issues with my code. Here's what I have: angular.module('socially').controller('PartyDetailsCtrl', function($scope, $statePa ...

What is the best way to connect socket.io to multiple instances of HTTPServer?

My Express server is set up to listen on both HTTP and HTTPS: Above, you can see the code snippet where I create the server instances for both HTTP and HTTPS protocols using Express. Currently, I am facing an issue with socket.io as it only listens to on ...

What steps should I take to modify this recursive function so that it can verify the property name of an object?

I stumbled upon the code snippet below online, which effectively and recursively eliminates properties from an object if their values are null, undefined, or 0 const removeEmpty = (obj) => { Object.keys(obj).forEach(key => (obj[key] & ...

Populating a ListBox without the need to constantly scroll upwards

I'm currently facing an issue with a ListBox that displays online users fetched from a MySQL database. Every second, the ListBox is updated with new users. The problem arises when adding an item to the ListBox causes it to scroll up, which I want to a ...

Querying with jQuery to Retrieve HTML from Elements with the Same Class

Greetings Everyone! Please take a look at my code... <font class="detDesc" > Uploaded 07-11&nbsp;2012, Size 105.79&nbsp;MiB, ULed by <a class="detDesc" href="/somelink" title="somelink title">somelink</a> </font> ...

Predicate returning negative type assertion

I need help writing two Jest functions that can verify if an object is an instance of a specific type or not. The function expectInstanceOf works perfectly, but unfortunately, the function expectNotInstanceOf is not functioning as expected. export functio ...

Utilizing AngularJS and Node.js to update MongoDB

Looking for a solution to update my MongoDB using Node.js and AngularJS within the front-end of my application. The code I currently have is causing an error stating `TypeError: Cannot read property 'put' of undefined. Here is my AngularJS contr ...

What is the method used by React or Next to prevent the <a> tag from refreshing the page while still loading content?

I'm currently diving into the world of NextJS and utilizing the Link component from the 'next/link' package. One thing that has been puzzling me is how the <Link> component ultimately renders an <a> tag with a href='/tosomew ...

What causes the "Error: method not allowed" message to appear when attempting to send a "DELETE" request from a Next Js component? (The POST method is

This is my first time on this platform, and I'm currently following a tutorial from Javascript Mastery to create a clone of a thread application. After watching the entire video and building the basic functionality based on it, I decided to enhance th ...

Tips for creating a tooltip above an SVG circle with AngularJS

I'm currently working on a project where I am using AngularJS and SVG to plot circles on a page. My goal is to have a tooltip appear when a user hovers over one of the circles. I came across an explanation on how to achieve this on this website, but u ...

Storing data in MongoDB upon the emission of a Socket.io event

In my project, I am using a MEAN stack and Socket.io to retrieve images from the real-time Instagram API. The current setup is functioning well, but now I want to store image data in a MongoDB database to maintain a record of images based on locations, rat ...