Array Spread Operator in Pure Function - javascript

In Redux Tutorial, they have used array spread operator a lot for writing reducers(which have to be pure functions) . Go through the following script.
let a = {
b : "ddff",
c : "adxas"
}
let c = {
b : "ssdds",
c : "asdxasdsad"
}
let d = [];
d.push(a);
d.push(c);
console.log(d);
const pureFunc = (arr,b,c) => {
return [...arr, { b , c}];
}
let n = pureFunc(d,"daaaa","sdadad");
console.log(n);
d[0].b = "Hello";
console.log(n)
Is the function "pureFunc" is a proper pure function. Mutations on array d are getting reflected in object n.

Yes, pureFunc is pure. The mutation does not occur within pureFunc.
One of the most common and basic pure functions is the identity function:
let identity = x => x;
So, if we pass that an object, we'll get the same object back. We can modify it after the fact, but that doesn't make identity impure, because identity isn't doing the mutation.
Basically, pure functions only need to satisfy two requirements:
They always produce the same output given the same input
They do not cause side effects

Related

How can I see if 2 specific string variables added

How can I check if 2 variables with the same value are the same variable?
For example in the below code I created 2 variables with the same values and i pass:
function check_var(v){
// Check if "v" (string) came from a or b
}
let a = "string";
let b = "string";
check_var(b);
I able to install v8 engine locally and change the the source code, but i am looking for more easy way to do it.
One way to do it is if I had a method in javascript that returns a unique value for each variable based on the variable name.
One more way to solve the problem is by logging all the javascript actions, by doing that i could see after the code executed if var a is the var that got into the check_var function.
In general you cannot, JavaScript doesn't have a universal identity equality operator.
Strings, numbers and some other simple values can only be compared by value. Tho objects, including arrays are compared by identity.
const a = [1]
const b = [1]
a===b // false
If this is important you could box the value
const a = { value: 'string' }
const b = { value: 'string' }
const c = a
a.value === b.value // true
a === b // false
a === c // true

How to access a function calling context in JavaScript?

Pandas Dataframe's query method can refer to variables in the environment by prefixing them with an ‘#’ character like #a, ex:
seq = [1,2,3,4]
df.query('col1.isin(#seq)')
The method df.query can access the calling context and assign the seq variable value to #seq. I want to add this function in JavaScript, but how to access the function calling context in JavaScript?
Pandas is built on Python, which is different from JavaScript. (You knew that, of course, but... 🙂)
If we had code like your example in JavaScript, there would be no way for the query function to access the value of the seq local variable (I'm assuming it's local, not global). It just has no way to reach it.
If we wanted similar functionality, we'd probably use a tagged template function:
seq = [1,2,3,4];
df.query`col1.isin(${seq})`;
(That's a tagged function call, one of two/three kinds of function calls in JavaScript that don't use ().)
That creates a template object and calls df.query with that template object and an argument for each substitution (${...}) in the template. The function still doesn't reach out and get it, it's the template literal (the bit in backticks) that gets the value, which is then passed to the function.
Just for illustration:
function logArray(label, array) {
console.log(label + ":");
array.forEach((element, index) => {
console.log(` ${index}: ${JSON.stringify(element)}`);
});
}
const df = {
query(template, ...args) {
logArray("template", template);
logArray("args", args);
}
};
const seq = [1,2,3,4];
df.query`col1.isin(${seq})`;
Note that what gets passed to the function is the actual array, not a string version of it, so we can use that array to see if col1 is in [1,2,3,4], like this:
const df = {
col1: 2,
query(template, ...args) {
// (You'd need to have some parser here for the DSL aspects
// of your query; this is just a hardcoded example)
if (template[1] === ".isin(") {
// In `${"col1"}.isin(${seq})`, args[0] will be the
// string "col1" and args[1] will be the array from
// `seq`
return args[1].includes(this[args[0]]);
} else {
throw new Error(`Unknown expression`);
}
}
};
let seq = [1,2,3,4];
let result = df.query`${"col1"}.isin(${seq})`;
console.log(result); // true, because df.col1 is 2 and that's
// in [1,2,3,4]
seq = [5,6,7,8];
result = df.query`${"col1"}.isin(${seq})`;
console.log(result); // false, because df.col1 is 2 and that's not
// in [5,6,7,8]

