Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add _.toggle/_.transition/_.fsm to underscore #2850

Open
sktguha opened this issue May 10, 2020 · 5 comments · May be fixed by #2897
Open

Add _.toggle/_.transition/_.fsm to underscore #2850

sktguha opened this issue May 10, 2020 · 5 comments · May be fixed by #2897
Labels
contrib probably belongs in Underscore-contrib enhancement question

Comments

@sktguha
Copy link

sktguha commented May 10, 2020

Hi,
I want to propose to add a new function called toggle to underscore.
At simple level it would toggle the value given to it. i.e if it is passed true it will return false and if it is passed false it will return true.
ex-
flag = _.toggle(flag)
// if flag was true then it will get set to false

Also additionally we can have another function that if passed custom arguments then it will return a new function which can be used to toggle with those arguments
For ex -
bitToggler = getTogglingfunction(0,1)
Now if we do
bit = bitToggler (bit)
// If bit had value of 0 it will be set as 1

@jgonggrijp
Copy link
Collaborator

@sktguha Thanks for reaching out.

The toggle function you describe is just _.negate(_.identity). So you can do this:

_.mixin({toggle: _.negate(_.identity)});

flag = _.toggle(flag);
// or
flag = _(flag).toggle();

Regarding getTogglingfunction, please give a real-world example where such a function would be useful.

@sktguha
Copy link
Author

sktguha commented May 11, 2020

Ok thanks for the explanation regd toggle. I guess then it is already available.
Well regd getToggling function, it can be useful when you need to toggle between custom values ,
for ex - 'block' and 'none'
toggle = getTogglingfunction ('block','none')
elem.style.display = toggle(elem.style.display)

@jgonggrijp
Copy link
Collaborator

Thanks. Yes, I can see the practical value in that and I think there is no function yet in Underscore that makes this easy.

To make it as general as possible, I would suggest that this function accepts arbitrary mappings rather than only pairs of alternative values:

var changeTrafficLight = getTogglingfunction({
    red: green,
    yellow: red,
    green: yellow
});

var currentState = 'red';
currentState = changeTrafficLight(currentState); // 'green'
currentState = changeTrafficLight(currentState); // 'yellow'
currentState = changeTrafficLight(currentState); // 'red' again

getTogglingfunction('block', 'none') could then be a convenience shorthand for getTogglingfunction({block: 'none', none: 'block'}).

In order to support all value types instead of only strings, it should maybe (also) support a pair of arrays and/or an array of pairs à la _.object:

var matchStart = /<[^/][^>]*>/, matchEnd = /<\/[^>]+>/;
var toggleParsingMode = getTogglingfunction([
    [matchStart, matchEnd],
    [matchEnd, matchStart]
]);

var parsingMode = matchStart; // match SGML opening tags
parsingMode = toggleParsingMode(parsingMode); // match SGML closing tags from now on

This reminds me a bit of a finite state machine à la Machina. We could take this even further in that direction by allowing callers of getTogglingfunction to pass a transitioning function as an optional third entry and by forwarding additional arguments to the transitioning function:

var changeTrafficLight = getTogglingfunction([
    ['red', null, function(signal) {
        return signal === 'carWaiting' ? 'green' : 'red';
    }],
    ['yellow', 'red'],
    ['green', null, function(signal) {
        return signal === 'pedestrianWaiting' ? 'yellow' : 'green';
    }]
]);

var currentState = 'green';
currentState = changeTrafficLight(currentState); // still 'red'
currentState = changeTrafficLight(currentState, 'pedestrianWaiting'); // still 'red'
currentState = changeTrafficLight(currentState, 'carWaiting'); // 'green'
currentState = changeTrafficLight(currentState); // still 'green'
currentState = changeTrafficLight(currentState, 'carWaiting'); // still 'green'
currentState = changeTrafficLight(currentState, 'pedestrianWaiting'); // 'yellow'

Although if people want this kind of functionality, maybe they should just use Machina. I'm only thinking out loud.

Some things to think about:

  • Decide on what this interface should and shouldn't do.
  • How to name it? If we go all the way to transitioning functions, it may be appropriate to call it _.fsm. Otherwise, something like _.transition, _.rename or just _.toggle might be more suiting.
  • What to do if somebody passes a value that isn't in the transition table? For example, var toggle = getTogglingfunction('block', 'none'); toggle('inline').
  • Should this be added to Underscore directly, or should it rather be added to Underscore-Contrib first? Contrib is unmaintained right now, but I'm looking into a way to blow new life into it.

@jgonggrijp jgonggrijp changed the title Add _.toggle to underscore Add _.toggle/_.transition/_.fsm to underscore May 11, 2020
@sktguha
Copy link
Author

sktguha commented May 20, 2020

Wow that quite a comprehensive feature request. You have raised very good points. I am not sure how the interface should be yet. Do you have any additional thoughts on this ?

@jgonggrijp
Copy link
Collaborator

Other than what I already wrote, no not really. I'm not in a hurry, though. Are you?

@jgonggrijp jgonggrijp added the contrib probably belongs in Underscore-contrib label Aug 29, 2020
mohammadali-seifkashani added a commit to mohammadali-seifkashani/underscore that referenced this issue Dec 18, 2020
@jgonggrijp jgonggrijp linked a pull request Dec 18, 2020 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contrib probably belongs in Underscore-contrib enhancement question
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants
@jgonggrijp @sktguha and others