-
Notifications
You must be signed in to change notification settings - Fork 143
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
[style-guide] Extra space in fluent code #648
Comments
@dsyme These lowercase method names look very non-idiomatic to me. The current approach is to add space for lowercase-starting names, since it's the style normally used for curried functions, and not to add space before uppercase-starting names that normally are references to methods. Unfortunately, there's no way to distinguish functions and method invocations based on syntax, and I think it's a very sensible approach with these constraints. |
This is a tricky one. We currently have some settings to control whether there should be a space or not. So using the default settings, if the function names are uppercase they don't have the space. If we were to change the current behaviour, it would require input from the style guide as the next person will lovely open an issue that there has been a regression. It might be a good idea to put out some rules when to have a space and when not. For example, in this case, does the lambda remove the need for a space? |
I understand this perspective. That said, in the context of projects like DiffSharp and TorchSharp, lower case fluent is becoming more common (for good reasons - they are mimicking a Python API and it's the right choice in balance). FSharp.Core.Fluent also allows this naming though that's a slightly separate matter.
I would imagine the rule would be "a chain of fluent of length two or more means no space on application throughout" so I notice that in the default settings for uppercase the presence of parens in the original source is also relevant I guess chained lower case application (not just There's no rush with this, I just noticed it when experimenting with fluent notations.
I get that. The problem is they look really idomatic once you're in the F# world of DiffSharp and TorchSharp (or if coming fresh from Python, Javascript or Scala). And then you come back to .NET-focused programming and think about doing it. Leaky I know. |
Wouldn't it be better to have idiomatic .NET/F# wrappers for these libraries instead of trying to apply a not very compatible Python code style to F#, a different and a mature language, only making experience of using F# inconsistent (thus, harder to learn)? |
Well, no parenthesis leaves us with no other options than having the space anyway right? xs.Prop.Map b // xs.Prop.Mapb is no longer a function call
xs.Prop.Map(b) or are you referring to something else?
That could work out although we should probably come up with sufficient examples as the scope will be larger than that. xs.[x].whack (a) // space or not?
// what happens with long constructs?
xs
.whack( //
a)
.mole(
// long expression
b) The current support now isn't always perfect, check out DotIndexedGetTests.fs and DotIndexedGetTests.fs. |
Sorry to chime in, but I still don't get why the style guide (and hence, the fantomas defaults) recommends different spacing depending if the function is lowercase or not. (Disclaimer: I'm myself not a fan either of the decision of having F# conventions use lowercase for functions, given that it goes against .NET API style guidelines; and yes I know about the attribute that you can use to decorate your functions to become accessible with an uppercase...) I think the whole thing is very confusing, especially to newcomers (I will not put a "IMHO" here because my opinion is not that humble, I've mentored most of the developers of my company to learn F# so I know a thing or two about that). |
@knocte Historically, the space is usually added for curried F# functions applications, like in The problem is functions and methods applications share the same syntax, and you can't use a single formatting rule for these two different styles without making half of the cases look bad. The current formatting rule was the best heuristic proposed for the problem: normally, functions are lowercase and methods are uppercase (and are not curried), so it works OK in the most of the cases for both functions and methods. The only cases where formatter produces unexpected results are when naming conventions are violated, like here with the lowercase methods. |
From the perspective of an F# developer, the only difference between In fact, the best case in point is when using one only argument: as there is no tuple and no currification, then what should be used here, uppercase or lowercase? The standard/convention would just be much less confusing if an space was added always regardless if it's uppercase or lowercase. |
Sorry for being silent here, I guess I don't really have a good response for this remark. This is a historical thing I guess.
Yes, for newcomers this would be a lot less confusing. But a lot of people will find |
It never felt alienating to me, that's why I enable all fantomas' space_before settings in my repos. But the reason might be that I'm biased because in my first .NET years when coding in C# I contributed to many repositories in the Mono ecosystem, and most of them shared some coding guidelines that advocated for adding a space to every invocation: https://www.mono-project.com/community/contributing/coding-guidelines/
Let's imagine we opened an issue and after some debate we agreed to change the standard to make it less confusing for newcomers (making the change in the style guide and so fantomas defaulting fsharp_space_before_uppercase_invocation to true), despite the alienating feeling expressed above: we would have solved only one piece of the cake, because then we would still have the inconsistency that fantomas could not add a space when doing fluent calls (and then we would still see the strangeness raised in this bug filed by Don). So I just realised that, despite my dislike of it, the best thing to do here is actually do the opposite: remove the space when it's not needed. And bringing up Therefore, the idea would be the following (let's see if I don't miss any of the possible cases):
If the coding style recommended the above style, there would be consistency across uppercase/lowercase invocations and across fluent calls (so, we could just make fantomas default to this, and converge the settings fsharp_space_before_uppercase_invocation and fsharp_space_before_lowercase_invocation into just a single one If it sounds too good to be true, let me know what did I miss, but if not, I can raise this in the style guideline as an issue or a PR. |
And when I wrote this I fell into my own trap, because then the last case above that I described as most convoluted case, wouldn't be able to be used in a fluent call: |
I'd say it is subjective (like my feedback), I think the idea of F# being it's own, in terms of feel of the language, irrespective of being firstly a dotnet language, doesn't make the style incompatible/not very compatible to me. At some points, those conventions, that were set in framework design guidelines, they pertain to a very OO centric approach, with few distinctions, to make it look like "not a 1 to 1 of java", and I don't feel enforcing those same guidelines, in essence, is what is going to foster the ecosystem the most, for adoption, versus other concerns in the grand scheme. |
Getting back to the OP, I will make a proposal to the style guide:
I think this is consistent - we either remove all the spaces (for N > 2) or none. The current situation of removing all but one of the spaces is just odd. |
In Fabulous v2 we have a new DSL a la SwiftUI . the existing way causing some formatting issues . We added
to out .editorconfig to make it more consistent (HStack(16.) {
Label("New address")
.textColor(Colors.StandardTextColor.Light, Colors.StandardTextColor.Dark)
.alignStartHorizontal(true)
.verticalTextAlignment(TextAlignment.Center)
TextButton(AppResources.Cancel, CancelManualAddress, true)
.alignEndHorizontal()
}).gridRow(0) |
I notice that a sequence of fluent applications is getting an extra space in the last application, so for
we get
Note the space after the "filter".
I understand why this is happening, and that in some sense it's the consistent application of rules. However I think I'd expect
That is, two or more fluent applications all get no space. A single application would still get a space, per the usual rules, e.g.
gets
That said, it's a tricky business and stems from the fact that consecuitive fluent notation is only supported in F# by omitting spaces that are otherwise natural.
Issue created from fantomas-online
Code
Result
Problem description
Please describe here the Fantomas problem you encountered.
Check out our Contribution Guidelines.
Extra information
Options
Fantomas 4.6 branch at 10/05/2021 16:21:15 - 835872c91bf490f6aeffb1efc77f2b47f517aec0
Default Fantomas configuration
Did you know that you can ignore files when formatting from fantomas-tool or the FAKE targets by using a .fantomasignore file?
The text was updated successfully, but these errors were encountered: