Closed boyland closed 4 years ago
It seems that SugarCube recently added
<<cycle>>
.
If by recently you mean almost a year ago now, sure.
It's almost what I want, except that
optionsfrom
seems to handle arrays (and maps and generic objects) in the opposite way that I was expecting, and need. In particular, it makes sense to me to have the variable set to the index/key and that the label (visible to the reader) should be the value/element.
I appreciate you want it to work in a particular way, but I think you're overlooking, IME, more common use cases.
In the case of generic objects and Maps. How would that work when their values don't make sense as the label, either because they simply don't or because they're objects of some type without a sensible .toString()
method.
In the case of Arrays and Sets, I'll just cover probably the most common use case—by far. How would that work when you simply want to be able to chose a value from the Array or Set.
What you seem to want is simply not the most common use cases, IME, which is what the <<cycle>>
and <<listbox>>
macros were coded to handle by default.
That aside. You really don't need a custom macro to get what you want, unless you simply want to write one. You should simply be able to invert your indices/keys and values for the <<optionsfrom>>
tag.
For example, you can use <Array>.reduce()
with a Map to invert any of the mentioned data structures so it's used as you prefer.
<<set _choicesArray to [
"A",
"B",
"C"
]>>
<<cycle "$choiceFromArray" autoselect>>
<<optionsfrom
_choicesArray.reduce(function (map, value, i) {
map.set(value, i);
return map;
}, new Map())
>>
<</cycle>>
<<set _choicesSet to new Set([
"A",
"B",
"C"
])>>
<<cycle "$choiceFromSet" autoselect>>
<<optionsfrom
Array.from(_choicesSet).reduce(function (map, value, i) {
map.set(value, i);
return map;
}, new Map())
>>
<</cycle>>
<<set _choicesObj to {
"0" : "A",
"1" : "B",
"2" : "C"
}>>
<<cycle "$choiceFromObj" autoselect>>
<<optionsfrom
Object.entries(_choicesObj).reduce(function (map, kvPair) {
map.set(kvPair[1], kvPair[0]);
return map;
}, new Map())
>>
<</cycle>>
<<set _choicesMap to new Map([
[0, "A"],
[1, "B"],
[2, "C"]
])>>
<<cycle "$choiceFromMap" autoselect>>
<<optionsfrom
Array.from(_choicesMap.entries()).reduce(function (map, kvPair) {
map.set(kvPair[1], kvPair[0]);
return map;
}, new Map())
>>
<</cycle>>
Thank you. I appreciate the thoughtful and detailed reply. In the event, I wrote a custom macro; it ends up being very short, I can write:
089 int free = <<cyclearray "$freei" setup.free>>;
090 E pivot = source[free];
091 <<cyclearray "$adjloi" setup.adjlo>>
092 <<cyclearray "$adjhii" setup.adjhi>>
And then test $freei
etc later. (I'm using this for a code-writing exercise. The student chooses what to do for each part and then I use the choices to select a JUnit test that will fail.)
It seems that SugarCube recently added
<<cycle>>
. That's great! When I was using Harlowe, I had to simulate it with a lot of complex stuff. It's almost what I want, except thatoptionsfrom
seems to handle arrays (and maps and generic objects) in the opposite way that I was expecting, and need. In particular, it makes sense to me to have the variable set to the index/key and that the label (visible to the reader) should be the value/element. Of course, people have presumably already been using<<cycle>>
, so it seems the best thing for me to do is to define a<<cycle*>>
custom macro that does it the way that seems to make more sense to me. But I wanted to check to see the reasoning behind the current macro.