UNPKG

7.12 kBMarkdownView Raw
1# Extension
2
3The library can easily be extended with functions and variables using the
4[`import`](../reference/functions/import.md) function. The function `import`
5accepts an object with functions and variables.
6
7Function `import` has the following syntax:
8
9```js
10math.import(object: Object [, options: Object])
11```
12
13Where:
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
35The following code example shows how to import a function and a value into math.js:
36
37```js
38// define new functions and variables
39math.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
47math.myvalue * 2 // 84
48math.hello('user') // 'hello, user!'
49
50const parser = math.parser()
51parser.eval('myvalue + 10') // 52
52parser.eval('hello("user")') // 'hello, user!'
53```
54
55## Import external libraries
56
57External libraries like
58[numbers.js](https://github.com/sjkaliski/numbers.js) and
59[numeric.js](https://github.com/sloisel/numeric) can be imported as follows.
60The libraries must be installed using npm:
61
62 $ npm install numbers
63 $ npm install numeric
64
65The libraries can be easily imported into math.js using `import`.
66In order to convert math.js specific data types like `Matrix` to primitive types
67like `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
71math.import(require('numbers'), {wrap: true, silent: true})
72math.import(require('numeric'), {wrap: true, silent: true})
73
74// use functions from numbers.js
75math.fibonacci(7) // 13
76math.eval('fibonacci(7)') // 13
77
78// use functions from numeric.js
79math.eval('eig([1, 2; 4, 3])').lambda.x // [5, -1]
80```
81
82
83## Typed functions
84
85Typed functions can be created using `math.typed`. A typed function is a function
86which does type checking on the input arguments. It can have multiple signatures.
87And can automatically convert input types where needed.
88
89A typed function can be created like:
90
91```js
92const 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
103Typed functions can be merged as long as there are no conflicts in the signatures.
104This allows for extending existing functions in math.js with support for new
105data types.
106
107```js
108// create a new data type
109function MyType (value) {
110 this.value = value
111}
112MyType.prototype.isMyType = true
113MyType.prototype.toString = function () {
114 return 'MyType:' + this.value
115}
116
117// define a new datatype
118math.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
127const 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
134math.import({add: add})
135
136// use the new type
137const ans = math.add(new MyType(2), new MyType(3)) // returns MyType(5)
138console.log(ans) // outputs 'MyType:5'
139```
140
141Detailed 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
149Regular JavaScript functions can be imported in math.js using `math.import`:
150
151```js
152math.import({
153 myFunction: function (a, b) {
154 // ...
155 }
156})
157```
158
159The function can be stored in a separate file:
160
161```js
162exports.myFunction = function (a, b) {
163 // ...
164}
165```
166
167Which can be imported like:
168
169```js
170math.import(require('./myFunction.js'))
171```
172
173An issue arises when `myFunction` needs functionality from math.js:
174it doesn't have access to the current instance of math.js when in a separate file.
175Factory functions can be used to solve this issue. A file exporting a factory function
176looks like:
177
178```js
179exports.name = 'myFunction'
180exports.factory = function (type, config, load, typed) {
181 return function myFunction (a, b) {
182 // ...
183 }
184}
185```
186
187The file exports a name and a factory function. When running `math.import`, the factory
188function 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 const 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
208The result returned by a factory function will be imported into the `math`
209namespace under the given `name`, `math.myFunction` in the above example.
210
211A 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
226To import a set of factory functions, the function `math.import` accepts an
227array containing factory functions:
228
229```js
230math.import([
231 require('./myFactoryFunction1.js'),
232 require('./myFactoryFunction2.js'),
233 require('./myFactoryFunction3.js'),
234 // ...
235])
236```