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

Augmenting Composite Types and Default Type Data #1672

Closed
aschmahmann opened this issue Dec 4, 2012 · 5 comments
Closed

Augmenting Composite Types and Default Type Data #1672

aschmahmann opened this issue Dec 4, 2012 · 5 comments

Comments

@aschmahmann
Copy link

Suppose you have a type

type SomeIntegers
    field1::Int
    field2::Int
end

and then you decided that you wanted to change the type by doing the following:

SomeIntegers.types = tuple(SomeIntegers.types...,Int)
SomeIntegers.names= tuple(SomeIntegers.names...,:field3)

Then it is possible to both create new SomeIntegers and augment existing SomeIntegers as follows:

threeInts = SomeIntegers(1,2)
threeInts.field3 = 3

However, the below gives a segmentation fault

type SomeStrings
    field1::String
    field2::String
end

SomeStrings.names= tuple(SomeStrings.names...,:field3)
SomeStrings.types = tuple(SomeStrings.types...,String)

threeStrings = SomeStrings("1","2") #Segmentation Fault

This is likely due to the fact that Int gets some sort of irrelevant default data, whereas String does not. As a result, this error also occurs with many other types (for example a custom Composite Type that only contains an Int).

Some interesting things to notice:

  • On the Windows version you can do this exactly once before Julia core dumps (however, when I augment Function I can sometimes squeeze out one more execution before Julia crashes)
  • When it does work it has the new String default to (Any...,) which is pretty surprising given that (Any...,) is not of type String
  • If you switch the order of the augmentations to names then types instead of types then names the behavior changes slightly (I'm having trouble reproducing this). This leads leads me to believe that maybe these should be stored in a dictionary or tuples of (name,type) instead of in two separate fields.
@pao
Copy link
Member

pao commented Dec 4, 2012

You shouldn't be able to redefine the fields of the CompositeKind, but since composite types don't have immutability yet there's no way to enforce it. I'm pretty sure this is a "doctor, it hurts when I do this" problem. Don't do that.

Dupe of #708. See #13.

@pao pao closed this as completed Dec 4, 2012
@aschmahmann
Copy link
Author

I definitely understand not being allowed to change types at run-time (some languages like Python with reflection allow it, while others such as the .NET family do not). However, because Julia does not allow creating subtypes of concrete types this makes it either impossible or messy to use existing typed code but have your objects carry around additional tagging information. While composition can be a good alternative it would be nice if there was something like an interface so that all of the functions that need to be implemented to properly subtype, for example, String were all listed in one place. Without interfaces, subtyping seems pretty difficult to get right since there could always be some function you were supposed to implement that you forgot about.

Additionally, if the Function type is not going to be augmentable then maybe it should be an AbstractKind with a CompositeKind implementation so that there can be other types of Functions.

@JeffBezanson
Copy link
Member

Interfaces are fine but have absolutely nothing to do with mutating types.

@JeffBezanson
Copy link
Member

Occasionally there has been talk about allowing overloading () so you could have other function-like things. I'm not sure whether it will happen, but never say never.

The key thing is, even if there were other kinds of functions, there still must be some underlying mechanism that involves passing arguments to some piece of code, and that's what Function is. If you could overload apply so that x(y) called some method of x, that would just be an extra lookup step followed by invoking an ActualFunction. Then one might want new kinds of ActualFunction, at which point you would have ActualActualFunction, and so on...

@JeffBezanson
Copy link
Member

Also, in all such things it is typically very helpful to talk at the level of what one wants to accomplish, rather than mechanism detail like whether Function can be subtyped. For example, why isn't passing a closure appropriate, etc.

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