UNPKG

2.75 kBJavaScriptView Raw
1const { create, all } = require('../..')
2
3const math = create(all)
4
5// The expression evaluator accepts an optional scope object.
6// This is the symbol table for variable defintions and function declations.
7
8// Scope can be a bare object.
9function withObjectScope () {
10 const scope = { x: 3 }
11
12 math.evaluate('x', scope) // 1
13 math.evaluate('y = 2 x', scope)
14 math.evaluate('scalar = 1', scope)
15 math.evaluate('area(length, width) = length * width * scalar', scope)
16 math.evaluate('A = area(x, y)', scope)
17
18 console.log('Object scope:', scope)
19}
20
21// Where flexibility is important, scope can duck type appear to be a Map.
22function withMapScope (scope, name) {
23 scope.set('x', 3)
24
25 math.evaluate('x', scope) // 1
26 math.evaluate('y = 2 x', scope)
27 math.evaluate('scalar = 1', scope)
28 math.evaluate('area(length, width) = length * width * scalar', scope)
29 math.evaluate('A = area(x, y)', scope)
30
31 console.log(`Map-like scope (${name}):`, scope.localScope)
32}
33
34// This is a minimal set of functions to look like a Map.
35class MapScope {
36 constructor () {
37 this.localScope = new Map()
38 }
39
40 get (key) {
41 // Remember to sanitize your inputs, or use
42 // a datastructure that isn't a footgun.
43 return this.localScope.get(key)
44 }
45
46 set (key, value) {
47 return this.localScope.set(key, value)
48 }
49
50 has (key) {
51 return this.localScope.has(key)
52 }
53
54 keys () {
55 return this.localScope.keys()
56 }
57}
58
59/*
60 * This is a more fully featured example, with all methods
61 * used in mathjs.
62 *
63 */
64class AdvancedMapScope extends MapScope {
65 constructor (parent) {
66 super()
67 this.parentScope = parent
68 }
69
70 get (key) {
71 return this.localScope.get(key) ?? this.parentScope?.get(key)
72 }
73
74 has (key) {
75 return this.localScope.has(key) ?? this.parentScope?.get(key)
76 }
77
78 keys () {
79 if (this.parentScope) {
80 return new Set([...this.localScope.keys(), ...this.parentScope.keys()])
81 } else {
82 return this.localScope.keys()
83 }
84 }
85
86 delete () {
87 return this.localScope.delete()
88 }
89
90 clear () {
91 return this.localScope.clear()
92 }
93
94 /**
95 * Creates a child scope from this one. This is used in function calls.
96 *
97 * @returns a new Map scope that has access to the symbols in the parent, but
98 * cannot overwrite them.
99 */
100 createSubScope () {
101 return new AdvancedMapScope(this)
102 }
103
104 toString () {
105 return this.localScope.toString()
106 }
107}
108
109withObjectScope()
110// Where safety is important, scope can also be a Map
111withMapScope(new Map(), 'simple Map')
112// Where flexibility is important, scope can duck type appear to be a Map.
113withMapScope(new MapScope(), 'MapScope example')
114// Extra methods allow even finer grain control.
115withMapScope(new AdvancedMapScope(), 'AdvancedScope example')