Skip to content

Instantly share code, notes, and snippets.

@jrsinclair
jrsinclair / json-compress.ts
Created August 3, 2023 00:21
A couple of rough compression/decompression functions
const countSubstringMatches = (str: string, substr: string, startAt: number) => {
const substringLength = substr.length;
let count = 1;
for (
let substringPos = str.indexOf(substr, startAt + substringLength);
substringPos >= 0;
++count
)
substringPos = str.indexOf(substr, substringPos + substringLength);
return count;
@jrsinclair
jrsinclair / dangerous-push-all.js
Created August 9, 2022 23:22
A mutating version of concat. Do not recommend using this unless absolutely necessary.
const dangerousPushAll = (xs, ys) => {
for (const y in ys) {
xs.push(y);
}
return xs;
}
@jrsinclair
jrsinclair / lenses.js
Created May 13, 2022 06:11
Lenses that seem to work in Flow
// @flow strict-local
// Lenses
// ------------------------------------------------------------------------------------------------
export type LensInternal<S, T, A, B> = {
getVal: (S) => A,
setVal: (B, S) => T,
};
@jrsinclair
jrsinclair / aoc-day01.js
Created December 2, 2021 00:23
Advent of Code Day 1 Solution
import fs from 'fs';
const data = fs.readFileSync('/path/to/my/copy/of/input.txt');
const input = data.toString('utf-8').split('\n').filter(x => x !== '').map(x => parseInt(x));
// Chop goes through the array, but gives you less and less of it each time. If you fed it [1, 2, 3], then
// the first iteration would get [1, 2, 3], the next would get [2, 3] and the final would get [3]. Idea is stolen
// from fp-ts: https://gcanti.github.io/fp-ts/modules/ReadonlyArray.ts.html#chop
const chop = (f) => (arr) => [...(new Array(arr.length))].map((_, i) => f(arr.slice(i)));
@jrsinclair
jrsinclair / dom-listening.js
Last active September 4, 2019 12:22
Fun with binding event handlers
const setAttr = _.curry((attrName, el, val) => { el.setAttribute(val)); return el; });
const listen = _.curry((evtName, el, f) => { el.addEventListener(evtName, f); return el; })
const bindCreateResultButton = (createResultButton, postTextarea, getPostData, preTextarea) =>
_.compose(
listen('click', createResultButton),
_.compose(x => () => setAttr('value', postTextArea, x), getPostData),
)(preTextArea);
function csvToMessages(csvData) {
const csvRows = splitCSVToRows(csvData);
const headerFields = csvRows.map(_.head).map(splitFields);
const dataRows = csvRows.map(_.tail);
const processRowsA = liftA2(processRows);
const messagesArr = processRowsA(headerFields, dataRows);
return either(showError, showMessages, messagesArr);
}
@jrsinclair
jrsinclair / liftA2.js
Created December 5, 2018 22:14
Elegant Error Handling Code Samples
function liftA2(func) {
return function runApplicativeFunc(a, b) {
return b.ap(a.map(func));
};
}
@jrsinclair
jrsinclair / csv-to-messages-03.js
Created December 5, 2018 22:12
Elegant Error Handling Code Samples
function csvToMessages(csvData) {
const csvRows = splitCSVToRows(csvData);
const headerFields = csvRows.map(_.head).map(splitFields);
const dataRows = csvRows.map(_.tail);
const funcInEither = headerFields.map(processRows);
const messagesArr = dataRows.ap(funcInEither);
return either(showError, showMessages, messagesArr);
}
@jrsinclair
jrsinclair / ap-left.js
Created December 5, 2018 22:11
Elegant Error Handling Code Samples
/* Rest of Left class is hidden to save space */
// Ap In Left (the sad path)
ap() {
return this;
}
@jrsinclair
jrsinclair / csv-to-messages-02.js
Created December 5, 2018 22:07
Elegant Error Handling Code Samples
function csvToMessages(csvData) {
const csvRows = splitCSVToRows(csvData);
const headerFields = csvRows.map(_.head).map(splitFields);
const dataRows = csvRows.map(_.tail);
// How will we pass headerFields and dataRows to
// processRows() ?
const funcInEither = headerFields.map(processRows);
}