What is the equivalent of executing multiple instance methods in functional programming in JS? - javascript

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 execute function 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 execute does 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 move function 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 createCar function within the move function, which is technically not allowed for pure functions, correct?
What would be the best way to fix that? Pass the createCar function as an argument to move?
Thanks!

Doing two things at once doesn't necessarily make a function invalid functional programming (I think by "valid" you're referring to pure functional programming). What makes a function "pure" in functional programming is that its return value is only determined by its input values and nothing else. It also does not modify any external state or variables (referred to as "free variables" or global variables, meaning a variable that is not bound in the input parameters). What you're doing in execute can be expressed in a functional programming language trivially, for example Haskell:
execute :: Car -> Command -> (Car, String)
execute car cmd = let newCar = move car cmd in (newCar, reportPosition newCar)
If move had to report additional data, you could include it in the return type and it would remain pure. However, assuming "if the car crashed" is an error state, then typically this would be modeled by returning a sum type (Maybe or Either in Haskell). Take Maybe for example: data Maybe a = Just a | Nothing, if the car crashed you could return Nothing and if it didn't then return Just position, then anything using the move function can verify that it didn't return Nothing.
Why would you not be allowed to call createCar inside move? Neither move nor createCar are modifying any external state/variables, both are only using the inputs provided in their returns.
Re-iterating my comment in the main post, a lot of these things from Haskell that I mentioned above (e.g. Maybe) are available in libraries for JavaScript/TypeScript. For TypeScript in particular, there's https://github.com/gcanti/fp-ts. It can be a little bit confusing sometimes, as usually there are many names that refer to the same concept. For instance, some libraries refer to Maybe as Option.

Related

Lifespan of JS closure context objects?

