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

Collapse member val to member #1062

Closed
5 tasks done
texastoland opened this issue Aug 16, 2021 · 7 comments
Closed
5 tasks done

Collapse member val to member #1062

texastoland opened this issue Aug 16, 2021 · 7 comments

Comments

@texastoland
Copy link

texastoland commented Aug 16, 2021

Collapse member val to member and abstract method to abstract

Copied from #523 (comment) (closed discussion: more consistent and more simple syntax).

I propose the compiler parse member in place of member val in property shorthand declaration.

Likewise abstract in place of abstract method in virtual method declaration.

The existing way of approaching this problem in F# is ...

                  let   privateField             = expr
                  let   privateMethod       arg  = expr
                  val   uninitializedField
abstract                VirtualProperty                 with get, set
abstract member         VirtualMethod      (arg)
         member   val   ImplicitProperty         = expr with get, set
         member       _.ReadOnlyProperty         = expr
         member       _.ExplicitProperty                with get      () = expr
                                                        and       set v  = expr
         member       _.SealedMethod       (arg) = expr

I'm currently reading through the Language Reference (which is missing a couple things noted in my linked comment) and particularly struggled to gain an intuition about member syntax. I arrived at:

  • let is effectively private.
  • val is an uninitialized field (except for member val).
  • abstract (+ member for methods) is virtual.
  • member (+ val for property shorthand) is sealed (except for abstract member).
  • default and override follow the same pattern as ExplicitProperty and SealedMethod.
  • static can prefix any non-virtual declaration.

The only confusing cases were member val and abstract member. If accepted my columns would collapse into a single keyword per concept and be useful in documentation:

let        privateField             = expr
let        privateMethod       arg  = expr
val        uninitializedField
abstract   VirtualProperty                 with get, set
abstract   VirtualMethod      (arg)
member     ImplicitProperty         = expr with get, set
member   _.ReadOnlyProperty         = expr
member   _.ExplicitProperty                with get      () = expr
                                           and       set v  = expr
member   _.SealedMethod       (arg) = expr

Pardon me if this should've been posted in another forum 🙏🏼

Pros and Cons

The advantages of making this adjustment to F# are ...

  • Easier to learn and remember.

The disadvantages of making this adjustment to F# are ...

  • Yet another way of doing the same thing.
  • Some unforseen potential parsing ambiguity.

Extra information

Estimated cost (XS, S, M, L, XL, XXL): S

Related suggestions: None

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this

For Readers

If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.

@dsyme
Copy link
Collaborator

dsyme commented Aug 16, 2021

Just to mention you can already just use just abstract (I've added strikethrough removing these parts from the suggestion, I assume that corresponds with an appropriate adjustment)

type IA =
    abstract X: int -> int

The main problem with member P = expr is there is no indication that expr is evaluated eagerly during object construction. The val acts as an indication of that.

@texastoland texastoland changed the title Collapse member val to member and abstract method to abstract Collapse member val to member Aug 16, 2021
@texastoland
Copy link
Author

texastoland commented Aug 16, 2021

Just to mention you can already just use just abstract

Brilliant! I didn't consider just trying it out. That's 1 more I could update in the Language Reference. Should I make an issue in https://github.com/dotnet/docs first or just PR?

The main problem with member P = expr is there is no indication that expr is evaluated eagerly during object construction.

As a new F# learner (from other MLs) ...
I expected member P = expr with get to be eager because it looks similar to a let binding.
member val actually confused me because it isn't uninitialized nor related to ML signatures.
I have to remind myself that member _.P = expr isn't only deferred but also not memoized.
I find member _.P with get () = expr explicit about being a function.

@dsyme
Copy link
Collaborator

dsyme commented Aug 16, 2021

Brilliant! I didn't consider just trying it out. That's 1 more I could update in the Language Reference. Should I make an issue in https://github.com/dotnet/docs first or just PR?

Just PR please :)

As a new F# learner (from other MLs) ...

Yup, understood.

@charlesroddie
Copy link

The main problem with member P = expr is there is no indication that expr is evaluated eagerly during object construction. The val acts as an indication of that.

In other words, member X = would be expected to be equivalent to member _.X = not member val X =, and this is the suggestion in #626 .

@texastoland
Copy link
Author

texastoland commented Aug 17, 2021

Oh I see your point. If I only include read-only properties from my table:

abstract     VirtualProperty         with get           // not defined yet
member val   ImplicitProperty = expr with get           // explicitly eager
member       ImplicitProperty = expr with get           // implicitly eager (proposed)
member     _.ReadOnlyProperty = expr                    // implicitly deferred
member     _.ExplicitProperty        with get () = expr // explicitly deferred

Then without the self identifier ImplicitProperty wouldn't be visually distinct from ReadOnlyProperty. I agree but as another new learner via Fable I echo the sentiment from #626 (comment):

And for me having this implicitly bound is much harder to read and reason about.

The self identifier (unlike the member keyword which could be substituted for override or default) clearly communicates there is another value in scope (that can be explicitly ignored). Like Python but prettier.

The main problem with member P = expr is there is no indication that expr is evaluated eagerly during object construction.

In retrospect the lack of a self identifier or function arguments is what led me to expect property shorthand to be eager. Now I see the logic behind val but I initially googled whether I misunderstood the keyword in F#. The presence of the self identifier in the read-only shorthand is my mnemonic for remembering that it's deferred.

The val acts as an indication of that.

I agree my proposal is mutually exclusive with #626. If this is ultimately rejected I think I should try to help communicate the val-ness of property shorthand in the Language Reference. I appreciate such an open and thoughtful language designer and community!

@dsyme
Copy link
Collaborator

dsyme commented Aug 17, 2021

Another good thing we can do is proper hover-tips over all keywords in typical IDEs

@dsyme
Copy link
Collaborator

dsyme commented Jun 14, 2022

The member val --> member collapse falls under the category of "already decided in earlier versions of F#" and won't be progressed, thanks

@dsyme dsyme closed this as completed Jun 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants