Hello … a small suggestion. I suggest that instead of calling Julia instances ‘objects’, that instead they be consistently called ‘instances’ in the documention. The explanation about how objects are different, and using both the ‘instance’ and ‘object’ terms mixed is a bit confusing. If the documentation project need helpers I would be happy to join and make this update, and people could review it and see what they think. Just give me a pointer there. It would be a great excuse for learning the documentation better.
Sounds reasonable to me. To help, go to the doc page in question (use the “latest”) and click “Edit on Github”.
Can you elaborate on what you find confusing? It seems fairly common in programming language books and other documentation to talk about about objects which are instances of types and therefore use both “object” and “instance” to talk about values in a language. Some languages distinguish objects—e.g. instances of
Integer in Java—from primitive values—e.g. instances of
int in Java—but in Julia these are not different kinds of things, so we use the terms “value”, “object” and “instance” interchangeably since there’s no meaningful distinction between these concepts in the language.
The primary confusion is that object and instance are used in the text as though different, when they are not in this context. Perhaps by different authors who are accustomed to different terminology.
‘value’ is the result of applying a representation to an instance. It might be said to be the contents of something, though we apply representations in the abstract also, e.g. “1 + 1” has the value of 2. 1 1 and 2 all being ascii symbols applied against an standard representation system. Anyway, not objects.
‘object’ is something sent as a message in OO systems. Not sure how that fits into multiple dispatch. Someone might expand on that.
‘instance’ is memory that has been bound to type. Type definition typically carries with it a system of representation, and thus through the representation component of type, one can get the value of an instance.
A bit of a wrap up here.
I’ve spent a bit more time with Julia and plan to use it for a project. I’ve used CLOS quite a bit, and I like its approach. I also found with CLOS that the composition pattern worked out better than inheritance, so I don’t miss inheritance. (Otherwise in CLOS there were problems writing methods to access only the parent type for doing parent type specific stuff. Composition avoids that. … Some of that discussion can probably be found in the common lisp forums.) This is all good. I like the basic approach adopted here with Julia.
Here I’m not talking about the basic approach just rather suggesting with the doc that what is being instantiated are instances, not objects. Sometimes the doc says this, sometimes it doesn’t - the mix is a bit confusing. You can find others also confused by this, for example, Inheritance in Julia, where kristoffer.carlsson observes “Julia is not really a OO language.”
Julia has instantiated types. Those instances are matched by their types against function calls at time of dispatch. Inheritance applies to interfaces, not to data, so the implementation is free to change the data format as long as the interface stays in tact. Hence, the data is nothing more than an instance of concrete type - which is a good thing.
So I was wondering what it would look like if the doc page on types was written explaining that one instantiated type to get instances, rather than one was building objects. I wrote something up and put it on github, https://github.com/JuliaLang/julia/pull/28484
There were places where it made a lot of sense, and some rough spots that needed improving. The pull request on that page, which surely needed revision, was closed while mentioning that the language of objects was common in Java and other languages - which is a bit quizzical given the approach in Julia is so different than the mentioned languages.
Anyway, there are the hooks in case anyone else wants to take a look, or have a hand it a revision.
Seems to me that … a person can find objects in Julia programs, but not in one place.
There is not a closed syntactical unit for declaring them, nor functions for manipulating them as such. One can manipulate type, one works with instances, but one never encapsulates the two as a unit. … so it would be correct to say one sends a print message to a point object, but that object is an abstraction not to be confused with the data instance.
Highly subjective but I
awked ‘doc/src’ for ‘objects’ and wouldn’t like most ‘objects’ to be replaced with ‘instances’. Difficult to argue, it’s just a feeling from looking at the terms.
The manual seems to consistently use ‘instance’ when it wants to focus that the object is coming from a type. Otherwise it uses object. This distinction would get lost. In addition, I’m lazy and don’t want the ‘mental overhead’ to translate the fact that an object is an instance from a type. It suffice that it is an object.
The term ‘object’ has evolve over the years. At this point it seems many people use it the way same way ‘data’ used to used. Programs are data. The program object … LOL seems to work. data -> abstract data type -> structured data -> objects ->data ; -) Also interesting how in C++ the class keyword became ‘type’ in the templates, and then type definition melded with class definition, such that using ‘new’ to create an object was the same syntax as one would use to create an instance in memory with malloc while bind type to the pointer. … Of course CLOS does it differently, and you don’t see functions bound with data in a class definition. … If you go through the type section in the doc there are some specious uses of ‘object’. And referring to instances of a given type as objects then begs questions when explaining dispatch. It brings to mind trying to add functions into a class through a different syntax. Pretty sure that is how most folks are reading it at first, judging from the discussions.
This may influence how you perceive the Julia manual. The committee that authored the Common Lisp Hyperspec carefully worked out definitions like
object n. 1. any Lisp datum. “The function cons creates an object which refers to two other objects.” 2. (immediately following the name of a type) an object which is of that type, used to emphasize that the object is not just a name for an object of that type but really an element of the type in cases where objects of that type (such as function or class) are commonly referred to by name. “The function symbol-function takes a function name and returns a function object.”
and similarly for instance. I suspect they had good reasons for trying to be so precise, mostly because the CLHS determines what is and isn’t a conforming implementation (for those who like reading such things, the error terminology is a real gem).
In contrast, Julia has a single implementation, which is evolving rapidly. Imposing a very strict terminology in the documentation may not be worth it at this point, if otherwise the meaning is clear from the context.
I brought up CLOS due to the dispatch approach. Julia’s type system does not carry all the features that CLOS does. In addition, at the time CLOS was proposed there was a competition for means for adding OO features to LISP, hence the proliferation of the terminology about objects was obligatory. Our understanding has also improved since that time.
The language of type relative to dispatch models at that time lacked expressiveness, and this is at the heart of what I am have been trying to explain here. So for all these reasons, perhaps quoting the hyperspec and pointing at the word ‘object’ is not entirely helpful.
Consider the concept of abstract type - type determined by the way that data is used. This is being called ‘duck typing’ more recently (i.e. if it quacks like a duck…). This concept of type is embodied by the interface to data. In the C++ style of object, the interface is given along with the data. It would be nice if things could be that simple, but interfaces often have an aggregation of types among their operands. In Julia you have a hierarchical manner for dealing with interfaces including via inheritance among ‘abstract types’ (here abstract meaning there isn’t a data implementation, not meaning that we are talking about Knuth’s abstract type).
Though there is a second concept of type, and that is that type describes data format. There is a sub-language in C to allow a programmers to describe data format. On the other hand, C gives us only primitive language features for abstract typing. There is not even a namespace construct.
Now Julia flips this over. It gives us language features for abstract typing, but only primitive features for dealing with data format hierarchy. Consequently we end up typing redundant field lines in concrete types.
I.e. interface code is inherited, that interface code is going to reference data in fields of the data instances it is given as arguments. Hence if I inherit a more general interface, then I will have to repeat the fields in my more specific data instances, or the interface won’t be able to find them. Furthermore, it falls upon me the programmer to do this. Take a simple field, say ‘id’, and an interface for objects that have this property, say id(x). Then in Julia every more specific type will have to have a repeated field called ‘id’. If I forget it, or if it gets modified later, say by another programmer, there will be a bug. This contract is not denoted anywhere, and must be maintained by convention.
In a language like C++ interface inheritance corresponds to data format inheritance, so it is not incumbent upon the programmer to duplicate field names to make inheritance work. However, it is also not possible to leave out a field that is not needed because a more specific interface had an alternative implementation that did not use data from said field.
But notice, we can not have had this nice conversation about the difference between abstract type, i.e. interface, inheritance and data format inheritance, if one calls everything an object. The above explanation in the difference between Juila style inheritance and C++ style inheritance would be out of reach, or at least much more cumbersome.
I suggest that having a more expressive and accurate terminology will facilitate the evolution of the Julia in a good direction, and will not as you suggest, hinder that. Though that is just my opinion.
The linked issue was closed, in my humble opinion with good reason (rational has been given multiple times).
Julia is different from CLOS and C++, what I knew as
methods before was not the same in Julia having generic functions and specialized methods. I had to read a bit. – I don’t think you can always break down things to one truth/single definition and slight variations for the ~same make the manual more lively. Regarding “Perhaps by different authors who are accustomed to different terminology.” I believe you are wrong, the authors knew very well what they were writing.
to put that quote in context, it was not suggesting that the authors did not know what they were doing, as you seem to be indicating it meant, but rather that they may have used different terms. Given the conversation thus far about values and objects and instances and objects, it seems reasonable to conclude one man’s instance is another mans object etc. Tamas_Papp pointed out above, that being imprecise might even be a good thing.
You shouldn’t: use composition instead of emulating inheritance.