|
1 | 1 | # Extension |
2 | 2 |
|
3 | | -This page has been moved here: [Import](import.md). |
| 3 | +The library can easily be extended with functions and variables using the |
| 4 | +[`import`](reference/functions/import.md) function. The function `import` |
| 5 | +accepts an object with functions and variables. |
| 6 | + |
| 7 | +Function `import` has the following syntax: |
| 8 | + |
| 9 | +```js |
| 10 | +math.import(object: Object [, options: Object]) |
| 11 | +``` |
| 12 | + |
| 13 | +Where: |
| 14 | + |
| 15 | +- `object` is an object or array containing the functions and/or values to be |
| 16 | + imported. `import` support regular values and functions, typed functions |
| 17 | + (see section [Typed functions](#typed-functions)), and factory functions |
| 18 | + (see section [Factory functions](#factory-functions)). |
| 19 | + An array is only applicable when it contains factory functions. |
| 20 | + |
| 21 | +- `options` is an optional second argument with options. |
| 22 | + The following options are available: |
| 23 | + |
| 24 | + - `{boolean} override` |
| 25 | + If `true`, existing functions will be overwritten. The default value is `false`. |
| 26 | + - `{boolean} silent` |
| 27 | + If `true`, the function will not throw errors on duplicates or invalid |
| 28 | + types. Default value is `false`. |
| 29 | + - `{boolean} wrap` |
| 30 | + If `true`, the functions will be wrapped in a wrapper function which |
| 31 | + converts data types like Matrix to primitive data types like Array. |
| 32 | + The wrapper is needed when extending math.js with libraries which do not |
| 33 | + support the math.js data types. The default value is `false`. |
| 34 | + |
| 35 | +The following code example shows how to import a function and a value into math.js: |
| 36 | + |
| 37 | +```js |
| 38 | +// define new functions and variables |
| 39 | +math.import({ |
| 40 | + myvalue: 42, |
| 41 | + hello: function (name) { |
| 42 | + return 'hello, ' + name + '!'; |
| 43 | + } |
| 44 | +}); |
| 45 | + |
| 46 | +// defined functions can be used in both JavaScript as well as the parser |
| 47 | +math.myvalue * 2; // 84 |
| 48 | +math.hello('user'); // 'hello, user!' |
| 49 | + |
| 50 | +var parser = math.parser(); |
| 51 | +parser.eval('myvalue + 10'); // 52 |
| 52 | +parser.eval('hello("user")'); // 'hello, user!' |
| 53 | +``` |
| 54 | + |
| 55 | +## Import external libraries |
| 56 | + |
| 57 | +External libraries like |
| 58 | +[numbers.js](https://github.com/sjkaliski/numbers.js) and |
| 59 | +[numeric.js](http://numericjs.com/) can be imported as follows. |
| 60 | +The libraries must be installed using npm: |
| 61 | + |
| 62 | + $ npm install numbers |
| 63 | + $ npm install numeric |
| 64 | + |
| 65 | +The libraries can be easily imported into math.js using `import`. |
| 66 | +In order to convert math.js specific data types like `Matrix` to primitive types |
| 67 | +like `Array`, the imported functions can be wrapped by enabling `{wrap: true}`. |
| 68 | + |
| 69 | +```js |
| 70 | +// import the numbers.js and numeric.js libraries into math.js |
| 71 | +math.import(require('numbers'), {wrap: true, silent: true}); |
| 72 | +math.import(require('numeric'), {wrap: true, silent: true}); |
| 73 | + |
| 74 | +// use functions from numbers.js |
| 75 | +math.fibonacci(7); // 13 |
| 76 | +math.eval('fibonacci(7)'); // 13 |
| 77 | + |
| 78 | +// use functions from numeric.js |
| 79 | +math.eval('eig([1, 2; 4, 3])').lambda.x; // [5, -1] |
| 80 | +``` |
| 81 | + |
| 82 | + |
| 83 | +## Typed functions |
| 84 | + |
| 85 | +Typed functions can be created using `math.typed`. A typed function is a function |
| 86 | +which does type checking on the input arguments. It can have multiple signatures. |
| 87 | +And can automatically convert input types where needed. |
| 88 | + |
| 89 | +A typed function can be created like: |
| 90 | + |
| 91 | +```js |
| 92 | +var max = typed('max', { |
| 93 | + 'number, number': function (a, b) { |
| 94 | + return Math.max(a, b); |
| 95 | + }, |
| 96 | + |
| 97 | + 'BigNumber, BigNumber': function (a, b) { |
| 98 | + return a.greaterThan(b) ? a : b; |
| 99 | + } |
| 100 | +}); |
| 101 | +``` |
| 102 | + |
| 103 | +Typed functions can be merged as long as there are no conflicts in the signatures. |
| 104 | +This allows for extending existing functions in math.js with support for new |
| 105 | +data types. |
| 106 | + |
| 107 | +```js |
| 108 | +// create a new data type |
| 109 | +function MyType (value) { |
| 110 | + this.value = value; |
| 111 | +} |
| 112 | +MyType.prototype.isMyType = true; |
| 113 | +MyType.prototype.toString = function () { |
| 114 | + return 'MyType:' + this.value; |
| 115 | +} |
| 116 | + |
| 117 | +// define a new datatype |
| 118 | +math.typed.addType({ |
| 119 | + name: 'MyType', |
| 120 | + test: function (x) { |
| 121 | + // test whether x is of type MyType |
| 122 | + return x && x.isMyType; |
| 123 | + } |
| 124 | +}) |
| 125 | + |
| 126 | +// use the type in a new typed function |
| 127 | +var add = typed('add', { |
| 128 | + 'MyType, MyType': function (a, b) { |
| 129 | + return new MyType(a.value + b.value); |
| 130 | + } |
| 131 | +}); |
| 132 | + |
| 133 | +// import in math.js, extend the existing function `add` with support for MyType |
| 134 | +math.import({add: add}); |
| 135 | + |
| 136 | +// use the new type |
| 137 | +var ans = math.add(new MyType(2), new MyType(3)); // returns MyType(5) |
| 138 | +console.log(ans); // outputs 'MyType:5' |
| 139 | +``` |
| 140 | + |
| 141 | +Detailed information on typed functions is available here: |
| 142 | +[https://github.com/josdejong/typed-function](https://github.com/josdejong/typed-function) |
| 143 | + |
| 144 | + |
| 145 | + |
| 146 | + |
| 147 | +## Factory functions |
| 148 | + |
| 149 | +Regular JavaScript functions can be imported in math.js using `math.import`: |
| 150 | + |
| 151 | +```js |
| 152 | +math.import({ |
| 153 | + myFunction: function (a, b) { |
| 154 | + // ... |
| 155 | + } |
| 156 | +}); |
| 157 | +``` |
| 158 | + |
| 159 | +The function can be stored in a separate file: |
| 160 | + |
| 161 | +```js |
| 162 | +exports.myFunction = function (a, b) { |
| 163 | + // ... |
| 164 | +} |
| 165 | +``` |
| 166 | + |
| 167 | +Which can be imported like: |
| 168 | + |
| 169 | +```js |
| 170 | +math.import(require('./myFunction.js')); |
| 171 | +``` |
| 172 | + |
| 173 | +An issue arises when `myFunction` needs functionality from math.js: |
| 174 | +it doesn't have access to the current instance of math.js when in a separate file. |
| 175 | +Factory functions can be used to solve this issue. A file exporting a factory function |
| 176 | +looks like: |
| 177 | + |
| 178 | +```js |
| 179 | +exports.name = 'myFunction'; |
| 180 | +exports.factory = function (type, config, load, typed) { |
| 181 | + return myFunction (a, b) { |
| 182 | + // ... |
| 183 | + } |
| 184 | +}; |
| 185 | +``` |
| 186 | + |
| 187 | +The file exports a name and a factory function. When running `math.import`, the factory |
| 188 | +function is invoked by math.js with four arguments: |
| 189 | + |
| 190 | +- `type: Object`: Object containing the data types of math.js, |
| 191 | + like `type.BigNumber` and `type.Unit`. |
| 192 | +- `config: Object`: object with the configuration of math.js. |
| 193 | +- `load: function`: loader function to access functions from math.js. For example to |
| 194 | + load the function `add`: |
| 195 | + |
| 196 | + ```js |
| 197 | + exports.factory = function (type, config, load, typed) { |
| 198 | + var add = load(require('mathjs/lib/function/arithmetic/add')); |
| 199 | + |
| 200 | + return myFunction (a, b) { |
| 201 | + // ... |
| 202 | + } |
| 203 | + }; |
| 204 | + ``` |
| 205 | + |
| 206 | +- `typed: function`: function to create typed-functions. |
| 207 | + |
| 208 | +The result returned by a factory function will be imported into the `math` |
| 209 | +namespace under the given `name`, `math.myFunction` in the above example. |
| 210 | + |
| 211 | +A factory can contain the following properties: |
| 212 | + |
| 213 | +- `name: string`. The name of the exported function or value. Required. |
| 214 | +- `factory: function (type, config, load, typed) `. The factory function, |
| 215 | + must return the function or value to be imported in math.js. Required. |
| 216 | +- `path: string`. An optional path to where the function or value will be |
| 217 | + imported. By default, imported functions have no path and are imported in |
| 218 | + the 'flat' namespace `math`. Data types have `type` as path, and will be |
| 219 | + located under `math.type.*`. Optional. |
| 220 | +- `lazy: boolean`. If true (default), the factory function will be lazy loaded: |
| 221 | + it is executed as soon as the function is about to be used. |
| 222 | +- `math: boolean`. False by default. If true, the `math` namespace is passed |
| 223 | + to the factory function as fifth argument. Should not be used unless there |
| 224 | + is a very good reason for it. |
| 225 | + |
| 226 | +To import a set of factory functions, the function `math.import` accepts an |
| 227 | +array containing factory functions: |
| 228 | + |
| 229 | +```js |
| 230 | +math.import([ |
| 231 | + require('./myFactoryFunction1.js'), |
| 232 | + require('./myFactoryFunction2.js'), |
| 233 | + require('./myFactoryFunction3.js'), |
| 234 | + // ... |
| 235 | +]); |
| 236 | +``` |
0 commit comments