Open ghoomfrog opened 2 years ago
You could just do something like
type Foo[T] = object
x: T
proc newFoo(x: int): Foo[int] =
Foo[int](x: x)
var x = newFoo(99)
This seems to just be a workaround version of "Object constructors should infer the type". There is no reason one needs to specify default specialization if the following is valid.
type O[T] = object
x: T
var x = O(x: 99)
This seems to just be a workaround version of "Object constructors should infer the type". There is no reason one needs to specify default specialization if the following is valid.
This feature would still be useful to save some typing in the common case where the type parameter is the default type. Imo it's useful for the same reason default parameters for routines are useful: you avoid repeating the default parameter or having to define a new type alias. Another use case I can think of is if the type parameter isn't the type of a field directly, but rather determines some "strategy" to use (this would probably be a static generic in Nim).
Better type inference would certainly be nice regardless though.
Well I thought this was going to be a few sentences but I have written a bit more.
This feature would still be useful to save some typing in the common case where the type parameter is the default type
Is this really a common case? I've personally never had a generic that had a "default" generic parameter as it defeats the purpose of generics.
My main concern with any changes to what a generic base symbol is that it can ruin generic composite typeclasses which are a godsend when writing generic code.
Let's look at a simple example.
type MyObject[size: static int = 1] = object
when size == 1:
a: string
else:
a: float
proc doThing(myObj: MyObject) = discard
With an addition of a default generic parameter what would the MyObject
symbol mean. Would it still be generic typeclass? Would it be a case of having a default generic means that specialization is used, but if you have none it's a typeclass? Might it be the specialized MyObject[1]
? These have large side effects on other code
If it's the former then we just made it so we now need to do MyObject[1]
so we did nothing except make object constructors less readable by removing an non inferable specialization from the callsite. As all MyObject()
s would be MyObject[1]
except in type semantics so var a: MyObject
would not compile.
Changing the semantics of MyObject
to be dependent on whether MyObject
has any default parameters makes code much much harder for the programmer to reason about. Consider the following:
# module a.nim
type
MyObject*[T = int] = object
SomeOtherObject*[T] = object
# module b.nim
import a
proc doThing(myObj: SomeOtherObj) = discard # This covers all
proc doThing(myObj: MyObject) = discard # Only our specialized version comes here, we only know this if we read the `T = int`
# module c.nim
import b
doThing(SomeOtherObject[int]()) # Compiles
doThing(SomeOtherObject[float]()) # Compiles
doThing(MyObject()) # Compiles
doThing(MyObject[string]) # Does not compile
doThing(SomeOtherObject()) # Does not compile
# It's very unclear here why these fail to me.
With the final proposed case I have we've made it so type classes need to be written MyObject[auto]
which is more code, and given that it's very common(in my experience) to use composite type classes(consider ref or ptr or seq
for instance) we've made the more common use case more complicated (ref[auto] or ptr[auto] or seq[auto]
). With more complex generics this means array
for instance is now array[auto, auto]
making code more redundant.
This feature would still be useful to save some typing in the common case where the type parameter is the default type
Is this really a common case? I've personally never had a generic that had a "default" generic parameter as it defeats the purpose of generics.
I meant that the common case when using a type with a default generic parameter would be to not specify the parameter. In that case, it saves some typing. I didn't mean to imply that default generic parameters themselves are commonly needed. Why would it defeat the purpose of generics though? All it essentially is is sugar for typing out the default parameter.
With an addition of a default generic parameter what would the
MyObject
symbol mean. Would it still be generic typeclass? Would it be a case of having a default generic means that specialization is used, but if you have none it's a typeclass? Might it be the specializedMyObject[1]
? These have large side effects on other code
That is a good point, probably good enough to not accept this RFC. The only workaround I can think of would be requiring MyObject[]
for defaulting, but that would be pretty ugly and I don't like it.
Abstract
generic object type definitions should allow default generic types to be specified, so when instantiating, the generic type could be omitted
Motivation
laziness
Description
code intention could be unclear if you don't know the type's definition
Code Examples
this should work:
where the second line expands to:
Backwards Compatibility
No response