jkuczm / mathematicaclasslessobjects Goto Github PK
View Code? Open in Web Editor NEWTools for creating classless objects, with prototype based inheritance, in Mathematica.
License: Other
Tools for creating classless objects, with prototype based inheritance, in Mathematica.
License: Other
When object obj
is protected, WithOrdinaryObjectSet
doesn't remove it's special up values.
Attempt of setting obj@member
results in infinite recursion instead of Set::write
warning.
Wrap up value changing code in WithOrdinaryObjectSet
with Unprotect ... Protect
.
If evaluation of body
passed to WithOrdinaryObjectSet[obj, body]
Abort
s Throw
s or Goto
s outside of WithOrdinaryObjectSet
than up values of obj
are not restored.
When setting members on $self
object inside bound member, set altering up values of object are not used. Those members are not automatically made inheritable nor bound.
Hi.
First: Thanks 10^3 for creating and sharing this. It is a Godsend.
Second: Please forgive me if this is the wrong venue for communicating questions to you. I don't have enough reputation points on Stack Exchange yet to post a comment on your excellent answer there, and I'm new to GitHub so I'm unfamiliar with the conventions.
Third: I'm trying to use this package in a Mathematica project, and I'm having trouble figuring out how to accomplish a couple of less basic things. The first is simple to describe: Is it possible to define a "constructor" that takes methods (set-delayed rules) as well as properties (set-immediately rules)? I tried the obvious, simply passing a function in as one of the constructor parameters and then setting the object rule to it, but no luck:
ancestor@construct[obj_Symbol, v0$_, r0$_, f$_Function] := (
DeclareObject[obj, $self];
obj@r0 = r0$;
obj@v0 = v0$;
obj@f := f$;
obj )
I've tried with :=
and =
in that code, and I've tried various methods of defining the function that I pass to the constructor: delayed or not, as a normal f[x_] rule or a pure function, etc.
ClearAll[child];
ff = (#^2) &;
ancestor@construct[child, 20, 0, ff];
In all cases, I'm getting the following error message:
Object::objectMember: The call child@0 didn't match any of defined member patterns in child nor in its ancestors: {ancestor,Object}.
I can, of course, bypass the constructor and simply define the method for the child directly, with setDelayed, but it would be helpful (and ultimately easier for users of my project) if I could handle it in the constructor. Is this possible? Am I being dumb or blind?
BTW, I'm moderately but not expertly skilled with Mathematica, but I'm not yet conversant with the subtleties of HoldAll and when/how to use it.
Thanks,
:Ian
Hi again. Here's a second question. It is considerably more subtle and specialized, but perhaps you might find it interesting.
Each of the child objects I'm subclassing from a superclass object has a function we'll call a[t_]
. The specific function differs for each child, but I've got superclass methods that use it (via your excellent $self
syntax) to generate a set of graphs. Specifically, these superclass methods graph the function, its integral, and its second integral (acceleration, velocity, and position -- this is a physics application).
The way they work is that I've defined superclass methods thusly:
ancestor@v[t_] := $self@v0 + Integrate[$self@a[tt], {tt, 0, t}, Assumptions -> t \[Element] Reals];
ancestor@r[t_] := $self@r0 + Integrate[$self@v[tt], {tt, 0, t}, Assumptions -> t \[Element] Reals];
I then use Plot[$self@v[t]]
or Plot[$self@r[t]]
in the superclass methods that generate the plots. This all works just fine, EXCEPT that it's hideously slow, especially for the plot of the second integral r[t]
. I've wrestled with this before, when not using objects or subclassing or anything, and what I decided is that the Integrate[...]
functions were being called many many times during plotting, for every single plot point (and perhaps the first integral was being called many times during each execution of the second integral). Well, of course! It is defined as set-delayed, after all.
That is really unnecessary, since the a[t]
function does not change once defined, and the indefinite integral only needs to be calculated once. Before using your OOP package, I simply replaced SetDelayed with Set in my definitions of the v[t]
and a[t]
functions, and all speed problems disappeared.
Unfortunately, I can't figure out how to do the same thing within this OOP/inheritance context. If I replace SetDelayed with Set in the superclass definitions of ancestor@v[t_]
and ancestor@r[t_]
, I get nasty cross-contamination between different child objects; it looks like the rule is being executed once per argument, regardless of which $self
is involved. Somehow, the rule needs to execute once for each child object, and it needs to execute once for a generic variable argument to create a new function that gets stored, rather than once per numerical argument value.
I have come up with a workaround for my particular case: putting the plotting functions inside a Module and setting (not delayed) a temporary function equal to that original superclass set-delayed that worked fine but was slow, like this:
ancestor@vGraph[tF_] := Module[{vFunc},
vFunc[t_] = $self@v[t];
Plot[vFunc[t], {t, 0, tF},]]
That's not ideal, since in principle the integrated functions v[t]
and r[t]
should only be calculated once per child object (assuming the child's a[t]
doesn't change once set), rather than once per call to the graphing method. It does, however, make my code work adequately.
I'm wondering whether you had any thoughts on this, because they might go a long way towards improving my understanding of your OOP system and how to navigate per-child vs. once-per-superclass issues.
(BTW, if you'd like me to re-post this as a question on Stack Exchange, please say so. I put it here because it seems very specific to your answer to a prior question, and to this package, and I don't yet have the reputation to post a comment.)
Thanks,
:Ian
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.