Operating on two Eithers - javascript

Suppose that you have the following code:
import R from "ramda";
import S from "sanctuary";
import { Left, Right } from "sanctuary-either";
const add = R.curry((p1, p2) => p1 + p2);
const addOne = add(1);
const func1 = () => Right(2);
const func2 = () => Right(7);
Combining addOne with func1 or func2 is relatively easy:
const res = R.compose(
S.map(addOne),
func1
)();
but how can one call add using func1 and func2 as arguments?
p.s. I know that ramda offers an add function. Consider the example as an abstraction of a real world problem.

You are probably looking for the lift2 function:
const addEithers = S.lift2(add)
console.log(addEithers(func1())(func2()))
Alternatively, you can use ap:
S.ap(S.map(add)(func1()))(func2())

Related

Why use destructuring here?

I asked this question on The Odin Project where I encountered it and was directed to research destructuring, which I did. I understand what is happening but I'm at a loss as to why it is being done this way. Simply using raw variable names with no destructuring braces gets the same result (see my jfiddle link where I removed the destructuring and got the same result). I find it hard to learn something when I'm directed to use more code, typing, and complexity to achieve the same outcome. what benefit is received here by using return {sayName} in const Person and const {sayName} = Person(name) in const Nerd? I used return sayName and const sayName in the jfiddle and got the same result.
Original code:
const Person = (name) => {
const sayName = () => console.log(`my name is ${name}`)
return {sayName}
}
const Nerd = (name) => {
// simply create a person and pull out the sayName function with destructuring assignment syntax!
const {sayName} = Person(name)
const doSomethingNerdy = () => console.log('nerd stuff')
return {sayName, doSomethingNerdy}
}
const jeff = Nerd('jeff')
jeff.sayName() //my name is jeff
jeff.doSomethingNerdy() // nerd stuff
jfiddle:
const Person = (name) => {
const sayName = () => console.log(`my name is ${name}`)
return sayName
}
const Nerd = (name) => {
// simply create a person and pull out the sayName function with destructuring assignment syntax!
const sayName = Person(name)
const doSomethingNerdy = () => console.log('nerd stuff')
return {sayName, doSomethingNerdy}
}
const jeff = Nerd('jeff')
jeff.sayName() //my name is jeff
jeff.doSomethingNerdy() // nerd stuff
The general consensus is that this is a bad example for destructuring, but I've gone too far deep and will still attempt to make sense of it.
By using destructuring, it becomes possible to add additional functions to Person.
For example, Person needs to jump:
const Person = (name) => {
const sayName = () => console.log(`my name is ${name}`)
const jump = () => console.log('I jumped') // new feature
return {sayName, jump} // jump can inserted into the object here and used externally
}
Then, as pointed out in the comments, a much better way to pass Person into Nerd would be to:
const Nerd = (name) => {
// simply create a person and pull out the sayName function with destructuring assignment syntax!
const doSomethingNerdy = () => console.log('nerd stuff')
return {...Person(name) , doSomethingNerdy}
}
Before finally, Nerd can be destructured, and all the functions inside Person and Nerd can be used.
I suppose that's what they're trying to get at.

Check and modify functions default argument values

I have the following function:
const setDefaults = (func, defArgs) => {
//should return the func with default arguments modified
// so that in case that an argument is not passed to the function,
// but it is provided in default Argument, the default argumnt is used
}
func: is a function that needs to have default parameters assigned from the defArgs
defArgs: set of default arguments
For example:
const greet = name => `Hi, ${name}!`
setDefaults(greet, {name: 'friend'})
greet(); // Hi, friend!
So far I have started diving into func.toString() and thinking about modifying the original function as a string and then eval the output, but that seems a bit verbose, so I was wondering if there is any better way to do this.
greet(); // Hi, friend!
You can't modify the original function because it's a const. If you mean to do something like this:
const greet = name => `Hi, ${name}!`
const parasiticGreet = setDefaults(greet, {name: 'friend'})
parasiticGreet(); // Hi, friend!
It is possible but I would simplify it like this:
const greet = name => `Hi, ${name}!`
const setDefaults = (func, defArgs = []) => (...args) => func(...defArgs.map((x, i) => args[i] === undefined ? x : args[i]));
const parasiticGreet = setDefaults(greet, ['friend']);
console.log(parasiticGreet()); // Hi, friend!

How to change the value that a template string extrapolates

