Skip to content
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

More dangling functions #660

Closed
Niols opened this issue Dec 1, 2023 · 3 comments · Fixed by #724
Closed

More dangling functions #660

Niols opened this issue Dec 1, 2023 · 3 comments · Fixed by #724
Labels

Comments

@Niols
Copy link
Member

Niols commented Dec 1, 2023

Is your feature request related to a problem? Please describe.

Topiary's default OCaml formatting is very aerated (especially in multi-line mode), which I enjoy quite a lot. However, sometimes, I find it too aerated and I wished some things stayed on the same line. This is for instance the case with functions (fun x -> and function). I feel we could often opt for a slightly more compact style by making functions dangle at the end of the previous line. We currently do that specifically in the case of let . = fun . -> (and function) but I would maybe like to see that in other situations.

Describe the solution you'd like

Here are few examples of how I would format things and how Topiary actually formats them right now. I am not necessarily super attached to all of those, the goal is more to start a conversation on this.

A.

My inputTopiary's output
let foo x = fun y ->
  zzzzzzzzzz
let foo x = fun y ->
    zzzzzzzzzz

This is the case that Topiary already handles, although I would prefer it with only one indentation level.

B.

My inputTopiary's output
let () =
  foo @@ fun y ->
    zzzzzzzzzz

or maybe:

let () =
  foo
    @@ fun y ->
      zzzzzzzzzz
let () =
  foo @@
    fun y ->
      zzzzzzzzzz

I would use the first one. My current editor gives no indentation level then, but I can see how we would prefer one, even if chaining such operators would then give a funny look:

foo @@ fun x ->
  bar @@ fun y ->
    baz @@ fun z ->
      vvvvvvvv

Not that bad, actually. Still, This would be somewhat more compact than Topiary's output and would lead to less indentation levels. Where to put the @@ operators is somewhat covered in #657. No matter where it goes, I think I'd prefer having fun . -> dangle onto it.

C.

My inputTopiary's output
let () =
  foo >>= fun y ->
    zzzzzzzzzz
let () =
  foo
  >>= fun y ->
    zzzzzzzzzz

This is actually not a bad output. I think we probably want to add indentation to this operator, but I'm not sure. Again, positioning of the >>= operator is covered in #657. I am not sure I understand why the output is like this; is it because the operator ends with an =?

D.

My inputTopiary's output
let () =
  foo x
    (fun y ->
       zzzzzzzzzz)

or

let () =
  foo x (fun y ->
    zzzzzzzzzz
  )
let () =
  foo
    x
    (
      fun y ->
        zzzzzzzzzz
    )

This is probably the one that annoys me the most. I see where it comes from, and it sometimes makes sense when the lambda is a very big function, but I feel that most of the time this is too much. I would say that the style

(fun y ->
   zzzzzzzzzz)

is more common but I suppose it doesn't fit so well in our aerated style and it also behaves a bit less well with Git diffs, so maybe

(fun y ->
   zzzzzzzzzz
)

is better? I have similar considerations about function but this issue is getting big so maybe in another comment.

Describe alternatives you've considered

The current style is not bad, frankly, and I use it in a fair amount of projects. For some projects of mine, though, I have tried adding it, and really struggled with the result, especially for B. and D. Maybe I will share a snippet of an actual piece of code that I am not happy with.

Additional context

Related to #657
Related to an incoming issue on dangling tuples/lists/arrays.
I know we have discussed similar things at various points, but I am not sure where. Maybe we should link those here.

@Niols
Copy link
Member Author

Niols commented Dec 1, 2023

A.

My inputTopiary's output
let foo x = function
  | y -> zzzzzzzzzz
  | u -> vvvvvvvv
let foo x = function
  | y -> zzzzzzzzzz
  | u -> vvvvvvvv

B.

My inputTopiary's output
let () =
  foo x @@ function
    | y -> zzzzzzzzzz
    | u -> vvvvvvvv

or

let () =
  foo x
    @@ function
      | y -> zzzzzzzzzz
      | u -> vvvvvvvv
let () =
  foo x @@
    function
    | y -> zzzzzzzzzz
    | u -> vvvvvvvv

Not bad, actually, could keep that, although I'd prefer my first snippet.

C.

My inputTopiary's output
let () =
  foo x >>= function
    | y -> zzzzzzzzzz
    | u -> vvvvvvvv

or

let () =
  foo x
    >>= function
      | y -> zzzzzzzzzz
      | u -> vvvvvvvv
let () =
  foo x
  >>= function
  | y -> zzzzzzzzzz
  | u -> vvvvvvvv

Also not bad. Would want some indentation of the cases at least, probably.

D.

My inputTopiary's output
let () =
  foo x
    (function
      | y -> zzzzzzzzzz
      | u -> vvvvvvvvv)

or

let () =
  foo x (function
    | y -> zzzzzzzzzz
    | u -> vvvvvvvvv
  )
let () =
  foo
    x
    (
      function
      | y -> zzzzzzzzzz
      | u -> vvvvvvvvv
    )

@Niols
Copy link
Member Author

Niols commented Dec 1, 2023

@aspiwack You might have an opinion on those things. The tree sitter grammar maintainer might also have one.

@Niols Niols added the language: ocaml OCaml formatting issues label Dec 1, 2023
@Niols
Copy link
Member Author

Niols commented Mar 4, 2024

I realised today that Ormolu lets you chose whether to dangle a do: it will leave unchanged the two following pieces of code:

f = do
  do_something
f =
  do 
    do_something

Maybe that's a way to go?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant