#To `()`, or not to `()`?

1 messages ยท Page 1 of 1 (latest)

boreal zinc
#

That is the question:

// To:
value |> function_foo() |> function_bar()

// Or:
value |> function_foo |> function_bar

Me personally, to () because it's feel clearer by make it look more like a function call. It's also made it look more consistent with pipe to function with additional arguments:

value
|> foo()
|> bar(1, 2, 3)
|> baz()

// VS:

value
|> foo
|> bar(1, 2, 3)
|> baz

But stdlib and many other libs go with "not to ()"...

Gleam currently doesn't have any style guide about this, but I wish it does... But what do you think?

scarlet vigil
#

The recommended style is no brackets

brave belfry
#

I guess it's too late for the formatter to remove them

#

๐Ÿ˜„

#

Was that ever considered?

scarlet vigil
#

We would make the formatter remove them if possible

#

But depending on the types, it might not be possible to remove them

brave belfry
#

๐Ÿ‘

scarlet vigil
#

We have considered deprecating that syntax though

brave belfry
#

and enforce the parens?

#

I guess I like to be able to omit them, but I've learnt to appreciate consistency

scarlet vigil
#

Nope, deprecating the syntax with parens

brave belfry
#

but you said you can't always remove them if they are not needed, no?

scarlet vigil
#

Right. The formatter wouldn't be able to remove them, but we could still throw a warning

#

The formatter works on the untyped AST, meaning it doesn't have enough information to know if the parens are needed, but the type-checker would have access to that information

brave belfry
#

fair enough

green blade
weary owl
green blade
#

no special syntax for it, at least

#

like you can get the same effect with a second function definition but no support for automatically recognizing a function call without all the required arguments as a function itself

weary owl
green blade
#

yeah, that's essentially a special case of writing another function definition

#

it doesn't extend to the arbitrary case of providing/omitting any number of arguments, just the 1 specific marked one

#

i believe fn (x) { f(x, a) } and f(_, a) compile to the same thing

upbeat echo
#

No () ๐Ÿ‘

frozen hinge
#

Contrarian vote: yes ()

golden bridge
# frozen hinge Contrarian vote: yes `()`

Wasn't gonna say anything but for me () reads much better too, if I see a function without () I don't immediately get that a function is being called, looks more like a reference to a function being passed or something.
I guess because I'm used to js.

sly prawn
#

looks more like a reference to a function being passed or something.
yeah because it is

#
pipe(value, wibble)
golden bridge
# sly prawn ```js pipe(value, wibble) ```

I don't get it, I'm supposed to look at the pipe operator as a function call?
But that doesn't work with

|> bar(1, 2, 3)

does it?
I'm simple, I see pipe operator, I think "it puts value from the left in parens on the right"

feral canopy
#

I'd error on the side of no parens since the formatter would eventually perform that removal anyway and then you'd have a large diff.

scarlet vigil
#

What makes you say the formatter will eventually remove them?

scarlet vigil
#

But it isn't possible

feral canopy
#

oh ok.. but the inclination seems in that direction at least.

dusky birch
#

In my opinion, without parentheses seems more proper, because:

  • Without parentheses, you are referring to the functions as a first-class thing, that is understood, without having to do anything function specific like having parens there.
  • Parens make it seem like you are calling the function right then and there. But you are not, actually. The call happens when the pipeline is run, and then it will look different from what you see anyway, because the first argument will be inserted. So the "look of a call" is a "wrong" look anyway, because the real look will be with first argument inserted.
  • With the parentheses, it looks more like a syntax modifying macro thing, that "inserts" the argument by looking syntactically for the open, parenthesis and putting the argument there.
golden bridge
# dusky birch In my opinion, without parentheses seems more proper, because: * Without parent...

With the parentheses, it looks more like a syntax modifying macro thing, that "inserts" the argument by looking syntactically for the open, parenthesis and putting the argument there.
Yeah exactly, that's how it looks like in my brain when I'm looking at the code, so maybe that's why I prefer it ๐Ÿ˜…
I find that easiest to visualize, I don't know how else I'm supposed to think of it with the more-than-one argument case from above, and I'm not sure it matters much that it's not how it's actually implemented 'under the hood'?

upbeat echo
#

With () is more abiguous because there's two ways it could desugar

#

Without then you know what it does

golden bridge
#

The two ways would be wibble(wobble) and wibble()(wobble)?

scarlet vigil
#

Yep

frozen hinge
#

Does that not apply to all other arities as well?

#

wibble(1, 2, 3)(wobble)

feral canopy
#

Adding parenthesis would stay consistent with all the arities too:

x |> foo(1, 2) // => foo(x, 1, 2)
x |> foo(1) // => foo(x, 1)
x |> foo() // => foo(x)
upbeat echo
errant kite
#

Out of curiosity, why does Gleam have both versions of |>? It's a small thing, but it feels like one of the very few redundancies in the language.

upbeat echo
#

It improves ergonimics of pipes a lot

#

Previously we didn't have it and it was annoying