`String` returns true for `isstructtype`

help?> isstructtypesearch: isstructtype  Base.isstructtype(T) -> Bool

  Determine whether type T was declared as a struct type (i.e. using the struct or mutable
  struct keyword).

julia> xs = "test"; isstructtype(typeof(xs))
true

I clearly did not define xs using struct or mutable struct. Bug?

This category of
types is significant since they are valid as type parameters, may not track isdefined /
isassigned status, and have a defined layout that is compatible with C.

Thus, Symbol is also not an isbitstype but may be used as a type parameter.

How you define xs doesn’t matter, it’s the T, i.e. typeof(xs), that matters.

You never defined that, i.e. String and within Base it is indeed effectively defined as a struct.

FWIW, just in case it isn’t clear to you, the syntax you use for anything doesn’t matter, since you can always hide the actual syntax under a macro or function that you didn’t write. It’s what actually run at the lowest level that metters.

And what’s the problem?

1 Like

Thank you. I guess I misinterpreted what isstructtype meant from a user’s perspective who is not concerned about how String is implemented in the world of lower level code (perhaps I should be a bit more concerned about implementation details). Now, as far as isbitstype goes, I guess, I am just having an interpretation issue (again) with the documentation, expected it to return true for Symbol, since I that’s what I understand the isbitstype to mean, to mean types I can use as parameters to other types, but it seems I might have misunderstood that as well.

I am still not clear what an isbitstype is given the documentation:

  Return true if type T is a "plain data" type, meaning it is immutable and contains no references
  to other values, only primitive types and other isbitstype types. Typical examples are numeric
  types such as UInt8, Float64, and Complex{Float64}. This category of types is significant since
  they are valid as type parameters, may not track isdefined / isassigned status, and have a
  defined layout that is compatible with C.

and how Symbol is not an isbitstype. Is a symbol not “plain data”? My confusion mostly stems from the fact that I can do this

struct S{T} end
s = S{:some_symbol}

which seems to conform with the definition of isbitstype for Symbol.

This is the property, not the definition, so whatever you observe with the type parameter has nothing conflict with this property. It does not say that this category of types is the ONLY valid type parameters. In fact, Symbol is hardly the only exception.

Symbol is indeed special but it’s not immutable so it’s not isbitstype.

What exactly are you trying to do? The questions you are asking are fine but they aren’t something very useful for understanding much of julia.

1 Like

I am not an specialist, and probably a developer of the language would have a much better answer but:

  1. This category of types is significant since they are valid as type parameters [...] The fact that all types for which isbitstype returns true are valid as type parameters does not mean every type that returns false is invalid. This is a logic error.
  2. Do you know how Symbol is defined? I think it is here. For what I know about Symbols (that is mostly from Ruby, Julia sees the concept differently, but I think it implements in a similar fashion) they are a pointer for that string in a global table with all strings which were used as symbols at some moment. So their comparison is efficient (just a pointer equality) and :abc === :abc even if they are !isbits.

I am trying to employ the use of functions such as isstructtype and isbitstype, I ran into issues because I misunderstood how to use these functions, that is, the results were unexpected to me, I got the wrong behavior because I did not understand the documentation properly. Also, FWIW, the documentation, at least to me, seems a bit hard to interpret correctly (but that’s just my opinion). How is it hard? Case in point, my confusion.

Yes, I agree. I drew wrong conclusions from reading the documentation. Thanks for sharing the link to the source. It seems I am better off understanding a bit more how things are implemented in lower-level code. I do think it’s useful to understand that a Symbol comparison is efficient (only that before I was the under the impression that it would also mean that it would be an isbits, but like you pointed out, that was simply wrong logic).

The question is what are you using them for. What properties do you want to know about them.

I’m not saying that the documents are perfect but I don’t think these particular ones have much of a problem. For example, for isstructtype, you tested

and complained about xs not matching what the document says about T, i.e. the input to isstructtype. However, you should at least complain about typeof(xs) or String as what I said in the first reply and your question should be how is String defined. This would be a good question as there is indeed something special about it even though it doesn’t really conflict with the document of the function.

For the isbitstype, I personally think it’s also pretty clear that the “This category of types…” is talking about the properties and not the definition anymore, especially since it’s after the example list. If you really find it confusing, you are welcome to add clearifications that this sentense and whatever follows isn’t the definition anymore.

I am not complaining about anything. Just pointing out my confusion, I am ok if you feel these examples are clear. Thanks for your time and effort as a committer.