Skip to content

Bikeshedding the Hack topic token

Jonas-Seiler-Wave edited this page Mar 17, 2023 · 93 revisions

Hack pipes use topic references as placeholders in their pipes’ RHS bodies. The body expressions essentially acts as an inner lexical scope, in which the placeholder is statically bound to their left-hand side’s (LHS) value, once the LHS is evaluated. This allows the RHS to be any expression, not only simple unary function calls; you simply write the code you would have without pipes, but now you can postfix-chain the expressions like in jQuery or other fluent interfaces.

Assuming that Hack pipes are chosen by TC39, the placeholder’s spelling would need to be bikeshedded. Possible spellings can be sorted into four categories: nullary operators, keywords, and special variables (although any special variable would be likely be blocked by several TC39 members).

Discussion is ongoing in issue #91.

Criteria for choosing the token

Parsing simplicity: Does the topic make parsing more complex or contextual for computer or human readers?

Visual distinguishability: Is the topic easy to identify when humans quickly scan code? How often will other symbols resemble the topic reference? Does visual noise frequently blur into ASCII soup?

Textual brevity: Does it make code excessively more verbose?

Typing easiness: Is it difficult to type in common keyboard formats?

When judging how each candidate topic token fulfills these criteria, we must weigh its benefits and costs by how often we expect them to occur in code.

Expected Benefit
= Expected Number of Occurrences
× Expected Benefit per Occurrence

Expected Cost
= Expected Number of Occurrences
× Expected Cost per Occurrence

For example, the candidate topic ## and tuple literals #[ ] resemble each other, which has a cost to visual distinguishability. If tuple literals (and therefore that cost) are expected to occur frequently, then the cost must be multiplied by that large number of occurrences.

Current possibilities

Token Notes TC39 opinions
~ Must be parenthesized when used as a called function (e.g., f() |> [(~)(0)]). Confusion with bitwise xor is mitigated by the “pipe body must contain a topic” early error (e.g., f() |> [~(0)] is a SyntaxError). Also, if PFA syntax ever advances, it would still be compatible: f() |> g~(~, 0). @js-choi: Likes.
@TabAtkins: Neutral?
@gibson042: Dislikes.
^^ Bitwise xor ^ is extremely rare; would require separation from bitwise xor with space or parentheses (e.g., x |> ^^ ^ 2).
Unlike surrounding code, ^^ does not sit on the typographic midline.
Many non-English keyboard layouts use their ^ key as a dead key for inserting circumflex letters. Most keyboard layouts can still type ^^, although some platforms require three or four keystrokes.
The arrow points “upwards” at the previous value.
@jamiebuilds: Likes.
@js-choi: Likes more than @@ and %%.
@leobalter: Likes.
%% Most pipe expressions would not contain the remainder operator %; would require separation from remainder with space or parentheses (e.g., x |> %% % 2).
Somewhat resembles printf format strings.
@@ Most pipe expressions would not contain decorator expressions; unambiguous with them. @rbuckton: Neutral; had wished to preserve for compile-time decorators but subsequently withdrew this request.
#_ May be visually noisy with tuple literals #[], record literals #{}, and private fields. Not ambiguous with private fields (which must be qualified with this. etc.) – except in #_ in this (which would need to be special-cased). Also would preclude adding bare private fields in the future. @rkirsling: “Worth considering”. @js-choi: Mildly negative; prefers to ##.
## May be visually noisy with tuple literals #[], record literals #{}, and private fields. @js-choi: Against.
@TabAtkins: Slightly in favor over @@ and %%.

Disqualified tokens

Token Disqualification reason
% Pushback from implementor due to parsing complexity. Would increase coupling between tokenizer and tree parser like currently for / (distinguishing binary division vs. RegExp literal).
^ ″″
* ″″
# #[0] is ambiguous with tuple literals.
? Confusing with conditional ? :, nullish coalescing ??, and optional chaining .?.
@ Complex interactions with decorator syntax that may close off further extensions to decorator syntax.
>< Complicated tokenization in 3>><.
<> Complicated tokenization in 3<<>. Also, JSX already uses <>.
:: Lack of support from any TC39 representative.
<?> ″″
>?< ″″
{?} ″″
(?) ″″
var var[x] = y is ambiguous in do expressions: a |> do { var[x] = y }.
?var Lack of support from any TC39 representative. Excessive length.
@var ″″
var() ″″
var.$ ″″
$ May unexpectedly shadow outer variables; @ljharb would always block in TC39 for this reason. @jamiebuilds is also against.
_ ″″
$_ ″″
it ″″
@it Lack of support from any TC39 representative. Excessive length. Ambiguous with decorators due to automatic semicolon insertion.
Non-ASCII symbols Almost certainly would be rejected by TC39.