Skip to content

Instantly share code, notes, and snippets.

View chrispsn's full-sized avatar

Chris Pearson chrispsn

View GitHub Profile
@chrispsn
chrispsn / demo.js
Last active June 17, 2018 12:55
Generating tables of arbitrary length.
/* Mesh boilerplate - do not change. 2018-06-16-1 */
'use strict';
var _defProp = Object.defineProperty, _OUTPUT = {};
function _isFn(value) {return typeof value === 'function'};
function _defCell(k, c) {
return _defProp(self, k, {configurable: true, get() {
if (k in _OUTPUT) return _OUTPUT[k].v;
var o = _OUTPUT[k] = {};
var t = o.t = c.t; o.s = c.s; o.n = c.n;
@chrispsn
chrispsn / short_functions.js
Created July 3, 2018 13:31
Making short functions
// ES5 hasn't got arrow functions, so we need another way to make short functions...
// Highest arity in a built-in I've found so far is 4, in Array.prototype.reduce:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce)
function F(_){return Function('a','b','c','d','"use strict";return '+_)};
const sum = F("a+b"), product = F("a*b");
const A = [1, 2, 3, 4];
@chrispsn
chrispsn / simple_find.js
Last active July 22, 2018 08:29
Toying with adding a find function for arrays to boilerplate as IE11 doesn't have Array.prototype.find
// TODO make extend to sets and objects too?
// TODO allow user to supply an index?
function find(a, p, options) {
const l = a.length, o = options || {};
for (let k = 0; k < l; k++) {
const v = a[k];
if (p(v)) return (o.index ? k : v);
}
return o.default;
};
@chrispsn
chrispsn / simple_sql.js
Last active July 23, 2018 13:10
Experimenting with a small SQL-like query function
/*
A recordset or 'SQL-like' function has a different use case to a 'find' function.
Find:
- can be made faster by returning as soon as a match is found
- has the typical use case of 'use default if no match'
- has no use for 'select' (use standard property access) or 'distinct'/'order by'/'group by'
*/
function q(t, o) {
if (!o) return t;
@chrispsn
chrispsn / lazy_memo.js
Created August 8, 2018 11:36
Silly alternative to defining lazy, memoising variables
var g = Function('return this')();
function memo(fn) {
var name = fn.name;
Object.defineProperty(g, name, {
get: function() {
console.log(name); // Should appear just once
delete this[name];
return this[name] = fn();
}, configurable: true
How should Mesh spreadsheets send and receive data to each other?
Some simple ways:
- Make Mesh sheets be functions that are callable.
- Make Mesh sheets be objects that can have their properties read and set.
While functions had the advantage of creating a separate scope (so no `sheet.cell_name` prefix was necessary), I soon abandoned that approach in favour of objects: they allowed use of `Object.defineProperty` to get/set both cell *values* and lazy cell *formulas* without having to use brackets to call the latter.
I still wanted cell references to not require a `sheet` prefix, so the current format of Mesh sheets sets the cells as properties on the global object. Dangers around dirtying the global environment are mitigated by having each Mesh sheet live in its own environment (via Web Workers).
@chrispsn
chrispsn / scheduler.js
Last active October 25, 2018 12:06
Simple task scheduler
const _SUBS = [
{
name: "hi",
task: function() {console.log("Hello!")}, // Could also send override values to the sheet
freq: 2
}
]
function startSubs() {
_SUBS.forEach(function(sub) {sub.id = setInterval(sub.task, sub.freq * 1000)});
@chrispsn
chrispsn / ASCII_separator.js
Last active November 6, 2018 12:33
ASCII separator characters in action
// https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text
const FS = String.fromCharCode(28); // File separator; end of file. Or between a concatenation of what might otherwise be separate files.
const GS = String.fromCharCode(29); // Group separator; between sections of data. Not needed in simple data files.
const RS = String.fromCharCode(30); // Record separator; end of a record or row.
const US = String.fromCharCode(31); // Unit separator; between fields of a record, or members of a row.
function print_to_string_table(str) {
let o = "";
for (var i = 0; i < str.length; i++) {
const char = str[i];
@chrispsn
chrispsn / why_tables.js
Last active November 18, 2018 03:22
Exploring why tables are more appropriate for Mesh than arrays or objects alone
// 1. Array literals don't have a way to set getters, which are essential for self-references
// They *do* work if you manage them directly, but this produces source code that's difficult to manage.
const arr = [1];
Object.defineProperty(arr, '1', {get: function() {return this[0] + 1}})
console.log(arr[1]) // prints 2
arr[0] = 1234;
console.log(arr[1]) // prints 1235
// 2. Objects literals don't have a key order, which is essential for self-refences to preceding values.
// (You could *potentially* mimic this by making an object literal with keys that are numbers that has __proto__ = Array.prototype,
@chrispsn
chrispsn / putting_functions_into_cells_in_mesh_sheets.md
Last active December 4, 2018 13:04
Putting functions into cells in Mesh sheets

Putting functions into cells in Mesh sheets

Right now, when you write something in the formula bar and press Enter, one of two things will happen, depending on whether you prefixed it with =:

  • if you didn't, Mesh will run the contents of the formula bar through a series of regexes and try to transform your input into a JavaScript equivalent (string, number, percentage, date, etc).
  • if you did, Mesh will defer evaluating that input by writing a function to that cell, with the stuff after the = as the return value. When another cell references that cell, the Mesh calc engine will then call that function and use its return value.

So:

  • 2018-11-04 would be transformed into new Date(2018, 11, 4)
  • =2018-11-04 would be written directly, in this case resulting in a calculation (returning 2003).