Is there any way for one tiddler to serve as the prototype of another?
I hope to get back to my Periodic Table demo this weekend, and I will probably focus on cosmetic and usability issues. But when I get to content, I was thinking that there is a feature from JS that I would love to have in TW. I don’t know if something like it exists, or if even if it’s remotely compatible with the architecture. But I could see it being useful.
For people who understand JS reasonably well, what I want is something very similar to JS prototypal inheritance. It would be useful if the user could create a Tiddler that doesn’t shadow the version from a plugin, but instead treats the plugin one as we would the prototype of an object in JS.
For non-JS folks: that is, if I went to use fieldA from UserTiddler, and UserTiddler has such a field, we simply use it it. But if it doesn’t, then I look to the PluginTiddler'sfieldA. (And if that one has a parent, we look in itsfieldA, and so on, until we run out of ancestors.)
This may be an insanely stupid idea in the existing architecture, but I could see all sorts of useful possibilities for customization of a wiki using it. And probably headaches too: How do you remove a field?How do you remove a single element from a list field?Is there some notion of super?, etc. But my gut feeling is that the benefits – if starting fresh – would outweigh the benefits. Since we’re not starting fresh, but have years of prior work, that seems less likely. But I’m still curious.
So, does this exist? Is it something other people want? Is it even remotely possible?
Edit: If the discussion of JavaScript internals is a turn-off, in answering Charlie, I thought of a cleaner way of asking the question:
We have a shadowing mechanism, allowing us to use our tiddler in place of another, even though that other one still exists and will be resurrected the minute our own is deleted. Could we do the same thing at the field level?
I think we are going to need a practical “real-world” example of why that kind of thing should ever see the light of day in TiddlyWiki.
In my mind, I’m thinking: stop thinking like a JavaScript programmer, and start thinking “how would I do this with a native TiddlyWiki approach?”
The generic hypothetical you’ve given, my instant reaction: you are putting into fields what should be in tiddlers.
But these thoughts can totally bite the biscuit if you give a clear scenario. If a “The TiddlyWiki Way” answer does not materialise, then maybe you are onto something.
Personally, though, if that gets into the core and it isn’t something that solves any problems for me, it is likely a nail in the coffin for me, cementing in my mind that TiddlyWiki is heading in a direction very different from mine.
I’m no Javascript guy, so what all prototyping entails, not necessarily sure, and not really all that curious.
But if you want and idea of what I mean by a “real-world” example, here’s a totally ridiculous sample, which may help. If I am way off in left-field, maybe your example can point in the right direction.
5 tiddlers in the attached json file. Start with the tiddler “The Apples”, working your way to the other four tiddlers from there.
Encouragement in these forums has made me consider turning my periodic table demo from a “look what we can do in TiddlyWiki” showcase into something that might actually be useful to various people. My first thought would be Chemistry students. I can easily see some training games based on the data and the table. I can imagine flash cards. I can see allowing students to add notes to the information, from the trivial (“IronMan’s suit isn’t actually made of Iron”) to the much more serious results of their own experiments. I can see them adding custom fields for their own uses, personalizing the wiki, adding new reports. I can see all sorts of possibilities.
To do this, it would make sense to have students work in their own copy of the data, with the “official” parts hidden beneath. The most likely alternative would be to clone the official data tiddler into their own playground, simply by overriding the shadowed tiddler But this has a real problem. Here’s a story:
Do you remember Beth? She was the short, cute, and very friendly girl who sat in front of you in Sophomore Chemistry class. Remember joking with her about how baseball coaches probably don’t make the best teachers? She went on to be valedictorian. No? Well, anyway, somehow, back in 1981 (am I dating myself here?) Beth has a copy of this periodic table wiki for her studies. She has been doing experiments with Tin, and has added copious notes to her copy of the Tin tiddler. She notices an anomaly. She did an experiment and found Tin’s melting point of 229.4°. (Pretty good for a High School student. The official number is 232.06°, but then Beth was always meticulous.)
But Beth looks in the wiki, and sees 505.21°. What? Huh? She couldn’t be that far off. She goes to the library to look it up. (Hey, this is my story; I can imagine she has TiddlyWiki but no Google!) Sure enough, she’s right, or close enough. So she changes the melting point field; it’s great that she could do this, so flexible. And because she’s conscientious, she also sends off a letter (yes, ink on paper; it’s 1981) to the guy who created this system. And she continues on adding her content, and you and she continue to read the textbook and help instruct the rest of the class because Mr. H certainly isn’t going to do it.
It turns out that there are several other fields the wiki got wrong, and she adds additional corrections. She loses track a little bit of what values are hers and what are from the original data, and she may have overwritten a few unnecessarily, and it’s possible she got something wrong. She can’t ask the moron at the front of the classroom; he’ll ramble an answer until he manages to get the familiar ground of sports. And she can’t ask you; you’re studying Lead. And Lynne has Potassium. But she’s not overly worried about this; her notes are good.
A week later she gets a letter back from the wiki’s creator. He’s touched by her writing to him, but has to correct her. All the temperatures in the wiki are in degrees Kelvin, not degrees Celsius. And sure enough, with absolute zero of -273.15° Celsius, the official melting point of Tin is 505.21° Kelvin. It looks like some of her other “corrections” were also mistaken.
How does she fix this?
Here’s how I know to do it currently in Tiddlywiki: she deletes her tiddler full of her own notes, restoring the shadowed plugin version. Beth is smart, so she’ll make a copy first, and painstakingly copy back over the notes she had about Tin into a fresh copy. Perhaps there’s another way. I don’t know how to see the plugin tiddler when it’s being shadowed by your own, but I wouldn’t be shocked to find out that it’s possible. Then she could copy back the changed fields from there. Either way, this is taking time away from the important parts of first-period Chemistry: playing with the Bunsen burners, laughing at the teacher’s gaffes, and gossiping with her friends. (You, an awkward, nerdy teenage boy feel uplifted to be part of this circle of friends, but that’s another story.) Anyway, it’s an annoying process and makes the tool feel a bit less friendly.
If there was a way for tiddlers to have prototypes, here’s how she’d do it. Her own version is a tiddler whose parent is the shadow Tin tiddler. She just deletes the field meltingpoint from her own tiddler. And boilingpoint. And density and specificheat. The underlying values shine through from beneath and everything is restored. All is well with the world.
As I said, it’s quite possibly a ridiculously stupid idea. But forget my mentioning JavaScript. That was just an analogy for those familiar with the language. A much more approachable way to ask this (and I’ll edit the OP to include it) is this:
We have a shadowing mechanism, allowing us to use our tiddler in place of another, even though that other one still exists and will be resurrected the minute our own is deleted. Could we do the same thing at the field level?
It’s not that you’re off in left-field. I’m just looking at a mechanism both more powerful and simpler to use, for some sorts of problems. So yes, there are ways to use cloning to achieve something similar, but it requires a lot more work from the user.
If as well as Clone, we had an Extend button that allowed my new tiddler to inherit all the fields of its parent, but also add new fields and selectively override the parent’s versions, there are a number of things that would be made easy.
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 …