晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。   林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。   见渔人,乃大惊,问所从来。具答之。便要还家,设酒杀鸡作食。村中闻有此人,咸来问讯。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”(间隔 一作:隔绝)   既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。   南阳刘子骥,高尚士也,闻之,欣然规往。未果,寻病终。后遂无问津者。 sh-3ll

HOME


sh-3ll 1.0
DIR:/lib/node_modules/npm/node_modules/genfun/
Upload File :
Current File : //lib/node_modules/npm/node_modules/genfun/README.md
# Genfun [![Travis](https://img.shields.io/travis/zkat/genfun.svg)](https://travis-ci.org/zkat/genfun) [![npm](https://img.shields.io/npm/v/genfun.svg)](https://npm.im/genfun) [![npm](https://img.shields.io/npm/l/genfun.svg)](https://npm.im/genfun)

[`genfun`](https://github.com/zkat/genfun) is a Javascript library that lets you
define generic functions: regular-seeming functions that can be invoked just
like any other function, but that automatically dispatch methods based on the
combination of arguments passed to it when it's called, also known as multiple
dispatch.

It was inspired by [Slate](http://slatelanguage.org/),
[CLOS](http://en.wikipedia.org/wiki/CLOS) and
[Sheeple](http://github.com/zkat/sheeple).

## Install

`$ npm install genfun`

## Table of Contents

* [Example](#example)
* [API](#api)
  * [`Genfun()`](#genfun)
  * [`gf.add()`](#addMethod)
  * [`Genfun.callNextMethod()`](#callNextMethod)
  * [`Genfun.noApplicableMethod()`](#noApplicableMethod)
* [Performance](#performance)

### Example

Various examples are available to look at in the examples/ folder included in
this project. Most examples are also runnable by just invoking them with node.

```javascript
import Genfun from "genfun"

class Person {}
class Dog {}

const frobnicate = Genfun()

frobnicate.add([Person], (person) => {
  console.log('Got a person!')
})

frobnicate.add([Dog], (dog) => {
  console.log('Got a dog!')
})

frobnicate.add([String, Person, Dog], (greeting, person, dog) => {
  console.log(person, ' greets ', dog, ', \'' + greeting + '\'')
})

const person = new Person()
const dog = new Dog()

frobnicate(person) // Got a person!
frobnicate(dog) // Got a dog!
frobnicate('Hi, dog!', person, dog); // {} greets {}, 'Hi, dog!'
```

### API

The basic API for `Genfun` is fairly simple: You create a new `genfun` by
calling `Genfun()`, and add methods to them. Then you call the `genfun` object
like a regular function, and it takes care of dispatching the appropriate
methods!

#### `Genfun()`

Takes no arguments. Simply creates a new `genfun`. A `genfun` is a regular
function object with overriden function call/dispatch behavior.

When called, it will look at its arguments and determine if a matching method
has been defined that applies to **all** arguments passed in, considered
together.

New methods may be added to the `genfun` object with [`gf.add()`](#addMethod).

If no method is found, or none has been defined, it will invoke
[`Genfun.noApplicableMethod`](#noApplicableMethod) with the appropriate
arguments.

Genfuns preserve the value of `this` if invoked using `.call` or `.apply`.

##### Example

```javascript
var gf = Genfun()

//... add some methods ..

// These calls are all identical.
gf(1, 2, 3)
gf.call(null, 1, 2, 3)
gf.apply(null, [1, 2, 3])
```

#### <a name="addMethod"></a> `gf.add(<selector>, <body>)`

Adds a new method to `gf` and returns `gf` to allow chaining multiple `add`s.

`<selector>` must be an array of objects that will receive new `Role`s (dispatch
positions) for the method. If an object in the selector is a function, its
`.prototype` field will receive the new `Role`. The array must not contain any
frozen objects.

When a `genfun` is called (like a function), it will look at its set of added
methods and, based on the `Role`s assigned, and corresponding prototype chains,
will determine which method, if any, will be invoked. On invocation, a method's
`<body>` argument will be the called with the arguments passed to the `genfun`,
including its `this` and `arguments` values`.

Within the `<body>`, [`Genfun.callNextMethod`](#callNextMethod) may be called.

##### Example

```javascript

var numStr = Genfun()

numStr.add([String, Number], function (str, num) {
  console.log('got a str:', str, 'and a num: ', num)
})

numStr.add([Number, String], function (num, str) {
  console.log('got a num:', num, 'and a str:', str)
})

```

#### <a name="callNextMethod"></a> `Genfun.callNextMethod([...<arguments>])`

**NOTE**: This function can only be called synchronously. To call it
asynchronously (for example, in a `Promise` or in a callback), use
[`getContext`](#getContext)

Calls the "next" applicable method in the method chain. Can only be called
within the body of a method.

If no arguments are given, `callNextMethod` will pass the current method's
original arguments to the next method.

If arguments are passed to `callNextMethod`, it will invoke the next applicable
method (based on the **original** method list calculation), with **the given
arguments**, even if they would otherwise not have triggered that method.

Returns whatever value the next method returns.

There **must** be a next method available when invoked. This function **will
not** call `noApplicableMethod` when it runs out of methods to call. It will
instead throw an error.

##### Example

```javascript
class Foo {}
class Bar extends Foo {}

var cnm = Genfun()

cnm.add([Foo], function (foo) {
  console.log('calling the method on Foo with', foo)
  return foo
})

cnm.add([Bar], function (bar) {
  console.log('calling the method on Bar with', bar)
  return Genfun.callNextMethod('some other value!')
})

cnm(new Bar())
// calling the method on Bar with {}
// calling the method on Foo with "some other value!"
// => 'some other value!'
```

#### <a name="getContext"></a> `Genfun.getContext()`

The `context` returned by this function will have a `callNextMethod` method
which can be used to invoke the correct next method even during asynchronous
calls (for example, when used in a callback or a `Promise`).

This function must be called synchronously within the body of the method before
any asynchronous calls, and will error if invoked outside the context of a
method call.

##### Example

```javascript
someGenfun.add([MyThing], function (thing) {
  const ctx = Genfun.getContext()
  return somePromisedCall(thing).then(res => ctx.callNextMethod(res))
})
```

#### <a name="noApplicableMethod"></a> `Genfun.noApplicableMethod(<gf>, <this>, <args>)`

`Genfun.noApplicableMethod` is a `genfun` itself, which is called whenever **any `genfun`** fails to find a matching method for its given arguments.

It will be called with the `genfun` as its first argument, then the `this`
value, and then the arguments it was called with.

By default, this will simply throw a NoApplicableMethod error.

Users may override this behavior for particular `genfun` and `this`
combinations, although `args` will always be an `Array`. The value returned from
the dispatched `noApplicableMethod` method will be returned by `genfun` as if it
had been its original method. Comparable to [Ruby's
`method_missing`](http://ruby-doc.org/core-2.1.0/BasicObject.html#method-i-method_missing).

### Performance

`Genfun` pulls a few caching tricks to make sure dispatch, specially for common
cases, is as fast as possible.

How fast? Well, not much slower than native methods:

```
Regular function: 30.402ms
Native method: 28.109ms
Singly-dispatched genfun: 64.467ms
Double-dispatched genfun: 70.052ms
Double-dispatched genfun with string primitive: 76.742ms
```