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:
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?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?Moreover, introducing the
createCar
function inside the pure functionmove
raises concerns regarding purity. How can this be rectified effectively? One potential solution could involve passing thecreateCar
function as an argument to themove
function?
Your insights are appreciated!