Suppose I have a class in JS with Typescript like this:
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()
}
}
When I create a Car instance and execute the execute method, two things happen:
- The internal state of the instance (x, y) is updated.
- The
executefunction returns a string.
Now I want to write the same thing in a more FP way, making the functions pure, but I stumble at the execute function.
My approach is this:
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]
}
My questions are the following:
Since
executedoes two things at once, I feel I am forced to return two values from it in the function. But this feels wrong. Is this "valid" functional programming? Or would I never create such a function in the FP world and just call each of the functions inside (move,reportPosition) separately.What if the
movefunction also had to return the information on whether the car has crashed after its move? Would I also have to return two values from that modified function: the new car instance and a boolean (indicating a crash)?Also, I used the
createCarfunction within themovefunction, which is technically not allowed for pure functions, correct? What would be the best way to fix that? Pass thecreateCarfunction as an argument tomove?
Thanks!
executefunction here.movereturns an altered state, then the caller can callreportPositionon the new state if they want to.