-
Notifications
You must be signed in to change notification settings - Fork 107
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
Named placeholders #203
Comments
It now looks quite similar to the F# proposal except it disallows point-free in exchange for dropping an arrow: envars
|> x => Object.keys(x)
|> keys => keys.map(x => `${x}=${envars[x]}`)
|> arr => arr.join(' ')
|> str => `$ ${str}`
|> line => chalk.dim(line, 'node', args.join(' '))
|> out => console.log(out) Where for clarity point-free means something more like this, which would've been deemed more idiomatic with that proposal: envars
|> keys
|> map(x => `${x}=${envars[x]}`)
|> join(' ')
|> prefix('$ ')
|> chalk.dim('node')(args.join(' '))
|> console.log If there is actually any chance of an F#-style operator following the blessed Hack one then I think it covers this use case without introducing more special syntax. |
Related comments: The named placeholder idea was also proposed here: #91 (comment) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I'm disappointed that I've had to once again mark a large chunk of an issue thread as off-topic. The OP and the first few comments presented a reasonable issue and discussion; this is not a place to diverge into yet another discussion of F#-vs-Hack or baseless speculation on committee proceedings. There are dedicated threads for that. |
@tabatkins - Apologies for my part in that. I've since caught up in much of the discussion and regret getting caught-up in the politics of it. |
I'm not certain the syntax suggested in the OP is actually viable; there might be parsing ambiguities with the preceding line. Putting that to the side, tho, this runs into some of the arguments against temp variables from the README. Definitely not all, since the bindings are still scoped to a single pipe step, which avoids several issues, but the "naming is hard" part still applies. Most of the time, you don't need to give a name to the topic; it's clear from context, and the topic value doesn't represent a semantically significant unit in your project. (See the README again, where several of the names are just restatements of the operation happening on the line, rather than actually meaningful names.) So I expect most of these lines would, in practice, just use the name That said, I'm not opposed to naming the placeholder sometimes, when it helps. It would just need a good syntax that doesn't cause issues. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Thank you for the reply @tabatkins . My initial crack at placeholder naming is as follows: envars
|> Object.keys(^)
|> ^keys.map(x => `${x}=${envars[x]}`)
|> ^arr.join(' ')
|> `$ ${^}`
|> chalk.dim(^line, 'node', args.join(' '))
|> console.log(^chalked); Essentially, everything following the token is working like an inline comment up until the next consumable character. Janky, but that's all I got at the moment. I do appreciate the arguments against temp-variables, but I'd like to think the Hack token is just about comparable to the |
It took me a while to realize that I suggested the exact same thing in another topic a few days after @shuckster, apologies for not giving proper credit, I must've tricked myself into thinking "iOriginal". Although I like the OP syntax the most (out of all the named-placeholder options I've seen), I share @tabatkins concern regarding grammar. I'm not sure how exactly it'd play out, at first I thought it's fairly simple: So it might be safer, though not as pretty, to place the identifier after the operator: Exploring further, here's something crazy:In this variant you could replace the // Expr |> BindingIdentifier [noLineBreak] Expr
// single-binding Hack behaviour
obj |> _ Object.keys(_) |> _ log(_.join(", "));
// Expr |> BindingPattern [noLineBreak] Expr
// destructuring Hack behaviour
/(?<k>\w+)=(?<v>.*)/.exec(input)
|> { groups: { k, v }} (options[k] = v);
// Expr |> Expr
// F# behaviour
arg |> foo |> (x => bar(x, 2));
// yes I would absolutely require parentheses around arrow functions
// to avoid all kinds of ambiguities |
@js-choi I just noticed you added the If we started with grammar such as:
Then if need arises you could allow destructuring the topic in place in a follow-up: And when bikeshedding the topic token finally concludes, you could enable: |
I did a search of this repository for the word "with" and didn't see this idea, which I take as an imperfect hint that this hasn't been suggested in the repo. Just thought, since
such as...
This would seem to be unambiguous to the untrained eye, since old-style |
@aikeru none of those pipelines seem to have an initial value. |
Ah, ha! Perhaps that foils this idea, then, but maybe something like this?
...or not. Thanks anyway! |
Whether to make declaring an identifier at each pipe step required in the initial proposal… It’s not only up to me, of course. But I’m personally lukewarm towards this. It seems pretty verbose, since it’d be required in each step. By the time we’re naming variables, we might as well be just using variable assignment, right? A lot of the purpose of this proposal is to Not Name the Thing When You Don’t Want to. Anyways, sorry if that response is disappointing. Hopefully it’s understandable. Also, it’s not only up to me—there are other champions—but I also suspect that it would be unpopular with the greater Committee… |
No. Because apples-to-apples equivalent would use const which you can't re-assign. Also variables don't go out of scope afterwards. The difference is who gets to name the variable: the committee, or the user. |
Yeah, baking this in as a requirement for each pipeline step is a no-go. The existing piping syntaxes in JS (method chaining, userland pipe()) don't name the topic variable being passed between each stage, and that still makes for perfectly reasonable and readable code. We don't need to require additional verbosity at each stage for this piping syntax. |
Not sure how that's relevant, as this piping syntax does name the topic.
That's assuming a single-character topic token. Otherwise there's no additional verbosity required. |
Yeah, sorry, by “variable assignment” I meant “constant assignment”. By the time we’re naming constants, we might as well be just using constant assignment, right?
Well, right now Hack pipes are associative. Having In fact, my own mental model of In any case, I also suspect that it would be unpopular with the greater Committee, but yeah. |
I didn't mean to imply Whether I meant that if you used |
This comment has been minimized.
This comment has been minimized.
I would like to propose a syntax for the named placeholder idea; const superhero = [] as powers
|> grantPower("nightvision", powers)
|> make("invincible", powers)
|> powers.map(x => x.toUpperCase()) We've been discussing about it at TC39 Discourse Group |
I’m unclear on the argument for naming the token that doesn’t allow you to name it in each step. |
Not sure if this has been said before but 2 things about this proposal:
Which is neat. Anyways, just my 2 cents. |
@edeboursetty I'm not sure the current proposal permits a |
One option would be to allow us to provide a name after the pipeline token. For example, say we go with As an example: id
|> getUserById(%%)
|> getGroupFromUser(%%user)
|> doOperation(%%group) + anotherOperation(%%group)
// And this would be a syntax error
// because you can't use different names within the same pipeline step
data |> doOperation(%%xyz) + anotherOperation(%%abc) This would require us picking a hack-pipe token that can actually be used in this way (i.e. using a binary operator, such as This solution also doesn't fix the nested pipeline issue, but what I care about more is the ability to name the token (to help self-document it), then the ability to nest pipelines in a more readable way. |
Just wondering if it wouldn't guide our intuition a little better if we could gives names to placeholders in the same manner as arrow-function arguments?
No need to choose between
^
or%
, no conflicts with mod/pow, and has a better chance of producing self-documenting code.What are the drawbacks to this approach?
The text was updated successfully, but these errors were encountered: