My way of thinking about object-oriented inheritance/overrides is to make the work the responsibility of “visualizers” that have the know-how filters for getting the data from the child objects and, if the child objects don’t have the data, then go to the parent/prototype to get the defaults.
The idea is to never access the tiddlers directly, but rather use a custom interface that embrace the powers of TiddlyWiki: transclusion and filtering.
In the Apple Thing sample, the template tiddler for displaying apples does the job of inheritance and override.
I’m not sure if there’s some communication breakdown, but I’m not suggesting that they override the actual periodic table. While I wouldn’t try to stop that (not that I could!), what I could see likely to be overridden is the data tiddlers for the elements. In Beth’s case, Tin.
That’s fine for TiddlyWiki experts. But my users (in this imaginary case) are chemistry students who want to do their own filtering. May of them would be proud of themselves if they manage this much:
My first thought is to use a custom ViewTemplate with a recursive macro that first looks to the <<currentTiddler>> for a field value, then goes to another tiddler for an alternative. You may be able to have the macro work through either a defined list of tiddlers, a set of tags, or title namespacing; to define the structure to work through.
As someone who is nowhere near qualified to do this, it seems like a cludgy and fragile setup…but maybe this is actually a fairly straightforward code pattern for someone with the requisite knowledge.
Hmm, I’m not sure this would work with a ViewTemplate, as we might want to offer users the same techniques for getting at the data for their own tiddlers or templates. But I think it brings up a similar idea at the data level: a field (the name is likely already taken, but we could consider that later) macro that looks something like this:
<<field "meltingpoint">> <!-- defaulting to currentTiddler, but overridable -->
but that macro recursively checks the tiddler, then its parent if it doesn’t have the field, then its grandparent, and so on until it reaches a tiddler which doesn’t have a __proto__ (or parent, or whatever) field pointing to another tiddler. This coupled with a “Clone”-like “Extend” button that automatically sets the __proto__ field could do just what I’m thinking about.
This sounds like it might work.
That depends on whether there’s a method to access the shadow tiddler, but while I don’t know of one, this seems likely.
Thank you! This looks promising. Not that I’m anywhere near close to trying it. Other things to do first. But I’m excited to realize that this might not involve rearchitecting the core.
For sure you’ll need recursion to handle multi-level inheritance. Recursion is easy.
But recursion is putting the cart way before the horse. You’ve got a lot of work to do.
Long before recursion, you might want to figure out what you need and how to get working the pieces for the basics of one parent and a bunch of children.
She can’t overwrite the original data if you provide an interface (forms, dialogs, navigation) that keep her from messing with the tiddlers directly. She has a “form” with her data in it that she maintains, with a popup window that can show the original data at any time.
I think you’ll need to create a very small prototype with small data sample, something like Apple Thing
The very first thing you’ll need to do is, to make a plugin out of your periodic table and the content. If that’s done it should be possible to make differences between shadows and user tiddlers visible on a per field basis.
I’m preparing a new thread that will contain the info and filters needed to get access to the shadow fields. … BUT … It will not contain a finished solution for your usecase.
Oh yes, I spend too much time answering recursion questions on StackOverflow. That part doesn’t scare me at all. For a tool that is meant for other users, I’d have to add some cycle-detection (A's parent is B, B's parent is C, C's parent is A.) But that should still be easy.
As I said up front, this is still at the dreaming stage. At this point I’m simply asking if the tooling as I’d like to have it is even possible in TW. The answer from @Brian_Radspinner made me realize that yes, this is possible, and I probably already have the skills to write it. I can write a macro and a filter operator that allow access to fields in a tiddler or (recursively) its parents. Then document them for users. I couldn’t prevent them from direct access to the underlying data, but I can document it and use it in my own internal work.
Possibly, but that doesn’t really feel in the spirit I imagine, something vaguely related to the right-to-repair movement.
Great! I had fun writing it. (And yes, Beth, Lynne, and Mr. H are real; he was the baseball coach who had to teach something, I guess. Beth, Lynne, and I didn’t really teach the class, but we did a lot of tutoring of our peers.)
Yes, building a plugin for this is already part of my build process. It may have gotten out-of-sync as I focus right now on presentation, but will be easy to fix. After the CSS work, I will probably stop the process of deriving my tiddlers from Tony’s originals, and treat these versions as the source of truth. (A quick question: would there be concerns or even landmines involved in using spaces in field names?. Nevermind; I raised a separate question.)
Very cool. I look forward to reading and learning from it.
No, of course not. I wouldn’t dream of asking that.
Interesting idea @Scott_Sauyet. Conceptually, I think it’s a solid idea, but as you have inferred I think it would be too late to implement it as an intrinsic core feature.
Internally, tiddlers are stored as a JavaScript object with string (or array of string) properties. One could certainly imagine setting a prototype for one of these objects that caused the fields to be inherited from a parent tiddler.
The first obstacle is the refresh mechanism. It works by tracking and accumulating changes to the tiddler store and then passing the list of modified tiddlers as a parameter to the refresh method of the root widget. It then decides how to refresh itself, and calls its children to refresh themselves. Each widget participating in the refresh cycle must inspect the list of modified tiddlers in order to figure out what if anything has changed.
With prototypes, that list of tiddlers would need to be expanded to include the tiddlers inheriting fields from each tiddler that has changed (and subtly, if a prototype chain is broken, we’d also need to refresh tiddlers that had previous been in that prototype chain). None of that is insoluble, but I am pretty sure it would be impossible to do in a backwards compatible way.
As others have noted, it’s certainly possible to makes structures like this at the tiddler level, within the current wikitext syntax. For example, in one of my projects I model objects as a tiddler with a “class” field that contains the title of a class tiddler that provides macro definitions for methods to operate on that tiddler. That class tiddler can in turn inherit from a superclass. To invoke a method, one imports the prototype chain and then invokes the macro. (The code I am describing is part of TWPub - there’s a storyriver class for a single tiddler view here and the parent class from which is inherits here).
That’s what I expected. But I think discussions here are making me realize that I could probably achieve what I hoped to by including deep versions of a few things: the get operator, the view widget, and field transclusions. There would probably be others, but I already know how to do the first two and could investigate the third.
Ouch! Yes, that would be ugly.
Triple ouch! This would probably be a deal-breaker on its own.
That makes me wonder, though, if my thoughts of macros and operators that could do this sort of traversal to fetch content would also have the same problems with the refresh mechanism. (BTW, this mechanism is so brilliant that I never think to notice it; it simply works in the background for me, on my generally fairly small wikis. At some point, I’m going to have to pay it attention, but I’m still operating as an [almost-?] intermediate-level user, and have spent no time with the core.)
Thanks. I’ll check them out.
And also, more generally, thank you for all the work you’ve put into this wonderful tool.
No, they wouldn’t. The issue with tiddler prototype chains would be that the value of a tiddler could change via an ancestor without it being present in the list of changed tiddlers. Undoubtedly more code could be added to fix those references up but it would be nowhere near as elegant as if the design had started with the idea.
Thank you! It’s a privilege to be given the chance to work on something that I am deeply interested in and benefits other people.
Here’s the info, with which it should be possible to create a UI that allows you to show the differences between a shadow and its tiddler on a per field basis. … Including a possibility to exactly see what’s different.
While creating the blog post I did have a lot of ideas, what could be done …
That’s an interesting tool, but I think it’s for a different purpose.
The demo you shared seems to be chiefly about editing fields. Is there an internal delegation model that I’m missing?
My thought – which might be handled other ways, as seen in this discussion – was that there might be a way for a tiddler than inherits from another tiddler to only override the fields it cares about. Any field it doesn’t override is retrieved from the parent. Thus if I delete a field in a child tiddler, and try to use that field, it once again gets the parent’s value.
(I have the impression that you’re a JavaScript person. Is that correct? If so, this is very similar to JS’s prototypal inheritance model.)
As @jeremyruston pointed out, this might be logically sound, but it is far too different a model from the current one to ever really have a chance of making the core. But the answer from @Brian_Radspinner shows a way I might achieve the desired effect.
You clone my wiki to make your own chemistry studying tool. You edit, say, the Chlorine tiddler, which is a shadow tiddler, but instead of of the current Clone mechanism, you use my imaginary Inherit one. Your new tiddler has no fields except for one specific name dedicated to inheritance, let’s call it __proto__.
But if you try to fetch the atomic-mass property of your new tiddler, the system still finds the value of 35.453, because if the property is not on your tiddler, it will be looked up on the parent tiddler (the shadow tiddler Chlorine.) When you set a value, it is set directly on your tiddler. Perhaps your own research convinces you that Chlorine was discovered centuries earlier, by Muḥammad ibn Mūsā al-Khwārizmī, and you set the discoverer to al-Khwārizmī and the year to 823. These values are on your inherited tiddler.
Later, you discover that this was Ottoman propaganda. al-Khwārizmī was an astronomer and mathematician. He didn’t do any serious chemistry.
To fix this, you don’t try to recall and reset the old values of year and discoverer. Instead, you simply delete those fields on your own tiddler. And the underlying values are once again available. If you check [[Chlorine]get[year]] it will now report 1774 and [[Chloring]get[discoverer]] will report Scheele… because those are the values on the prototype (shadow) tiddler.