Background
I'm trying to port the elixir's actor model language primitives into JS. I came up with a solution (in JS) to emulate the receive elixir keyword, using a "receiver" function and a generator.
Here's a simplified implementation and demo to show you the idea.
APIs:
type ActorRef: { send(msg: any): void }
type Receiver = (msg: any) => Receiver
/**
* `spawn` takes a `initializer` and returns an `actorRef`.
* `initializer` is a factory function that should return a `receiver` function.
* `receiver` is called to handle `msg` sent through `actorRef.send(msg)`
*/
function spawn(initializer: () => Receiver): ActorRef
Demo:
function* coroutine(ref) {
let result
while (true) {
const msg = yield result
result = ref.receive(msg)
}
}
function spawn(initializer) {
const ref = {}
const receiver = initializer()
ref.receive = receiver
const gen = coroutine(ref)
gen.next()
function send(msg) {
const ret = gen.next(msg)
const nextReceiver = ret.value
ref.receive = nextReceiver
}
return { send }
}
function loop(state) {
console.log('current state', state)
return function receiver(msg) {
if (msg.type === 'ADD') {
return loop(state + msg.value)
} else {
console.log('unhandled msg', msg)
return loop(state)
}
}
}
function main() {
const actor = spawn(() => loop(42))
actor.send({ type: 'ADD', value: 1 })
actor.send({ type: 'BLAH', value: 1 })
actor.send({ type: 'ADD', value: 1 })
return actor
}
window.actor = main()
Concern
Above model works. However I'm a bit concern about the performance impact of this approach, I'm not clear about the memory impact of all the closure contexts it creates.
function loop(state) {
console.log('current state', state) // <--- `state` in a closure context <─┐ <─────┐
return function receiver(msg) { // ---> `receiver` closure reference ──┘ │
if (msg.type === 'ADD') { │
return loop(state + msg.value) // ---> create another context that link to this one???
} else {
console.log('unhandled msg', msg)
return loop(state)
}
}
}
loop is the "initializer" that returns a "receiver". In order to maintain a internal state, I keep it (state variable) inside the closure context of the "receiver" function.
When receive a message, the current receiver can modifies the internal state, and pass it to loop and recursively create a new receiver to replace current one.
Apparently the new receiver also has a new closure context that keeps the new state. This process seems to me may create a deep chain of linked context objects that prevents GC?
I know that context objects referenced by closure could be linked under some circumstance. And if they're linked, they are obviously not released before the inner-most closure is released. According to this article V8 optimization is very conservative on this regard, the picture doesn't look pretty.
Questions
I'd be very grateful if someone can answer these questions:
Does the loop example creates deeply linked context objects?
What does the lifespan of context object look like in this example?
If current example does not, can this receiver creates receiver mechanism ends up creating deeply linked context objects under other situation?
If "yes" to question 3, can you please show an example to illustrate such situation?
Follow-Up 1
A follow-up question to #TJCrowder.
Closures are lexical, so the nesting of them follows the nesting of the source code.
Well said, that's something obvious but I missed 😅
Just wanna confirm my understanding is correct, with an unnecessarily complicated example (pls bear with me).
These two are logically equivalent:
// global context here
function loop_simple(state) {
return msg => {
return loop_simple(state + msg.value)
}
}
// Notations:
// `c` for context, `s` for state, `r` for receiver.
function loop_trouble(s0) { // c0 : { s0 }
// return r0
return msg => { // c1 : { s1, gibberish } -> c0
const s1 = s0 + msg.value
const gibberish = "foobar"
// return r1
return msg => { // c2 : { s2 } -> c1 -> c0
const s2 = s1 + msg.value
// return r2
return msg => {
console.log(gibberish)
// c3 is not created, since there's no closure
const s3 = s2 + msg.value
return loop_trouble(s3)
}
}
}
}
However the memory impact is totally different.
step into loop_trouble, c0 is created holding s0; returns r0 -> c0.
step into r0, c1 is created, holding s1 and gibberish, returns r1 -> c1.
step into r1, c2 is created, holding s2, returns r2 -> c2
I believe in the above case, when r2 (the inner most arrow function) is used as the "current receiver", it's actually not just r2 -> c2, but r2 -> c2 -> c1 -> c0, all three context objects are kept (Correct me if I'm already wrong here).
Question: which case is true?
All three context objects are kept simply because of the gibberish variable that I deliberately put in there.
Or they're kept even if I remove gibberish. In other word, the dependency of s1 = s0 + msg.value is enough to link c1 -> c0.
Follow-Up 2
So environment record as a "container" is always retained, as of what "content" is included in the container might vary across engines, right?
A very naive unoptimized approach could be blindly include into the "content" all local variables, plus arguments and this, since the spec didn't say anything about optimization.
A smarter approach could be peek into the nest function and check what exactly is needed, then decide what to include into content. This is referred as "promotion" in the article I linked, but that piece of info dates back to 2013 and I'm afraid it might be outdated.
By any chance, do you have more up-to-date information on this topic to share? I'm particularly interested in how V8 implements such strategy, cus my current work heavily relies on electron runtime.
Note: This answer assumes you're using strict mode. Your snippet doesn't. I recommend always using strict mode, by using ECMAScript modules (which are automatically in strict mode) or putting "use strict"; at the top of your code files. (I'd have to think more about arguments.callee.caller and other such monstrosities if you wanted to use loose mode, and I haven't below.)
Does the loop example creates deeply linked context objects?
Not deeply, no. The inner calls to loop don't link the contexts those calls create to the context where the call to them was made. What matters is where the function loop was created, not where it was called from. If I do:
const r1 = loop(1);
const r2 = r1({type: "ADD", value: 2});
That creates two functions, each of which closes over the context in which it was created. That context is the call to loop. That call context links to the context where loop is declared — global context in your snippet. The contexts for the two calls to loop don't link to each other.
What does the lifespan of context object look like in this example?
Each of them is retained as long as the receiver function referring to it is retained (at least in specification terms). When the receiver function no longer has any references, it and the context are both eligible for GC. In my example above, r1 doesn't retain r2, and r2 doesn't retain r1.
If current example does not, can this receiver creates receiver mechanism ends up creating deeply linked context objects under other situation?
It's hard to rule everything out, but I wouldn't think so. Closures are lexical, so the nesting of them follows the nesting of the source code.
If "yes" to question 3, can you please show an example to illustrate such situation?
N/A
Note: In the above I've used "context" the same way you did in the question, but it's probably worth noting that what's retained is the environment record, which is part of the execution context created by a call to a function. The execution context isn't retained by the closure, the environment record is. But the distinction is a very minor one, I mention it only because if you're delving into the spec, you'll see that distinction.
Re your Follow-Up 1:
c3 is not created, since there's no closure
c3 is created, it's just that it isn't retained after the end of the call, because nothing closes over it.
Question: which case is true?
Neither. All three contexts (c0, c1, and c2) are kept (at least in specification terms) regardless of whether there's a gibberish variable or an s0 parameter or s1 variable, etc. A context doesn't have to have parameters or variables or any other bindings in order to exist. Consider:
// ge = global environment record
function f1() {
// Environment record for each call to f1: e1(n) -> ge
return function f2() {
// Environment record for each call to f2: e2(n) -> e1(n) -> ge
return function f3() {
// Environment record for each call to f3: e3(n) -> e2(n) -> e1(n) -> ge
};
};
}
const f = f1()();
Even though e1(n), e2(n), and e3(n) have no parameters or variables, they still exist (and in the above they'll have at least two bindings, one for arguments and one for this, since those aren't arrow functions). In the code above e1(n) and e2(n) are both retained as long as f continues to refer to the f3 function created by f1()().
At least, that's how the specification defines it. In theory those environment records could be optimized away, but that's a detail of the JavaScript engine implementation. V8 did some closure optimization at one stage but backed off most of it because (as I understand it) it cost more in execution time than it made up for in memory reduction. But even when they were optimizing, I think it was the contents of the environment records they optimized (removing unused bindings, that sort of thing), not whether they continued to exist. See below, I found a blog post from 2018 indicating that they do leave them out entirely sometimes.
Re Follow-Up 2:
So environment record as a "container" is always retained...
In specification terms, yes; that isn't necessarily what engines literally do.
...as of what "content" is included in the container might vary across engines, right?
Right, all the spec dictates is behavior, not how you achieve it. From the section on environment records linked above:
Environment Records are purely specification mechanisms and need not correspond to any specific artefact of an ECMAScript implementation.
...but that piece of info dates back to 2013 and I'm afraid it might be outdated.
I think so, yes, not least because V8 has changed engines entirely since then, replacing Full-codegen and Crankshaft with Ignition and TurboFan.
By any chance, do you have more up-to-date information on this topic to share?
Not really, but I did find this V8 blog post from 2018 which says they do "elide" context allocation in some cases. So there is definitely some optimization that goes on.

