Skip to content

Instantly share code, notes, and snippets.

View axefrog's full-sized avatar

Nathan Ridley axefrog

  • Brisbane, Australia
View GitHub Profile
@axefrog
axefrog / suffix-tree-console.js
Last active January 7, 2023 01:19
Simple suffix tree implementation in JavaScript. Install chalk to run the script below, or strip it down and remove all the debug messages and test cases.
const defaultIfZero = (a, x) => x === 0 ? a : x;
const isDefined = x => x !== void 0;
const isUndefined = x => x === void 0;
const NONE = Symbol('NONE');
const chalk = require('chalk');
const val = x => (x === NONE ? (x = 'none', chalk.bold.grey) : chalk.cyan)(String(x));
let highlightActiveNode = null;
let highlightedEdges = [];
@axefrog
axefrog / explanation.md
Last active April 19, 2018 19:23
My note-taking process, followed by an example taken from my own notes in 2016.

My process for designing systems and solving problems is fairly simple, and in a way it seems like an obvious approach, but the degree of effectiveness of the technique is greater than what you'd intuitively expect. When most developers write notes and try to work out how to tackle some kind of architectural design challenge, it usually takes the form of a few whiteboard notes, some scribbles in a notepad, etc. Usually this is fine because the problem is small and constrained to a manageable level. If you want to tackle something bigger and more challenging though, or if you want to design a much more effective system in the first iteration, rather than two-to-three years down the track after several deployments finally lead you to the conclusions you'd like to reach up front, then this process works really well. It does feel like you're committing to a chore if you haven't done it before, and the reason it works isn't itself obvious, which is part of the reason I get pushback from a lot of developers before

@axefrog
axefrog / extensible.ts
Last active June 16, 2017 02:31
Hot-swappable pipelines for Most.js streams
import {Stream, Sink, Scheduler, Disposable} from '@most/types';
import {disposeOnce, disposeAll} from '@most/disposable';
export type ActivateExtension<A = any> = (source: Stream<A>) => Stream<A>;
export type DeactivateExtension = null;
export type ExtensionAction<A = any> = ActivateExtension<A>|DeactivateExtension;
export type ExtensionLifecycle<A = any> = Stream<ExtensionAction<A>>;
export function extensible<A>(source: Stream<A>, extensions: Stream<ExtensionLifecycle<A>>): Stream<A> {
return new ExtensiblePipeline(extensions, source);
@axefrog
axefrog / (a) inspect.ts
Last active June 6, 2017 19:09
Most.js introspection concept
function identity<T>(value: T): T {
return value;
}
let wrap = identity;
export function inspect<T>(fn: (value: T) => T): void {
wrap = fn;
}
@axefrog
axefrog / preprocessor.js
Created February 26, 2017 17:22
Simple DEV vs PROD preprocessor for JS and TS source code
/*
Preprocessor Directives
=======================
// --- OMIT A SINGLE LINE ----------------------------------------------------
log("This line will be excluded from the build"); // ## DEV ##
// --- OMIT A WHOLE BLOCK ----------------------------------------------------
@axefrog
axefrog / CriticalSection.ts
Last active January 17, 2017 04:14
A stream-flavoured critical section implementation for isolating access to a stream subgraph
/*
# CriticalSection
"A stream-flavoured critical section implementation for isolating access to a stream subgraph"
Events entering a stream graph fenced off by a critical section will cause all other entry points to switch into
blocking mode, with events received at a given entry point being retained in that entry point's internal buffer,
and the entry point buffer enqueued for subsequent processing. Each time an event flows through an exit point, the
next entry point in the queue will be dequeued and its next buffered event emitted into the inner stream graph.
When no data is buffered at any entry point, the critical section unblocks, allowing direct dispatch of the next
future data item to arrive, at which point it will switch back into blocking mode. Errors ignore critical section
function copyArray<T>(values: T[]): T[] {
switch(value.length) {
case 0: return [];
case 1: return [value[0]];
case 2: return [value[0], value[1]];
case 3: return [value[0], value[1], value[2]];
case 4: return [value[0], value[1], value[2], value[3]];
case 5: return [value[0], value[1], value[2], value[3], value[4]];
case 6: return [value[0], value[1], value[2], value[3], value[4], value[5]];
case 7: return [value[0], value[1], value[2], value[3], value[4], value[5], value[6]];
@axefrog
axefrog / example.js
Last active January 17, 2017 04:17
A cleaner abstraction for creating and resolving stream proxies
import {using} from 'proxy-abstraction';
function render() {
// The `using` function takes a callback function. It looks at the functions `.length` property
// and generates a proxy for each. You then return a tuple containing the value you want to
// persist, and fulfillment streams for each of the referenced proxies. The using function will
// automatically complete the proxies internally and return the first tuple argument.
return using((click$, hover$) => {
const view = div(......);
return [
@axefrog
axefrog / debug.js
Last active January 17, 2017 04:17
Full-featured console-based log/trace debugger for most.js, borrowing ideas from CQRS.
import Immutable from 'immutable';
import formatDate from 'date-fns/format';
import immutableDiff from 'immutablediff';
/* eslint-disable no-underscore-dangle */
var colors = {
0: ['white', '#7fbad8', '#0075b2'],
1: ['white', '#91a0ce', '#24429e'],
2: ['white', '#ab86e0', '#570ec1'],
@axefrog
axefrog / flatScan.js
Last active August 12, 2016 09:43
A multi-pass scan operator for most.js
import {sample} from '@most/sample';
import {proxy as makeProxy} from 'most-proxy';
/**
* FlatScan is a multi-pass accumulation operator. It takes a first-stage
* initiator function and an initial state value, and returns a function that
* takes a stream of values and returns a stream of cumulatively-updated values.
*
* For each input value received from the source stream, the initiator function
* is called with the current accumulated state, the input value, and an