How to write a composed function using Ramda compose?

How to modify the zComposedFn function so that the output of both z and zComposedOutput is same?
const R = require('ramda');
let f1 = R.curry((p1, p2, p3) => {
let result = {
n1: p1,
n2: p2,
n3: p3
};
return result;
}
);
let x = f1(1, 2, 3);
let y = f1(1, 2, x);
let z = f1(1, x , y);
console.log(z);
let zComposedFn = R.compose(f1);
let input = [1,2,3];
let zComposedOutput = zComposedFn(...input);
console.log(zComposedOutput);
The goal is to create some metric calculation functions having the same signature and output type but different implementation.
const MetricFn = (m,f,a) => {<to be implemented using switch case on m> return b}
m : name of metric as string
f : Array of functions utilizing input data objects
a : input data object
example:
There is a financial dashboard, which receives the input data as (1,2,3). The dashboard displays the metric1, metric2 and metric3 calculated as below:
metric1 = MetricFn('metric1',[f1])(1,2,3);
metric2 = MetricFn('metric2',[f1, f2])(1,2,3);
metric3 = MetricFn('metric3',[f1, f2, f3])(1,2,3);
I am wondering on how to create the structure of MetricFn.
I can make very little sense out of your function. And I don't see anything that Ramda offers to help. While I'm a Ramda author, I don't always recall every function, but it seems unlikely.
Your requirements looks vaguely like the use of chain with functions, where chain(f, g) ~~> x => f(g(x))(x). But it's only a vague connection, and I can't see how to use chain to do what you are trying to do.
Is there an underlying problem you're trying to solve that we might be able to help with?
Here is a trivial implementation, but it's mostly just restating your code without the intermediate variables:
const foo = curry((f, a, b, c) => f(a, f(a, b, c), f(a, b, f(a, b, c))))
foo(f1)(1, 2, 3)

What would be a good example of an endofunctor that is not the identity functor?

In Professor Frisby Introduces Composable Functional JavaScript the identity functor was introduced:
const Box = x =>
({
map: f => Box(f(x)),
fold: f => f(x) // for testing
})
I spent the better part of the day understanding functors and why the above JavaScript code is actually the identity functor. So I thought I would alter it to get a "real" functor that is not the identity functor. I came up with this:
const Endo = x =>
({
map: f => Endo(f(x).split('')),
fold: f => f(x).split('') // for testing
})
My reasoning is that with Box, Id_Box: Box -> Box and Id_Box f = f. Endo would also map to itself but Endo(f): Endo(x) -> Endo(y) (if f: x -> y).
Am I on the right track?
EDIT:
Replaced string with the more generic x as it was in the original examples.
As pointed out in this answer, for our purposes as programmers we can treat all functors as endofunctors so don't get too caught up on the differences.
As for what a functor is, in brief it is
a data structure (Box in your example)
that can support a mapping operation (think Array.prototype.map)
and that mapping operation respects identity: xs === xs.map(x => x)
...and composition: xs.map(f).map(g) === xs.map(f . g) where . is function composition.
That's it. No more, no less. Looking at your Box, it's a data structure that has a map function (check 1 & 2) and that map function looks like it should respect identity and composition (check 3 & 4). So it's a functor. But it doesn't do anything, which is why it's the identity functor. The fold function isn't strictly necessary, it just provides a way to 'unwrap' the box.
For a useful functor, let's look at JavaScript arrays. Arrays actually do something: namely they contain multiple values rather than just a single one. If an array could only have one element, it'd be your Box. For our purposes we'll pretend that they can only hold values of the same type to simply things. So an array is a data structure, that has a map function, that respects identity and composition.
let plus = x => y => x + y;
let mult = x => y => x * y;
let plus2 = plus(2);
let times3 = mult(3);
let id = x => x;
let compose = (...fs) => arg => fs.reverse().reduce((x, f) => { return f(x) }, arg);
// Here we need to stringify the arrays as JS will compare on
// ref rather than value. I'm omitting it after the first for
// brevity, but know that it's necessary.
[1,2,3].map(plus2).toString() === [3,4,5].toString(); // true
[1,2,3].map(id) === [1,2,3]; // true
[1,2,3].map(plus2).map(times3) === [1,2,3].map(compose(times3, plus2)); // true
So when we map a function over a functor (array) we get back another instance of the same functor (a new Array) with the function applied to whatever the functor (array) was holding.
So now lets look at another ubiquitous JavaScript data structure, the object. There's no built in map function for objects. Can we make them a functor? Assume again that the object is homogenous (only has keys to one type of value, in this example Number):
let mapOverObj = obj => f => {
return Object.entries(obj).reduce((newObj, [key, value]) => {
newObj[key] = f(value);
return newObj;
}, {});
};
let foo = { 'bar': 2 };
let fooPrime = mapOverObj(foo)(plus2); // { 'bar': 4 }
And you can continue on to test that the function accurately (as far as is possible in JavaScript) supports identity and composition to satisfy the functor laws.

