-
-
Notifications
You must be signed in to change notification settings - Fork 71
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
RFC: Overload-based binding syntax #87
Comments
Changes pushed to |
Released in 3.0.0. See the changelog for details. |
I think I found another (minor) drawback. When the
I created a temporary PR in my fork of Elmish.WPF to clearly demonstrate the issue. Among those three solutions, I prefer adding the type annotation. The main reason is that it is the most local solution (i.e. the scope of the additional code needed is as small as possible and no other code is adversely affected). If #F ever gets shorthand function accessors to record properties, then it might become possible to directly refer to the sufficiently qualified property accessor function, which is essentially what I am doing elsewhere in my example (such as for the
|
Thanks for the heads-up! F#'s overload resolution certainly isn't perfect. Personally I prefer opening modules in those situations. The module in question, at least the way I structure my code (and as shown in your PR), mostly contains stuff relevant for the bindings anyway (the If you don't want that, you could simply place the types ( |
If I remember correctly, here is my experience when opening submodules. Consider the I think that is worse than just adding type annotation in the first place. Are you able to avoid that situation when you open the submodules? |
I avoid that situation by only opening a single module with one module A
type Model
type Msg
let update
module B
type Model
type Msg
let update
module ABindings
open A
let bindings
module BBindings
open B
let bindings I have never needed to open modules for multiple models when creating bindings, because the bindings I have created have always been specific to one model. |
That said; sometimes type annotations are simply required with F#. The type inference has some quirks, particularly when combined with overloads. I haven't come across the problems you mention myself due to how I have structured my code. There may of course be valid use-cases that require another structure that brings about these type problems, but I don't know at the moment what use-cases those would be. |
Oh, fantastic! I had seen |
Yeah, you can pretty much open anything anywhere :) |
Another alternative is all unique function names (for example, in a one-to-one correspondence with the Here is the comparison I see with the current overload-based syntax. Drawbacks
Benefits
Roughly the same
Another idea that could be combined with the previous one is passing optional arguments with the same fluent-like syntax that Emlish uses with its I am willing to "argue" for this in future comments, but the main reason that I am writing this comment is to get this idea out of my head. |
Interestingly, that is one of the few posts of Mark's that I don't agree with. I don't find the syntax compelling, nor particularly discoverable without qualifying the union type name. Also it's more verbose than overloaded static methods. (Since it's an early F# blog post of his, I am curious if he still holds the same view. I can't recall seeing that syntax much in later blog posts.)
Certainly an option, though many bindings would require several parameters immediately (on the first call) anyway, and there are several ways you could specify them ( In general, I find that the current overloaded syntax, while not perfect, is the most pleasant and concise I variant I have considered/tried. I do appreciate that you're writing this down! It's always nice to have more pros and cons. But just to go on record and be clear (to anyone who might read this), an alternative syntax would have to be pretty elegant, concise, and generally dev-friendly in order for me to consider another breaking change in the binding API. |
This doesn't seem as bad to me now. The compiler branches in order to determine the function/method to call. When overloading, the branching happens implicitly based on the types of the arguments. When using DUs as described by Mark, the bracing happens explicitly in a match of the DU instance. Overloaded methods don't have (meaningful) differentiating identifiers (since the branching is implicit), and we could closely preserve this by having the DU case names be as short as possible. For example, they could be With such short case names, I don't think the two disadvantage above are that bad. If there are always less than ten cases, then this only requires adding four additional charters. It would look something like Binding.oneWay(f) changing to Binding.oneWay(C1(f)) |
Currently there's quite a bit of friction in implementing alternative/simpler versions of existing bindings, because it requires new functions with unique names. This can quickly lead to a mess of functions and confuse users (and get unnecessarily verbose).
For example, based in the changes described in #86, there's
subModel
,subModelOpt
, andsubModelOptSticky
. These functions have also become more complex (in order to become more powerful/general), and it might be nice to have simpler variants of them. But I don't want to have 6 or 12 differentsubModel
bindings just for convenience. So if we stick with functions, I'm not that likely to add many such conveniences.An alternative is an overload-based syntax, in the form of static methods on a
Binding
class. To keep the syntax as similar as possible to the existing one, I can imagine all the overloads returnstring -> Binding<_,_>
. That way one could do something like this (not an exhaustive list, but also includes several combinations not currently supported):The drawbacks I see are:
The benefits I see are:
uiTrigger
, and won't pollute the function list like nowPersonally I like this, but I'd like to hear what others think before delving into this. Even just a positive reaction emoji is helpful to let me know that you agree. (If you disagree, please explain in a comment! :) )
The text was updated successfully, but these errors were encountered: