Hi all,
a topic that has been briefly touched on are that many fields in JIF will be optional. I would like to propose a stronger version of this: ALL fields should be optional! Yes, I want the string {} to be valid JIF. Hear me out.
The goal of this is (a) to make the user experience of passing JIF around different programs as seamless as possible, and (b) to reduce the barrier of entry for programmers looking to support JIF by making it simple to generate.# Optionality and user experience
I think we all agree that many values are going to be irrelevant to certain software types -- classic example of the vanilla siteswap generator which does not care about limb movement, prop types, dwell times, etc.. This ties into the and physical vs. logical throws discussion.
For the user's sake, I strongly want to avoid having different "versions" or "levels" of JIF. As a user, I don't want to pipe a generator's JIF output through some converters before I can give it to an animator to see what is going on. As a user, if I click "Export JIF ..." in one software and then "Import JIF ..." in a different software, I expect things to just work.
As a tiny community, I don't think we can afford fragmentation.
So for all fields, this rules out any option related to "this is required to be present only for some programs". That would automatically create fragmentation, because as soon as program X requires a field to be there that program Y does not export, they become incompatible.
Conclusion: Every field MUST be either optional or required for
ALL software, nothing in-between.
# Optionality and simplicity
Now, let's discuss "required" vs "optional". There is a trade-off here: Programs that only generate JIF greatly benefit from not having to bother with unnecessary boilerplate that they don't care about. If a developer only supports vanilla solo siteswaps, they do not want to think about how many hands are in the pattern, that beats could have different timings, or that objects could have different colors.
On the other hand, programs that consume JIF need to always fill in missing values with defaults, for every optional field that they care about. So a developer might prefer required values. More on this in the section "Default values".
(Side note: Exact field names of the following JIF examples
are not too relevant and I don't want to make them point of the
discussion in this thread. I use integer references as was
discussed in a different thread, where "throws" reference
"limbs", and "limbs" reference jugglers.)
Example 1: The vanilla siteswap generator needs to export 531, so it generates:
{throws: [{duration: 5}, {duration: 3}, {duration: 1}]}
It does not bother with number of jugglers, how many hands they have, synchronous throws, polyrhythms, etc.
Example 2: A generator color-codes magic throws wants to visualize how the 3 in 531 is always the same object, so it generates:
{objects: [{color: 'red'}, {color: 'red'}, {color: 'green'}],
throws: [
{duration: 5, object: 0},
{duration: 3, object: 2},
{duration: 1, object: 1},
]}
Example 3: In a 2D top-down view, I want to visualize who
passes with whom when, by drawing lines between circles, but only
when they pass ("(A) ----- (B) (C)"). Here you don't even
care about the throw duration, only the time and between whom. For
a 3-person feast, you generate:
{jugglers: [{}, {}, {}],
limbs: [{juggler: 0}, {juggler: 1}, {juggler: 2}],
throws: [
{time: 0, from: 0, to: 1},
{time: 1, from: 0, to: 2},
{time: 2, from: 1, to: 2},
]}
This is slightly cumbersome because you first assert that each juggler only has 1 limb (not something the software programmer would naturally model in this use case), but I would be ok with that. An alternative would be to rely on the default that jugglers have 2 limbs and just use only the first (default: right) limb of each juggler for the throws (0, 2, 4):
{jugglers: [{}, {}, {}],
throws: [
{time: 0, from: 0, to: 2},
{time: 1, from: 0, to: 4},
{time: 2, from: 2, to: 4},
]}
Again, "limbs" is optionally and 6 limbs would be the default for 3 jugglers (Or we could decide to allow specifying either "fromLimb" and "toLimb", or "fromJuggler" and "toJuggler", with the limbs implicit. But this adds redundancy, which I am not really a fan of.)
Note how I use [{}, {}, {}] for 3 jugglers, and not "numJugglers: 3". A field like "numJugglers" introduces redundancy, because to add properties to the jugglers you need a "jugglers" array anyway. A programmer can easily extend {} to {label: "Alice", position: [4,2]} without changes to the JIF structure.
While [{}, {}, {}] is also boilerplate in the eyes of a programmer who does not care about naming or positioning their jugglers, I believe that in this case the extensibility benefits outweigh the cost.
You could argue that it is allowed to leave out the "jugglers"
line completely, because there exists a throw to limb #4, so it
can be implicitly inferred that there must be 3 jugglers. But this
has a cost for the JIF consumers, see the section "Default values"
below.
Example 4: I want to animate 2 people without clubs who are facing each other and who are dancing the Macarena.
{jugglers: [{}, {}],
jugglerMovement: [/* lots of instructions */],
limbMovement: [/* lots of instructions */]}
All clear? Great :)
# Default values
A program that reads JIF always need to check for presence of
fields to validate the input. When a field you care about is
absent, you usually have the choice of throwing an error or
filling in a default value. In many cases, default values are
trivial and even less work than throwing a (good) error.
By making developers ALWAYS check for presence and using default
values, I claim that we even encourage more robust implementations
of JIF, and prevent things like "Oh I guess the 'throws' property
always exists, it's fine if my program crashes if it is missing".
Consistency is king.
However, the computation of some default values also introduces complexities that may hinder adoption. I don't wanna sweep this under the rug. Some we can just specify the procedure in the spec and it becomes relatively easy and uncontroversial to adopt, for example:
* If "jugglers" is missing, there is 1 juggler.
* If "limbs" is missing, there are 2 limbs per juggler, with
juggler n "owning" limb 2n (right hand) and limb 2n+1 (left hand).
* If "throws" is missing, there are no throws.
Some other default rules we can put in the spec, but different
programmers might disagree with them, or they might be cumbersome
to implement or have hard edge cases:
* Jugglers are labeled A, B, C, ... by default. (Not too hard to implement, but already forces a decision on what happens if there happen to be more than 26 jugglers.)
* 1 juggler stands at position (0,0). More jugglers stand evenly
spaced around a circle with radius 1. (arbitrary)
* "time" starts at 0, and each throw without a time defaults to the time of the previous throw plus 1.
* The default throw duration is 3. (arbitrary choice)
* In a pattern with k limbs, for a throw at time t and duration
d:
* "from" (fromLimb) defaults to limb (t mod k)
* "to" (toLimb) defaults to limb (t+d mod k)
(This is elegant for n-handed siteswap aka asynchronous passing,
but what to do if t or d are not integers?)
* Patterns repeat by default. (But what is the period if the last throw is written to be at time=5.333?!)
* A throw's dwell time defaults to 1. (But what if duration is
<=1? See the discussion on zip timings.)
.... the list goes on for quite a bit, which is a downsides in itself, since there will be many such rules that need to be implemented. Luckily, most programs won't need to bother with many of them (the causal editor does not care where jugglers stand by default).
One more thing to throw in is that we may want to adopt W3C's wording of MUST, SHOULD and MAY that is used in RFCs. Some defaults are really not crucial (e.g. beats per second, number of spins) and if a developer wants to change it for aesthetic reasons, that's ok, but others are REALLY important to ensure compatibility.
## Example 1 with defaults filled in
Just to illustrate what I mean more, here is what {throws: [{duration: 5}, {duration: 3}, {duration: 1}]} could be expanded to (with some made up field names, of course not complete):
{
jugglers: [
{label: "A", position: [0,0]}
],
limbs: [
{juggler: 0, label: "R", type: "right_hand"},
{juggler: 1, label: "L", type: "left_hand"},
],
throws: [
{time: 0, duration: 5, from: 0, to: 1, dwellTime: 1},
{time: 1, duration: 3, from: 1, to: 0, dwellTime: 1},
{time: 2, duration: 1, from: 0, to: 1, dwellTime: 1},
],
repeating: true,
beatsPerSecond: 3,
jugglerMovement: [],
limbMovement: [],
}
# Conclusion
I believe this topic is important because thinking about default values helps while deciding the overall structure of JIF, and also while deciding how certain fields should work (e.g. optional values are a strong argument for integer references over strings).
Despite the drawbacks, I believe that making ALL values optional maximizes compatibility and mostly minimizes developer annoyance.
Thanks for reading, would love to hear your thoughts!
Cheers,
Lukas
Correction: For 4-handed siteswap to fit in elegantly, the default limb order has to be different from what I described!
The assumption I put forward was that "default throw order equals default limb order". I assumed the default limbs of 2 jugglers to be: [A:right, A:left, B:right, B:left], which of course is not the natural throwing order for 4-handed siteswap. That would be [A:right, B:right, A:left, B:left].
Sadly, that ordering looses the nice property that you wouldn't
have to change limb indices when adding a juggler:
With [A, A, B, B, C, C, ...], limbs #0 and #1 always belong to A,
no matter how many jugglers.
But with [A, B, C, ..., A, B, C, ...] it depends on the total
number of jugglers, making code slightly more complicated for all
use cases except n-handed siteswap (at least the ones that want to
use the default limbs settings, which I expect to be most common).
Not sure right now which option I would even prefer ... Some defaults are hard :(
It sounds like a great idea, especially because it makes the files more elegant.This is especially nice if you want to combine different aspects of juggling (say, combine causal diagrams from one program with the walks from another program)
However, it may require more from the programmers to fill the gaps.It will not be difficult to fill in missing durations if the value is always 3, but to fill missing jugglers or limbs requires already a tiny bit of arithmetic.And a simple parameter like "repeating" may require very precise descriptions (how do the limbs permute? what is the period of the pattern?).
On Saturday, 14 November 2020 at 21:13:06 UTC+1 lukas....@yahoo.de wrote:
Hi all,
a topic that has been briefly touched on are that many fields in JIF will be optional. I would like to propose a stronger version of this: ALL fields should be optional! Yes, I want the string {} to be valid JIF. Hear me out.
The goal of this is (a) to make the user experience of passing JIF around different programs as seamless as possible, and (b) to reduce the barrier of entry for programmers looking to support JIF by making it simple to generate.# Optionality and user experience
I think we all agree that many values are going to be irrelevant to certain software types -- classic example of the vanilla siteswap generator which does not care about limb movement, prop types, dwell times, etc.. This ties into the and physical vs. logical throws discussion.
For the user's sake, I strongly want to avoid having different "versions" or "levels" of JIF. As a user, I don't want to pipe a generator's JIF output through some converters before I can give it to an animator to see what is going on. As a user, if I click "Export JIF ..." in one software and then "Import JIF .." in a different software, I expect things to just work.
--
You received this message because you are subscribed to the Google Groups "juggling-interchange-format" group.
To unsubscribe from this group and stop receiving emails from it, send an email to juggling-interchang...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/juggling-interchange-format/b6405a10-824c-4c7f-af53-bdb35ed6a9f8n%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/juggling-interchange-format/a0e9c349-10ee-126c-d1d1-fdd55b7b31b2%40yahoo.de.