Constructor
new MathConcept(…children)
Create a new MathConcept. Any argument that is not a MathConcept is ignored.
Parameters
-
children
MathConcept
<repeatable>
child MathConcepts to be added to this one (using insertChild())
Source
Classes
Members
className
The name of this class, as a JavaScript string. For the MathConcept class,
this is, of course, "MathConcept"
, but for subclasses, it will vary.
See the code initializing this member to see how subclasses should
initialize their className
members. This is used in deserialization,
to correctly reconstitute objects of the appropriate class.
Source
IDs
We want the capability of assigning each MathConcept in a given hierarchy a globally unique ID. We therefore need a global place to store the mapping of IDs to instances, and thus we create this Map in the MathConcept class.
Each key in the map is an ID and the corresponding value is the instance with that ID. Each ID is a string.
This data structure should not be accessed by clients; it is private to this class. Use instanceWithID() and trackIDs() instead.
Source
subclasses
In order for a hierarchy of MathConcepts to be able to be serialized and deserialized, we need to track the class of each MathConcept in the hierarchy. We cannot reconstitute an object from its serialized state if we do not know which class to construct. So we track all subclasses of this class in a single static map, here.
This class and each of its subclasses should add themselves to this map
and save the corresponding name in a static className
variable in their
class.
See
Source
Methods
addSubclass(name, classObject) → {string}
Adds a subclass to the static subclasses map tracked by this object, for use in reconsituting objects correctly from their serialized forms.
This method should be called once per subclass of MathConcept
. To see
how, see the code that initializes className.
Parameters
-
name
string
The name of the class, as it appears in code
-
classObject
class
The class itself, such as
MathConcept
, or any of its subclasses, that is, the JavaScript object used when constructing new instances.
See
Returns
-
string
The value of the
name
parameter, for convenience in initializing each class's staticclassName
field
Source
feedback(feedbackData)
This implementation of the feedback function is a stub. It does nothing except dump the data to the console. However, it serves as the central method that all MathConcepts should use to transmit feedback, so that when this class is used in the LDE, which has a mechanism for transmitting feedback messages to its clients, the LDE can override this implementation with a real one, and all calls that use this central channel will then be correctly routed.
Documentation will be forthcoming later about the required form and
content of the feedbackData
parameter.
Parameters
-
feedbackData
Object
Any data that can be encoded using
JSON.stringify()
(or predictableStringify()), to be transmitted
Source
fromJSON(data) → {MathConcept}
Deserialize the data in the argument, producing a new MathConcept instance (or, more specifically, sometimes an instance of one of its subclasses).
Note that because this function is static, clients access it as
MathConcept.fromJSON(...)
.
Parameters
-
data
Object
A JavaScript Object of the form produced by toJSON()
See
Returns
-
MathConcept
A new MathConcept instance (which may actually be an instance of a proper subclass of MathConcept) as encoded in the given
data
Source
fromSmackdown(string) → {Array.<MathConcept>}
MathConcept trees can be represented using a notation called "smackdown," which is a superset of the "putdown" notation used to represent LogicConcepts, as documented here. (Both of these are, of course, plays on the name of the famous format "markdown" by John Gruber.)
Smackdown supports all notation used in putdown (so readers may wish to begin learning about smackdown by following the link above to first learn about putdown) plus the following additional features:
- The notation
$...$
can be used to represent a LogicConcept, for example,$x^2-1$
. The use of dollar signs is intentionally reminiscent of $\LaTeX$ notation for in-line math.- Note!
$x^2-1$
is merely an example stating that mathematics of some sort can be placed between the dollar signs; it is not an indication that the specific notationx^2-1
is supported. - At present, no notation is supported, and any text between
dollar signs is simply stored as a MathConcept instance with attribute "Interpret as" set to
["notation","X"]
, where X is the contents of the$...$
(without the dollar signs)---e.g.,["notation","x^2-1"]
. - We will later add support for defining custom mathematical
notation for use in
$...$
expressions, and then create a more robust way to interpret() MathConcept trees into LogicConcepts, which will parse such notation to create real expressions. - To include a literal
$
inside a$...$
section, escape it as\$
.
- Note!
- The notation
\command{argument1}...{argumentN}
is also intentionally reminiscent of $\LaTeX$ notation, and has an analogous meaning: some command applied to a sequence of $N$ arguments. For now, only the following commands are supported.\begin{proof}
and\end{proof}
are replaced with{
and}
, respectively, so that they can be used to construct Environments, which is the meaning one would expect.\label{X}
is interpreted as if it were putdown notation for adding a JSON attribute to the preceding LogicConcept, associating the key "label" with the value X.\ref{X}
is exactly like the previous, but using attribute key "ref" instead of "label."- Any other command is stored as a MathConcept
instance with attribute "Interpret as" having the form
["command",...]
, for example,\foo{bar}{baz}
would become["command","foo","bar","baz"]
.
The two notations given above will work hand-in-hand more over time.
Specifically, we will create types of \command
s that can define new
notation to appear inside $...$
blocks.
For now, this routine fully supports parsing smackdown notation, but does not yet obey a robust set of commands, only those shown above.
Parameters
-
string
string
the smackdown code to be interpreted
See
Returns
-
Array.<MathConcept>
an array of MathConcept instances, the meaning of the smackdown code provided as input
Source
instanceWithID(id) → {MathConcept}
Find a MathConcept instance from a given string ID. This assumes that the assignment of ID to MathConcept has been recorded in the global mapping in IDs, by the function trackIDs(). If it has not been so recorded, then this function will not find the instance and will return undefined.
Note that because this function is static, clients access it as
MathConcept.instanceWithID("...")
.
Parameters
-
id
string
The MathConcept ID to look up
See
Returns
-
MathConcept
The MathConcept that has the given ID, if any, or undefined if no MathConcept has the given ID
Source
typeAttributeKey(type) → {String}
Several functions internal to this object (isA(), asA(), and makeIntoA()) all take a type name as an argument, but do not use it directly as an attribute key, to avoid collisions among commonly used words. Rather, they use this function to slightly obfuscate the type name, thus making accidental name collisions less likely.
To give a specific example, if we wanted to designate a symbol as, say,
a number, we might not want to set its attribute "number"
to true,
because some other piece of code might have a different meaning/intent
for the common word "number"
and might overwrite or misread our data.
So for saying that a MathConcept is a number (or any other type), we
use this function, which turns the text "number"
into the text
"_type_number"
, which almost no one would accidentally also use.
Parameters
-
type
String
The type that will be stored/queried using the resulting key
Returns
-
String
The key to use for querying the given
type
Source
accessibles(reflexive, inThis) → {Array.<MathConcept>}
The full contents of accessiblesIterator(), but put into an array rather than an iterator, for convenience, possibly at the cost of efficiency.
Parameters
-
reflexive
boolean
falsePassed directly to accessiblesIterator(); see that function for more information
-
inThis
MathConcept
nullPassed directly to accessiblesIterator(); see that function for more information
Returns
-
Array.<MathConcept>
All MathConcepts accessible to this one, with the latest (closest to this MathConcept) first, proceeding on to the earliest at the end of the array
Source
accessiblesIterator(reflexive, inThis)
For a definition of accessibility, refer to the documentation for the isAccessibleTo() function.
In short, the accessibles of a node are its previous siblings, the
previous siblings of its parent, the previous siblings of its
grandparent, and so on, where each node yielded
isLaterThan() all nodes yielded thereafter.
You can limit the list to only those accessibles within a given ancestor
by using the inThis
parameter, documented below.
This function is a generator that yields each MathConcept accessible to this one, beginning with the one closest to this one (often its previous sibling) and proceeding back through the hierarchy, so that each new result is accessible to (and earlier than) the previous).
Parameters
-
reflexive
boolean
falseFunctions analogously to the
reflexive
parameter for isAccessibleTo(); that is, do we include this MathConcept on its list of accessibles? The default value is false. -
inThis
MathConcept
nullThe container MathConcept in which to list accessibles. No accessible outside this ancestor will be returned. (If this is not actually an ancestor, it is ignored, and all accessibles are returned, which is the default.)
Source
address(ancestoropt) → {Array.<number>}
My address within the given ancestor, as a sequence of indices
[i1,i2,...,in]
such that ancestor.child(i1).child(i2)....child(in)
is
this MathConcept.
This is a kind of inverse to index().
Parameters
-
ancestor
MathConcept
<optional>
The ancestor in which to compute my address, which defaults to my highest ancestor. If this argument is not actually an ancestor of this MathConcept, then we treat it as if it had been omitted.
Returns
-
Array.<number>
An array of numbers as described above, which will be empty in the degenerate case where this MathConcept has no parent or this MathConcept is the given ancestor
Source
allButFirstChild() → {Array.<MathConcept>}
Convenience function for fetching the array containing all children of this MathConcept except for the first
Returns
-
Array.<MathConcept>
All but the first child of this MathConcept, or an empty array if there is one or fewer children
Source
allButLastChild() → {Array.<MathConcept>}
Convenience function for fetching the array containing all children of this MathConcept except for the last
Returns
-
Array.<MathConcept>
All but the last child of this MathConcept, or an empty array if there is one or fewer children
Source
ancestors() → {Array.<MathConcept>}
An array of all ancestors of this MathConcept, starting with itself. This array is the exact contents of ancestorsIterator(), but in array form rather than as an iterator.
Returns
-
Array.<MathConcept>
An array beginning with this MathConcept, then its parent, grandparent, etc.
Source
ancestorsIterator()
An iterator through all the ancestors of this MathConcept, starting with itself as the first (trivial) ancestor, and walking upwards from there.
This function is a generator that yields this MathConcept, then its parent, grandparent, etc.
See
Source
ancestorsSatisfying(predicate) → {Array.<MathConcept>}
Find all ancestors of this MathConcept satisfying the given predicate. Note that this MathConcept counts as a trivial ancestor of itself, so if you don't want that, modify your predicate to exclude it.
Parameters
-
predicate
function
Predicate to evaluate on each ancestor
Returns
-
Array.<MathConcept>
The ancestors satisfying the predicate, which may be an empty array
Source
asA(type) → {MathConcept}
Create a copy of this MathConcept, but with the given type added, using makeIntoA().
Parameters
-
type
string
The type to add to the copy
See
Returns
-
MathConcept
A copy of this MathConcept, with the given type added
Source
attr(attributes) → {MathConcept}
Add attributes to a MathConcept and return the MathConcept. This function is a convenient form of repeated calls to setAttribute(), and returns the MathConcept for ease of use in method chaining.
Example use: const S = new MathConcept().attr( { k1 : 'v1', k2 : 'v2' } )
Because this calls setAttribute() zero or
more times, as dictated by the contents of attributes
, it may result in
multiple firings of the events
willBeChanged and
wasChanged.
Parameters
-
attributes
Object
|Map
|Array
A collection of key-value pairs to add to this MathConcept's attributes. This can be a JavaScript Object, with keys and values in the usual
{'key':value,...}
form, a JavaScriptMap
object, or a JavaScript Array of key-value pairs, of the form[['key',value],...]
. If this argument is not of any of these three forms (or is omitted), this function does not add any attributes to the MathConcept.
See
Returns
-
MathConcept
The MathConcept itself, for use in method chaining, as in the example shown above.
Source
binds() → {boolean}
By default, MathConcepts do not bind symbols. Subclasses of MathConcept may import the BindingInterface and therefore override the following function, but in the base case, it simply returns false to indicate that no symbols are bound.
See
Returns
-
boolean
the constant false
Source
changeID(newID) → {boolean}
If a MathConcept wishes to change its ID, then we may need to update the internal IDs mapping. The following function changes the ID and updates that mapping if needed all in one action, to make it easy for the client to change a MathConcept's ID, just by calling this function.
If for some reason the change was not possible, then this function will take no action and return false. Possible reasons include:
- the old ID isn't tracked in the IDs mapping
- the new ID is already associated with another MathConcept
- the new ID is the same as the old ID
This function also updates other MathConcepts that connect to this one, changing their connections to use this MathConcept's new ID, so that all connections are preserved across the use of this function.
Parameters
-
newID
string
The ID to use as the replacement for this MathConcept's existing ID. It will be treated as a string if it is not already one.
Returns
-
boolean
True if the operation succeeded, false if it could not be performed (and thus no action was taken)
Source
child(i) → {MathConcept}
Get the child of this MathConcept at index i.
If the index is invalid (that is, it is anything other than one of {0,1,...,n-1} if there are n children) then undefined will be returned instead.
Parameters
-
i
number
The index of the child being fetched
Returns
-
MathConcept
The child at the given index, or undefined if none
Source
children() → {Array.<MathConcept>}
An array containing this MathConcept's children, in the correct order.
To get a specific child, it is more efficient to use the MathConcept.child() function instead.
Returns
-
Array.<MathConcept>
A shallow copy of the MathConcept's children array
Source
childrenSatisfying(predicate) → {Array.<MathConcept>}
The list of children of this MathConcept that satisfy the given predicate, in the same order that they appear as children. Obviously, not all children may be included in the result, depending on the predicate.
Parameters
-
predicate
function
The predicate to use for testing children
Returns
-
Array.<MathConcept>
The array of children satisfying the given predicate
Source
clearAttributes(…keys)
For details on how MathConcepts store attributes, see the documentation for the getAttribute() function.
This function removes zero or more key-value pairs from the MathConcept's attribute dictionary. See the restrictions on keys and values in the documentation linked to above.
The change events are fired only if the given keys are actually currently in use by some key-value pairs in the MathConcept. If you pass multiple keys to be removed, each will generate a separate pair of willBeChanged and wasChanged events.
Parameters
-
keys
Array
<repeatable>
The list of keys indicating which key-value pairs should be removed from this MathConcept; each of these keys must be a string, or it will be converted into one; if this parameter is omitted, it defaults to all the keys for this MathConcept's attributes
Fires
Source
clearIDs(recursive)
Remove the ID of this MathConcept and, if requested, all of its descendants. This does not change anything about the global IDs mapping, so if this MathConcept's IDs are tracked, you should call untrackIDs() first.
Because connections use the ID system, any connections that this MathConcept is a part of will also be severed, by a call to removeConnections().
Parameters
-
recursive
boolean
trueWhether to clear IDs from all descendants of this MathConcept as well
See
Source
connectTo(target, connectionID, data) → {Connection}
Connect this MathConcept to another, called the target, optionally attaching some data to the connection as well. This function just calls Connection.create(), and is thus here just for convenience.
Parameters
-
target
MathConcept
The target of the new connection
-
connectionID
string
The unique ID to use for the new connection we are to create
-
data
*
nullThe optional data to attach to the new connection. See the create() function in the Connection class for the acceptable formats of this data.
Returns
-
Connection
A Connection instance for the newly created connection between this MathConcept and the target. This return value can be safely ignored, because the connection data is stored in the source and target MathConcepts, and is not dependent on the Connection object itself. However, the return value will be false if the chosen connection ID is in use or if this MathConcept or the target does not pass idIsTracked().
Source
copy() → {MathConcept}
A deep copy of this MathConcept. It will have no subtree in common with this one, and yet it will satisfy an equals() check with this MathConcept.
In order to ensure that the copy has the same class as the original (even if that is a proper subclass of MathConcept), this function depends upon that subclass's having registered itself with the subclasses static member.
See
Returns
-
MathConcept
A deep copy
Source
copyAttributesFrom(mathConcept) → {MathConcept}
Copy all the attributes from another MathConcept instance to this one. The attributes are copied deeply, so that if the values are arrays or objects, they are not shared between the two MathConcepts. The attributes are copied using attr(), which calls setAttribute() on each key separately, thus possibly generating many pairs of willBeChanged and wasChanged events.
If this MathConcept shares some attribute keys with the one passed as the
parameter, the attributes of mathConcept
will overwrite the attributes
already in this object.
Parameters
-
mathConcept
MathConcept
another MathConcept instance from which to copy all of its attributes
Returns
-
MathConcept
this object, for method chaining, as in attr()
Source
descendantsIterator()
An iterator over all descendants of this MathConcept, in a pre-order tree traversal.
This function is a generator that yields this MathConcept, then its first child, and so on down that branch of the tree, and onward in a pre-order traversal.
Source
descendantsSatisfying(predicate) → {Array.<MathConcept>}
An array of those descendants of this MathConcept that satisfy the given predicate. These are not copies, but the actual descendants; if you alter one, it changes the hierarchy beneath this MathConcept.
Note that this MathConcept counts as a descendant of itself. To exclude
this MathConcept from consideration, simply change your predicate, as in
X.descendantsSatisfying( d => X != d && predicate(d) )
.
Parameters
-
predicate
function
The predicate to use for testing descendants
Returns
-
Array.<MathConcept>
A list of descendants of this MathConcept, precisely those that satisfy the given predicate, listed in the order they would be visited in a depth-first traversal of the tree
Source
equals(other) → {boolean}
Whether this MathConcept is structurally equal to the one passed as parameter. In particular, this means that this function will return true if and only if all the following are true.
other
is an instance of the MathConcept classother
has the same set of attribute keys as this instance- each of those keys maps to the same data in each instance (where comparison of attribute values is done by JSON.equals())
other
has the same number of children as this instance- each of
other
's children passes a recursive equals() check with the corresponding child of this instance
Parameters
-
other
MathConcept
See
Returns
-
boolean
true if and only if this MathConcept equals
other
Source
feedback(feedbackData)
Send feedback on this particular MathConcept instance. This takes the given feedback data, adds to it the fact that this particular instance is the subject of the feedback (by using its id(), and then asks the static feedback() function to send that feedback to the LDE.
Parameters
-
feedbackData
Object
Any data that can be encoded using
JSON.stringify()
(or predictableStringify()), to be transmitted
Source
firstChild() → {MathConcept}
Convenience function for fetching just the first child of this MathConcept
Returns
-
MathConcept
The first child of this MathConcept, or undefined if none
Source
freeSymbolNames() → {Array.<string>}
A Symbol X is free in an ancestor Y if and only if no MathConcept
that is an ancestor A of X inside of (or equal to) Y satisfies
A.binds( X.text() )
. This function returns an array of all symbol
names that appear within this MathConcept and, at the point where they
appear, are free in this ancestor MathConcept.
If, instead of just the names of the symbols, you wish to have the Symbol instances themselves, you can couple the isFree() function with the descendantsSatisfying() function to achieve that.
Returns
-
Array.<string>
an array of names of free symbols appearing as descendants of this MathConcept
Source
getAttribute(key, defaultValue) → {*}
Every MathConcept stores a dictionary of attributes as key-value pairs. All keys should be strings (or they will be converted into strings) and their associated values must be amenable to a JSON encoding.
This function looks up and returns the value of an attribute in this
MathConcept, the one with the given key
.
Parameters
-
key
*
name of the attribute to look up
-
defaultValue
*
the value that should be returned if the
key
does not appear as the name of an attribute in this MathConcept (defaults to undefined)
Returns
-
*
the value associated with the given
key
Source
getAttributeKeys() → {Array}
Get the list of keys used in the attributes dictionary within this MathConcept. For more details on the MathConcept attribution system, see the documentation for getAttribute().
Each key must be atomic and will be converted into a string if it is not already one.
See
Returns
-
Array
A list of values used as keys
Source
getConnectionIDs() → {Array.<string>}
Get the IDs of all connections into or out of this MathConcept.
Returns
-
Array.<string>
An array of all the IDs of all the connections into or out of this MathConcept. These unique IDs can be used to get a Connection object; see that class's withID() function.
Source
getConnectionIDsIn() → {Array.<string>}
Get the IDs of all connections into this MathConcept.
Returns
-
Array.<string>
An array of all the IDs of all the connections into this MathConcept. These unique IDs can be used to get a Connection object; see that class's withID() function.
Source
getConnectionIDsOut() → {Array.<string>}
Get the IDs of all connections out of this MathConcept.
Returns
-
Array.<string>
An array of all the IDs of all the connections out of this MathConcept. These unique IDs can be used to get a Connection object; see that class's withID() function.
Source
getConnections() → {Array.<Connection>}
Get all connections into or out of this MathConcept, as Connection instances. This function simply maps the withID() function over the result of getConnectionIDs().
Returns
-
Array.<Connection>
An array of all the Connections into or out of this MathConcept.
Source
getConnectionsIn() → {Array.<Connection>}
Get all connections into this MathConcept, as Connection instances. This function simply maps the withID() function over the result of getConnectionIDsIn().
Returns
-
Array.<Connection>
An array of all the Connections into this MathConcept.
Source
getConnectionsOut() → {Array.<Connection>}
Get all connections out of this MathConcept, as Connection instances. This function simply maps the withID() function over the result of getConnectionIDsOut().
Returns
-
Array.<Connection>
An array of all the Connections out of this MathConcept.
Source
hasAncestorSatisfying(predicate) → {boolean}
Whether this MathConcept has an ancestor (including itself) satisfying the given predicate.
Parameters
-
predicate
function
Predicate to evaluate on each ancestor
Returns
-
boolean
Whether an ancestor satisfying the given predicate exists
Source
hasAttribute(key)
Whether this MathConcept has an attribute with the given key. For more details on the MathConcept attribution system, see the documentation for getAttribute().
Parameters
-
key
*
name of the attribute to look up; this should be atomic and will be converted into a string if it is not already one
Source
hasChildSatisfying(predicate) → {boolean}
Whether this MathConcept has any children satisfying the given predicate. The predicate will be evaluated on each child in order until one passes or all fail; it may not be evaluated on all children, if not needed.
Parameters
-
predicate
function
The predicate to use for testing children
Returns
-
boolean
True if and only if some child satisfies the given predicate
Source
hasDescendantSatisfying(predicate) → {boolean}
Whether this MathConcept has any descendant satisfying the given predicate. The predicate will be evaluated on each descendant in depth-first order until one passes or all fail; it may not be evaluated on all descendants, if not needed.
Note that this MathConcept counts as a descendant of itself. To ignore
this MathConcept, simply change the predicate to do so, as in
X.descendantsSatisfying( d => X != d && predicate(d) )
.
Parameters
-
predicate
function
The predicate to use for testing descendants
Returns
-
boolean
True if and only if some descendant satisfies the given predicate
Source
ID() → {string}
The ID of this MathConcept, if it has one, or undefined otherwise. An ID is always a string; this is ensured by the setId() function.
See
- setID()
Returns
-
string
The ID of this MathConcept, or undefined if there is none
Source
idIsTracked() → {boolean}
Check whether this MathConcept's ID is currently tracked and associated with this MathConcept itself.
See
Returns
-
boolean
Whether the ID of this MathConcept is currently tracked by the global IDs mapping and that it is associated, by that mapping, with this MathConcept
Source
index(address) → {MathConcept}
Performs repeated child indexing to find a specific descendant. If the
address given as input is the array [i1,i2,...,in]
, then this returns
this.child(i1).child(i2)....child(in)
.
If the given address is the empty array, the result is this MathConcept.
This is a kind of inverse to address().
Parameters
-
address
Array.<number>
A sequence of nonnegative indices, as described in the documentation for address()
Returns
-
MathConcept
A descendant MathConcept, following the definition above, or undefined if there is no such MathConcept
Source
indexInParent() → {number}
Returns the value i
such that this.parent().child(i)
is this object,
provided that this MathConcept has a parent.
Returns
-
number
The index of this MathConcept in its parent's children list
Source
insertChild(child, atIndex)
Insert a child into this MathConcept's list of children.
Any children at the given index or later will be moved one index later to make room for the new insertion. The index can be anything from 0 to the number of children (inclusive); this last value means insert at the end of the children array. The default insertion index is the beginning of the array.
If the child to be inserted is an ancestor of this MathConcept, then we remove this MathConcept from its parent, to obey the insertion command given while still maintaining acyclicity in the tree structure. If the child to be inserted is this node itself, this function does nothing.
Parameters
-
child
MathConcept
the child to insert
-
atIndex
number
0the index at which the new child will be
Fires
Source
interpret() → {LogicConcept}
This function is a temporary placeholder. Later, a sophisticated interpretation mechanism will be developed to convert a user's representation of their document into a hierarchy of LogicConcept instances.
(In fact, we will actually use the interpret() function when we do so, and remove this one. That one is the official permanent interpretation API.)
For now, we have this simple version in which many features are not yet implemented. Its behavior is as follows.
- The method of interpretation that should be followed is extracted from the "Interpret as" attribute of this object. If there is no such attribute, an error is thrown. The attribute value should be an array, call it $[a_1,\ldots,a_n]$, where $a_1$ is the method of interpretation and each other $a_i$ is some parameter to it.
- If $a_1$ is "class" then $a_2$ must be the name of some subclass of LogicConcept, and this routine will contruct a new instance of that class, copy all this object's attributes to it, and give it a children list built by recursively interpreting this MathConcept's children.
- If $a_1$ is "notation" or "command" then a single Symbol will be created whose text content states that support for interpreting the notation or command in question has not yet been implemented.
- If $a_1$ is anything else, an error is thrown.
See
- fromSmackdown() (which creates MathConcept hierarchies intended for interpretation)
- toSmackdown()
Returns
-
LogicConcept
the meaning of this MathConcept, subject to the limitations documented above
Source
interpretation() → {Array.<LogicConcept>}
Any MathConcept can be interpreted, which means converting its high-level concepts into lower-level concepts that are only logical. For example, in mathematics, we my write A=B=C, but logically, this is two separate statements, A=B and B=C.
The interpretation function defined here can be used by any subclass to implement its specific means of interpretation of mathematical concepts into logical ones. In this abstract base class, the default is simply to return an empty list, meaning "no logic concepts." Subclasses should override this with an implementation specific to their actual mathematical meaning.
Returns
-
Array.<LogicConcept>
The ordered list of LogicConcepts whose combined meaning is equal to the meaning of this MathConcept
Source
isA(type) → {boolean}
MathConcepts can be categorized into types with simple string labels. For instance, we might want to say that some MathConcepts are assumptions, and flag that using an attribute. Some of these attributes have meanings that may be respected by methods in this class or its subclasses, but the client is free to use any type names they wish. A MathConcept may have zero, one, or more types.
This convenience function, together with makeIntoA() and asA(), makes it easy to use the MathConcept's attributes to store such information.
Note that the word "type" is being used in the informal, English sense, here. There is no intended or implied reference to mathematical types, variable types in programming languages, or type theory in general. This suite of functions is for adding boolean flags to MathConcepts in an easy way.
Parameters
-
type
string
The type we wish to query
Returns
-
boolean
Whether this MathConcept has that type
Source
isAccessibleTo(other, reflexive) → {boolean}
In computer programming, the notion of variable scope is common. A line of code can "see" a variable (or is in the scope of that variable) if it appears later than the variable's declaration and at a deeper level of block nesting. We have the same concept within MathConcepts, and we call it both "scope" and "accessibility." We say that any later MathConcept is "in the scope of" an earlier one, or equivalently, the earlier one "is accessible to" the later one, if the nesting of intermediate MathConcepts permits it in the usual way.
More specifically, a MathConcept X
is in the scope of precisely the
following other MathConcepts: all of X
's previous siblings, all of
X.parent()
's previous siblings (if X.parent()
exists), all of
X.parent().parent()
's previous siblings (if X.parent().parent()
exists), and so on. In particular, a MathConcept is not in its own scope,
nor in the scope of any of its other ancestors.
The one exception to what's stated above is the reflexive case, whether
X.isAccessibleTo(X)
. By default, this is false, because we typically
think of X.isAccessibleTo(Y)
as answering the question, "Can Y
justify itself by citing X
?" and we do not wish that relation to be
reflexive. However, X.isInTheScopeOf(X)
would typically be considered
true, because a variable declaration is the beginning of the scope of
that variable. So we provide the second parameter, reflexive
, for
customizing this behavior, and we have that, for any boolean value b
,
X.isAccessibleTo(Y,b)
if and only if Y.isInTheScopeOf(X,b)
.
Parameters
-
other
MathConcept
The MathConcept to which we're asking whether the current one is accessible. If this parameter is not a MathConcept, the result is undefined.
-
reflexive
boolean
falseWhether the relation should be reflexive, that is, whether it should judge
X.isAccessibleTo(X)
to be true.
See
Returns
-
boolean
Whether this MathConcept is accessible to
other
.
Source
isAtomic() → {boolean}
A MathConcept is atomic if and only if it has no children. Thus this is a
shorthand for S.numChildren() == 0
.
See
Returns
-
boolean
Whether the number of children is zero
Source
isDirty() → {boolean}
Getter for the "dirty" flag of this MathConcept. A MathConcept may be marked dirty by the client for any number of reasons. For instance, if a MathConcept changes and thus needs to be reprocessed (such as interpreted or validated) to reflect those most recent changes, it may be marked dirty until such processing takes place.
MathConcept instances are constructed with their dirty flag set to false.
See
Returns
-
boolean
Whether this MathConcept is currently marked dirty
Source
isEarlierThan(other) → {boolean}
Under pre-order tree traversal, which of two MathConcept comes first? We call the first "earlier than" the other MathConcept, because we will use MathConcept hierarchies to represent documents, and first in a pre-order tree traversal would then mean earlier in the document.
Note that this is a strict ordering, so a MathConcept is not earlier than itself.
Parameters
-
other
MathConcept
The MathConcept with which to compare this one. (The result is undefined if this is not a MathConcept.)
Returns
-
boolean
Whether this MathConcept is earlier than the other, or undefined if they are incomparable (not in the same tree)
Source
isFree(inThisopt) → {boolean}
Is this MathConcept free in one of its ancestors? If the ancestor is not specified, it defaults to the MathConcept's topmost ancestor. Otherwise, you can specify it with the parameter.
A MathConcept is free in an ancestor if none of the MathConcept's free identifiers are bound within that ancestor.
Note the one rare corner case that the head of a binding (even if it is
a compound expression) is not bound by the binding. For instance, if
we have an expression like $\sum_{i=a}^b A_i$, then $i$ is bound in
$A_i$, but not in either $a$ or $b$, which are part of the compound head
symbol, written in LISP notation something like ((sum a b) i (A i))
.
This corner case rarely arises, because it would be very confusing for
$i$ to appear free in either $a$ or $b$, but is important to document.
Parameters
-
inThis
MathConcept
<optional>
The ancestor in which the question takes place, as described above
See
Returns
-
boolean
Whether this MathConcept is free in the specified ancestor (or its topmost ancestor if none is specified)
Source
isFreeToReplace(original, inThisopt) → {boolean}
A MathConcept A is free to replace a MathConcept B if no identifier free in A becomes bound when B is replaced by A.
Parameters
-
original
MathConcept
The MathConcept to be replaced with this one
-
inThis
MathConcept
<optional>
The ancestor we use as a context in which to gauge bound/free identifiers, as in the
inThis
parameter to isFree(). If omitted, the context defaults to the top-level ancestor oforiginal
.
See
Returns
-
boolean
True if this MathConcept is free to replace
original
, and false if it is not.
Source
isInTheScopeOf(other, reflexive) → {boolean}
A full definition of both isAccessibleTo() and isInTheScopeOf() appears in the documentation for isAccessibleTo(). Refer there for details.
Parameters
-
other
MathConcept
The MathConcept in whose scope we're asking whether this one lies. If this parameter is not a MathConcept, the result is undefined.
-
reflexive
boolean
trueWhether the relation should be reflexive, that is, whether it should judge
X.isInTheScopeOf(X)
to be true.
See
Returns
-
boolean
Whether this MathConcept is in the scope of
other
.
Source
isLaterThan(other) → {boolean}
This is the opposite of isEarlierThan().
We have A.isLaterThan(B)
if and only if B.isEarlierThan(A)
. This is
therefore just a convenience function.
Parameters
-
other
MathConcept
The MathConcept with which to compare this one. (The result is undefined if this is not a MathConcept.)
Returns
-
boolean
Whether this MathConcept is later than the other, or undefined if they are incomparable (not in the same tree)
Source
lastChild() → {MathConcept}
Convenience function for fetching just the last child of this MathConcept
Returns
-
MathConcept
The last child of this MathConcept, or undefined if none
Source
makeIntoA(type) → {MathConcept}
For a full explanation of the typing features afforded by this function, see the documentation for isA().
This function adds the requested type to the MathConcept's attributes and
returns the MathConcept itself, for use in method chaining, as in
S.makeIntoA( 'fruit' ).setAttribute( 'color', 'green' )
.
Parameters
-
type
string
The type to add to this MathConcept
See
Returns
-
MathConcept
This MathConcept, after the change has been made to it
Source
markDirty(onopt, propagateopt)
Setter for the "dirty" flag of this MathConcept. For information on the meaning of the flag, see isDirty().
Parameters
-
on
boolean
<optional>
trueWhether to mark it dirty (true) or clean (false). If this value is not boolean, it will be converted to one (with the
!!
idiom). -
propagate
boolean
<optional>
Whether to propagate the change upwards to parent MathConcepts. By default, this happens if and only if the
on
member is true, so that dirtiness propagates upwards, but cleanness does not. This is appropriate because when a child needs reprocessing, this often requires reprocessing its parent as well, but when a child has been reprocessed, its parent may still need to be.
See
Source
nextInTree() → {MathConcept}
Finds the next node in the same tree as this one, where "next" is defined in terms of a pre-order tree traversal. If there is no such node, this will return undefined.
Therefore this function also returns the earliest node later than this one, in the sense of isEarlierThan() and isLaterThan().
For example, in a parent node with several atomic children, the next node of the parent is the first child, and the next node of each child is the one after, but the last child has no next node.
Returns
-
MathConcept
The next node in pre-order traversal after this one
Source
nextSibling() → {MathConcept}
Find the next sibling of this MathConcept in its parent, if any
Returns
-
MathConcept
The next sibling, or undefined if there is none
Source
numChildren() → {number}
The number of children of this MathConcept
See
Returns
-
number
A nonnegative integer indicating the number of children
Source
occursFree(concept, inThisopt) → {boolean}
Does a copy of the given MathConcept concept
occur free anywhere in this
MathConcept? More specifically, is there a descendant D of this MathConcept
such that D.equals( concept )
and D.isFree( inThis )
?
Parameters
-
concept
MathConcept
This function looks for copies of this MathConcept
-
inThis
MathConcept
<optional>
The notion of "free" is relative to this MathConcept, in the same sense of the
inThis
parameter to isFree()
Returns
-
boolean
True if and only if there is a copy of
concept
as a descendant of this MathConcept satisfying.isFree( inThis )
Source
parent() → {MathConcept}
This MathConcept's parent MathConcept, that is, the one enclosing it, if any
See
Returns
-
MathConcept
This MathConcept's parent node, or null if there isn't one
Source
popChild() → {MathConcept}
Remove the last child of this MathConcept and return it. If there is no such child, take no action and return undefined.
Returns
-
MathConcept
The popped last child, or undefined if none
Source
preOrderIterator(inThisTreeOnly)
An iterator that walks through the entire tree from this node onward, in a pre-order tree traversal, yielding each node in turn.
This function is a generator that yields the next node after this one in pre-order tree traversal, just as nextInTree() would yield, then the next after that, and so on.
Parameters
-
inThisTreeOnly
boolean
trueSet this to true to limit the iterator to return only descendants of this MathConcept. Set it to false to permit the iterator to proceed outside of this tree into its context, once all nodes within this tree have been exhausted. If this MathConcept has no parent, then this parameter is irrelevant.
Source
preOrderTraversal(inThisTreeOnly) → {Array.<MathConcept>}
The same as preOrderIterator(), but already computed into array form for convenience (usually at a cost of efficiency).
Parameters
-
inThisTreeOnly
boolean
trueHas the same meaning as it does in preOrderIterator()
Returns
-
Array.<MathConcept>
The array containing a pre-order tree traversal starting with this node, beginning with nextInTree(), then the next after that, and so on.
Source
previousInTree() → {MathConcept}
Finds the previous node in the same tree as this one, where "previous" is defined in terms of a pre-order tree traversal. If there is no such node, this will return undefined.
Therefore this function also returns the latest node earlierr than this one, in the sense of isEarlierThan() and isLaterThan().
This is the reverse of nextInTree(), in the
sense that X.nextInTree().previousInTree()
and
X.previousInTree().nextInTree()
will, in general, be X
, unless one of
the computations involved is undefined.
Returns
-
MathConcept
The previous node in pre-order traversal before this one
Source
previousSibling() → {MathConcept}
Find the previous sibling of this MathConcept in its parent, if any
Returns
-
MathConcept
The previous sibling, or undefined if there is none
Source
pushChild(child)
Append a new child to the end of this MathConcept's list of children. This
is equivalent to a call to insertChild()
with the length of the current
children array as the index at which to insert.
Parameters
-
child
MathConcept
The new MathConcept to append
Source
remove()
If this MathConcept has a parent, remove this from its parent's child list and set our parent pointer to null, thus severing the relationship. If this has no parent, do nothing.
Fires
Source
removeChild(i)
Calls remove() on the child with index i
.
Does nothing if the index is invalid.
Parameters
-
i
number
the index of the child to remove
Source
removeConnections()
Remove all connections into or out of this MathConcept. This deletes the relevant data from this MathConcept's attributes as well as those of the MathConcepts on the other end of each connection. For documentation on the data format for this stored data, see the Connection class.
This function simply runs remove() on every connection in getConnections().
Source
replaceFree(original, replacement, inThisopt)
Consider every free occurrence of original
within this MathConcept, and
replace each with a copy of replacement
if and only if replacement
is
free to replace that instance. Each instance is judged separately, so
there may be any number of replacements, from zero up to the number of
free occurrences of original
.
Parameters
-
original
MathConcept
Replace copies of this MathConcept with copies of
replacement
-
replacement
MathConcept
Replace copies of
original
with copies of this MathConcept -
inThis
MathConcept
<optional>
When judging free/bound identifiers, judge them relative to this ancestor context, in the same sense of the
inThis
parameter to isFree()
See
Source
replaceWith(other)
Replace this MathConcept, exactly where it sits in its parent MathConcept, with the given one, thus deparenting this one.
For example, if A
is a child of B
and we call B.replaceWith(C)
,
then C
will now be a child of A
at the same index that B
formerly
occupied, and B
will now have no parent. If C
had a parent before,
it will have been removed from it (thus decreasing that parent's number
of children by one).
Parameters
-
other
MathConcept
the MathConcept with which to replace this one
Source
scope(reflexive) → {Array.<MathConcept>}
The full contents of scopeIterator(), but put into an array rather than an iterator, for convenience, possibly at the cost of efficiency.
Parameters
-
reflexive
boolean
truePassed directly to scopeIterator(); see that function for more information
Returns
-
Array.<MathConcept>
All MathConcepts in the scope of to this one, with the earliest (closest to this MathConcept) first, proceeding on to the latest at the end of the array
Source
scopeIterator(reflexive)
For a definition of scope, refer to the documentation for the isAccessibleTo() function.
In short, the scope of a node is itself, all of its later siblings, and all their descendants, where each node yielded by the iterator isEarlierThan() all nodes yielded thereafter.
This function is a generator that yields each MathConcept in the scope of this one, beginning with the one closest to this one (often its previous sibling) and proceeding forward through the hierarchy, so that each new result isLaterThan() the previous.
Parameters
-
reflexive
boolean
trueFunctions analogously to the
reflexive
parameter for isInTheScopeOf(); that is, do we include this MathConcept on its list of things in its scope? The default value is true.
Source
setAttribute(key, value)
For details on how MathConcepts store attributes, see the documentation for the getAttribute() function.
This function stores a new key-value pair in the MathConcept's attribute
dictionary. See the restrictions on keys and values in the documentation
linked to above. Calling this function overwrites any old value that was
stored under the given key
.
The change events are fired only if the new value is different from the
old value, according to JSON.equals()
.
Parameters
-
key
*
The key that indexes the key-value pair we are about to insert or overwrite; this must be a string or will be converted into one
-
value
*
The value to associate with the given key; this must be a JavaScript value amenable to JSON encoding
See
Fires
Source
setChildren(children)
Replace the entire children array of this MathConcept with a new one.
This is equivalent to removing all the current children of this MathConcept in order from lowest index to highest, then inserting all the children in the given array, again from lowest index to highest.
The intent is not for any of the elements of the given array to be ancestors or descendants of one another, but even if they are, the action taken here still follows the explanation given in the previous paragraph.
Parameters
-
children
Array.<MathConcept>
New list of children
Source
setID(id)
Set the ID of this MathConcept. Note that this does not change the global tracking of IDs, because one could easily call this function to assign an already-in-use ID. To ensure that the IDs in a hierarchy are tracked, call trackIDs(), and if that has already been called, then to change a MathConcept's ID assignment, call changeID().
Parameters
-
id
string
The new ID to assign. If this is not a string, it will be converted into one.
See
Source
shiftChild() → {MathConcept}
Remove the first child of this MathConcept and return it. If there is no such child, take no action and return undefined.
Returns
-
MathConcept
The popped first child, or undefined if none
Source
toJSON(includeIDs) → {Object}
Convert this object to JavaScript data ready for JSON serialization.
Note that the result of this function is not a string, but is ready to
be converted into one through JSON.stringify()
or (preferably),
predictableStringify().
The resulting object has some of its attributes directly re-used (not
copied) from within this MathConcept (notably the values of many
attributes), for the sake of efficiency. Thus you should not modify
the contents of the returned MathConcept. If you want a completely
independent copy, call JSON.copy()
on the return value.
The particular classes of this MathConcept and any of its children are stored in the result, so that a deep copy of this MathConcept can be recreated from that object using fromJSON().
If the serialized result will later be deserialized after the original has been destroyed, then you may wish to preserve the unique IDs of each MathConcept in the hierarchy in the serialization. But if the original will still exist, you may not. Thus the parameter lets you choose which of these behaviors you need. By default, IDs are included.
Parameters
-
includeIDs
boolean
trueWhether to include the IDs of the MathConcept and its descendants in the serialized form (as part of the MathConcept's attributes)
See
- fromJSON()
- subclasses
Returns
-
Object
A serialized version of this MathConcept
Source
toSmackdown() → {string}
This function reverses the operation of
fromSmackdown(). It requires this
MathConcept to be of the particular form created by that function; it
cannot operate on arbitrary MathConcepts, because not all can be
represented by smackdown notation. (For instance, a MathConcept
created by a call to new MathConcept()
is too vague to be
representable using smackdown notation.)
Returns
-
string
smackdown notation for this MathConcept
Source
toString() → {string}
A simple string representation that represents any MathConcept using
an S-expression (that is, (a b c ...)
) of the string representations of
its children. This produces LISP-like results, although they will
contain only parentheses if all are MathConcept instances. But
subclasses can override this method to specialize it.
See
Returns
-
string
A simple string representation
Source
trackConnections() → {boolean}
There are some situations in which a MathConcept hierarchy will have data in it about connections, and yet those connections were not created with the API in the Connections class. For example, if a MathConcept hierarchy has been saved in serialized form and then deserialized at a later date. Thus we need a way to place into the IDs member of the Connection class all the IDs of the connections in any given MathConcept hierarchy. This function does so. In that way, it is very similar to trackIDs().
Connections are processed only at the source node, so that we do not process each one twice. Thus any connection into this MathConcept from outside will not be processed by this function, but connections from this one out or among this one's descendants in either direction will be processed.
Returns
-
boolean
True if and only if every connection ID that appers in this MathConcept and its descendants was able to be added to the global mapping in IDs. If any fail (because the ID was already in use), this returns false. Even if it returns false, it still adds as many connections as it can to that global mapping.
Source
trackIDs(recursive)
Store in the global IDs mapping the association of this MathConcept's ID with this MathConcept instance itself. If the parameter is set to true (the default), then do the same recursively to all of its descendants.
Calling this function then enables you to call instanceWithID() on any of the IDs of a descendant and get that descendant in return. Note that this does not check to see if a MathConcept with the given ID has already been recorded; it will overwrite any past data in the IDs mapping.
This function also makes a call to trackConnections(), because IDs are required in order for connections to exist, and enabling IDs almost always coincides with enabling connections as well.
Important: To prevent memory leaks, whenever a MathConcept hierarchy is no longer used by the client, you should call untrackIDs() on it.
Parameters
-
recursive
boolean
trueWhether to recursively track IDs of all child, grandchild, etc. MathConcepts. (If false, only this MathConcept's ID is tracked, not those of its descendants.)
Source
transferConnectionsTo(recipient)
When replacing a MathConcept in a hierarchy with another, we often want to transfer all connections that went into or out of the old MathConcept to its replacement instead. This function performs that task.
This function is merely a convenient interface that just calls Connection.transferConnections() on your behalf.
Parameters
-
recipient
MathConcept
The MathConcept to which to transfer all of this one's connections
Source
unmakeIntoA(type) → {MathConcept}
For a full explanation of the typing features afforded by this function, see the documentation for isA().
This function removes the requested type to the MathConcept's attributes
and returns the MathConcept itself, for use in method chaining, as in
S.unmakeIntoA( 'fruit' ).setAttribute( 'sad', true )
.
Admittedly, this is a pretty bad name for a function, but it is the reverse of makeIntoA(), so there you go.
Parameters
-
type
string
The type to remove from this MathConcept
See
Returns
-
MathConcept
This MathConcept, after the change has been made to it
Source
unshiftChild(child)
Prepend a new child to the beginning of this MathConcept's list of children.
This is equivalent to a call to insertChild()
with the default second
parameter (i.e., insert at index zero), and thus this function is here
only for convenience, to fit with shiftChild().
Parameters
-
child
MathConcept
The new MathConcept to prepend
Source
untrackIDs(recursive)
This removes the ID of this MathConcept (and, if requested, all descendant MathConcepts) from the global IDs mapping. It is the reverse of trackIDs(), and should always be called once the client is finished using a MathConcept, to prevent memory leaks.
Because connections use the ID system, any connections that this MathConcept is a part of will also be severed, by a call to removeConnections().
Parameters
-
recursive
boolean
trueWhether to recursively apply this function to all child, grandchild, etc. MathConcepts. (If false, only this MathConcept's ID is untracked, not those of its descendants.)
See
Source
Events
wasChanged
An event of this type is fired in a MathConcept immediately after one of that MathConcept's attributes is changed.
Type
-
Object
Properties
-
concept
MathConcept
The MathConcept emitting the event, which just had one of its attributes changed
-
key
*
A string value, the key of the attribute that just changed
-
oldValue
*
A JavaScript value amenable to JSON encoding, the value formerly associated with the key; this is undefined if the value is being associated with an unused key
-
newValue
*
A JavaScript value amenable to JSON encoding, the value now associated with the key; this is undefined if the key-value pair is being removed rather than changed to have a new value
See
- willBeChanged
- setAttribute()
wasInserted
An event of this type is fired in a MathConcept immediately after that MathConcept is inserted as a child within a new parent.
Type
-
Object
Properties
-
child
MathConcept
The MathConcept emitting the event, which just became a child of a new parent MathConcept
-
parent
MathConcept
The new parent the child now has
-
index
number
The index the child now has in its new parent
See
- willBeInserted
- insertChild()
wasRemoved
This event is fired in a MathConcept immediately after that MathConcept is removed from its parent MathConcept. This could be from a simple removal, or it might be the first step in a re-parenting process that ends up with the MathConcept as the child of a new parent.
Type
-
Object
Properties
-
child
MathConcept
The MathConcept emitting the event, which was just removed from its parent MathConcept
-
parent
MathConcept
The old parent MathConcept from which the child was just removed
-
index
number
The index the child had in its parent, before the removal
See
willBeChanged
An event of this type is fired in a MathConcept immediately before one of that MathConcept's attributes is changed.
Type
-
Object
Properties
-
concept
MathConcept
The MathConcept emitting the event, which will soon have one of its attributes changed
-
key
*
A string value, the key of the attribute that is about to change
-
oldValue
*
A JavaScript value amenable to JSON encoding, the value currently associated with the key; this is undefined if the value is being associated with an unused key
-
newValue
*
A JavaScript value amenable to JSON encoding, the value about to be associated with the key; this is undefined if the key-value pair is being removed rather than changed to have a new value
See
- wasChanged
- setAttribute()
willBeInserted
An event of this type is fired in a MathConcept immediately before that MathConcept is inserted as a child within a new parent.
Type
-
Object
Properties
-
child
MathConcept
The MathConcept emitting the event, which will soon be a child of a new parent MathConcept
-
parent
MathConcept
The new parent the child will have after insertion
-
index
number
The new index the child will have after insertion
See
- wasInserted
- insertChild()
willBeRemoved
This event is fired in a MathConcept immediately before that MathConcept is removed from its parent MathConcept. This could be from a simple removal, or it might be the first step in a re-parenting process that ends up with the MathConcept as the child of a new parent.
Type
-
Object
Properties
-
child
MathConcept
The MathConcept emitting the event, which is about to be removed from its parent MathConcept
-
parent
MathConcept
The current parent MathConcept
-
index
number
The index the child has in its parent, before the removal