-
Notifications
You must be signed in to change notification settings - Fork 476
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
[Feature idea] Add support for common operators in conditional expressions (and maybe elsewhere?) #2411
Comments
Thanks for opening this issue! Yah, conditionals are a massive hack. They exist as a special case in the grammar of conditionals, not as expressions. My motivation for implementing them in this terrible, awful, no good way, was because I've wanted to avoid committing to the representation of This is tricky, because I can imagine that one might want For example, you might want:
So For example, with the inbound PR #2440, you could do:
I.e., get make, preferring Whereas if |
Having the empty string be the "falsy" value wouldn't mix well with some of the existing syntaxes:
Also, different justfiles may need different definitions of "falsy" (for example, the string Maybe could let the user decide what strings are falsy on a per-justfile basis? -
To avoid surprises when using functions like |
Yeah, I've ben thinking about our current functions that return My current thinking is that having them return I'm hesitant to introduce something like One option would be to deprecate those three functions, and introduce new versions which return I think this is something that's worth thinking hard about. Just only has a single type, the string, and using strings to represent other types is not ideal, precisely because of issues like these. (An additional issue is the case where the empty string is a valid value, so doing something like I think using Another thought is that I've often thought that perhaps the base type should actually not be strings, but lists of strings. (See the rc shell, which does this.) In which case it wouldn't be the empty string which is the best representation of So, to stop rambling and sum up:
A static type system would be great, but it's a huge undertaking, and although I did take a compilers class in college where we learned about type systems and wrote a compiler for a statically-typed python-like language, that was a long time ago and I've basically forgotten everything 😅 Any other options I'm missing? |
That would be weird and seems unnecessary. With such duplication, the use of the new functions represents an explicit opt-in to the new return value. In which case there would be no need to have both the old and new functions simultaneously available for backwards compatibility, since justfiles using the new functions are updated anyway, and the functions would be identical in behavior all the way until the exact text of the true/false return values. And as you pointed out, the new functions would need to have "not amazing" names, since the existing functions took the clear, concise names. That the "better" functions have the worse names adds even more confusion.
Landing as unstable sounds like a good idea for at first 👍 regardless of the ultimate path forward.
Not sure what would be a good name for this setting? |
Wouldn't you need both the new and the old functions? Maybe I'm misunderstanding, but removing the old functions would break old
This is true, but a deprecation warning, along with removing the old functions from the docs would hopefully minimize that.
I'll do that, just so I can get the PR in and then we can worry about the larger problems later.
I agree that the behavior of a setting like that is the end state that we want to get to, but I hesitate to add a setting like that because I think that you really just want it to be the default. It would also mean that you would have to remember to add it to your You could definitely do that, but it would be annoying. For example, the natural place to restrict Having worse names for three functions is lame, but seems less annoying and invasive to me. |
Landed |
Settings are the usual answer for opting into backwards-incompatible behavior. Having a setting to alter the functions' falsy return value would avoid duplication confusion and preserve the easy-to-understand existing function names. With the only difference being in the string representation of one specific return value, it would seem the rationale that would favor deprecating instead of a setting would be if migrating to the new functions is onerous, i.e. justfiles may need the option of a transition period of gradually migrating the function calls instance-by-instance instead of doing it all at once. But not seeing how that would be for only changing
For what it's worth I had #1201 in mind when thinking of that setting idea
Oops, didn't realise the implementation impact 😳 If the functions are going to be deprecated in favor of new ones, then instead of basically renaming, what about switching to non-boolean return values to prevent this problem recurring in face of a better (or different canonical) representation/idea of "truthy"? This could reduce the negative impact of not being able to use the existing function names. As examples of this idea:
For |
I think I overstated the implementation impact. It's actually not so bad to note use of unstable features in the parser, and convert use of unstable features into errors in the analyzer later. Let me rephrase I think the main reason I prefer deprecating the old functions. If the functions are deprecated and new versions with better behavior are introduced, the impact is:
1 is annoying, but it's a one-time cost, 2 is ongoing but I think pretty marginal, and 3 is ongoing but also pretty marginal. Whereas with a setting:
I think these are both slightly more annoying drawbacks than with deprecation, and they're ongoing, users will forever have to add the setting if they want to use the logical operators. Not to overstate my case though! I think a setting isn't a terrible idea, and deprecation is annoying. You all of a sudden start getting warnings for things that used to work. Rolling it into a hypothetical future edition does make it better, since multiple such changes can be bundled into a single setting, but it would still be better if we could avoid gating things behind editions, i.e., they're kind of a last-ditch solution for things that absolutely cannot be done in a backwards compatible way. |
I wanted to write some code like this:
But apparently most common operators aren't implemented beyond what looks like string concatenation (judging from the error message). For example, logical operators would be quite useful here.
This time, I can work around this with a condition like
if os_family() + "-" + arch() == "windows-x86_64" {
, but I would imagine there are other scenarios out there where it doesn't work out as cleanly.It seems that GNU make has similar limitations: https://stackoverflow.com/questions/6451477/makefile-ifeq-logical-and
But I don't know if those limitations from GNU make are worth keeping in just? None of the proposed solutions in the above StackOverflow link look "better" to me than what the original poster was trying to do.
Some operators I could imagine being useful:
&&
||
!
(unary NOT)+
,-
,*
,/
, etc). But unless just gains a type system, IDK if that's something you'd want to do (else,+
is ambiguous with strong concatenation)...To me, the logical operators would be the most nice ones to have, but maybe keep options open for math operators in the future?
The text was updated successfully, but these errors were encountered: