Skip to content

Instantly share code, notes, and snippets.

@andrejewski
andrejewski / dattle.bnf
Created January 30, 2023 03:18
Dattle specification described in Backus–Naur form (BNF). Note: I was using the Rust `bnf` crate to iterate which doesn't seem to support UTF-8 ranges but Dattle is built atop UTF-8 and this grammar should be expanded to support UTF-8 quoted strings.
<value> ::= <nil> | <boolean> | <string> | <vector> | <map>
<nil> ::= "nil"
<boolean> ::= "true" | "false"
<character> ::= <bring-your-own-utf8-character-term>
<quote-escape> ::= '\"'
<string-value> ::= <character> | <quote-escape>
<string-content> ::= <string-value> | <string-value> <string-content>
<string> ::= '"' <string-content> '"'
@andrejewski
andrejewski / sub.js
Created March 21, 2020 19:32
A safer String.prototype.replace
// "substitute" is too hard to type
function sub (str, candidate, replacer) {
/*
NOTE: Using String.prototype.replace is bad because:
1) casting an arbitrary string to a RegExp is unsafe
2) replacement has obscure substitution rules ($ is special)
*/
let match = str.indexOf(candidate)
if (match === -1) {
@andrejewski
andrejewski / sock-scratch.js
Created October 7, 2018 17:59
Playing with a new kind of mock/stub/spy
function withTest (service, tester) {
function mark () {
if (process.env.NODE_ENV !== 'test') {
return service
}
}
return { ...service, mark, testMark }
}
@andrejewski
andrejewski / logger.js
Created September 29, 2018 03:36
A good logger
exports.createLogger = function createLogger (write, values = []) {
return {
log: value => write([...values, value]),
withContext: value => createLogger(write, [...values, value])
}
}
<style>
* {
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
box-sizing: border-box;
}
body {
margin: 0px;
position: fixed;
top: 0;
@andrejewski
andrejewski / koatil.js
Created August 12, 2018 22:07
Koa middleware utilities [WIP]
// koatil/index
function group (middlewares) {
return function _group (ctx, next) {
return runGroup(middlewares, 0, ctx, next)
}
}
function runGroup (routes, routeIndex, ctx, next) {
const route = routes[routeIndex]
@andrejewski
andrejewski / reconciler.js
Created July 19, 2018 02:01
A data reconciler with subscriptions
function createReconciler ({
mergeEntity,
getEntityKey,
entityStore = {},
subscriptions = new Set(),
}) {
function notify (subscriptions) {
subscriptions.forEach(subscription => {
const entities = []
@andrejewski
andrejewski / raj-emitter.js
Created July 15, 2018 19:12
A single value emitter
exports.createEmitter = function createEmitter ({ shouldPrime, initialValue }) {
let currentValue = initialValue
let listeners = []
return {
emit: value => () => {
currentValue = value
listeners.forEach(listener => listener(currentValue))
},
@andrejewski
andrejewski / raj-faq.md
Last active June 18, 2018 20:15
Frequently asked Raj questions

How do Raj and Redux compare performance wise?

Raj is faster theoretically. In Redux you have N reducers that need to be iterated, in Raj you have a single update which can call sub graph updates (log N). Redux also can have multiple subscriptions whereas Raj doesn't have any. Looking at code size and the amount of work each project does and the list-vs-tree distribution of work, Raj should be better.

Also since (logic+view+data) assemble into Raj programs, it's easier to code-split and lazy-load. There's no definite story for how to do at in Redux. In Raj, you use raj-spa where a program can resolve from a promise.

Is there a way to apply Raj to a backend state machine where there is no view?

So view is mostly for apps with UIs. It is a side-effect that receives the whole state as opposed to plain effects which need portions of state explicitly passed. If you don't need a view, you can think of it like a "window" into the current state. For example, you can have something like tapProgram wh

@andrejewski
andrejewski / what-is-raj.md
Created May 17, 2018 02:10
A description of Raj and comparison to Redux and Elm

What is Raj

Raj solves two problems: state management and running side-effects. These problems are the hardest problems in building client applications.

State management is two things: storing state and handling state transitions. Raj holds a single variable called state which stores the application state. Raj will update this variable as messages are dispatched. State transitions are synchronous and preferably written in an immutable manner as to be simple to test quickly.