Using variables with nested Javascript object

Suppose I have this:
var a = { A : { AA : 1 }, B : 2 };
Is there a way for me to create a variable that could allow me to reference either AA or B? What would the syntax look like?
// I know I can do this:
a['B']; // 2
a['A']['AA']; // 1
// something like this?
var myRef = ???;
a[myRef]; 1 or 2 depending on myRef
If not, what's a better way to get what I'm going for here?
Not directly.
Solution 1 - use object flattening
Flatten object, to have new object var a = { 'A.AA' : 1; B : 2 };.
See compressing object hierarchies in JavaScript
or Flattening a complex json object for mvc binding to get the javascript function for it.
Soution 2 - write key-path accessor
I can see it was already addressed by Eugen.
Reposted code-reviewed version:
function Leaf(obj,path) {
path=path.split('.');
var res=obj;
for (var i=0;i<path.length;i++) res=res[path[i]];
return res;
}
Solution 3 - use eval
var x = eval("a." + myRef); // x will be 1 for myRef == "A.AA", 2 for "B"
Be careful with this solution as you may introduce some security issues. It is more of the curiosity.
Since i also encounter this problem, i wrote also a one line util for this (ES6):
const leaf = (obj, path) => (path.split('.').reduce((value,el) => value[el], obj))
Example:
const objSample = { owner: { name: 'Neo' } };
const pathSample = 'owner.name';
leaf(objSample, pathSample) //'Neo'
function Leaf(obj,path) {
path=path.split('.');
var res=obj;
for (var i=0;i<path.length;i++) obj=obj[path[i]];
return res;
}
Leaf(a,'B')=2
Leaf(a,'A.AA')=1
Decorate with error handling etc. according to your needs.
With lodash _.get function, you can access nested properties with dot syntax.
Node server-side example:
const _ = require('lodash');
let item = { a: {b:'AA'}};
_.get(item, 'a.b');
Actually no, because js object are seen as property bags and doing a[X] is for accessing first level properties only...
But you could wrap the logic a['A']['AA']; // 1 in a function that does the same, like this
//WARN... no undefined check here => todo !
function _(o, path) {
var tmp = o
for (var i=0 ; i < path.length ; i++) {
tmp = tmp[path[i]]
}
return tmp
}
var r = _(a, ['A', 'AA'])
This is pretty much the same as other answers, but the difference is when dummy boy create object property name containing dots... Like var a = {"a.a" : 3 } is valid.
Now, such problem would occurs maybe more often now with the help of IndexedDB to store anything locally...

Categories

Resources