Skip to content

Instantly share code, notes, and snippets.

@gordonbrander
gordonbrander / singledispatch.js
Last active October 19, 2023 13:57
singledispatch.js - single dispatch generic function like Python's singledispatch
// Create a Python singledispatch / Clojure multimethod style function that
// dispatches on the first argument.
//
// Returns a wrapped function that calls appropriate underlying function
// based on prototype of first argument.
//
// Custom implementations for specific types can be registered through calling
// `.define(constructor, fun)` on the wrapped function.
export const singledispatch = fallback => {
let _key = Symbol('singledispatch method')
@gordonbrander
gordonbrander / freeze.js
Created March 21, 2023 19:17
freeze.js - immutable JS object helpers
// Shorthand for Object.freeze
export const freeze = Object.freeze
// Define an immutable model intializer.
// Objects are frozen on the way out.
export const Model = init => flags => freeze(init(flags))
// Put a value to a key, returning a new frozen object
export const put = (state, key, val) => freeze({...state, [key]: val})
@gordonbrander
gordonbrander / read-only-proxy.js
Created March 8, 2023 13:55
Ready-only Proxy - a read-only view over JS objects
export const isObject = thing => thing != null && typeof thing === "object"
export class ReadOnlyProxyWriteError extends Error {}
const ReadOnlyProxyDescriptor = {
get: (target, key) => {
let value = target[key]
if (!isObject(value)) {
return value
}
@gordonbrander
gordonbrander / versioned-proxy.js
Created March 6, 2023 14:30
Versioned Proxy - using proxy to increment a version on object mutation
export const $version = Symbol('version')
const VersionedProxy = {
set(target, prop, value) {
target[$version] = target[$version] + 1
target[prop] = value
},
deleteProperty(target, prop) {
target[$version] = target[$version] + 1
@gordonbrander
gordonbrander / rendering-element.js
Created March 6, 2023 13:39
RenderingElement - A custom element that batches updates on animation frame
// RenderingElement
// A custom element that batches state updates on animation frame.
export class RenderingElement extends HTMLElement {
// Element state to render
#state = this.defaults();
// Has an animation frame been scheduled?
#isAnimationFrameScheduled = false
// Perform a render and flag that animationFrame has completed.
@gordonbrander
gordonbrander / mut.js
Last active March 6, 2023 16:13
Mut.js - efficient DOM writing via mutation and version flag
const $version = Symbol('version')
export const version = state => {
if state[$version] == null {
return 0
}
return state[$version]
}
export const markSynced = (following, leading) => {
@gordonbrander
gordonbrander / DispatchQueue+future.swift
Created February 16, 2023 19:22
DispatchQueue.future
import Foundation
import Combine
extension DispatchQueue {
/// Run a closure on a dispatch queue asyncronously.
/// - Returns a future.
func future<Output>(
perform: @escaping () -> Output
) -> Future<Output, Never> {
Future<Output, Never> { promise in
@gordonbrander
gordonbrander / Store.swift
Last active February 17, 2022 01:55
Store.swift - a simple Elm-like ObservableObject store for SwiftUI
//
// Store.swift
//
// Created by Gordon Brander on 9/15/21.
//
// MIT LICENSE
// Copyright 2021 Gordon Brander
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
import Foundation
import Combine
/// Holds cancellables returned by Publisher until the publisher completes.
///
/// Combine Publishers return a Cancellable that will automatically cancel the Publisher if the
/// Cancellable falls out of scope. Since Publishers can take some time to complete, you often
/// want to hold on to the Cancellable reference until the publisher has completed.
///
/// PublisherManager takes care of the boilerplate of holding on to Cancellables, and helps
@gordonbrander
gordonbrander / UnwrapOptional.swift
Created June 15, 2021 13:51
UnwrapOptional.swift
import Foundation
extension Optional {
struct NilError: Error {
let file: String
let line: Int
let column: Int
let function: String
}