git ssb

0+

dinoworm πŸ› / campjs-viii-ludditejs



Tree:
πŸ“„.gitignore
πŸ“„LICENSE
πŸ“„NOTES.md
πŸ“„README.md
πŸ“„avatar.png
πŸ“„catstack.jpg
πŸ“„dogstack.jpg
πŸ“„enspiral.png
πŸ“„example.js
πŸ“„index.css
πŸ“„index.html
πŸ“„index.js
πŸ“„luddite.jpg
πŸ“„moprheus-cat.png
πŸ“„package-lock.json
πŸ“„package.json
πŸ“„patchwork.png
πŸ“stuff
πŸ“test
README.md

luddite.js


hey CampJS

i'm Mikey (@ahdinosaur) from Enspiral

<div class="row">
<a href="http://dinosaur.is.com">
<img alt="Mikey's avatar" src="./avatar.png" width="200" />
</a>
<a href="http://enspiral.com">
<img alt="Enspiral logo" src="./enspiral.png" width="200" />
</a>
</div>

slides are available at http://dinosaur.is/campjs-viii-ludditejs.

???


what?

luddite.js

???

so...


Luddite?

the Luddites was a political movement against automated centralized technology.

<div style='display: flex; justify-content: center'>
<img src="./luddite.jpg" height='400' />
</div>

???


luddite.js?

luddite.js is a (made-up) meme for simple decentralized JavaScript.

???


decent userland

what if i told you...

that anyone can create a standard?

<img src="./morpheus-cat.png" height="500" class="center" />

???


what is a standard?

anything that enough people use is a "standard"

example: "standard style"

npm install --global standard

???


what is a luddite.js standard?

a standard based on a function signature

example: Redux reducers

const reducer = (state, action) => nextState

???


why is this important?

???


simple functional

what if i told you...

that you only needed plain functions and objects?

???


just a function

function fn (options) { return value }
const fn = (...args) => ({ [key]: value })

sync function signals

with a sync function, there are two possible signals:

  1. value: return value
  2. error: throw error

???

function fn (...args) { throw error }
try {
  fn(...args)
} catch (const err) {
  // handle error
}

es modules

import thing from 'module'

export default thing
import { thing as thingy } from 'module'

export const thing = thingy

???


or node modules

also known as "CommonJS"

const thing = require('module')

module.exports = thing
const { thing: thingy } = require('module')

module.exports = { thing: thingy }

???


jsx

import React from 'react'

export default Table

function Table ({ table }) {
  return <table className='table'>
    {table.map(row => {
      <tr className='row'>
        {row.map(item => {
          <td className='item'>{item}</td>
        })
      </tr>
    })
  </table>
}

???


or hyperscript

const h = require('react-hyperscript')

module.exports = Table

function Table ({ rows ) {
  return h('table.table', rows.map(row => {
    h('tr.row', row.map(item => {
      h('td.item', item)
    })
  })
}

???


or hyperx

const hyperx = require('hyperx')
const React = require('react')
const html = hyperx(React.createElement)

module.exports = Table

function Table ({ rows ) {
  return html`<table class='table'>
    ${rows.map(row => {
      html`<tr class='row'>
        ${row.map(item => {
          html`<td class='item'>${item}</td>`
        })}
      </tr>`
    })}
  </table>`
}

???


promise

a "promise" is an eventual value

const promise = new Promise((resolve, reject) => {
  // do stuff...
  resolve(value)
  // oh no!
  reject(error)
}

???

module.exports = fetchCats

function fetchCats ({ cats }) {
  return Promise.all(cats.map(cat => {
    return fetch(cat)
  }))
})

continuable

a "continuable" is a function that takes a single argument, a node-style error-first callback

const continuable = (cb) => {
  // do stuff...
  cb(null, data)
  // oh no!
  cb(error)
}

???

a continuable is the callback version of a promise

can be passed around as an "eventual value", same as promises. but without the resolved, pending, rejected state machine complexity.

const request = require('request')
const parallel = require('run-parallel')

module.exports = fetchCats

function fetchCats ({ cats }) {
  return cb => parallel(cats.map(cat => {
    return request(cat, cb)
  }))
})

async errors

with a node-style error-first callback, there are three possible signals:

  1. value: cb(null, value)
  2. user error: cb(error)
  3. programmer error: throw error

???


pull streams

async streams using only functions!

pull(source(), through(), sink())

???

compare with


source

example:

function values (array) {
  var i = 0
  return (abort, callback) => {
    if (abort || i === array.length) {
      callback(true)
    }
    else {
      cb(null, array[i++]
    }
  }
}

usage:

const source = values([0, 1, 2, 3])

source(null, (err, value) {
  console.log('first value:', value)
})
// first value: 0

???


sink

example:

function log (read) {
  read(null, function next (err, data) {
    if (err) return console.log(err)
    console.log(data)
    // recursively call read again!
    read(null, next)
  })
}

usage:

const source = values([0, 1, 2, 3])

log(source)
// 0
// 1
// 2
// 3

???

with continuables:

function log (read) {
  return (cb) => {
    read(null, function next (err, data) {
      if (err) return cb(err)
      console.log(data)
      // recursively call read again!
      read(null, next)
    })
  }
}

through

example:

function map (mapper) {
  // a sink function: accept a source
  return function (read) {
    // but return another source!
    return function (abort, cb) {
      read(abort, function (err, data) {
        // if the stream has ended, pass that on.
        if (err) cb(err)
        // apply a mapping to that data
        else cb(null, mapper(data))
      })
    }
  }
}

usage:

const source = values([0, 1, 2, 3])
const double = map(x => x * 2)

log(double(source))

real pull streams

const pull = require('pull-stream')

pull(
  pull.values([0, 1, 2, 3]),
  pull.map(x => x * 2),
  pull.log()
)

???


pull stream errors

with a pull stream source callback, there are four possible signals:

  1. value: cb(null, value)
  2. user error: cb(error)
  3. programmer error: throw error
  4. complete: cb(true)

???


luddite.js benefits


better performance

software performance is less about gaining muscle, more about losing weight


easier to describe

specification is a function signature, not a complex state machine


easier to understand

less "snippet-driven development"

more learnable tools focused on power users

???


stories


story: catstack

build a framework from scratch, alone

<img src="./catstack.jpg" height="450" class="center" />

???

reinvent all the wheels!

https://github.com/root-systems/catstack


learning:

yay, reinventing wheels for fun and learning

boo, the world on your shoulders

???

pros

cons


revised: dogstack

choose your battles

<img src="./dogstack.jpg" height="450" class="center" />

???

http://dogstack.js.org/


story: patch ecosystem

bring-your-own-framework potluck

<img src="./patchwork.png" height="400" class="center" />

???

build an app with others, bring-your-own framework

references:


learning: somebody should...

if you see something that needs doing, it's your job to do

???


conclusion


so what

everyone has opinions.

this one is mine. :3

???

takaways

all the "standards"

make up your own "standards"!

you have just as much a right to make the next JavaScript standard as anyone else.


thanks!

<3

https://dinosaur.is

Built with git-ssb-web