// The original purpose of this JSL was to demonstrate how JSL
// classes use references rather than copies. It evolved into a
// graph making demonstration. To see the references, look at the
// _init_ functions that use m_rate = v( rate ); which are storing
// an object reference into a member variable. (Not the vwrap class,
// but all the others.)
// Demonstration of composing functions in JSL; a function composed
// of other functions is represented by a JSL class. The class
// member variables reference other functions or JSL primitives.
// In these examples, the classes all have a common evaluator named
// next() that will return the next value from a generator at the
// bottom. There is no conversion from infix "a+b" to function "add(a,b)"
// but it could be done...though it might not make it better.
// this code is slower than a non-functional approach because it makes
// many user defined function calls to calculate sin(x) (for example).
// There are also issues with reinitializing and sharing a "counter"
// class that need more thought; if x is a counter, there is no way to
// peek at its value without incrementing it and no way to start it over.
// number/matrix wrapper class
Define Class(
"vwrap",
m_v = .; // holds the number or matrix
_init_ = Method( {v},
If( Type( v ) == "Class",
Throw( "vwrap is for number or matrix, not class " || Char( v << getname ) )
);
m_v = v;
);
set = Method( {v},
If( Type( v ) == "Class",
Throw( "vwrap is for number or matrix, not class " || Char( v << getname ) )
);
m_v = v;
);
next = Method( {},
m_v; // return
);
);
// helper function v(...) converts a scalar or matrix to a vwrap, or returns an instance unchanged
v = Function( {x},
If( Type( x ) == "Class",
If( !(x << Contains( "next" )),
Throw( "v expects number, matrix, or one of the classes it supports, not class " || (x << getname) )
);
x; // x supports a next function, it is probably OK
, // else
If( !Is Number( x ) & !Is Matrix( x ),
Throw( "v expects number or matrix, not " || Type( x ) )
);
New Object( vwrap( x ) ); // wrap the number or matrix
)
);
// global function gr(...) makes a graph
gr = Function( {Xvar, Yvar, title, n},
{Xs, Ys, dt}, // locals
Yvar = v( Yvar );
Xvar = v( Xvar );
Ys = J( n, 1, Yvar:next() );
Xs = J( n, 1, Xvar:next() );
dt = As Table( Ys || Xs, <