-
Notifications
You must be signed in to change notification settings - Fork 23
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
Allow overloading on type name #14
Comments
IMHO we shouldn't do this, but I'm leaving it open so people can discuss. |
If this were to be added, I'd prefer it to be like destructors: proc create(): Foo =
return Foo(a: 213)
... For consistency reasons. |
~~One name has several different meanings. What could go possibly wrong?~~~ Edit: changed opinion. Added a comment down bellow. |
@kirbyfan64 Nim has a long tradition of using overloading, so it would be consistent. I wouldn't mind the @PavelVozenilek Of course the programmer should exercise discretion when using it, but Nim already provides a thousand different ways to shoot yourself in the foot, what's one more? 😉 |
@kirbyfan64 isn't this just a regular function as we already have? |
@superfunc No; It'd work like destructors do. With destructors, Nim automatically invokes the Basically, |
That makes sense, my bad |
I think there's use case for this. Say I define a type and want to limited functionality on it, via templates
Here I need to use helper name
|
Related: http://forum.nim-lang.org/t/703 |
I would like to see this feature added as it provides consistency between the construction of built-in types and user-defined types. Also it improves readability of the code when objects are constructed as arguments for function calls. |
There is no inconsistency right now, the compiler treats every type the same. |
Sure, but if I need to create a special constructor for a user-defined type it has to be named differently whereas constructors for built-in types are named the same as the type. If you were to add another constructor for a built-in type would you also name it the same as the type or differently? |
I think you're misunderstanding what
One cannot name it the same. |
I am referring to constructors of the form:
I would like to be able to create other constructors for object types and it would be convenient and, at least to me, consistent to also name them the same.
Right, currently not, but if you could would you? If not what convention would you use and why should the other constructors be named differently given that overloading is used for other functions? If you/others are interested in having support for this overloading do you have some idea of how much effort it would take to implement it? |
@Henry Those aren't constructors, at least, not in the usual sense. It's merely syntactic sugar for simple object initialization. I don't see how the syntax differs between user types and built-in types. |
OK, sure, they do not create a location or allocate storage, they are basically initializers. So how do a create a set of object initializers which have the same name as the object type or provide the syntactic sugar so that they appear so? Basically how do I write types so that they look and behave like built-in types but with additional initializers? This is the consistency I was referring to. |
I still don't see what you mean by "like built-in types". Built-in types like integers are assigned to directly, while sequences and strings are created using regular procedures, like |
Take the example
This is a user-defined object type initialized using the default/builtin initializer. Now imagine Student could be created/initialized in other ways than simply providing all the elements as arguments:
OK this is a trivial example but in the applications I would like to translate from C++ to Nim there are lots of complex classes which can be constructed/initialized is many ways and in practice it is convenient if these functions name the same as the class (standard C++ constructor naming) particularly when constructing a temporary instance as an argument to a function e.g.:
|
The convention for constructors is to define a new proc named |
I understand, in which case shouldn't we use:
Why is the name of the type used for built-in initializers and initType for user-defined initializers? Wouldn't it be better to overload the type name? Do you prefer
or
|
Can we consider type definition as automatically defining magic function(s) with the same name constructing object from field values? : type Foo = tuple a,b: int
# defines the magic function
proc Foo(a,b: int): Foo
type Bar = object case kind: bool of
true: n: int
false: b: bool
# defines the magic functions
proc Bar( kind:static[true], n: int): Bar
proc Bar( kind:static[false], b: bool): Bar and user can provide other overloads of Foo/Bar and even overwrite these default definitions with his own ones (or just discard them). Also, my arguments for using Foo/Bar as object constructors: https://github.com/nim-lang/Nim/issues/7474#issuecomment-405100389 |
That's already the case... Bar(kind: true, n: 42) https://nim-lang.org/docs/manual.html#types-object-construction |
Well, my point - can we just add these auto-generated definitions to the procedures list and then allow user to provide other procedures with the same name but different parameters? What is the catch - is it hard to implement or it doesn't look useful? And yeah, currently object constructor require field names. For Algebraic datatypes similar to Haskell it will be great to allow using these constructors without field names. Similarly, it will be great to allow to use field names in tuple constructor. I.e. in both cases generate a procedure with the same name as type and parameter names equal to the field names, and allow to overload this procedure. |
The comments here don't really indicate a consensus, but I'm guessing it's likely this will not be done? Do we need to revitalize discussion or is this safe to be rejected? |
There are ideas about adding constructors via a type bound |
I think the other RFCs about initialization cover enough about initialization, this RFC seems to specifically be about being able to giving routines type names. Another similar proposal might be like being able to define a call operator on typenames, not specifically related to custom initializers but related to the semantics of how custom initializers could be done. |
I don't like this RFC (overloading on type), it creates ambiguities: type Foo = object
x: int
proc Foo(x = 1): Foo = Foo(x: x)
echo Foo().x # 0 or 1?
echo Foo is proc # true or false?
Foo.bar # can MCS happen ? (ie: Foo().bar) the following already works today, works in generic code, is explicit and has 0 ambiguities: type Foo = object
x: int
type Bar1 = object
y: int
type Bar2[T] = object
y: T
type Baz = object
x: int
type Goo[T] = object
x: T
proc init(T: typedesc[Foo], x = 123): T = T(x: x)
proc init(T: typedesc[Bar1 | Bar2], y = 123): T = T(y: y)
proc init[U](T: typedesc[seq[U]], n = 0, cap = 0): T =
if cap == 0: result = newSeq[U](n)
else: (result = newSeqOfCap[U](cap); if n > 0: result.setLen(n))
proc init[U](T: typedesc[Goo], x: U): Goo[U] = Goo[U](x: x)
echo Foo.init()
echo Foo.init(x=2)
echo Foo.init(2)
echo Bar1.init(2)
echo Bar2[int].init(2)
echo seq[int].init(2)
echo seq[int].init()
echo seq[float].init(cap = 3)
echo Goo.init("abc") # infers Goo[string]
doAssert not compiles(Baz.init(2)) IMO these are better than the case of default constructors (ie, IMO we should close this RFC related
|
It's impossible to overload on a type name, ex.
Ideally, this would be possible and possibly even unified with the type construction syntax.
The text was updated successfully, but these errors were encountered: