In this tutorial we're going to build a set of parser combinators.
We'll answer the above question in 2 steps.
- What is a parser?
- and, what is a parser combinator?
So first question: What is parser?
| // We model the call stack using a linked list of Generators | |
| // Each Generator has a _return field pointing back to its parent | |
| function stepGen(gen, arg) { | |
| const {done, value} = gen.next(arg) | |
| if(done) { | |
| if(gen._return) { | |
| stepGen(gen._return, value) | |
| } |
| function*example() { | |
| const x = 10 | |
| const y = yield callcc(function*(k) { | |
| // ... | |
| yield k(20) | |
| throw "Unreachable code" | |
| }) | |
| console.log(x + y) | |
| } |
| import React from 'react'; | |
| import reclass from './reclass'; | |
| import Greeter from './Greeter'; | |
| function App(ctx) { | |
| ctx.state = { civility: 'Mr.' }; | |
| function changeCivility(e) { | |
| ctx.setState({ civility: e.target.value }); | |
| } |
| <!doctype html> | |
| <html lang="en"> | |
| <body> | |
| <script> | |
| const sagaMiddleware = store => gen => { | |
| var resolve, reject | |
| var done = new Promise((res, rej) => { | |
| resolve = res |
In Redux, reducer composition with combineReducers offers a powerful way to handle
complex update logic of an application. A reducer can encapsulate all the ways a part
of the state is mutated because it can react to multiple types of actions.
But in some cases there is also a need for another type of factoring: often the update logic is simple (for example setting a single value), and the there are many places in the state shape where the update logic is the same.
| import React, { Component } from 'react' | |
| import { runSaga, delay } from 'redux-saga' | |
| import { take, put, call } from 'redux-saga/effects' | |
| // helper functions | |
| const bindFunc = (comp, method) => (...args) => method.apply(comp, args) | |
| const bindSaga = (comp, method) => (...args) => runSaga(method.apply(comp, args), {}) | |
| export default class Counter extends React.Component { |
| syntax seq = function (ctx) { | |
| let monad = ctx.next().value; | |
| let bodyCtx = ctx.next().value.inner(); | |
| function next() { | |
| let result | |
| let n = bodyCtx.next() | |
| if(n.done) return #`` |
| // Getter a :: () -> a | |
| // gmap :: ((a -> b), Getter a), Getter b | |
| function gmap(fn, getter) { | |
| return () => fn(getter()) | |
| } | |
| // gcombine2 :: ((a,b) -> c, Getter a, Getter ab) -> Getter c | |
| function gcombine2(fn, getter1, getter2) { |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Redux basic example</title> | |
| <script src="https://npmcdn.com/redux@latest/dist/redux.min.js"></script> | |
| <script src="redux-dirty.js" charset="utf-8"></script> | |
| </head> | |
| <body> | |
| <script> |