Open crystalthoughts opened 5 months ago
The TC39 pipe proposal actually uses %
currently, though there's various other notation mentioned. (I think ^^
is an older proposal. Note that it currently means logical xor
in Civet, though that might be fine parsing wise, just confusing.)
TC39's %
placeholder also has a different meaning than our current placeholders .
and &
: it can only be used in pipelines, and the arrow function gets pulled all the way out to just before the pipeline. See https://github.com/DanielXMoore/Civet/issues/75#issuecomment-1365340146
It's interesting to look at the examples from the proposal. All of them currently can be written using .
and/or &
, but it depends on the example. Here's one example that needs both:
return links
|> Object.keys(.).map(function (rel) {
return '<' + links[rel] + '>; rel="' + rel + '"';
})
|> link + &.join(', ')
|> this.set('Link', .);
Now that we have good general support for placeholders, I wonder if we should add a pipeline-specific one, in particular to align with the TC39 pipe proposal as you say. Simple example:
data |> f(%) + g(%)
↓↓↓
f(data) + g(data)
This example can't be written with &
(it won't pull outside the function calls) nor with .
(each call makes its own function). And in general it could be nice to work with pipelines without having to think about the intricacies of &
vs. .
, and just have a placeholder that refers to the previous pipeline result.
I think the only hard part is we need to choose a placeholder syntax. %
seems OK. ^
and <
, or ^^
or <<
, make some sense in the ways they point, though we've discussed using ^
for other things (implicit imports). I wonder if there's something obviously syntactically related to the pipeline |>
itself.
Related, another option we've discussed (also mentioned in the TC39 bikeshedding issue) is
data |x> f(x) + g(x)
↓↓↓
f(data) + g(data)
where you can put any identifier (e.g. $
) in between |
and >
.
I think the last suggestion is really nice - it sidesteps the issue of needing to remember an explicit symbol out of the mix of candidates. $ (or x) could be the suggested placeholder. It could even unpack an array or an object:
[1,2] |(a,b)> a + b //3
["head","tail","tail"] |(h,t)> [h,t] // ["head",["tail","tail"]]
[1,2,10] |$> $[0]+$[2] //11
{a:1,b:2,c:10} |(a,b)> a+b //3
Of course this gets away from the TC39 a bit...
I'm not sure about that paren operator, but I'd definitely like to support standard JS destructuring:
[1,2] |[a,b]> a + b // 3
["head","tail","tail"] |[h,...t]> [h,t] // ["head",["tail","tail"]]
[1,2,10] |$> $[0]+$[2] // 11
{a:1,b:2,c:10} |{a,b}> a+b // 3
Admittedly |x>
looks a little unwieldly when it grows to a destructuring pattern.
This notation is mentioned in https://github.com/tc39/proposal-pipeline-operator/issues/91#issuecomment-363092439 (more examples here: https://github.com/tc39/proposal-pipeline-operator/issues/91#issuecomment-1188236632, https://github.com/tc39/proposal-pipeline-operator/issues/91#issuecomment-1332224740) so it's plausibly being considered for the TC39 proposal. Although there are hundreds of proposals in that issue, so who knows what they will decide.
@STRd6 What do you think of this notation? Worth trying? It is a little funny that |x>
is just shorthand for |> (x) =>
, but it is shorter, and it will be easy to implement.
@edemaine if you're excited about trying |id>
it go for it! Destructuring in there is fine as well. We probably won't really know the pros and cons until we try out using it ourselves.
Hi, I think it would be a good idea to have the possiblity of aligning Civet more closely to the pipeline operator proposal (hack style). I think the only thing needed would be a configuration option to change something like:
pp:= & |> (JSON.stringify ., null, 2) |> console.log
topp:= & |> (JSON.stringify ^^, null, 2) |> console.log
I also think it's a bit more readable. Any thoughts welcome :)