I'm implementing the game Tic Tac Toe/Naughts and Crosses in a functional programming style and have stumbled across a hurdle with curried functions.
I have a reoccurring pattern of functions in the form func(width, height, index) which I then wish to curry, binding width and height and leaving curriedFunc(index).
However the problem arises when I have functions that expect one of these curried functions to be defined at compile-time.
They cannot be defined at compile time, because they need input from the user to then bind the values to the function.
Below is some example code of the pattern I've encountered.
// Board indexes:
// 0 | 1 | 2
// ---+---+---
// 3 | 4 | 5
// ---+---+---
// 6 | 7 | 8
const getRowNumGivenWidth = w => i => Math.floor(i/w);
// I want to be able to declare nextIndexInRowGivenWidth() here, outside of main()
// but getRowNum() needs to be defined beforehand
const main = () => {
// User input:
const width = 3;
// ...
const getRowNum = getRowNumGivenWidth(width);
const nextIndexInRowGivenWidth = width => currentIndex => {
const rowNum = getRowNum(currentIndex);
const nextIndex = currentIndex + 1;
if (getRowNum(nextIndex) != rowNum)
result = nextIndex - width;
else
result = nextIndex;
return result;
};
const nextIndexInRow = nextIndexInRowGivenWidth(width);
const board = [0, 1, 2, 3, 4, 5, 6, 7, 8];
board.map(x => console.log(x, " -> ", nextIndexInRow(x)));
// ...
}
main();
The only way I can think of solving this is to pass the curried function as an argument (to nextIndexInRowGivenWidth() in this example).
However I don't think this is ideal as if a function requires a few similarly curried functions at run-time, it quickly becomes unwieldy to define and curry said function.
The ideal solution would be if I could somehow make the binding of the values dynamic, suppose I could put the declaration getRowNum = getRowNumGivenWidth(width); before main(). This way I could call something like getRowNum(someInt) to initialise getRowNum() which I could then use in other functions that are already expecting it to be defined.
As this is a reoccurring pattern in my code, I was wondering if there is a design pattern to achieve this.
I think you are looking for
const getRowNumGivenWidth = w => i => Math.floor(i/w);
const nextIndexInRowGivenWidth = width => {
const getRowNum = getRowNumGivenWidth(width);
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
return currentIndex => {
const nextIndex = currentIndex + 1;
if (getRowNum(nextIndex) != getRowNum(currentIndex))
return nextIndex - width;
else
return nextIndex;
};
};
const main = () => {
// User input:
const width = 3;
const nextIndexInRow = nextIndexInRowGivenWidth(width);
// ...
}
Alternatively, you could define that nextIndexInRowGiven… function not with the width as the first curried parameter, but with getRowNum itself as the parameter:
const getRowNumGivenWidth = w => i => Math.floor(i/w);
const nextIndexInRowGivenRowNumGetter = getRowNum => currentIndex => {
const nextIndex = currentIndex + 1;
if (getRowNum(nextIndex) != getRowNum(currentIndex))
return nextIndex - width;
else
return nextIndex;
};
const main = () => {
// User input:
const width = 3;
const nextIndexInRow = nextIndexInRowGivenRowNumGetter(getRowNumGivenWidth(width));
// ...
}
Related
I am working on a project that visualizes various path algorithms.
The method I chose to update the visual effects were to use document.querySelector(node).classList and update the class to match CSS.
This is the start of the logic, which is triggered by click event.
const visualizeDijkstra = () => {
isVisualizing = true;
const startNode = grid[startNodePos.row][startNodePos.col];
const finishNode = grid[finNodePos.row][finNodePos.col];
const visited = initiateDijkstra(grid, startNode, finishNode);
const path = getPath(finishNode);
animateVisitedAndPath(visited, path);
};
The variables visited and path are arrays containing the result of the algorithm. Each item inside the array is an object containing the coordinates for the grid.
const animateVisitedAndPath = (visited: INode[], path: INode[]) => {
let totalTime = 0;
for (let i = 0; i < visited.length; i++) {
const { row, col } = visited[i];
animateAsVisited(row, col, i, speed, startNodePos, finNodePos);
if (i === visited.length - 1) {
animatePath(path, i, speed, startNodePos, finNodePos);
}
if (i === visited.length - 1) {
totalTime = (i + path.length) * speed;
setTimeout(() => {
isVisualizing = false;
}, totalTime);
}
}
};
Inside animatedVisitedAndPath function, I use a for loop and setTimeOut function to visualize the coordinates which are inside visited and path array.
export function animateAsVisited(
row: number,
col: number,
turn: number,
speed: number,
startNodePos: NodePos,
finishNodePos: NodePos
) {
setTimeout(() => {
const { row: sRow, col: sCol } = startNodePos;
const { row: fRow, col: fCol } = finishNodePos;
if (row === sRow && col === sCol) return;
if (row === fRow && col === fCol) return;
document.getElementById(`node-${row}-${col}`)?.classList.add('visited');
}, speed * turn);
}
And here, I use the document object to access each node, and update the classList.
Everything works fine, but when I want to stop the user to interact with the program using a state variable such as isVisualizing, the moment I update the state before, or after visualizeDijkstra, all of my setTimeOut call back functions invokes immediately, updating all visualizations at the same time when visualizeDijkstra gets invoked.
I apolgize if this is a duplicated question, or the way I ask the question is inappropriate.
I have four counters that I would like to animate (incrementing the count from 0 to a specific number) using JavaScript. My code is the following:
const allCounters = document.querySelectorAll('.counterClass');
counters.forEach(allCounters => {
const updateCounter = () => {
const end = +allCounters.getAttribute('data-target');
const count = +allCounters.innerText;
const increment = end / 200;
if (count < end) {
allCounters.innerText = count + increment;
setTimeout(updateCounter, 1);
} else {
allCounters.innerText = end;
}
};
updateCounter();
});
In React, I wasn't sure how to get it to run. I tried including the code after the using dangerouslySetInnerHTML, but that's not working. (I'm new to React).
I appreciate any assistance you could give me. Thanks so much!
Right before I posted my question, I found a plug-in (https://github.com/glennreyes/react-countup) that could do it, but wondered if it's still possible using JS. Thanks!
While using React, try to avoid direct DOM operations (both query and modifications). Instead, let React do the DOM job:
const Counter = ({start, end}) = {
// useState maintains the value of a state across
// renders and correctly handles its changes
const {count, setCount} = React.useState(start);
// useMemo only executes the callback when some dependency changes
const increment = React.useMemo(() => end/200, [end]);
// The logic of your counter
// Return a callback to "unsubscribe" the timer (clear it)
const doIncrement = () => {
if(count < end) {
const timer = setTimeout(
() => setCount(
count < (end - increment)
? count + increment
: end
),
1);
return () => clearTimeout(timer);
}
}
// useEffect only executes the callback once and when some dependency changes
React.useEffect(doIncrement, [count, end, increment]);
// Render the counter's DOM
return (
<div>{count}</div>
)
}
const App = (props) => {
// Generate example values:
// - Generate 5 counters
// - All of them start at 0
// - Each one ends at it's index * 5 + 10
// - useMemo only executes the callback once and
// when numCounters changes (here, never)
const numCounters = 5;
const countersExample = React.useMemo(
() => new Array(numCounters)
.fill(0)
.map( (c, index) => ({
start: 0,
end: index*5 + 10,
})
),
[numCounters]
);
return (
<div id="counters-container">
{
// Map generated values to React elements
countersExample
.map( (counter, index) => <Counter key={index} {...counter}/> )
}
</div>
)
}
I have an observable get data from stream each time at size 512 each next I have to break it up to 200 char at other observable and keep [12] char in other buffer to concatenate with next block, I solve it by using new subject and for loop, I believe there maybe a better, more pretty solution.
received Observable ----------------------------------------
1st next [512] -------> [112] [200] [200] -------> [200] [200]
2nd next [512][112] --> [24][200][200] [88+112] --> [200] [200]
3rd next [512][24] --> [136] [200] [76+124] .....
nth iteration [512][194] --> [106][200][200][106+94] --> [200][200][200]
n+1th [512][6].......
maxValueSize = 200
this._sreamRecord$.subscribe(
{
next: (val) => {
const bufferToSend: Buffer = Buffer.concat([completationBuffer, val])
for (let i = 0; i < bufferToSend.length; i += maxValueSize) {
if (bufferToSend.length - i > maxValueSize) {
bufferStreamer.next(bufferToSend.slice(i, i + maxValueSize))
} else {
completationBuffer = bufferToSend.slice(i, i + maxValueSize)
}
}
},
complete() {
if (completationBuffer.length) {
bufferStreamer.next(completationBuffer)
}
bufferStreamer.complete()
}
})
You may want to consider a solution along these lines
const splitInChunksWithRemainder = (remainder: Array<any>) => {
return (streamRecord: Array<any>) => {
const streamRecordWithRemainder = remainder.concat(streamRecord);
let chunks = _.chunk(streamRecordWithRemainder, maxValueSize);
const last = chunks[chunks.length - 1];
let newRemainder = [];
if (last.length != maxValueSize) {
newRemainder = chunks[chunks.length - 1];
chunks.length = chunks.length - 1;
}
return {chunks, newRemainder};
};
}
let f = splitInChunksWithRemainder([]);
this._sreamRecord$.pipe(
switchMap(s => {
const res = f(s);
f = splitInChunksWithRemainder(res.newRemainder);
return from(res.chunks);
})
)
.subscribe(console.log);
The idea is to split each streamRecord with lodash chunk function after having concatenated the previous remainder, i.e. the array left as tail from the split of the previous streamRecord.
This is done using the function splitInChunksWithRemainder, which is an higher level function, i.e. a function which returns a function, in this case after having set the remainder coming from the previous split.
UPDATE after comment
If you need to emit also the last newRemainder, than you can consider a slightly more complex solution such as the following
const splitInChunksWithRemainder = (remainder: Array<any>) => {
return (streamRecord: Array<any>) => {
const streamRecordWithRemainder = remainder.concat(streamRecord);
let chunks = _.chunk(streamRecordWithRemainder, maxValueSize);
const last = chunks[chunks.length - 1];
let newRemainder = [];
if (last.length != maxValueSize) {
newRemainder = chunks[chunks.length - 1];
chunks.length = chunks.length - 1;
}
return {chunks, newRemainder};
};
}
const pipeableChain = () => (source: Observable<any>) => {
let f = splitInChunksWithRemainder([]);
let lastRemainder: any[];
return source.pipe(
switchMap(s => {
const res = f(s);
lastRemainder = res.newRemainder;
f = splitInChunksWithRemainder(lastRemainder);
return from(res.chunks);
}),
concat(defer(() => of(lastRemainder)))
)
}
_streamRecord$.pipe(
pipeableChain()
)
.subscribe(console.log);
We have introduced the pipeableChain function. In this function we save the remainder which is returned by the execution of splitInChunksWithRemainder. Once the source Observable completes, we add a last notification via the concat operator.
As you see, we have also to use the defer operator to make sure we create the Observable only when the Observer subscribes, i.e. after the source Observable completes. Without defer the Observable passed to concat as parameter would be created when the source Observable is initially subscribed, i.e. when lastRemainder is still undefined.
I am currently doing some 3d modeling using babylonjs. I need to create a pressure map from given pressure at specific points. I am doing that using IDW. However this means that even with my map being a size of 70x90 grid requires me to have an array of 25200 (4 rgba values for each pixel) entries. Then this buffer is passed to a RawTexture for assigning it to a material, that is overlaid on the object
I am using a web worker, because I have to update the pressure values every 100ms and I don't want to block the main thread.The issue occurs when I am return that array (created in calculate function) from a service worker.
For some reason the memory usage just keeps going up, without stopping. It eventually goes up to around 1.5 gigabytes and I have to kill it.
The question : Is there any way to prevent this and what could be causing such high memory usage?
Worker:
// #flow
import { find, propEq, both } from 'ramda';
import { colorFromValue } from './color';
import { inverseDistance, distanceValues } from './math';
const findPoint = (x: number, y: number) =>
find(both(propEq('x', x), propEq('y', y)));
const distanceDict = {};
/* eslint-disable */
function calculate(options: Object, pList: Array<*>) {
const points = pList || [];
const { height, width } = options;
const gridWidth = width * 4;
const grid = new Uint8Array(options.width * options.height * 4);
for (let y = 0; y < height; y += 1) {
const rW = y * gridWidth;
for (let i = 0; i < gridWidth; i += 4) {
const index = i + rW;
const x = i / 4;
const dictKey = `${x}--${y}`;
let bottoms = distanceDict[dictKey];
if (bottoms === undefined) {
bottoms = distanceValues(points, x, y);
distanceDict[dictKey] = bottoms;
}
const point = findPoint(x, y)(points);
const value = point !== undefined && point !== null ?
point.value : inverseDistance(points, bottoms);
const color = colorFromValue(value);
grid[index] = color[0];
grid[index + 1] = color[1];
grid[index + 2] = color[2];
grid[index + 3] = 255;
}
}
return grid;
}
self.onmessage = (e) => {
const { points, options } = e.data;
const grid = calculate(options, points);
self.postMessage(grid.buffer, [grid.buffer]);
};
Painting:
modifyNodes = (points: Array<*>) => new Promise((res, rej) => {
this.worker.onmessage = (e) => {
this._texture.update(new Uint8Array(e.data));
res();
}
const data = {
options: this._options,
points,
};
this.worker.postMessage(data);
})
So it seems the issue was in the colorFromValue function that was memoized. Because the values had quite few decimal points it could create up to 9! new entries into cache, so it drove up the memory usage...
Function composition composes from right to left:
const comp = f => g => x => f(g(x));
const inc = x => x + 1;
const dec = x => x - 1;
const sqr = x => x * x;
let seq = comp(dec)(comp(sqr)(inc));
seq(2); // 8
seq(2) is transformed to dec(sqr(inc(2))) and the application order is inc(2)...sqr...dec. Thus the functions are invoked in the reverse order in which they are passed to comp. This isn't intuitive for Javascript programmers, since they're used to method chaining, which goes from left to right:
o = {
x: 2,
inc() { return this.x + 1, this },
dec() { return this.x - 1, this },
sqr() { return this.x * this.x, this }
}
o.dec().sqr().inc(); // 2
I consider that confusing. Here's a reversed composition:
const flipped = f => g => x => g(f(x));
let seql = flipped(dec)(flipped(sqr)(inc));
seql(2); // 2
Are there any reasons why function composition goes from right to left?
To answer the original question: Why does function composition compose from right to left?
So it is traditionally made in mathematics
comp(f)(g)(x) has the same order as f(g(x))
It is trivial to create a reversed or forward composition (see example)
Forward function composition:
const comp = f => g => x => f(g(x));
const flip = f => x => y => f(y)(x);
const flipped = flip(comp);
const inc = a => a + 1;
const sqr = b => b * b;
comp(sqr)(inc)(2); // 9, since 2 is first put into inc then sqr
flipped(sqr)(inc)(2); // 5, since 2 is first put into sqr then inc
This way of calling functions is called currying, and works like this:
// the original:
comp(sqr)(inc)(2); // 9
// is interpreted by JS as:
( ( ( comp(sqr) ) (inc) ) (2) ); // 9 still (yes, this actually executes!)
// it is even clearer when we separate it into discrete steps:
const compSqr = comp(sqr); // g => x => sqr(g(x))
compSqr(inc)(2); // 9 still
const compSqrInc = compSqr(inc); // x => sqr(x + 1)
compSqrInc(2); // 9 still
const compSqrInc2 = compSqrInc(2); // sqr(3)
compSqrInc2; // 9 still
So functions are composed and interpreted (by the JS interpreter) left to right, while on execution, their values flow through each function from right to left. In short: first outside-in, then inside-out.
But flip has the restriction that a flipped composition can't be combined with itself to form a "higher order composition":
const comp2 = comp(comp)(comp);
const flipped2 = flipped(flipped)(flipped);
const add = x => y => x + y;
comp2(sqr)(add)(2)(3); // 25
flipped2(sqr)(add)(2)(3); // "x => f(g(x))3" which is nonsense
Conclusion: The right-to-left order is traditional/conventional but not intuitive.
Your question is actually about the order of arguments in a definition of the function composition operator rather than right- or left-associativity. In mathematics, we usually write "f o g" (equivalent to comp(f)(g) in your definition) to mean the function that takes x and returns f(g(x)). Thus "f o (g o h)" and "(f o g) o h" are equivalent and both mean the function that maps each argument x to f(g(h(x))).
That said, we sometimes write f;g (equivalent to compl(f)(g) in your code) to mean the function which maps x to g(f(x)). Thus, both (f;g);h and f;(g;h) mean the function mapping x to h(g(f(x))).
A reference: https://en.wikipedia.org/wiki/Function_composition#Alternative_notations