A Typescript syntax clarification

I am reading a code written in Typescript. I'm not sure if I understand it correctly:
export class MyClass<B> {
value: B;
constructor(value: B) {
this.value = value;
}
isMyClass(): this is MyClass<B> {
return true;
}
}
What does the <B> stand for? What does it represent, a Type? If so, what Type is it?
What is this is MyClass<B> in isMyClass(): this is MyClass<B>? Is it being evaluated for true or false? Why not to put this inside of the function itself then, something like this:
isMyClass() {
if (this is MyClass) {
return true;
}
else {
return false;
}
}
And I am not able to find the answer to a these questions.
What does the <B> stand for? What does it represent, a Type? If so, what Type is it?
That's a type parameter, also known as generics. See the TS handbook.
In languages like C# and Java, one of the main tools in the toolbox for creating reusable components is generics, that is, being able to create a component that can work over a variety of types rather than a single one. This allows users to consume these components and use their own types.
Whenever one calls a function or creates an instance, if the function or class is generic, you can "pass" a type parameter to it, similar to how arguments can be passed to a function or constructor. (The difference is that the type parameter, being a type, doesn't exist in the emitted JS - it's just there to help TS type-check).
If so, what Type is it?
It's whatever type the constructor parameter is called with.
const m = new MyClass(3);
will result in
constructor(value: B)
where value is 3, telling TypeScript that the resulting instance is a MyClass<number> - in other words, that its value property holds a number, a B.
What is this is MyClass<B> in isMyClass(): this is MyClass<B>? Is it being evaluated for true or false? Why not to put this inside of the function itself then, something like this:
The
isMyClass(): this is MyClass<B> {
is a type guard. If the method returns true, it tells TypeScript that the instance is of type MyClass<B>.
While you could do something like:
isMyClass() {
if (this instanceof MyClass) {
return true;
}
else {
return false;
}
}
That wouldn't allow TypeScript to understand that the type has been narrowed when isMyClass is called; it'll just return a boolean. In contrast, using the is will both return a Boolean and give TypeScript type information about what was called.

Type casting in JavaScript

Example:
function action(value) {
// I want to operate on a string
String(value)...;
}
When we pass dynamic values into JavaScript's primary types (String, Number, Boolean, Object, etc.) we can (for want of a better word) cast the value to the specified type.
Is it possible to build this feature in custom types, and how would I go about this?
Example of what I would like to do:
function action(value) {
Point(value)...;
// Value at this point (excuse the pun) is a point
// // *** Would like to see that intellisense is aware of the type at this point, but please don't assume this is ONLY for intellisense***
}
Is it possible to call constructor functions in this way and have the constructor function "cast" the value to an instance of itself - or does this only work for JavaScript's primary types?
Your custom constructor can just examine the typeof the arguments that it is passed and behave accordingly. This isn't technically a "cast", but rather writing code to examine the types of the arguments and then decide on the proper behavior which can include converting from one type to another.
See How to overload functions in javascript? for a much longer description of how to examine arguments sent to any function and then adjust the behavior of the function based on the type and position and presence of the arguments. This same functionality can be used to do something that is "cast" like (though we don't usually think of casting in Javascript, but rather just converting).
We could give you actual code examples if you can be more specific about what types you want to "cast" in your Point constructor.
There are some simple examples of "cast" like things:
function delay(fn, t) {
// if t is passed as a string represeantation of a number,
// convert it to an actual number
return setTimeout(fn, +t);
}
Or, a little more interesting example that can take a number of ms, a string with units at the end or an object with properties:
function delay(fn, t) {
var typeT = typeof t, ms, matches, num, multiplier,
suffixes = {ms: 1, sec: 1000, min: 1000 * 60, hr: 1000 * 60 * 60};
if (typeT === "string") {
matches = t.match(/^([\d.]+)(.+)$/);
if (matches) {
num = +matches[1];
multiplier = suffixes[matches[2]];
if (multiplier) {
ms = num * multiplier;
}
}
} else if (typeT === "number") {
// plain number is milliseconds
ms = t;
} else if (typeT === "object" && t.units && t.value) {
multiplier = suffixes[t.units];
if (multiplier) {
ms = t.value * multiplier;
}
}
if (ms === undefined) {
throw new Error("Invalid time argument for delay()");
}
return setTimeout(fn, ms);
}
delay(myFn, "2.5hr");
delay(myFn, "25sec");
delay(myFn, 150);
delay(myFn, {units: "sec", value: 25});
If you are serious about type enforcing
(and there is a lot of good reasons to be)...
and you want to continue to use Javascript...
maybe you should give a try to TypeScript
It enforces type checking and compiles down to Javascript
Which gives you the option to publish the TypeScript for inline compilation...
Or if you intent a bit for your work (like me)...
you can develop a project and spit-out the Javascript before uploading... in this phase you can optimize the 'thing'...
pass a Linter, a Minifier and a Obfuscator...
and you'll get highly optimized and a bit protected piece of code (if we are talking about client-side of course, at server side no obfuscation is advised).
Another BIG-BIG-BIG advantage (to me at least) is that you can use the best Intellitype/Intellisense/Refactor IDE (VS 2013R4 CE) which is free.
See here the last features in TypeScript...
TypeScript at Build/2014 by Anders Hejlsberg (channel9)
ZEE

why would I return a named function (object) from a javascript function?

Maybe I'm missing something obvious ... I've just started working with JavaScript, and when looking through an article about unit testing JavaScript with Jasmine, I came across this code:
function Convert(number, fromUnit) {
var conversions = {
distance : {
meters : 1,
cm : 0.01,
feet : 0.3048,
inches : 0.0254,
yards : 0.9144
},
volume : {
litres : 1,
gallons: 3.785411784,
cups : 0.236588236
}
},
betweenUnit = false,
type, unit;
for (type in conversions) {
if (conversions[type]) {
if ( (unit = conversions[type][fromUnit]) ) {
betweenUnit = number * unit * 1000;
}
}
}
return {
to : function (toUnit) {
if (betweenUnit) {
for (type in conversions) {
if (conversions.hasOwnProperty(type)) {
if ( (unit = conversions[type][toUnit]) ) {
return fix(betweenUnit / (unit * 1000));
}
}
}
throw new Error("unrecognized to-unit");
} else {
throw new Error("unrecognized from-unit");
}
function fix (num) {
return parseFloat( num.toFixed(2) );
}
}
};
}
It puzzled me as to why/how it is used, and what's the reason for it. It appears to return an object, which is a labeled function (method really, according to JavaScript naming convention), which wouldn't be called or returned upon creation.
After pondering about this and running it in chrome dev tools, it hit me that being called Convert with a capital C, it might be used as a constructor that would be used with new (again, according to JavaScript naming convention) so I might create an object like:
var tenFeet = new Convert(10, 'feet'); and then use it as tenFeet.to('cm');.
This still makes no sense, since I wouldn't call the object (read: class) Convert, since it's not converting. I'd call the to method convertTo, and probably name Convert to Measurement or something.
Is this simply bad code with bad naming, am I simply rooted too deeply in conventional OO and "formal" languages, or am I missing something basic?
When / where / why would I use something like the above: "return labeled method" from an object in JavaScript?
Couldn't the same be achieved by enhancing the prototype of Convert with the same method?
Cheers, and thanks in advance.
This is following the "read like a sentence" paradigm that some people like:
Convert(10, 'meters').to('feet') === 32.81
// Convert 10 meters to feet
You're right, the function goes against common naming conventions, but you can sort of guess that it shouldn't be created with the new keyword because there are no references to this in the function body.
This problem could've been avoided with proper documentation.
Blender answered this correctly, but just in case other people stumble upon page, here's a little more info on what's happening.
Coming from more "formal" languages, I guess I was having issues with the "label" appearance of the to in the return statement.
from MDN on Label:
Summary
Provides a statement with an identifier that you can refer to using a break or continue statement.
For example, you can use a label to identify a loop, and then use the break or continue statements to indicate whether a program should interrupt the loop or continue its execution.
Syntax
label : statement
Do notice that if you're creating an object, the syntax is similar. For example:
person={firstname:"John",lastname:"Doe",age:50,eyecolor:"blue"};
This will result in an object looking like:
object {firstname: "John", lastname: "Doe", age: 50, eyecolor: "blue"}
Another note is that if you're creating an array, you'll just use the commas, like this:
person=["John","Doe",50,"blue"];
This will give an array looking like:
["John", "Doe", 50, "blue"]
It takes a bit of time to get used to JavaScript syntax and logic, but all that really happens in my example is that the function returns an object, that has a method (named to) defined on it.
Once you have that object, you can call the method on it using the usual dot notation, which results in the chaining that is used in the above case. Or reusing Blender's example:
Convert(10, 'meters').to('feet') === 32.81`

Javascript OOP - Best practices when validating objects via interface or prototype

I am learning more advanced OO tactics for javascript coming from a C# background and am wondering about how to or if its even a good idea to implement prototype based validation. For instance when an object or function requires one of its parameters to satisfy a certain interface, you could check its interface like so,
var Interface = function Interface(i) {
var satisfied = function (t, i) {
for (var key in i) {
if (typeof t !== 'object') {
return false;
}
if (!(key in t && typeof t[key] == i[key])) {
return false;
}
}
return true;
}
this.satisfiedBy = function (t) { return satisfied(t, i); }
}
// the interface
var interfacePoint2D = new Interface({
x: 'number',
y: 'number'
});
// see if it satisfies
var satisfied = interfacePoint2D.satisfiedBy(someObject);
I came up with this strategy to validate an object by its interface only, ignoring the internal implementation of the object.
Alternatively say you are using prototype-based inheritance, should you or should not validate parameters based on their prototype functions? I understand that you'd use a prototype to implement default functionality whereas an interface doesn't specify any default functionality. Sometimes the object you are passing into a function might need certain default functionality in order for that function to work. Is it better to only validate against an interface, or should you ever validate against a prototype, and if so, whats the best way to do it?
EDIT -- I am providing some more context as to why I am asking this,
Say for instance in online game design (games written mostly in javascript). There are 2 main reasons I am interested in validation within this context,
1) Providing a strong public API for modding the game if desired
2) Preventing (or atleast discouraging greatly) potential cheaters
Which requires a balance between customizability and abuse. Specifically one situation would be in designing physics engine where objects in the game react to gravity. In a realistic system, users shouldn't be able to add objects to the system that do not react to gravity. The system has a function that expresses the global effect of gravity at any given point:
function getGravityAt(x, y) {
// return acceleration due to gravity at this point
}
And objects which react have a method that uses this to update their acceleration:
function update() {
this.acceleration = getGravity(this.position);
}
The minimum thing to do might be to ensure that any object added to the system has an 'update' method, but you still aren't ensuring that the update() method really is intended to react to gravity. If only objects that inherit from a prototypical update() method are allowed, then you know at least to some degree everything in the system reacts realistically.
This is a pretty subjective question. I'll pass on the question of whether it's a good idea to do interface-based validation in Javascript at all (there may well be good use-cases for it, but it's not a standard approach in the language). But I will say that it's probably not a good idea to validate objects based on their prototypes.
If you're validating by interface at all, you're probably working with objects created by other programmers. There are lots of ways to create objects - some rely on prototypes, some do not, and while they each have their proponents, they're all valid and likely approaches. For example:
var Point = function(x,y) {
return {
x: function() { return x },
y: function() { return y }
};
};
var p = new Point(1,1);
The object p conforms to an interface similar to yours above, except that x and y are functions. But there's no way to validate that p satisfies this interface by inspecting its constructor (which is Object()) or Point.prototype. All you can do is test that p has attributes called x and y and that they are of type "function" - what you're doing above.
You could potentially insist that p has a specific ancestor in its prototype chain, e.g. AbstractPoint, which would include the x and y functions - you can use instanceof to check this. But you can't be sure that x and y haven't been redefined in p:
var AbstractPoint = function() {};
AbstractPoint.prototype.x = function() {};
AbstractPoint.prototype.y = function() {};
var Point = function(x,y) {
var p = new AbstractPoint(x,y);
p.x = "foo";
return p;
}
var p = new Point(1,1);
p instanceof AbstractPoint; // true
p.x; // "foo"
And perhaps more importantly, this makes it harder to drop in custom objects that also satisfy the interface but don't inherit from your classes.
So I think what you're currently doing is probably the best you can hope for. In my experience, Javascript programmers are much more likely to use on-the-fly duck-typing than to try to mimic the capabilities of statically typed languages:
function doSomethingWithUntrustedPoint(point) {
if (!(point.x && point.y)) return false; // evasive action!
// etc.
}
I'll reiterate, type checking is not idiomatic javascript.
If you still want type checking, Google's closure compiler is the implementation I recommend. Type checking is done statically :) It has conventions for interfaces as well as (proto)type checking.

Categories