Over time, this keyword has increasingly bothered me. There are several problems:
type
is a very generic word and I'd just as soon leave it available for variable names (and keyword arguments!)type
to refer only to concrete, mutable, struct-like types.type
is the most obvious type-defining keyword, but usually immutable
is preferable and recommended.Here are some alternate keyword suggestions:
mutable
-- opposite of immutable
!struct
-- at least says something about what sort of type it isreftype
-- for "reference type", which also conveys some of its key propertiesMaking the word type
usable in other contexts would be great.
I do like mutable
for consistency.
If this is done, it should be done ASAP so that it can be included in 0.6
If this is going to happen, than use what everybody recognizes before thinking: struct
I also think type
is a bit awkward. When I explain it to other people I usually say "like a struct" so +1 for that.
If this is going to happen, than use what everybody recognizes before thinking:
struct
I thought immutable
was like a struct?
+1 for mutable
immutable
has the memory layout of a C struct
type
has the mutability of a C struct
Thus struct is related to both. I think mutable
instead of struct
is better to clarify this.
Any variable is mutable. Assigning that label to a universally recognized name (a struct
) seams all but clear for me.
For someone coming from Fortran the keyword type
is already natural.
For someone coming from C the keyword struct
would be natural.
For someone using immutable
a lot, the opposite keyword mutable
would be natural.
So maybe we should leave it as is.
struct{mutable}
struct{immutable}
or
record{mutable}
record{immutable}
if a more descriptive form is desired.
If we use struct
then the syntax for immutables can be immutable struct
(with the struct
part being optional at least initially).
I suspect Fortran programmers are familiar with the term "struct".
+1 for mutable
because of consistency. If struct
were chosen, wouldn't consistency dictate changing immutable to something like const struct
? ;)
I think struct
and immutable struct
would be pretty good actually; struct
is a very familiar term and we'd only need to add one new keyword. Allowing mutable struct
might make sense too, even though it isn't strictly required.
I should clarify that I think struct
being a noun is an advantage. It would be better not to only use adjectives to name these things.
Having to add the struct
to immutable struct
adds unnecessary line-noise, even more so having been used to not having to type this.
Otoh, I believe Fortran has a type
keyword that does something very similar to what ours does. I'm not averse to changing this, however.
@KristofferC above has it right: I also find myself saying "struct" when explaining what this is. Even in internal discussions type
has been a problem; somebody will say "suppose x
is a type", and it's not clear whether it means "thing declared with the type
keyword" or "type" in another sense.
If these names are really on the table (s/type/new name/
seems slightly obnoxious), I'd suggest we might want to make the most of this opportunity to make the default declaration an immutable.
So struct
would replace immutable
, and mutable [struct]
would replace type.
Just as a thought, another possible term for mutable might also be Ref
.
Another possible name would be composite
, since a generic CS term for this is a composite type. But I still prefer mutable Foo
and immutable Foo
to mutable struct Foo
and immutable struct Foo
— the struct
(or composite
, or class
, or whatever) seems superfluous.
:+1: to noun(s)
I always liked type
more than struct
in Julia (even though my background is _C_), because Julia's datatypes are a whole bunch more powerful and subtle and I think "struct" might be a bit simplistic for the idea. I also feel like since this is a new language we shouldn't be bound by convention that seasoned programmers are used to - you should also consider "what would be the best word to explain this to a person who's first language is Julia".
I also find myself saying "struct" when explaining what this is
Imagine introducing a newcomer to struct T
then telling them T::DataType
and you can dispatch using ::Type{T}
, all while explaining Julia's "powerful type system". I think this is just kicking the bucket further down the road.
being a noun is an advantage
:+1: to noun(s)
Probably worth noting that Latin-language-family adjectives like "mutable" are grammatically also allowed to be nouns in there own language. That's why when we ask "what is the noun form of mutable" we shrug our shoulders. But we always say "a variable" and in Julia-speak I would say "let's introduce an immutable for this". Unfortunately it feels awkward at first because of the Germanic roots of English grammar - but this happens really often in English (because we are also based on French and Latin) but you get used to it with time.
Finally, since the topic is "crazy idea", these keywords more-or-less construct a new DataType
so could we remove the keywords entirely and just use a constructor?
# Similar-ish to current
MyType = DataType(
a::Int,
b::Float64
)
# A DataFrame-like constructor
MyType = DataType(a = Int, b = Float64)
I guess these would have to be specially (statically) parsed like ccall
is and they can only be called at toplevel for now. (Also - not sure if we'd need Mutable <: DataType
and Immutable <: DataType
and BitsType <: DataType
to cover all possibilities, and probably const
for the binding).
I thought immutable was like a struct?
immutable has the memory layout of a C struct
type has the mutability of a C struct
Right... I think I was thinking of Swift, where:
This is the biggest difference between structs and classes. Structs are copied and classes are referenced. ... Thus, they will be passed as values not as a reference in the case of large objects.
which sounds like immutable
vs type
, and it is only the reference which allows the mutability in the context of the semantics of Julia bindings.
DataType
includes all nominal types: abstract
, bitstypes, immutable and mutable structs. So it doesn't add much clarity to replace type
with DataType
. I also draw a different conclusion from the "newcomer" scenario: ::Type
and ::DataType
select supersets of the things defined by type T
, so it's not crazy for them to have different names. "struct
is one kind of Type
" makes more sense than "type
is one kind of Type
".
I agree the adjectives can in practice serve as nouns. One can say e.g. "this is an immutable". I just think they are insufficiently descriptive. Rather than telling you what the thing _is_, it just tells you that whatever it is, you can/can't mutate it.
I like structure
and mutable structure
for types. maybe a = 1
and mutable a = 1
for variable assignment. Going off the idea of wanting consistency, no abbreviations, and immutability by default.
Edit: maybe constant
instead of const
in the mutability by default case
Or a version that involves having fewer keywords would be struct
vs. const struct
. Making all variables const by default would be too disruptive at this point I think.
I just think they are insufficiently descriptive. Rather than telling you what the thing is, it just tells you that whatever it is, you can/can't mutate it.
That's a good point - but I would consider the referencing behaviour vs "value" behaviour _much_ more important and interesting to describe than "is it a struct or a bitstype?" (mostly because bitstype
doesn't come up very frequently - every Julia type I've created is a struct). Immutability is just a consequence of the binding semantic and pass-by-value.
To completely obviate the need for struct
vs bitstype
we could also include this idea from @quinnj which was
immutable 32 Int32 <: Integer
or you could have un-adorned fields as number of bits
immutable Int32 <: Integer
32
end
which (in general when mixed with named fields) could also be useful for inserting padding when necessary.
Then it's just a choice between a value type (what is currently immutable) vs a reference type (what is currently mutable - but potentially with const
fields in the future which is another reason to not call it mutable
) and appropriate names are needed to distinguish these. And finally, using struct
for the value reference type will confuse Swift programmers...
It's true that bitstype
has all but disappeared since immutable
was introduced. But there are more things to distinguish than struct vs. bits: there are abstract types, tuples (also immutable), and likely immutable records in the future.
We originally picked immutable
since we felt that would be the most visible distinguishing feature: unlike other objects, you can't modify them. In fact, they are _not_ always passed by value; immutability means you can't tell the difference. Some immutable
s are inlined into arrays and other objects, and some aren't. Immutability means that difference causes no problems for plain julia code; it only becomes an issue when memory layout really matters e.g. for C interop.
In fact, they are _not_ always passed by value
Good point! Though, there are plans to change that, right?
I guess I'm saying you will need a future-proof set of keywords that mirror some future-proof concepts, since we are getting closer to 1.0. When immutables are inlined, it seems like that could be a reasonable time to rename them to something that is helpful with regards to the resulting semantics (and if those semantics help with FFI, that's even better).
I don't think people will get new concrete type definition keywords confused with abstract
, Tuple
s and "records" (which, if you mean the proposed tuple-like thing with fieldnames, I think I also heard being referred to as "structs" earlier...).
The real purpose of the notion of "pass by value" is to answer the question of what happens when f(x)
modifies (in some sense) x
: does it modify the same x
the caller passed in, or is the modification local-only? Julia has never had, and will never have (I hope), types, arguments, or functions that differ with respect to this behavior. Everything is "pass by sharing". For us, pass-by-value only exists at the ABI level, but that discussion only belongs in the FFI section of the manual. I'm not sure we will ever have a kind of type that is always passed by value or always inlined, since that can perform worse for large objects.
Anyway, I do think immutable
and mutable
are viable options for keywords.
It's true that bitstype has all but disappeared since immutable was introduced
While individuals don't usually have need to make new bitstypes, the difference between the existing bitstypes and common immutables is highly significant at the primitive level since the ABI for these are quite distinct. It just happens that most of the time users want the immutable struct, not the bitstype, when defining a new concrete data type.
FWIW, since there hasn't been much support for not changing things, I think type
and immutable
are fine the way they are.
(The do
syntax does bug me, though... ;-)
Everything is "pass by sharing".
I can respect that - and thanks for the discussion.
Everything is "pass by sharing".
On that note, just an observation - if we had const
keywords in type declarations then immutable
becomes completely unnecessary:
type Complex{T}
const re::T
const im::T
end
(the compiler could determine this type is immutable automatically, and users can come to understand that const
types allow us to compile to faster code). Then type
or struct
make sense. setfield!
can be disabled on const
fields in the mixed case.
What about type
and const type
? - The type keyword sounds more elegant for me than struct and with struct I kind of associate a technical memory layout and not an ~object having e.g. inner constructors. As the composite type is '... by far the most commonly used user-defined type in Julia ...', it's maybe not that bad if 'type is one kind of Type'? In communication using 'composite type' should clarify, same as I'd say 'abstract type'. Regarding line-noise, 'const type' is not worse than 'immutable'.
I'm not sure about the (slight) difference in the meaning of const
with variables vs. types. - In any case type and immutable always gave me a small mental hiccup. Good to see this issue here!
The main problem with using struct
would be that people might naturally make assumptions they are used to from C/C++ that are not necessarily true in Julia, e.g. a mutable composite type is not stored by value in an array whereas an immutable is.
What paradigms do immutable
represent more elegantly than type
? For example, atomically "transitioning" the state of multiple fields simultaneously without requiring synchronization primitives by instantiating a new immutable from the original with the desired fields updated.
Why should the type be separated into two distinct categories at the point of their definition rather than the point of their dispatch/usage (more like const
in C++)? By using only type
/struct
/composite
to define composite types and introducing an Immutable{T}
construct to promote mutable to immutable, we could have:
type CompositeType end
f(x::Immutable{CompositeType}) = x
a = f(CompositeType())
b = f(a)
Also, could a change to abstract
and bitstype
be considered here? AFAICT the usage of "abstract" is as an adjective, not a noun. There should be at least a linguistic consistency across the type keywords: all nouns, all adjectives, etc. bitstype
might be better stated as just bits
or primitive
.
Please, let's not turn this into an open thread for discussing changes to spelling (or semantics!) of Julia keywords. At this point, the ship has sailed on the basic _behavior_ of type
and immutable
. The only question raised here is whether we can have a spelling of type
and immutable
that better reflects their similarity.
I continue to support mutable
vs immutable
, or just leaving it as-is, as the two most reasonable options at this point. Anything else would be pointlessly disruptive.
@andyferris I really like that idea; some combination of struct
and const
would be good. If we go that way, I'd also want to be able to say const struct
or const type
, (1) to avoid needing to write const
on every field, (2) so we don't have to add the new feature of per-field immutability right away. If we ever want to add that feature, it would be good to have consistent vocabulary available for it.
In communication using 'composite type' should clarify
One of our favorite techniques for naming has been to explain a thing to somebody in one sentence, then pick out whatever word or two seems to be doing the most work. So to me this would be a vote for composite
.
Why should the type be separated into two distinct categories at the point of their definition rather than the point of their dispatch/usage (more like const in C++)?
That's easy: to provide global guarantees. In C++ a "const" object can still change under you if somebody has a non-const reference to it.
Also, could a change to abstract and bitstype be considered here?
Make a proposal. As for bitstype
, the keyword is very rarely used so I wouldn't want to steal a small useful word like bits
for it.
immutable
-> const type
seems also seems okay to me. Combined with type
-> composite
or struct
, if we really want to free up type
.
I'm not super happy about all of the code churn that this will cause, particularly as it can't be supported by @compat
, however. If we must do this, I think the upgrade path should be something like (1) introduce new keyword synonyms in 0.6 but _don't_ deprecate old ones (because of the lack of @compat
), then (2) deprecate the old ones in 0.7.
For bitstype
, how about calling this a primitive
type? The current name is a bit annoying due to its similarity to an isbits composite type
I like the way Julia has often avoided some of the "def/func/elif"-style abbreviations of some other languages. (Dn w abbrevs, kthx.) So mutable
wins over struct
for me.
FWIW, OCaml uses type
for records and variants (structs and unions) and aliases. Standard ML uses datatype
I think.
Symmetry is nice, but I find mutable
insufficiently descriptive; immutable
too, for that matter (I like the idea of const type
).
As Steve points out, this will cause pretty bad code churn across the community. And the benefit is dubious.
I definitely see the case for const type
; it would be net -1 keyword, and clarify the relationship between type and immutable. It would be really nice to be able to use type
in other ways though. Without that benefit it's much harder to justify a change. However updating code for this should be very easy; the syntax of type
is such that it basically can't be used in any other context.
+1 for composite
/const composite
.
I'm feeling that primitive
vs composite
is a great differentiator, with const
keywords added as necessary.
Do we need const primitive
to distinguish from some bits that can change (and for consistency)? So symmetrically we would have
primitive # something new...
const primitive # bitstype
composite # type
const composite # immutable
The problem being a mutable primitive type would have to be implemented... (of course this could possibly be at a later date, but we would want bitstype
-> const primitive
_now_ if that was going to become a thing. Being simpler, it could be a good "practice" target for bringing mutables to the stack, but I'm not an expert on that).
Similarly, the idea of adding const
to individual fields of a composite can easily be implemented at a later date, and even better, it is a non-breaking change.
If we go that way, I'd also want to be able to say const struct or const type, (1) to avoid needing to write const on every field, (2) so we don't have to add the new feature of per-field immutability right away. If we ever want to add that feature, it would be good to have consistent vocabulary available for it.
Makes perfect sense to me.
I looked up the composite
data type and found that at least Ada and Visual Basic also subsume array types under it. (Otherwise, a bit randomly, found: Haskell: lists and tuples (however a definition has been asked for); Python: lists, tuples, dicts; Lisp: lists, vector, hash tables, user-defined classes, structure).
Thus I now wonder how accurate composite is for the rather structure-like type
? (But I'm no computer scientist, I'm lacking the vocabulary / extensive view).
Hmm, that might be right: this particular kind of type always seems to be called a struct, structure or record (or class or object), with "composite" being a broader term. There are many examples at http://rosettacode.org/wiki/Compound_data_type
It would be nice to recover type
as an identifier and use a more specific name. The breakage of pretty much every trivial package written before ~0.6 would be super unfortunate, I'm not sure how to weigh that up.
The idea of reusing the const
keyword is quite compelling as it emphasizes the equivalence of const
variable bindings at global scope with the const
bindings of fields inside immutables. This seems like a good unification and better naming than immutable
.
As for names to replace type
, struct
seems to avoids ambiguity fairly well (I frequently find the phrases "a mutable type" and "immutable type" sound too similar).
The following looks fairly nice I guess:
struct A
a::Float64
end
const struct B
b::Float64
end
It would be nice to recover type as an identifier and use a more specific name.
I echo this sentiment.
If we are going to change names, how would the deprecation be handled? Will type
and immutable
still be valid in 0.6 and probably 1.0 with warnings? Can Compat.jl
handle this transparently. Quite a bit of literature on the net (blog posts, tutorials, etc) will show warnings - minor annoyances for a newcomer.
We could still reserve type
and immutable
for longer than usually done to ease the transition.
We are pre 1.0: The time to change this is now or never. Having the old keyword longer available is certainly good to ensure a smooth transition. I would not mix up the discussion on the actual naming with the pain that the transition will imply.
Personally I am all for calling it struct
. Having said that
I would not mix up the discussion on the actual naming with the pain that the transition will imply.
If the change is too painful, I would vote against the change. While a change pre1.0 is justifiable, weighing it against any disruption caused is IMO the right thing to do.
@stevengj had a good suggestion about how to do the deprecation, and it looks like @amitmurthy came to the same conclusion (keep the keywords around longer than we normally would). While we've all been using this language a while, it's still early days and we shouldn't be afraid to make the change. This one is just an easy search and replace, too.
I'll go ahead and put in a vote for struct
. I think this is one of those changes that will create a lot of buzz and complaints, but it's actually not very hard to fix packages/user code... just do it and people will figure it out.
immutable
-> const type
seems to be the path of least resistance, and IMO should definitely be done. I think this explains things much nicer.
type
-> composite
is more precise than type
but less precise than struct
, while being less jargon-y than struct
(to new programmers). It passes Jeff's 'write a sentence to explain it to a newbie" test and recovers the type
keyword. On the downside, I don't think composite
appears in other languages, so we'd be going it alone.
type
-> struct
is most precise, but possibly structure
would be prettier than an abbreviation (I'm trying to think of an abbreviation as ugly as struct
elsewhere in the language and came up empty - I suppose eye()
is a pretty disgusting tradition from an English language perspective).
bitstype -> primitive
makes sense if type
is changed.
@tbreloff is correct - the core devs have shown good taste in the past and, in the end, people will follow their lead. Do it soon!
I wonder if, since immutable
should be the standard unless you explicitly need to mutate, whether the rename should be:
immutable
--> struct
type
--> mutable
Then the common/expected name is the best practice, and there's an explicit and clear name for requesting mutability.
I like bitstype
--> primitive
as well...
I don't think const
should be the default. Optimizations that reduce functionality should not be the default.
+1 for struct
and const struct
.
The term composite
is slightly more descriptive but struct
is short, and very commonly known as a composite type.
I'd rather not steal an actual word for something as rarely used as bitstype
. Maybe primtype
or primitivetype
?
If we're not going to change bitstype
to a clearly better name like primitive
then I think leaving it as is would probably be better.
-1 to struct
. I don't use this term to explain what a type definition is unless I'm talking to a C programmer, and then only to mention that the layout is compatible and to compare/contrast their properties.
-1 to const
. C went this direction of having absolutely minimal keywords, and now we're stuck with many keywords have context-sensitive meanings. I don't really think const
is the key property of these types, but rather that they are value types (as opposed to reference types).
Going another direction though, how about using the keyword new
?
new abstract Abstract
new value Value <: Abstract
Value() = new()
end
new primitive 8 BitsByte <: Abstract
new record Object <: Abstract
Object() = new()
end
new function WhyNot # equivalent to `function WhyNot end`
The problem with "value type" is that it is something that only people who are quite deep into the language can understand. For new users, the fact that the fields are immutable is the _semantic_ fact that they are immediately confronted with; everything else is an implementation detail. So I prefer const
.
I see where you are going with record, but honestly I think this terminology is even less common than struct
(even if you google "record type ruby" vs "struct type ruby", or substitute python or perl or some other non-C language). There's also the problem that record
is quite a useful English word that it would be a shame to reserve as a keyword, whereas struct
is not likely to be needed for anything else in a program.
struct
is in very common use; looking over rosettacode it is used by:
algol, C, C#, C++, lisp, D, elixir, forth, go, maxima, racket, rust, seed7, swift, visual basic (structure
)
record
is used by:
ada, clojure, delphi, pascal, erlang, icon, modula-2, some schemes
record
seems to be preferred in older languages; these days as functional programming has gotten more popular it tends to refer to structurally-typed records.
Interestingly though seed7 uses new struct
.
A bit sad to see struct
(are the extra three letters to complete the word really that bad?) make it into a language which has so far had function
instead of func
, and so on. It's not something anyone is going to reject a language over, but still...
structure
is in fact used in PL/I and visual basic. VB also has structure immutable
. However struct
is so common I feel it has almost become a new word of its own.
I wonder if there also native speaking issue here. For me that am very used to word struct
in this context is structure
that that feels more strange. For the same reason func
sounds awful and function
natural.
Hasn't struct
become a self-contained term due to its use in various programming languages? The word structure
is (at least for me as a german native) much more abstract. For instance that type hierarchy has a certain "structure".
func
is for me no self-contained term but just an abbreviation.
func is for me no self-contained term but just an abbreviation.
How is struct not just an abbreviation as well? Isn't it literally short for structure, or did I just misunderstand the term ? You're just more used to it than func
. A lot of things are "self-contained terms" and common across many languages, but that doesn't necessarily mean that Julia should follow a tradition if it is better not to. Then it's just a fight over what is better or worse, and that's pretty much just a matter of taste.
Anyway, I would prefer mutable
, so I don't care _too_ deeply if it's struct or structure. mutable would avoid writing const
all the time for what is now immutable
.
But, even if it ends up being struct
or even strct
or stct
or strctr
it is very unlikely that I would change Julia for any other language for my work, so... :)
Sorry if this does not make sense in english: But isn't struct
an abbreviation of construct
. At least in german the word Konstrukt
makes much more sense to describe what a composite type is.
In english not being able to tell whether construct
is a noun or a verb has probably precluded its use in english-based programming languages :) The german use of uppercase is helpful there.
struct
is its own word the same way that TV, ASAP and LOL are words. I rarely hear people say "structure". In my experience, the word is "struct" both spoken and written.
BTW: Matlab uses the the word struct
, if that makes any difference.
OTOH, as noted above, in C# and Swift struct
corresponds to a value type (as opposed to class
). So using a similar terminology for both mutable and immutable types wouldn't really help people familiar with these languages. Not sure whether that's a decisive point....
mutable
/immutable
sounds like the most explicit choice, which should be quite obvious for newcomers.
Given the large number of different languages that use struct
, I don't think having identical semantics is required to use that name.
I like type
and const type
the best, but that doesn't free up the type
keyword. Since I don't know what's planned for type
, I don't know how large a cost that is.
But since the type
part is already implied in abstract
, perhaps using mutable
and immutable
by themselves makes the most sense. And its less typing that immutable struct
and a small change (type -> mutable).
the word structure is (at least for me as a german native) much more abstract.
While we are arguing over language, everyone is underestimating the amount of abbreviation that is struct
. It is short for "data structure". Similarly, I would say type
is short for "data type". I dare say an array or buffer is also a data structure, as is a linked list, and so on, but struct
has early roots as one of the first common data structures and within computing it has come to have a more specific meaning of its own (and hence to programmers native to English or otherwise, it doesn't sound as abstract as structure
).
-1 to
struct
. I don't use this term to explain what a type definition is unless I'm talking to a C programmer, and then only to mention that the layout is compatible and to compare/contrast their properties.
I feel exactly this way about struct
. I feel we would be introducing a new term to Julia for no specific reason.
-1 to
const
. C went this direction of having absolutely minimal keywords, and now we're stuck with many keywords have context-sensitive meanings. I don't really think const is the key property of these types, but rather that they are value types (as opposed to reference types).
Jeff explained to me (very kindly) above that semantically we don't care if things are values or references or whatever - these are implementation details not semantics and in a future golden age _we just won't care_. Things are "passed-by-sharing" in whatever way the compiler wants (with some FFI guarantees as necessary). In the past few days I've already come to call that "share-by-magic" and I feel this has been a revelation for me relieves a bunch of mental pressure that (ideally) I just shouldn't need to think about (@vtjnash you've seen how I've struggled with values and references and how these are implemented by the compiler and GC and so on in other packages and threads).
Bindings can either change or are constant (we use const
but constant
is also pretty cute). Similarly, the bindings of fields inside a composite data type can either change or are constant. This is why I suggested earlier attaching const
explicitly to each field - it made the semantics crystal clear (to me at least).
IMO we shouldn't need to use fancy words like "mutability" and "immutable" to talk about this stuff. Something can be rebound to a new object, or else it is constant. Removing the need for complex English language words like struct
and immutable
entirely from our discourse about Julia (not just the code) should be seen as a good thing (a goal, even).
I also feel like "struct" is its own word (meaning what it means in C) whereas "structure" is probably a "data structure" – because if you meant a record type, you would say "struct". But I'm showing my C roots here.
It's also in common lisp; defstruct
.
Probably more trivial than most other points here, but as long as we're bikeshedding: When spoken aloud, the phrases immutable object
and a mutable object
sound annoyingly similar. It would make conversing about Julia's type system more difficult than it needs to be. EDIT: It seems like this was already brought up in this thread.
+1 to type
--> struct
and immutable
--> const struct
. I don't think I've ever met anybody who'd be confused by this, especially after a cursory explanation.
Replacing type
is realistic for v0.6, and unrealistic for v0.8. We should do this. It is an opportunity to make more smooth and improve Julia's natural talent for clear communication and expressive rapidity. Types are so much of working well creating software that works. Better naming of typic things resonates powerfully and will carry for Julia a more storied future.
I suggest leaving struct
unused. In C, a struct is a syntactic container for a fixed sequence of type-fixed fields. Julia is not C, and pulling a C-ism into Julian discourse would push Julia's epiphemeral nature outside of serious discussion of best uses of and better ways to conceptualize aspects of Julia.
Also, "immutable" and "mutable" are too visually concordant. We can do better.
immutable ComplexNumber ... end
alterable MethodTable ... end
@JeffreySarnoff As an aside, per the community standards, it's preferred to refer to Julia as "it." Just thought I'd mention it. 🙂
@ararslan The community standard guidance on Julia appears to have changed, now eschewing literary pronoun application. Thank you for bringing this to my attention. :cricket:
Using the feminine pronoun is, in itself, not bad (and unavoidable in many languages), but it seems that many find it irresistible to jump from using the term "her" to talking about Julia as a hot date, so it seems best to avoid the temptation altogether as much as possible.
thx
On Thu, Nov 3, 2016 at 4:29 PM, Stefan Karpinski [email protected]
wrote:
Using the feminine pronoun is, in itself, not bad (and unavoidable in many
languages), but it seems that many find it irresistible to jump from using
the term "her" to talking about Julia as a hot date, so it seems best to
avoid the temptation altogether as much as possible.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/JuliaLang/julia/issues/19157#issuecomment-258264451,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABmqxopTX8oWKbwnLxfCBtIv-Ih7l-nXks5q6kRFgaJpZM4KkN_g
.
In regards to the issue at hand, I'm personally undecided about what I would consider the best change. But it does seem odd to me to talk about Julia's amazing _type_ system and then specify that the keyword used to construct a type is actually struct
rather than type
. I think it might encourage people to talk about types as structs instead, eventually leading to a shift in the language used to describe Julia, e.g. discussing Julia's amazing _struct_ system.
the keyword used to construct a type is actually struct rather than type
But the keyword isn't really about constructing types --- for example the expression Tuple{Int}
also constructs a type. It would be great if the things currently defined with type
were always referred to as struct
s, since then there would be no confusion regarding how Real
is a type, and Union{Int8,Int16}
is a type, etc.
yes, I am editing my prior note and just now wrote of that. It would be
pervasively detrimental to the "care and feeding" of the Julia and the
future development of expressive power and conciseness. Should the door be
opened to make legitimate the consideration of Julia's type system as
scaffolding on C structs, the war is lost.
On Thu, Nov 3, 2016 at 4:38 PM, Alex Arslan [email protected]
wrote:
In regards to the issue at hand, I'm personally undecided about what I
would consider the best change. But it does seem odd to me to talk about
Julia's amazing _type_ system and then specify that the keyword used to
construct a type is actually struct rather than type. I think it might
encourage people to talk about types as structs instead, eventually leading
to a shift in the language used to describe Julia, e.g. discussing Julia's
amazing _struct_ system.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/JuliaLang/julia/issues/19157#issuecomment-258266857,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABmqxsZ_rXkn6GpVFxhd6TZnkkao9plWks5q6kZggaJpZM4KkN_g
.
It would be great if the things currently defined with
type
were always referred to asstruct
s, since then there would be no confusion regarding howReal
is a type, andUnion{Int8,Int16}
is a type, etc.
Is there confusion regarding that currently? I guess that much seemed obvious to me though perhaps I've missed discussions about it.
@ararslan: The term type
is just much to generic for what is currently constructed. What we currently construct with the type
keyword is a structure that consists of composite types. But there are many other types within Julia that are not constructed using the type
keyword.
No, I don't think there's too much confusion about that currently, but nor would everybody think all julia types are structs if we used the keyword struct
.
Okay, good point.
and Union{Int8,Int16} is a type
Ah. I had forgotten that Union
also exists. Which makes the argument for struct
(Struct
?) more compelling, IMO. Still don't like mutable
and immutable
though.
I find _struct_ ignominous and really believe carrying Julia to it would, over time, pull the evolving zeitgeist downward. The principle is an antagonism between the exposition of bits in motion and the expression of computational maybes as higher-order melds and deeper gestalts. That using struct
would not lead everybody to think of types a structs is beside the point. ... let me overdramatize ...
I cannot argue that writing about Einstein as a patent clerk lessens appreciation of his contributions. It does not follow that, in a course where references to Albert Einstein temphasize the import of his time as patent clerk, more than a few students would enfold some sense of that in future conversation. That a thing is so
does not ensure it behaves just so
after moving to a new school.
If there is a compelling case for using _struct_, there should be a better case for one of
a structure
is a meaningful interrelation of parts, an informed composition
a construct
is a useful structuring of relevancies, a value-enhancing design
an immutable structure
is a perdurant composite
a mutuable structure
is an unfixed predelection
an immutable construct
is an established eventuality
a mutable construct
is an intentional constraint on context
We need both the "bits in places and through gates" way of speaking and the "data structuring reveals ontological information" and that can be made available as transformation modifier way of speaking. Community participants who are CS talents and most other domain experts who program in the large have a thorough handle on bytes, memory, logic, instructed operations etc. The other way of making desire, creativity, possibilities and imagination become software that works well and is well worth the work -- that is shared less. Any decision about term naming should reach to encourage that talk.
What about class
and immutable
?
I know class from Delphi and thought it would be impossible here, but in the Nice language, which has multimethods, it is used as a keyword (link). And - if I read the manuals correctly - also in Haskell and Dylan. It passes the "class is one kind of Type" test and still is quite vague (as 'type' today), something I like. In the 'An overview of arrays and Iteration' video at 15:00 - 15:20 min, Tim Holy (accidently) says 'class', an unimportant detail but nevertheless maybe shows that class would not be total foreign in the Julia context.
Otherwise, reftype
and immutable
? The reftype term was mentioned in the initial comment and has been ignored since. Why? For me it sounds quite nice, frees up type and transports the reference meaning.
(I didn't understand the purpose of the 'new' keyword. Couldn't 'new' be left out in all lines without change? The 'value' and 'record' terms would be keywords and replace the currently used 'immutable' and 'type', right?)
@swissr the only difference (that most users should be aware of) between these two types is that the fields in one can change and in the other the fields cannot. It would be logical if their names indicated their only semantic distinction. (As mentioned, the implementations using values and references is fluid - e.g. an improved compiler might pass large isbits
types by reference automatically as an optimization, and conversely small mutables could move to the stack in certain situations).
Regarding type
vs struct
, I do see that I can make abstract data types with abstract
, Union{}
, typealias
and so on (in the case of Tuple{}
it's arguable if it's a new type or just a parameterized type), but really the only _user-defined concrete types_ are created by bitstype
, type
and immutable
. The syntax for these is unmistakable w.r.t. the abstract definitions in that they define the data they contain somehow, and the abstract ones do not. Changing immutable
to const type
would seem to make the situation clear to me.
I do worry about language and propagating the technical word struct
with the only reason being tradition, when we have an opportunity to create a programming language that is discussed in layman's terms. An example of where I think this won't help is when I create a wrapper type like Symmetric{Matrix{T}}
- I don't want my discussions to be, "I created this struct
with just one field which ..." when I can say "I made a Symmetric
wrapper type
for Matrix
" (do note that half of that sentence is actual syntax). A "wrapper struct"? Sounds kind-of silly - and who makes a struct with one field? For that matter, what about singletons with no fields? A sizeable fraction of types
and immutables
are not defined to create any (non-trivial) data structure but rather with the express purpose of using the powerful type and dispatch system with wrappers and singletons. IMO this is the most interesting, powerful and expressive aspect of Julia (combined with the fact that it is _fast_).
I feel the full power of struct
would only be immediately apparent to experienced template C++ metaprogrammers who know they can implement traits, etc, with structs, and that's a bit of shame.
"Kind" has a fairly specific technical meaning in type theory.
If the goal/advantage is to free type
then how about:
const datatype # immutable
datatype # type
They are concrete types so they probably contain data, and it is one (of many) ways of constructing a DataType
.
"Kind" has a fairly specific technical meaning in type theory.
The introduction to the wiki sounds exactly like Type{}
(which accepts DataType
and TypeConstructor
, Union
, etc) (EDIT: not that I think such a change is worth the disruption)
kind
is not the right word here.
I feel that most often the best approach is just to learn a field's
standard vocabulary instead of trying to replace it with something you
guess will be easier.
This decision doesn't affect informal speech. You can still sensibly say "I
defined a type". Using a more specific keyword just makes it easier when
you need to be precise.
Fair point, Jeff. Please note that I _do_ think const struct
and struct
would be an improvement over immutable
vs type
(but that doesn't mean we shouldn't search for something even better).
When you think struct is that percept more as a structure or as a construct, neither or both?
@andyferris my 'class' and 'reftype' comment didn't mean that I wouldn't also like 'const type' or not support that const struct
and struct
would be an improvement. It was another attempt to look for possible terms when wanting to avoid 'const', preserve 'immutable' and keep out 'struct' (was aware of mentioned implementation but thought, if it is correct in say 80plus % of cases it is ok).
How about fieldtype
(or fieldstype
)? It is parallel to bitstype
and consistent with fieldnames()
.
Glen,
I like the verisimilitude. fieldstype is the better choice because using a plural form where something can be singular or plural is proper.
--Jeffrey
class
might be ok; we originally rejected it due to its association with class-based OO with methods inside objects. I would say struct
is more accurate.
I don't see struct
as short for anything; it's just what these kinds of data structures are called at this point. Somewhat amusingly, lisp has cons
, which may have originally been an abbreviation for construct
, but people forgot that pretty quickly and just started talking about "cons cells".
I think we should continue to reject class
. Using that term would invite a whole slew of OOP expectations that run counter to the Julia style.
I don't see struct
as short for anything, but I worry that the implicit reference to C's structs implies that Julia's would be value types, which they are not, of course. To that end, I'm currently leaning a bit towards record
since it has far fewer immediate connotations.
To clarify a point that may not be clear, I think that using const record
or const struct
is only viable if it's interpreted in the sense of being short for mapping const
over all fields, implying that we'd want to support marking individual fields as const
. So what I'm saying is that we could have these:
record T0
f::A
g::B
end
record T1
const f::A
g::B
end
record T2
f::A
const g::B
end
record T3
const f::A
const g::B
end
const record T4
f::A
g::B
end
Here T3 and T4 actually describe equivalent types – i.e. writing const record
is just shorthand for all of the fields being const
. If this is not the interpretation then I think the conflation of immutability with constness is kind of dangerous since this is already a common source of conceptual confusion and if we add to that terminological confusion, we're not going to be helping matters.
Here T3 and T4 actually describe equivalent types – i.e. writing const record is just shorthand for all of the fields being const.
If we make const record
mean what immutable
means now, this might not be true. const record
would describe a reference type for which none of the fields can be changed. Whereas the current immutable
is a value type.
See https://github.com/JuliaLang/julia/issues/19157#issuecomment-257942059 and the following comment for some discussion of record
.
@vtjnash That's a good point, but it's similar to what happens now where an immutable
becomes a "reference" type if it contains any references.
I think the fact that record
is less common is ok, the fact that it's a useful word as both a noun and a verb is more problematic.
How about nuple
? Short for "named tuple", of course.
I like the suggestion made above of
const datatype # immutable
datatype # type
best so far. It avoids bringing in an old word with historical baggage and seems completely clear to me. Sure it is not the only datatype in julia but it is the most common one defined by normal users.
Are there any plans to also change the terminology for explaining this in the documentation, more to the point change the titles of chapters like this? If not, I think I like composite
and immutable composite
or const composite
best. Since const
is also used for global constants, i'd choose either const
or immutable
for both of these, with a slight preference for const
because it's shorter. At least the word composite will not look familiar to most newcomers, forcing a look at the documentation and avoiding false assumptions due to similarity with a C name. False assumptions regarding const
seem less likely, since anyone used to that in C++ knows not to assume anything.
Also the advantage of using two words to indicate immutability frees up a possible future const abstract
and const bitstype
should the need ever arise.
If we make const record mean what immutable means now, this might not be true. const record would describe a reference type for which none of the fields can be changed. Whereas the current immutable is a value type.
Uh oh. I thought the value-or-not-ness of immutable
was defined at the implementation level, and all the user is meant to consider is that fields cannot be rebound. Passing by value (or not) is then a pure ABI issue, where the compiler should in principle be free to choose whatever is more efficient. To me the user visible semantics of immutable seems exactly equivalent to applying the current semantics of const
to all fields of a type.
Am I _still_ confused about the intended user-level semantics of immutable, or are you talking implementation details here?
How about nuple? Short for "named tuple", of course.
May as well go with record
, right? For example, a named tuple is what a record
is in Erlang. And I think in the database world too.
But if Julia has more of an overlap with folks who also know C
, struct
is a more appropriate change.
I personally find record
kind of bizarre and unclear. In the database world, a record is a row in a table; that seems like it would be a confusing conflict with something as general as a Julia type (immutable or otherwise).
After rereading this thread I am leaning towards composite
for type
. It holds Jeffs "one sentence rule" and there have not been so much negative votes for it. That the term is not so much uses in other languages is not an issue in my opinion. And composite
is really the most descriptive word that one can find for that. Thats the reason the documentation refers to these things as composite types
.
Coming from Fortran I still think that the keyword type
is just fine,
and a minimum sensible change would be immutable
-> const type
.
But if type
really has to go,
composite
and const composite
seem to be the next best choices.
immutable
-> const type
certainly seems viable: it simultaneously avoids disruption, removes a keyword, and adds clarity to the language.
It might be sad not to be able to use type
but to be honest the one I want to use is Type
anyway. Nine times out of ten my type variables are parameters for static dispatch not DataType
variables for dynamic type analysis (the exception being generated functions). Not true for people who write inference.jl but they aren't really the "target audience" of the language, if you will.
Related question: is it at all viable to use type
as it is at toplevel, but inside a function (where it is always invalid, currently) allow it to be a variable name? Or even further, the structure of a type definition is pretty specific... could we detect type definitions as specific syntax while allowing even global variables (or functions) to be bound to type
?
I.e. can we get rid of the keyword behavior while keeping the syntax for defining a type?
(unlikely imo) there is a strong risk attached: it becomes too easy for idiosyncratic lexicography to distract. And those missing micro-continuities are destructive to ease with collaboration and clear communication.
@c42f:
Am I still confused about the intended user-level semantics of immutable, or are you talking implementation details here?
No, you're not – I was being sloppy. Immutables aren't really value types, but mutables certainly aren't and I felt that using the same terms as C might suggest that they are.
I just realized that in the context of C it's not clear whether it makes sense to call structs "value types", since the actual situation is that C is a pass-by-value language. So arguably it's the passing and assignment conventions that are different, not the data types themselves.
I am fully in favor of enacting the change this issue opens. The usefulness outweighs any visceral preference that one rather than another of the candidate terms be used.
_although_
since the actual situation is that C
nicely captures why, of candidate terms,
struct
is my least favored
Here's the story I'm selling: "In both C and julia, a struct
is a data structure that maps a fixed set of field names to values of various types. But when you pass these around, C is pass-by-value and julia is pass-by-sharing."
That account is both non-onerous and fully accurate. Everything in it can be googled successfully. No PL theorist would complain about it, and non-PL-theorists would learn something by hearing it.
I buy that story. Though I wonder, are there any terms mentioned here that a PL theorist _would_ complain about? I like to think that Julia fits right in that niche that satisfies both PL theorists and non-theorists alike, so striking a balance between correctness and general clarity here seems crucial.
Well, I don't want to put words in anybody's mouth; I just wanted to address the idea that struct
could be confusing due to structs being "value types".
I think immutable
should remain a single-word keyword. I don't like const type
or const struct
or immutable struct
. I use immutable
a lot and I think it'd really quite awkward for these declarations to be two words when just about everything else is one word. Not in the sense of typing, as that's not a real concern; but in the sense that having immutable like a "tag" makes it feel second-class.
@TotalVerb I don't feel that is very compatible with the fact that
type MyType
const field::Int
end
should behave exactly like
immutable MyType
field::Int
end
does now.
Given that, having a const type
(or const struct
, const composite
, or whatever) broadcast the const
to each field as a shortcut seems like a useful (though not strictly necessary) feature. I would hope that in the future the compiler wouldn't even know which one you typed (const type
or const
in front of each field - the former could transform to the latter by the parser). At that point, why keep immutable
?
having immutable like a "tag" makes it feel second-class.
If I understand Jeff and Stefan correctly then, yes, immutable
is just a tag that says that the fields of a type are constant bindings. Being constant (_really_ constant, not like C) helps the compiler make optimizations, and if the fields themselves are constants or primitives recursively (i.e. isbits
) it helps it make even more optimizations. This is good-to-know, but not semantically important. Tying the semantics to current behaviour might make it more difficult to improve that behaviour in the future.
But there _is_ an important semantic difference: immutable types are values, and thus one can safely assume that an object's identity is specified by its fields. An object of an immutable type has, from the user's perspective, no special "identifying feature" not accessible from its fields. Any object of a non-singleton mutable type, on the other hand, clearly does have this invisible "identity". The fact that many immutable types are stored as boxed objects, and hence do indeed have this extra identity internally, is irrelevant to semantics.
In my opinion, it is not just an _optimization_ to do
immutable Complex{T} ... end
instead of
type Complex{T} ... end
because many aspects of user-visible behaviour change: ===
, the default ==
, objectid
, hash
, etc. It is simply not correct to say that immutable types provide a subset of the functionality of mutable types; on the contrary, the very fact that they are immutable provides important guarantees that allow immutable types to be more powerful.
Before the community settles on const
and struct
, I just wanted to make one more plug for constant
and structure
.
1) Just three extra letters for actual words!
2) Despite claims that struct
has become idiomatic
2a) Someone who is migrating from R (like me) might be confused
2b) Someone who is new to programming (those who need the most help) might be confused
Just for fun, silly words that struct might be confused for:
indestructibility
obstructionism
post-structuralism
the superstructure (oh hi Marx)
and const:
Constantinople
constellation
boa-constrictor
unconstitutional
Is there PL beauty/power gained by multicontextual immutable and const of this sort: immutable never broadcasting (projecting its nature) through/inside its resolved referent and const broadcasting through embedded referents that are not immutable, as if it were an adverb or gerund?
The same question, in other words:
For the moment, using variables in global scope is problematic and the trick
to work around is to wrap the varying value in a const vector with a single entry. In that case const
is does not broadcast. A broadcasting version of const
would apply ?imply constness to the value of the entry in the vector as well as to the vector. Similarly, a type declaration that has fields which may hold values that wrap or enclose other kinds of value. An immutable type now does not confer immutability on its fields' values (and not any value that may be indirectly reached through its fields). There is afaik an elegance and helpful capacity that comes with a broadcasting version of a keyword that means "once constructed/initialized the value ascribed to this item [or to items of this type] does not change [is not allowed to be changed]".
The immediate (non-broadcasting) sort is widely used, and assuming some of what people do with Julia becomes much easier for Julia's precompilation to make better/faster/simpler to use or rely upon with the introduction broadcastable constness, then that needs to play well with the immediate sort. I wonder if this is a way that brings additional _theoretical programming language goodness_ (ease of expression, representational power, ...): the broadcasting constness broadcasts through values of types that have embedded reference types and/or have ?are indirectly contained types until (a) reaching a value that does not have internal embeddings or containers or (b) reaching a value is itself (independently or otherwise) of a type that has non-broadcasting constness.
Thinking more about this, the only change that I really think is worth the breakage is bitstype
-> primitive
, mostly for how annoying it is to call something isbits
.
As for the real point of this discussion, type
and immutable
, at this point the option I find I'm liking the most is no change at all; type
to construct a type is clear, immutable
to construct an immutable type is clear. However, I'll happily take whatever our supreme overlords give us, as I implicitly trust their judgement on what's best for the language going forward.
Is there any reason not to use fixed rather than const or constant? To me at least, is seems a much clearer description.
@JeffreySarnoff It's difficult to imply const
ness to a thing you can get a reference (i.e. pointer) to. Julia's "sharing" semantic means that anything that the compiler cannot prove to be truly immutable needs to be a reference type. When you bind such a reference to the field of a const type
(immutable
), there is no proof that this reference doesn't exist elsewhere and therefore no proof that the data referred to is constant.
I think changing this behaviour would be a really fundamental change to the Julia language.
@andyferris Thank you for that clear answer.
Is there any reason not to use
fixed
rather thanconst
orconstant
? To me at least, is seems a much clearer description.
I had been wondering if there was something better than const
or constant
which reflects that it is the binding which is permanent, and not (necessarily) that the data inside the bound object be unchangeable. fixed
does go some way towards that, but I haven't seen that in other languages (then again, I also haven't noticed Julia's binding/sharing semantic in other languages).
Maybe something like bind
(e.g. bind x = 2
)... thesaurus suggests glue
... this is getting pretty speculative...
The idea of replacing const
with something more precise is enticing. However, we'd want it to sensibly apply to both the a type declaration and an individual variable assignment. fixed struct
makes some sense, but it's the fields of the struct which are fixed rather than the type declaration. Unfortunately bound struct
(tied struct
?) seems rather unclear. For some reason, const
seems clearer to me when applied to a type.
We'd want it to sensibly apply to both the a type declaration and an individual variable assignment.
I feel it would be productive to aim that
type A
const x::Int # fixed, bind, bound, tied, glue
end
makes sense. Having a shortcut in front of type
, struct
or whatever would be just a shortcut that means the above.
It could make sense to make this a macro, like other important decorations that change the character of a thing, such as @generated
. That would remove yet another keyword...
+1 for type
-> composite
, though really any change from type
sounds great.
I wish I could vote on GitHub issues without having to add a new comment to the thread... My vote is for mutable
and immutable
, it is pretty neat and clean. struct
is overused and doesn't emphasize the mutability part.
P.S.: Does anyone know or can contribute to GitHub and add a voting feature? I asked them in the "contact us" page, but my email was probably lost.
Having recently switched to Julia with a background in many other languages, I'd rather not see Julia adopt C-style naming and pulling in all the confusing const-ness issues of C/C++. Instead, giving a data type declaration a notion that reflects somehow the intent of being a value type or a shared reference type would have helped me significantly, instead of simply refering to mutability.
My initial expectation in Julia would have been a simple type
to behave similar to an immutable C-style struct
or Python object, since Julia appears to be much about a functional programming style and speed.
I'm still getting confused by the asymmetry in wording of type ...
and immutable...
, but getting a DataType
from typeof(SomeType)
, or the actual meaning of 'bitstype', and the necessity for a typealias
keyword instead of a simple Alias = DataType
statement.
Thus, I'd vote for datatype
, which would be consistent with typeof(SomeType) == DataType
, and would break the irritating similarity with ::Type{}
. Decorating the mutable type with composite [datatype]
could highlight its special and possibly more expensive nature compared to the fundamental 'bitstypes'.
pulling in all the confusing const-ness issues of C/C++
No renaming of this keyword would do that. Those issues have to do with static checking and casts, which aren't involved here at all.
the intent of being a value type or a shared reference type would have helped me significantly, instead of simply refering to mutability
I don't fully understand this. If an object is immutable there's no way to tell whether it's passed by value or reference, so how can the value/reference distinction be fundamental?
datatype
is not a bad choice. But I don't think datatype
vs. composite datatype
is a good way to convey the mutability distinction.
@JeffBezanson, with C-like const-ness I meant the possibly implied expectation of the Julia type to have same behaviour as in C/C++: immutable only after construction, modifiable anyway through casting, sometimes being without effect at all for function arguments or return types. Thus, when choosing keywords probably not refering to C/C++ is a good choice, hence please not const struct
.
Regarding 'value vs. reference': It took me quite a while to understand why an immutable type embeds the members directly and produces nice and compact fast assembler code, but 'type' didn't and still contains all the calls to objects. Or in other words, why I would typically want to use an NTuple when aiming for speed. Thus, when reading 'immutable' and 'mutable' I'd have expected the meaning as a 'parameter' in Fortran, but not also the change in the layout or kind of implementation of the actual datatype.
Probably, most of the time one might want to have 'immutable value' semantics for small composite types like a Complex, but 'mutable and refering/non-copying' for large data sets like arrays etc.
Then, the underlying intent is probably not the mutability, but avoiding copying data around.
However, that was my experience when learning the Julia low-level machinery to obtain fast assembler code, but I don't know how to better reflect that in naming keywords and how to combine or express that just with mutability.
I get where you're coming from @m-j-w, I've been there, but I think you're better off unlearning everything you know about C/C++. Here, it is the const
-ness that is immutable and whether something is stack or dynamically allocated, and whether it is passed by reference or value, are free to vary and will be optimization choices for the compiler. You could make a language where everything is dynamically allocated and passed by reference, and this is Julia's default way (for boxed values - it implements "pass by sharing" even if the type is unknown). You (and the rest of us) notice that small immutables are so much faster because that's where optimizations are currently implemented. This is the result of the semantics of immutable
making optimizations easier.
But, really, I would prefer large immutables were passed by reference (perhaps by stack pointers, where that makes sense, but it is probably best to heap allocate an NTuple{1_000_000}
) and that small mutables of known size are stack allocated (again, where possible). Even garbage collection could be statically determined in some cases, allowing heap-space to be reused inside loops for example. I picture these as future optimization opportunities that require escape analysis (and none of these affect the semantics of the language, just the performance).
I think what I'm saying is that the keywords need to reflect semantics which will stay constant for a decade or two, not implementation details that will change in a couple of years (i.e. efficient small mutables and efficient large immutables).
I meant the possibly implied expectation of the Julia type to have same behaviour as in C/C++
This might be a good enough reason in itself to consider const
-> constant
, to be honest. I think const
might be our only abbreviated keyword at the moment, making it an odd one out anyway.
a simple
Alias = DataType
statement.
I'm pretty sure this is absolutely fine where it makes sense, but it won't allow more complex modifications of the type, e.g. typealias RealMatrix{T<:Real} Matrix{T}
, nor should it (it's a simple binding, not creating a new Type
with new TypeVar
s). Unless you want to define it the other way around: RealMatrix = Matrix{T <: Real}
and generalize what apply
does for a TypeVar
(i.e. makes a TypeConstructor
)... actually that's an interesting idea (but it does have syntax issues, which is why typealias
is nice...).
@andyferris, I already 'unlearned', but for other new users it may be easier to get over the 'why is Julia so slow despite compilation' phase. Picking keywords that support a fast development of a mental model of those details can be a huge selling point to new users not having too much of a computer science background. Not to forget 'simple' keywords to avoid other spoken language barriers either.
@m-j-w Great, and I do agree with all of that. :)
Tell you what, let's try the closest thing we can to a poll using the very best GitHub functionality: reaction emojis.
Here I've tabulated, _in no particular order_, the suggestions that appear to have the most support. React using the specified emoji to cast your vote for that suggestion. I believe this requires accessing GitHub through a desktop browser; AFAIK reaction emojis haven't been implemented in the mobile interface. Click the face in the upper right corner of this post to access the menu of emojis.
| type
| immutable
| react with |
| :-: | :-: | :-: |
| struct
| const struct
| 👍 (+1) |
| mutable
| immutable
| 👎 (-1) |
| type
| immutable
| 😄 (Laugh) |
| composite
| const composite
| :tada: (Hooray) |
| datatype
| const datatype
| 😕 (Confused) |
| type
| const type
| ❤️ (Heart) |
Failure to vote corresponds to an implicit vote for nuple
, of course. :trollface:
I have to say, I'm not a huge fan of doing contentious decisions like this "democratically". If discussion has played out with no consensus, I would just defer to the decision of the BDFLs.
Fair point, @TotalVerb. As I said before, I'd be totally fine having the powers that be just give us whatever they think is best. It seems to me like the thread is meandering a bit and @juliohm's point about voting seems reasonable, so I figured I'd give this a go and see what happens. I see it as a way to more clearly show what the consensus is, but I definitely think the final decision should be left to our overlords, regardless of what the community consensus actually is.
Personally, I don't think I like having two words aesthetically (const type
). It also feels a little semantically dissonant. When we say const x = 1
. We mean that x
is constant. When we say const type; x; end
we'd mean that instances of this type don't change after construction. From straight interpolation it feels like saying something is a constant type means that the type itself doesn't change (which is already the case now). See also:
type foo
end
const bar = foo
So bar
is const and it's always foo, but yet it's not a const type
. It feels like wrt to the existing semantics of const
(applying to bindings), the names of types are already const.
I suspect there are no keywords that are concise, convey the intended semantics, and are unlikely to be desirable as variable names. The terminology I feel comes closest to these goals is mutable datatype
, immutable datatype
, and abstract datatype
for the three kinds of declared types.
I wish in addition to type
and immutable
there was an additional mutable value type.
I have seen a few discussions somewhere in issues, but basically at the moment it is impossible to efficiently handle scenarios like this (correct me if I missed something):
immutable T
a::Int
b::Float64
...
end
t = Vector{T}(10)
t[2].a = 5 # error here
# instead
c = t[2]
t[2] = T(5, c.b, ...) # works
The code creates a neat array of value types sizeof(T) * 10
, but to change some field one needs to reassign entire T(...)
, which is typically 3-5 fields long.
So basically my 5 cents:
type
- GC collected reference
immutable
- value (stack allocated) type which is impossible to change
mutable
- value type which is possible to change, especially in arrays
value type which is possible to change
I think this is an impossible-to-achieve goal since allowing changes is precisely what gives something object identity.
Perhaps you would like this approach instead: #11902
except for separating mutables and immutables, it should be better if we split values and references.
abstract Node{T}
immutable Link{T} <: Node{T}
value :: T
next :: ref{Link{T}} # next :: Link{T} will be an error: Recursive type
end
There is no need to overcomplicate the language with an artificial distinction between values and references. Mutable and immutable types are semantically much simpler; the fact that a type is a value type is merely an optimization.
@Keno makes a good point
Personally, I don't think I like having two words aesthetically (const type). It also feels a little semantically dissonant. When we say const x = 1. We mean that x is constant. When we say const type; x; end we'd mean that instances of this type don't change after construction. From straight interpolation it feels like saying something is a constant type means that the type itself doesn't change (which is already the case now)
As I mentioned earlier, I think the "correct" semantics is given by
type Complex{T}
const re::T
const im::T
end
z = Complex(1,2)
Here z.re
behaves just like when we type something akin to const z.re = 1
, so there is no semantic confusion about exactly which binding is const
.
As @JeffBezanson states, this isn't really convenient for large numbers of fields, and isn't compatible with the current implementation of types. Partially mutable, partially constant structs may or may not be implemented in the future. However, there is a syntax which makes sense both currently and into the future:
@const type Complex{T}
re::T
im::T
end
The current way this is implemented, a macro can change the from type
to immutable
in the AST. In the future, if partially-constant structs are implemented, then the macro can still do the manipulations to the AST by adding const
to each field, and it will be clear to all and sundry that it is the field bindings which are constant. Aesthetically, it is better than two keywords in a row - we do similar things for functions (@generated
, @inline
, @proagate_inbounds
, etc).
@const
could easily be @immutable
or something similar (@immutable type Val{T}; end
reads OK, IMO) and the macro idea is compatible with struct
, composite
, and so-on.
@be5invis yes, this is a usual way in many languages, e.g. in C# there is struct
, which behaves in many ways as immutable
: it is passed by copy to functions, is explicitly allocated in arrays (not references to GC-managed objects as in the case of class
|type
). However it is _mutable_, and in arrays can be modified by a single field.
What I do believe that in the case of immutable
there is a mix of 2 properties:
So basically I would love to see the introduction of a type with just property 2. This won't disrupt the existing codebase (immutable
remains), but for those who writes something fast with minimal GC involvement it would be valuable.
@johnmyleswhite thank you for #11902, still believe that it should not be that ugly
@wgreenr As mentioned earlier, and has been discussed many times, that is not possible. It is also not really related to the discussion in this issue.
Anything's possible but introducing mutable value types would be wildly disruptive and a very bad idea. I can understand why it's an apparently simple and appealing idea, but adding a new, entirely different kind of object semantics and bifurcating the type graph into reference and value semantics is not going to make the language better. What it would accomplish is making it impossible to write generic code safely since the same code would do very different things depending on unknown semantics. There's an extensive discussion with examples here. The point of #11902 is to recover benefits of mutable value types without wrecking things.
I'm not sure if this is even worth mentioning; but in C/C++ 'struct' also implies something about the layout of the data. On the other hand, it is frequently worthwhile to re-arrange struct members to get better memory layout. If you're considering a breaking change to the syntax, might it be worthwhile to have a mechanism to somehow differentiate between 'structs' (ordered -> C interop) and 'immutable's (could potentially be ordered in any way).
I'm fairly new to Julia, so I'm sorry if I missed something obvious.
I personally have no real preference wrt names; however, I'm surprised that nobody seemed to have suggested "concrete", given that there already exists "abstract".
To add yet another suggestion, the following seems best to me:
Use struct
instead of immutable
.
Use struct!
instead of type
. When speaking English, this should be referred to as a "mutable struct".
struct!
to be marked as const
.Some justification and thoughts:
1) Unless I missed something obvious, you never want to use a function with a !
to manipulate a value of an immutable type. If that is wrong (e.g. if there is an important case where the immutable type refers to a mutable one, and the function with a !
changes it), this suggestion may not be a good one.
2) I think that immutable types should generally be preferred over mutable ones, since they are subject to more optimizations and have a more predictable behavior for the programmer.
3) For this to work, it is probably a prerequisite to implement the optimizations to make immutable types at least as efficient as mutable types in almost all cases. In particular, the compiler should be smart about passing large immutable types by reference.
UPDATE: I used to have record
instead of struct
, but record!
is too much like a verb. Some other options that come to mind: newtype
, typedef
(which will confuse C programmers for 10 seconds), composite
, or concrete
as somebody above suggested.
Is it likely something will happen in this space before v0.6 feature freeze?
Probably not, given that no decision has been made (at least publicly) and we're just ~10 days away from the freeze.
I haven't followed this carefully, but one comment is that if/when this does change, I'd like to request that we first have really good reporting of the offending file/line number in place. Or at least the module; in 0.5 it's still sometimes difficult even to figure out which package has a @deprecate
d_binding
.
xref https://github.com/JuliaLang/julia/pull/20418#issuecomment-277475415
Most helpful comment
I do like
mutable
for consistency.