I'm trying to write a simple Id monad to play around with and learn.
Here is what I've written:
const util = require('util');
const Id = x => ({
[util.inspect.custom]: () => `Id(${x})`,
map: f => Id.of(f(x)),
flatMap: f => f(x),
valueOf: () => `Id(${x})`,
});
Id.of = Id;
const foo = Id.of('foo');
const toUpper = str => Id.of(str.toUpperCase());
const fooBoxed = foo.map(toUpper); // Oh oh, should be Id(Id('FOO'));
const FOO = foo.flatMap(toUpper); // Yay, Id('FOO');
console.log(fooBoxed);
console.log(FOO);
fooBoxed should log out Id(Id(Foo)), but it logs out Id([object object]).
I tried modifying valueOf and inspect but both doesn't work. I suspect that ${x} calls a different method and I couldn't find on the internet which that is. What do I have to modify so that ${x} returns the correct string for my nested Id monad?
You will want to overwrite toString, not valueOf. Concatenating with a string (or interpolating a template string) will coerce the value to a string, and your objects inherit Object.prototype.toString which returns [object …].
const Id = x => ({
toString: () => `Id(${x})`,
map: f => Id.of(f(x)),
flatMap: f => f(x),
});
Id.of = Id;
const foo = Id.of('foo');
const toUpper = str => Id.of(str.toUpperCase());
const fooBoxed = foo.map(toUpper);
const FOO = foo.flatMap(toUpper);
console.log(fooBoxed.toString()); // Yay, Id(Id('FOO'));
console.log(FOO.toString()); // Yay, Id('FOO');
However, since you seem to intend to use this for debugging, you should actually use the debugging representation of your x value. To do that, call util.inspect() yourself:
const util = require('util');
const Id = x => ({
[util.inspect.custom]: () => `Id(${util.inspect(x)})`,
// ^^^^^^^^^^^^
map: f => Id.of(f(x)),
flatMap: f => f(x),
valueOf: () => x,
});
Id.of = Id;

How to test class constructor in Jest

Let's say I have a class like following:
class SomeClass {
constructor(a, b) {
this.a = a;
this.b = b;
}
}
How can I test through Jest that constructor was initialized the right way? Say... this.a = a and this.b = b and not vice versa?
I know that I can execute toBeCalledWith but that won't let me check the constructor's logic. I was also thinking about making mockImplementation but in this case it seems pointless as I will rewrite the logic, or I may not be aware of all the nuances of creating mocks
Just create an instance of the object and check it directly. Since it sets them on this, they are essentially public values:
it('works', () => {
const obj = new SomeClass(1, 2);
expect(obj.a).toBe(1);
expect(obj.b).toBe(2);
});
You can simply check the instance properties after initializing the class. Basicly the same as you can test the side effects of any function.
const a = Symbol();
const b = Symbol();
const classInstance = new SomeClass(a, b);
expect(classInstance.a).toBe(a);
expect(classInstance.b).toBe(b);
if you know where the class is coming from you can do something like this:
jest.mock('path/to/module');
...
it('should work', () => {
const a = Symbol();
const b = Symbol();
expect(SomeClass).toBeCalledWith(a, b);
});

How do I test call and apply functions in jest?

Here's my callnapply.js file
const callAndApply = {
caller(object, method, nameArg, ageArg, tShirtSizeArg) {
method.call(object, nameArg, ageArg, tShirtSizeArg);
},
applier(object, method, argumentsArr) {
method.apply(object, argumentsArr);
},
};
module.exports = callAndApply;
And here's a snippet from the test file which contains the non-working test:
const callnapply = require('./callnapply');
test('testing Function.prototype.call as mock function', () => {
const outer = jest.fn();
const name = 'Aakash';
const age = 22;
const tee = 'M';
callnapply.caller(this, outer, name, age, tee);
expect(outer.call).toHaveBeenCalledWith(name, age, tee);
});
How do I write the test to check if the method that I am passing is, in fact, being called by the Function.prototype.call function only? I want to check whether .call() is being called and not some other implementation that has been written for the method call.
You can mock the .call() method itself:
const outer = function() {}
outer.call = jest.fn()
Then you can do usual jest mock tests on outer.call.
Here is the working test file:
const callnapply = require('./callnapply');
test('testing Function.prototype.call as mock function', () => {
const outer = function() {};
outer.call = jest.fn();
const name = 'Aakash';
const age = 22;
const tee = 'M';
callnapply.caller(this, outer, name, age, tee);
expect(outer.call).toHaveBeenCalledWith(this, name, age, tee);
});
See this working REPL.

Categories