git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 4/5] config.c: add a "tristate" helper

From
Junio C Hamano <gitster@pobox.com>
Date
Apr 9, 2021, 12:53 UTC
Message-ID
<xmqq35vzoc0e.fsf@gitster.g>
In-Reply-To
<87o8eogs2r.fsf@evledraar.gmail.com>
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> The benefit in this case is to human readers of the code who know
> they're being helped by the enum checking in "case" arms.

Well, do we have tristate that is handled with switch/case? And more importantly, do tristates benefit from getting handled with switch/case?

The one I cited as an existing example to decide that we should favour "special case 'auto' and then let it fall through to the normal bool" is in userdiff.c

        static int parse_tristate(int *b, const char *k, const char *v)
        {
                if (v && !strcasecmp(v, "auto"))
                        *b = -1;
                else
                        *b = git_config_bool(k, v);
                return 0;
        }
and the caller uses it to set -1/0/1 in driver->binary member.
And the member is often used like so:
	... else if (userdiff->binary != -1) {
		is_binary = userdiff->binary;
	} else {
		is_binary = auto_detect_based_on_contents(...);
	}
	if (is_binary) {
		... do the binary thing ...
	}

This is because "auto" is the only value among the three that needs "preprocessing" before it is turned into a concrete yes/no that is usable in the downstream code. So with AUTO being the only spelled out value, a construct like this:

	if ((driver->binary != TRISTATE_AUTO) 
	    ? driver->binary : auto_detect())
		...; /* do the binary thing */
	else
		...; /* do the non-binary thing */

would be sufficient to help human readers. You do not need enum to help, and you do not need switch/case.

You could use switch/case with enum if you really wanted to, but
	switch (temp = driver->binary) {
	case TRISTATE_AUTO:
		temp = auto_detect();
                break; /* ????? */
	case TRISTATE_FALSE:
		/* do the non-binary thing */
		...;
		break;
	case TRISTATE_TRUE:
		/* do the binary thing */
		...;
		break;
	}

would not be a useful construct for the "auto" use case, where tristate is used to mean "we cannot decide at the configuration time, as the appropriate value depends on other factors that are available when it actually is used, e.g. the contents in the buffer, if fd=1 is connected to the terminal, etc."

If you really wanted to, you could still use switch/case for such a use case, perhaps like this:

	switch (temp = driver->binary) {
	case TRISTATE_AUTO:
		temp = auto_detect();
		/* fallthrough */
	default:
		if (!temp) { /* TRISTATE_FALSE */
			/* do the non-binary thing */
			...;
		} else { /* TRISTATE_TRUE */
			/* do the binary thing */
			...;
		}
		break;
	}

and switch may help making sure that all enum values are handled, but I do not see a value in it. The earlier code that used "if auto, run autodetect, otherwise use the value as is" as the condition for an if/else statement would be far easier to follow, and equally safe.

> ... in config.c in the future it makes sense to pass a pointer to a
> "is_auto" parameter to these new tristate() functions, similar to
> e.g. the existing git_config_bool_or_int().

I am not sure what you are trying to gain by introducing is_auto here.

For bool_or_int(), is_bool pointer makes perfect sense, because the value spelled as "true" cannot be anything but bool, but "1" can be either boolean true or an integer. An extra is_bool bit can be used by callers that care if the user said "true/yes" or "1" and want to behave differently, when the configuration can take either bool or integer. For example, if you originally have a "do you want this operation to be verbose?" yes/no variable, and later extended it to add verbosity level, "yes/true" might mean "yes, please use the default verbosity level", while "1", "2", ... would mean "yes, and please set the verbosity level to this number". And the default verbosity level may not be "1", so the distinction between "yes" and "1" does matter.

I do not see such a disambiguation need for tristate parsing, so the immense usefulness of is_bool is not a good analogy to draw value for the proposed is_auto from.

Thanks.
Previous: Ævar Arnfjörð BjarmasonNext: Junio C Hamano
Message 14 of 21 in “config: support --type=bool-or-auto for "tristate" parsing”
  1. 0/5 config: support --type=bool-or-auto for "tristate" parsingÆvar Arnfjörð Bjarmason, Apr 8, 2021
  2. 1/5 config.c: add a comment about why value=NULL is trueÆvar Arnfjörð Bjarmason, Apr 8, 2021
  3. Junio C HamanoApr 8, 2021
  4. 2/5 config tests: test for --bool-or-strÆvar Arnfjörð Bjarmason, Apr 8, 2021
  5. Junio C HamanoApr 8, 2021
  6. Ævar Arnfjörð BjarmasonApr 8, 2021
  7. 3/5 git-config: document --bool-or-str and --type=bool-or-strÆvar Arnfjörð Bjarmason, Apr 8, 2021
  8. Junio C HamanoApr 8, 2021
  9. 4/5 config.c: add a "tristate" helperÆvar Arnfjörð Bjarmason, Apr 8, 2021
  10. Junio C HamanoApr 8, 2021
  11. Ævar Arnfjörð BjarmasonApr 8, 2021
  12. Junio C HamanoApr 8, 2021
  13. Ævar Arnfjörð BjarmasonApr 9, 2021
  14. Junio C HamanoApr 9, 2021
  15. Junio C HamanoApr 8, 2021
  16. Jeff KingApr 9, 2021
  17. Junio C HamanoApr 9, 2021
  18. Jeff KingApr 10, 2021
  19. Junio C HamanoApr 10, 2021
  20. 5/5 config: add --type=bool-or-auto switchÆvar Arnfjörð Bjarmason, Apr 8, 2021
  21. Junio C HamanoApr 8, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.