Comparing version 0.0.5 to 0.1.0
@@ -5,2 +5,14 @@ # overload2 | ||
## [0.1.0] - 2017-06 | ||
### Functions Added | ||
* __overload2.Type.and()__ | ||
* __overload2.Type.or()__ | ||
* __overload2.Type.not()__ | ||
### Changed | ||
Predefined datatypes are moved from `overload2.*` to `overload2.Type.*`. | ||
## [0.0.5] - 2017-05 | ||
@@ -7,0 +19,0 @@ |
266
overload2.js
@@ -6,4 +6,4 @@ /** | ||
/* eslint-disable no-shadow-restricted-names */ | ||
(function(global, undefined) { | ||
var MODULE_REQUIRE | ||
@@ -38,4 +38,6 @@ /* built-in */ | ||
/* eslint-disable new-cap */ | ||
var err = new parent; | ||
this.stack = [ this.name + ': ' + this.message ].concat( err.stack.split('\n').slice(2) ).join('\n'); | ||
/* eslint-enable new-cap */ | ||
this.stack = [ this.name + ': ' + this.message ].concat(err.stack.split('\n').slice(2)).join('\n'); | ||
}; | ||
@@ -57,2 +59,3 @@ | ||
// 同时,我们在自定义错误的设计上也尽量遵循了准确和具有建设性的原则。 | ||
/* eslint-disable key-spacing, comma-style */ | ||
, ERR = { | ||
@@ -66,3 +69,3 @@ Generic: declareException('Error'), | ||
Type: declareException('TypeError', TypeError, function(/*string*/ desc, /*string|Array*/ types, /*string*/ actual) { | ||
this.message = desc + ' must be ' + ( typeof types == 'string' ? types : types.join(' | ') ) + ': ' + actual; | ||
this.message = desc + ' must be ' + (typeof types == 'string' ? types : types.join(' | ')) + ': ' + actual; | ||
}), | ||
@@ -80,2 +83,3 @@ | ||
} | ||
/* eslint-enable key-spacing, comma-style */ | ||
@@ -121,36 +125,92 @@ /** | ||
if (matcher instanceof RegExp) | ||
this.match = function(value) { return matcher.test(value); } | ||
else | ||
if (matcher instanceof RegExp) { | ||
this.match = function(value) { | ||
return matcher.test(value); | ||
}; | ||
} | ||
else { | ||
this.match = matcher; | ||
} | ||
} | ||
// --------------------------- | ||
// 预定义数据类型。 | ||
Type.ANY = new Type(function() { | ||
return true; | ||
}); | ||
Type.BOOLEAN = new Type(function(value) { | ||
return typeof value === 'boolean'; | ||
}); | ||
Type.CHAR = new Type(function(value) { | ||
return typeof value === 'string' && value.length == 1; | ||
}); | ||
Type.NUMBER = new Type(function(value) { | ||
return typeof value === 'number'; | ||
}); | ||
Type.PLAIN_OBJECT = new Type(function(value) { | ||
return typeof value === 'object' && value.constructor === Object; | ||
}); | ||
Type.SCALAR = new Type(function(value) { | ||
return [ 'boolean', 'number', 'string' ].indexOf(typeof value) >= 0; | ||
}); | ||
Type.STRING = new Type(function(value) { | ||
return typeof value === 'string'; | ||
}); | ||
// --------------------------- | ||
// 自定义数据类型生成器。 | ||
/** | ||
* 参数类。 | ||
* 构造函数支持重载,可能的参数形式包括: | ||
* "alias ...decorator" | ||
* type, ...decorator | ||
* type, decorators | ||
* 其中 type 可以是 Type 对象、普通的构造函数或者类型别名,decorators 则代表由多个修饰符组成的字符串,以空格分隔。 | ||
* 创建枚举类型。 | ||
*/ | ||
function Param() { | ||
if (arguments.length == 0) { | ||
throw new ERR.Arguments('1+', 0); | ||
} | ||
Type.enum = function() { | ||
var args = Array.from(arguments); | ||
return new Type(function(value) { | ||
return args.indexOf(value) >= 0; | ||
}); | ||
}; | ||
if (arguments.length == 1 && arguments[0] instanceof Param) { | ||
return arguments[0]; | ||
} | ||
// --------------------------- | ||
// 有关类型的逻辑工具。 | ||
var type = arguments[0], decos = []; | ||
// 根据现有类型,创建新的复合类型。 | ||
Type.and = function() { | ||
var types = Array.from(arguments).map(Type.parse); | ||
return new Type(function(value) { | ||
var matched = true; | ||
for (var i = 0; i < types.length && matched; i++) { | ||
matched = types[i].match(value); | ||
} | ||
return matched; | ||
}); | ||
}; | ||
// --------------------------- | ||
// 处理数据类型。 | ||
// 根据现有类型,创建新的复合类型。 | ||
Type.or = function() { | ||
var types = Array.from(arguments).map(Type.parse); | ||
return new Type(function(value) { | ||
var matched = false; | ||
for (var i = 0; i < types.length && !matched; i++) { | ||
matched = types[i].match(value); | ||
} | ||
return matched; | ||
}); | ||
}; | ||
// 取当前类型的补集。 | ||
Type.not = function(type) { | ||
return new Type(function(value) { | ||
return !type.match(value); | ||
}); | ||
}; | ||
Type.parse = function(type) { | ||
if (typeof type == 'string') { | ||
// 如果首参数是字符串,则它可能包括数据类型别名及修饰符,我们需要首先将其拆分。 | ||
// 拆分后第一个字符串作为数据类型(别名,后面还会继续处理),其余作为修饰符。 | ||
decos = type.trim().split(/\s+/); | ||
type = decos.shift(); | ||
var formalType = TYPE_ALIAS[type]; | ||
@@ -180,13 +240,46 @@ if (!formalType) { | ||
} | ||
this.type = type; | ||
return type; | ||
}; | ||
/** | ||
* 参数类。 | ||
* 构造函数支持重载,可能的参数形式包括: | ||
* "alias ...decorator" | ||
* type, ...decorator | ||
* type, decorators | ||
* 其中 type 可以是 Type 对象、普通的构造函数或者类型别名,decorators 则代表由多个修饰符组成的字符串,以空格分隔。 | ||
*/ | ||
function Param() { | ||
if (arguments.length == 0) { | ||
throw new ERR.Arguments('1+', 0); | ||
} | ||
if (arguments.length == 1 && arguments[0] instanceof Param) { | ||
return arguments[0]; | ||
} | ||
var type = arguments[0], decos = []; | ||
// --------------------------- | ||
// 处理数据类型。 | ||
if (typeof type == 'string') { | ||
// 如果首参数是字符串,则它可能包括数据类型别名及修饰符,我们需要首先将其拆分。 | ||
// 拆分后第一个字符串作为数据类型(别名,后面还会继续处理),其余作为修饰符。 | ||
decos = type.trim().split(/\s+/); | ||
type = decos.shift(); | ||
} | ||
this.type = Type.parse(type); | ||
// --------------------------- | ||
// 处理修饰符。 | ||
var DECOS = ['NULL', 'UNDEFINED']; | ||
var DECOS = ['NULL', 'UNDEFINED'], i; | ||
for (var i = 1; i < arguments.length; i++) { | ||
for (i = 1; i < arguments.length; i++) { | ||
decos = decos.concat(arguments[i].trim().split(/\s+/)); | ||
} | ||
for (var i = 0; i < decos.length; i++) { | ||
for (i = 0; i < decos.length; i++) { | ||
var rawDeco = decos[i]; | ||
@@ -409,3 +502,2 @@ | ||
function Overloader() { | ||
var overloaded = new OverloadedFunction(); | ||
@@ -416,19 +508,2 @@ var append = function(args) { | ||
// 保存多态实现。 | ||
// 注意:如果多态实现不合规,应当在定义时抛出异常,调用时不再进行合规校验。 | ||
var saveDEF = function(args, isDefault) { | ||
var overloadInstance; | ||
if (args[0] instanceof Overload) { | ||
overloadInstance = args[0]; | ||
} | ||
else { | ||
overloadInstance = Overload.parse.apply(null, args); | ||
} | ||
overloaded.overload(overloadInstance); | ||
if (isDefault) { | ||
overloaded.defaultMethod = overloadInstance.method; | ||
} | ||
}; | ||
if (arguments.length) { | ||
@@ -460,63 +535,36 @@ // append(arguments); | ||
// 预定义数据类型。 | ||
// 为了向前兼容,保留 0.1.0 版本之前的预定义数据类型,但以后新增类型仅挂靠 Type 函数。 | ||
Overloader.ANY = new Type(function(value) { | ||
return true; | ||
}); | ||
Overloader.ANY = Type.ANY; | ||
Overloader.BOOLEAN = Type.BOOLEAN; | ||
Overloader.CHAR = Type.CHAR; | ||
Overloader.NUMBER = Type.NUMBER; | ||
Overloader.SCALAR = Type.SCALAR; | ||
Overloader.STRING = Type.STRING; | ||
Overloader.BOOLEAN = new Type(function(value) { | ||
return typeof value == 'boolean'; | ||
}); | ||
Overloader.CHAR = new Type(function(value) { | ||
return typeof value == 'string' && value.length == 1; | ||
}); | ||
Overloader.NUMBER = new Type(function(value) { | ||
return typeof value == 'number'; | ||
}); | ||
Overloader.SCALAR = new Type(function(value) { | ||
return [ 'boolean', 'number', 'string' ].indexOf(typeof value) >= 0; | ||
}); | ||
Overloader.STRING = new Type(function(value) { | ||
return typeof value == 'string'; | ||
}); | ||
// --------------------------- | ||
// 自定义数据类型生成器。 | ||
// 为了向前兼容,保留 0.1.0 版本之前的数据类型生成工具,但以后新增工具仅挂靠 Type 函数。 | ||
/** | ||
* 创建枚举类型。 | ||
*/ | ||
Overloader.enum = function() { | ||
var args = []; | ||
for (var i = 0; i < arguments.length; i++) { | ||
args.push(arguments[i]); | ||
} | ||
Overloader.enum = Type.enum; | ||
return new Type(function(value) { | ||
return args.indexOf(value) >= 0; | ||
}); | ||
}; | ||
// --------------------------- | ||
Overloader.Type = Type; | ||
Overloader.type = Type; | ||
Overloader.parseType = Type; | ||
Overloader.Type = Type; | ||
Overloader.type = Type; | ||
// Overloader.parseType = Type; | ||
Overloader.Param = Param; | ||
Overloader.param = Param.parse; | ||
Overloader.parseParam = Param.parse; | ||
Overloader.Param = Param; | ||
Overloader.param = Param.parse; | ||
Overloader.parseParam = Param.parse; | ||
Overloader.ParamList = ParamList; | ||
Overloader.paramList = ParamList.parse; | ||
Overloader.ParamList = ParamList; | ||
Overloader.paramList = ParamList.parse; | ||
Overloader.parseParamList = ParamList.parse; | ||
Overloader.Overload = Overload; | ||
Overloader.overload = Overload.parse; | ||
Overloader.parseOverload = Overload.parse; | ||
Overloader.Overload = Overload; | ||
Overloader.overload = Overload.parse; | ||
Overloader.parseOverload = Overload.parse; | ||
Overloader.Function = OverloadedFunction; | ||
Overloader.Function = OverloadedFunction; | ||
Overloader.createFunction = OverloadedFunction; | ||
@@ -533,13 +581,13 @@ | ||
var TYPE_ALIAS = { | ||
'*' : Overloader.ANY | ||
, 'any' : Overloader.ANY | ||
, 'boolean' : Overloader.BOOLEAN | ||
, 'char' : Overloader.CHAR | ||
, 'number' : Overloader.NUMBER | ||
, 'scalar' : Overloader.SCALAR | ||
, 'string' : Overloader.STRING | ||
}; | ||
var TYPE_ALIAS = | ||
{ '*' : Type.ANY | ||
, 'any' : Type.ANY | ||
, 'boolean' : Type.BOOLEAN | ||
, 'char' : Type.CHAR | ||
, 'number' : Type.NUMBER | ||
, 'object' : Type.PLAIN_OBJECT | ||
, 'scalar' : Type.SCALAR | ||
, 'string' : Type.STRING | ||
}; | ||
// --------------------------- | ||
@@ -554,4 +602,4 @@ // 模块输出 | ||
// RequireJS | ||
else if (typeof define == 'function') { | ||
define(function() { | ||
else if (typeof global.define == 'function') { | ||
global.define(function() { | ||
return Overloader; | ||
@@ -558,0 +606,0 @@ }); |
{ | ||
"name": "overload2", | ||
"version": "0.0.5", | ||
"version": "0.1.0", | ||
"description": "Elegant solution for function overloading in JavaScript", | ||
@@ -19,3 +19,5 @@ "main": "overload2.js", | ||
"overload", | ||
"overloading", | ||
"function-overloading", | ||
"class-overloading", | ||
"constructor-overloading", | ||
@@ -22,0 +24,0 @@ "strongly-typed" |
130
README.md
# overload2 | ||
__Elegant solution for function overloading in JavaScript.__ | ||
@@ -24,2 +23,3 @@ | ||
* [Why overload2](#why-overload2) | ||
* [Honorable Dependents](#dependents) | ||
* [About](#about) | ||
@@ -91,3 +91,3 @@ * [References](#references) | ||
*overload2* can match any instance with its constructor function, e.g. ``[0,1]`` is matched with ``Array``. See another example: | ||
*overload2* can match any instance with its constructor function, e.g. `[0,1]` is matched with `Array`. See another example: | ||
@@ -106,3 +106,3 @@ ```javascript | ||
You may create customized datatypes by ``new overload2.Type(fn)``, e.g. | ||
You may create customized datatypes by `new overload2.Type(fn)`, e.g. | ||
@@ -129,11 +129,17 @@ ```javascript | ||
| Predefined Data Type | Remark | | ||
| :--------------------- | :------------- | | ||
| __overload2.ANY__ | Anything. | | ||
| __overload2.BOOLEAN__ | It must be ``true`` or ``false``, anything else including instance of ``Boolean`` is unmatched. | | ||
| __overload2.CHAR__ | A string whose length equals 1, e.g. "a" | | ||
| __overload2.NUMBER__ | A number, but NOT instance of ``Number``. | | ||
| __overload2.SCALAR__ | A number, string or boolean, but NOT instance of ``Number`, ``String`` or ``Boolean``. | | ||
| __overload2.STRING__ | A string, but NOT instance of ``String``. | | ||
| Predefined Data Type | Remark | | ||
| :-------------------------- | :------------- | | ||
| __overload2.Type.ANY__ | Anything. | | ||
| __overload2.Type.BOOLEAN__ | It must be `true` or `false`, anything else including instance of `Boolean` is unmatched. | | ||
| __overload2.Type.CHAR__ | A string whose length equals 1, e.g. "a" | | ||
| __overload2.Type.NUMBER__ | A number, but NOT instance of `Number`. | | ||
| __overload2.Type.SCALAR__ | A number, string or boolean, but NOT instance of `Number`, `String` or `Boolean`. | | ||
| __overload2.Type.STRING__ | A string, but NOT instance of `String`. | | ||
ATTENTION: | ||
1. Predefined datatypes named `Type.BOOLEAN`, `Type.NUMBER` and `Type.STRING` refers to primitive values with types of `boolean`, `number` and `string`, not their Object-wrapped forms. If Object-wrapped form required, just directly use constructor functions `Boolean`, `Number` and `String` as datatype, see [Datatypes: Constructor Function](#constructor-function). | ||
1. Before version 0.1.0, predefined datatypes are appended directly to the `overload2` module. To avoid ambiguity in future, predefined datatypes will be appended to `overload2.Type`. Although the old ones reserved, it's strongly suggested not to use `overload2.<PREDEFINED_TYPE_NAME>` any longer. | ||
### Datatype Alias | ||
@@ -143,11 +149,12 @@ | ||
| Alias | Corresponding Datetype | | ||
| :--------- | :--------------------- | | ||
| * | __overload2.ANY__ | | ||
| any | __overload2.ANY__ | | ||
| boolean | __overload2.BOOLEAN__ | | ||
| char | __overload2.CHAR__ | | ||
| number | __overload2.NUMBER__ | | ||
| scalar | __overload2.SCALAR__ | | ||
| string | __overload2.STRING__ | | ||
| Alias | Corresponding Datetype | | ||
| :--------- | :------------------------------ | | ||
| * | __overload2.Type.ANY__ | | ||
| any | __overload2.Type.ANY__ | | ||
| boolean | __overload2.Type.BOOLEAN__ | | ||
| char | __overload2.Type.CHAR__ | | ||
| number | __overload2.Type.NUMBER__ | | ||
| object | __overload2.Type.PLAIN_OBJECT__ | | ||
| scalar | __overload2.Type.SCALAR__ | | ||
| string | __overload2.Type.STRING__ | | ||
@@ -158,5 +165,14 @@ ### Create Datatype With Factory Method | ||
* __overload2.enum(item[, ...])__ | ||
* __overload2.Type.enum(item [, ...])__ | ||
Return an enumeration type. | ||
* __overload2.Type.and(type1, type2 [, ...])__ | ||
Create a compound type. | ||
* __overload2.Type.or(type1, type2 [, ...])__ | ||
Create a compound type. | ||
* __overload2.Type.not(type)__ | ||
Create a new type which is complementary to the origin type. | ||
## Move Forward | ||
@@ -178,3 +194,3 @@ <a name="move-forward"></a> | ||
Instances of ``Type``, ``Param``, ``ParamList`` and ``Overload`` are able to be created independently and be re-used in creating instances of superior class(es). | ||
Instances of `Type`, `Param`, `ParamList` and `Overload` are able to be created independently and be re-used in creating instances of superior class(es). | ||
@@ -186,8 +202,16 @@ Here is an [example](./example/advanced.js) for advanced mode. | ||
### Overloaded Function Instance | ||
* [overload2()](#api-overload2) | ||
* [class overload2.Type](#api-class-type) | ||
* [class overload2.Param](#api-class-param) | ||
* [class overload2.ParamList](#api-class-paramlist) | ||
* [class overload2.Overload](#api-class-overload) | ||
* [class overload2.OverloadedFunction](#api-class-overloadedfunction) | ||
``overload2`` itself is a function, when invoked, it will return an overloded function instance. | ||
### overload2(), Create An Overloaded Function | ||
<a name="api-overload2"></a> | ||
`overload2` itself is a function, when invoked, it will return an overloded function instance. | ||
* \<fn\> __overload2__() | ||
Create a new overloaded function. The function has no implementations before ``.overload()`` called. | ||
Create a new overloaded function. The function has no implementations before `.overload()` called. | ||
@@ -200,13 +224,15 @@ * \<fn\> __\<fn\>.overload__( [ \<datatype\>, ... ] function \<implementation\> ) | ||
### overload2.Type | ||
### class overload2.Type | ||
<a name="api-class-type"></a> | ||
To define a datatype in context of *overload2*, there are different ways including ``overload2.Type``. And all other datatypes will be converted to instances of ``overload2.Type`` before being used. | ||
To define a datatype in context of *overload2*, there are different ways including `overload2.Type`. And all other datatypes will be converted to instances of `overload2.Type` before being used. | ||
* new __overload2.Type__( function | RegExp \<matcher\> ) | ||
Here ``matcher`` may be a function or RegExp object. | ||
Here `matcher` may be a function or RegExp object. | ||
* *private* boolean __\<type\>.match__( \<value\> ) | ||
Return ``true`` if value matches the datatype, otherwise return ``false``. | ||
Return `true` if value matches the datatype, otherwise return `false`. | ||
### overload2.Param | ||
### class overload2.Param | ||
<a name="api-class-param"></a> | ||
@@ -221,6 +247,6 @@ A Param is made up of a Type and some decorators. Available decorators are: | ||
* new __overload2.Param__( string "\<alias\> \<decorator\> ..." ) | ||
The ``alias`` should be one of alias listed in table [Datatype Alias](#datatype-alias). | ||
The `alias` should be one of alias listed in table [Datatype Alias](#datatype-alias). | ||
* new __overload2.Param__( Type | function | string \<datatype\>, string \<decorator(s)\> [ , string \<decorator(s)\> ] ) | ||
Here ``datatype`` may be instance of ``Type``, or construtor function, or datatype alias. | ||
Here `datatype` may be instance of `Type`, or construtor function, or datatype alias. | ||
@@ -231,36 +257,39 @@ * *private* boolean __\<param\>.satisfy__( \<value\> ) | ||
* Param __overload2.Param.parse__( ? ) | ||
Arguments suitable for ``new Param()`` are also suitable for the ``Param.parse()``. | ||
Arguments suitable for `new Param()` are also suitable for the `Param.parse()`. | ||
### overload2.ParamList | ||
### class overload2.ParamList | ||
<a name="api-class-paramlist"></a> | ||
* new __overload2.ParamList__( [ Param | Array | String \<param\> [ , ... ] ] ) | ||
Here ``param`` may be an instance of ``Param``, or a string or an array which may used as argument(s) for ``new Param()``. | ||
Here `param` may be an instance of `Param`, or a string or an array which may used as argument(s) for `new Param()`. | ||
* *private* boolean __\<paramList\>.satisfy__( Array | Arguments \<args\> ) | ||
To check arguments with parameters, return ``true`` if matched or ``false`` if not. | ||
To check arguments with parameters, return `true` if matched or `false` if not. | ||
* ParamList __overload2.ParamList.parse__( ? ) | ||
Arguments suitable for ``new ParamList()`` are also suitable for the ``ParamList.parse()``. | ||
Arguments suitable for `new ParamList()` are also suitable for the `ParamList.parse()`. | ||
### overload2.Overload | ||
### class overload2.Overload | ||
<a name="api-class-overload"></a> | ||
* new __overload2.Overload__( number <argumentsNumber>, function \<implementation\> ) | ||
Create an ``Overload`` instance by restricting the number of arguments. | ||
Create an `Overload` instance by restricting the number of arguments. | ||
* new __overload2.Overload__( ParamList, function \<implementation\> ) | ||
Create an ``Overload`` instance bound to specified ``ParamList``. | ||
Create an `Overload` instance bound to specified `ParamList`. | ||
* new __overload2.Overload__( \<param\> [ , ... ] , function \<implementation\> ) | ||
Create an ``Overload`` instance with optional definitions of ``Param``. | ||
Create an `Overload` instance with optional definitions of `Param`. | ||
* new __overload2.Overload__(function \<implementation\> ) | ||
Create an ``Overload`` instance which will be invoked while arguments length equals 0. | ||
Create an `Overload` instance which will be invoked while arguments length equals 0. | ||
* Overload __overload2.Overload.parse__( ? ) | ||
Arguments suitable for ``new Overload()`` are also suitable for the ``Overload.parse()``. | ||
Arguments suitable for `new Overload()` are also suitable for the `Overload.parse()`. | ||
### overload2.OverloadedFunction | ||
### class overload2.OverloadedFunction | ||
<a name="api-class-overloadedfunction"></a> | ||
* new __overload2.OverloadedFunction__() | ||
The instance of ``OverloadedFunction`` is a wrapper, not a function itself. | ||
The instance of `OverloadedFunction` is a wrapper, not a function itself. | ||
@@ -276,7 +305,7 @@ * __\<wrapper\>.exec__( ... ) | ||
* __\<wrapper\>.overload__( Overload \<overloadInstance\> ) | ||
* __\<wrapper\>.overload__( Overload \<overloadInstance\> [ , Boolean <setAsDefault> ] ) | ||
Append an overloading implementation. | ||
* __\<wrapper\>.overload__( ? ) | ||
Append an overloading implementation, arguments suitable for ``new Overload()`` are also suitable for the ``<wrapper>.overload()``. | ||
Append an overloading implementation, arguments suitable for `new Overload()` are also suitable for the `<wrapper>.overload()`. | ||
@@ -325,2 +354,7 @@ ## Examples | ||
## Honorable Dependents | ||
<a name="dependents"></a> | ||
Welcome to be the first dependent of *overload2*! | ||
## About | ||
@@ -330,2 +364,4 @@ | ||
Why postfixed the package name with number 2? Since name "overload" has been occupied, inspired by well-known package "pm2" and "through2", I thought "overload2" is not bad. The most important reason why I choose "overload2" was because 2 /tu:/ is pronounced like tool /tu:l/. | ||
## References | ||
@@ -332,0 +368,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
104680
1471
358