You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Essentially the idea comes from Rust support of the default values for generic arguments like here. pub struct Vec<T, A = Global> where A: Allocator...
The reason to use such approach is to avoid situations when certain object behavior depends on parameters passed to its constructor. That's leverage object composition to deliver functionality also achievable with extra generic parameter for a type restricted by certain trait(s) (aka interface with static abstract methods/properties)
Like in .net we could create Dictionary<string, int> with different equality comparers: StringComparer.Ordinal vs StringComparer.OrdinalIgnoreCase. In terms of type equality both instances are equal, but their behavior is not. Adding one dictionary data to another could produce different result depending on which one is target.
Things get more complicated when we start working with functional approach and make our types immutable. For a functional composition to work we expect the behavior is controlled by generic parameters and types like HashMap have several of those important behaviors:
The IEq is just a static interface (trait) equivalent to IEqualityComparer but allows to execute code on static type specified as generic argument of closed type. No instance and no allocation required. THsh is custom hash algorithm providers like Fowler–Noll–Vo. All such behaviors are pure functional there for no issues for threading there too.
Creating such a type in the functional frameworks (like few monad oriented ones) fully relies upon type inference and pipelining. Parameters are seamlessly pass for one functor to another. However having regular developers on board is also important. Whose people need default implementation for most of traits, there for right now duplicate types with those parameters specified with defaults are created. Eventually those two types start to drift apart as changes sometime are forgotten to be placed in both types. This is a nightmare for maintainers.😟
Does it make sense to design default generic arguments values to deal with such cases? Or perhaps object composition is a better way to go?
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Essentially the idea comes from Rust support of the default values for generic arguments like here.
pub struct Vec<T, A = Global> where A: Allocator...
The reason to use such approach is to avoid situations when certain object behavior depends on parameters passed to its constructor. That's leverage object composition to deliver functionality also achievable with extra generic parameter for a type restricted by certain trait(s) (aka interface with static abstract methods/properties)
Like in .net we could create Dictionary<string, int> with different equality comparers: StringComparer.Ordinal vs StringComparer.OrdinalIgnoreCase. In terms of type equality both instances are equal, but their behavior is not. Adding one dictionary data to another could produce different result depending on which one is target.
Things get more complicated when we start working with functional approach and make our types immutable. For a functional composition to work we expect the behavior is controlled by generic parameters and types like HashMap have several of those important behaviors:
The IEq is just a static interface (trait) equivalent to IEqualityComparer but allows to execute code on static type specified as generic argument of closed type. No instance and no allocation required. THsh is custom hash algorithm providers like Fowler–Noll–Vo. All such behaviors are pure functional there for no issues for threading there too.
Creating such a type in the functional frameworks (like few monad oriented ones) fully relies upon type inference and pipelining. Parameters are seamlessly pass for one functor to another. However having regular developers on board is also important. Whose people need default implementation for most of traits, there for right now duplicate types with those parameters specified with defaults are created. Eventually those two types start to drift apart as changes sometime are forgotten to be placed in both types. This is a nightmare for maintainers.😟
Does it make sense to design default generic arguments values to deal with such cases? Or perhaps object composition is a better way to go?
Beta Was this translation helpful? Give feedback.
All reactions