Open remexre opened 2 years ago
While the first code block is somewhat hard to read, as someone who doesn't use the postfix application operator, I would have no idea how to read the second code block. It might make more sense to write it as a series of let
s or local
s to keep it readable for everyone.
Readability aside, I think it might be difficult to add this as an extension because of MDA. Unless I'm wrong about how binary operators are implemented, this doesn't have a marking terminal.
Readability aside, I think it might be difficult to add this as an extension because of MDA. Unless I'm wrong about how binary operators are implemented, this doesn't have a marking terminal.
The Silver "extensions" are only extensions in the MWDA sense, most of them probably wouldn't pass the MDA without some significant refactoring. And regardless it is possible to refactor the host grammar putting infix operators in their own nonterminal, such that the operator is effectively the marking terminal for that grammar. So I wouldn't put the MDA as a reason not to do this.
let
s
I think this'd require making let
s act as a prefixy thing to look nice
top.foo =
let one = flatMap(idkAnEnvLookupOrSomething, myThings) in
let two = filter(someOtherFunction, one) in
filter(someFunction, two)
end end; -- <- sad!
(Is our translation for let
s actually reasonable, btw? I think it would be less efficient than having the operator, right?)
local
s
Unless we get "uncached locals," aren't these measurably less efficient?
They also make it less obvious that "this is an intermediate value of this one computation, not something that other things should be using."
readable for everyone.
idk, this feels like something we could put in the docs, assuming the characters can be found by search. Ideally we'd probably choose the OCaml syntax for searchability too; it looks like JavaScript might be adopting the same syntax for the same operator too; a SO question about this is actually the first thing I get on Google for "|> operator".
Readability aside, I think it might be difficult to add this as an extension because of MDA.
Plus, we could do the operator refactor where
syn assoc::Assoc;
data Assoc { left(), right(), none() }
syn prec::Integer;
syn elabOper::(Expr ::= Expr Expr);
closed nt Operator with assoc, elabOper, prec;
nt Expr_1, Expr_2, Expr_3;
nt ExprOpRHSes;
concrete prod opRHSesNil
this::ExprOpRHSes ::=
{}
concrete prod opRHSesCons
this::ExprOpRHSes ::= op::Operator expr::Expr_3 tl::ExprOpRHSes
{}
concrete prod op
this::Expr_2 ::= lhs::Expr_3 rhses::ExprOpRHSes
{ forwards to ...; }
Then, the operator terminal would be the marking terminal.
Sometimes there's Silver code like:
but I find this slightly hard to read. With OCaml's
|>
operator (justlet (|>) x f = f x
), this can be written:which IMO is more "naturally readable."
Other prior art includes:
(f >>> g) x = g (f x)
) about as often as "normal" composition in point-free code, but we don't really do point-free, so that's perhaps less immediately useful as a point in design-space.f(x, _, z)
-syntax with|>
seems kinda equivalent to-<>
(from swiss-arrows).&
, but I've literally only ever seen it used with van Laarhoven lenses), but I guess people are just fine reading point-free code right-to-left? The nesting is a bigger problem than the direction, IMO.This feels like it's probably a 100-line extension; possibly a "good first extension." Finding overly-nested code and refactoring it is possibly less of a good-first-issue thing, but like convenience aspects, I think we should be fine with saying "use it when you touch code that you think would benefit from it."