I have a struct defined as follows:
julia> struct test
test1::Int64
test2::Float64
end
I want to be able to see the names of the attributes in the struct as well as the type. What is the most straight forward way to do this? I know I can do:
julia> t = test(1,1.0)
test(1, 1.0)
julia> fieldnames(typeof(t))
(:test1, :test2)
but I would like to see the attribute name and type together.
Use fieldtypes(typeof(t))
julia> DataFrame(name=[fieldnames(typeof(t))...], type=[fieldtypes(typeof(t))...])
2×2 DataFrame
│ Row │ name │ type │
│ │ Symbol │ DataType │
├─────┼────────┼──────────┤
│ 1 │ test1 │ Int64 │
│ 2 │ test2 │ Float64 │
Regarding the other answer note that dump outputs always the entire data structure which is not good for fields having complex types. Try doing dump on a struct that has a Dict field to find out my point (or just try in the console) dump(Dict()).
The most straight forward way to do this would be to use the dump method:
help?> dump
search: dump
dump(x; maxdepth=8)
Show every part of the representation of a value. The depth of the
output is truncated at maxdepth.
So in this case, it would show:
julia> dump(t)
test
test1: Int64 1
test2: Float64 1.0
See here for more details: https://docs.julialang.org/en/v1/base/io-network/#Base.dump
Related
Using Documenter.jl, I keep getting these warnings:
┌ Warning: 60 docstrings not included in the manual:
│
│ ProtoSyn.Calculators.TorchANI.r_xml_travel! :: Union{Tuple{T}, Tuple{Union{LightXML.XMLDocument, LightXML.XMLElement}, String, Vector{T}}} where T<:AbstractFloat
│ ProtoSyn.Clustering.dunn_index :: Union{Tuple{T}, Tuple{Vector{T}, Matrix{T}}} where T<:AbstractFloat
│ ProtoSyn.Calculators.get_available_energy_function_components :: Tuple{Module}
│ Base.resize! :: Tuple{ProtoSyn.Calculators.VerletList, Int64}
│ ProtoSyn.Common
(...)
I want to ignore some (most) of these docstrings (they exist in the code base but I do not want to export them to the final documentation website). How can I ignore individual docstrings?
You should try suppressing such warnings by specifying the checkdocs keyword option when calling makedocs(). Using checkdocs=:exports complains only if the unused docstring's function is exported. If you use checkdocs=:none in makedocs that should cause makedocs to ignore the unused docstrings. You might lose some error warnings for malformed docstrings though.
I have a module, say, called Constants,
module Constants
const zero = 0.0 :: Float64
const czero = 0.0 + 0.0im :: Complex
end
I know like I can define like zero as Float64. But How do I define a "Complex" and "Float64" variable such as czero? Currently I use Complex, but I want to be more specific. If I use ComplexF64
const czero = 0.0 + 0.0im :: ComplexF64
it gives me an error,
ERROR: LoadError: TypeError: in typeassert, expected Complex{Float64}, got a value of type Complex{Bool}
So what concrete type of Complex should I use?
I give each variable a concrete type is because I heard that if the code looks like Fortran it can run like Fortran, because I define the type first so Julia do not have to convert the type which can be very slow.
This question is not quite clear, but perhpas what you need is zero:
julia> zero(ComplexF64)
0.0 + 0.0im
julia> dump(zero(ComplexF64))
ComplexF64
re: Float64 0.0
im: Float64 0.0
Other options include using the constructor such as ComplexF64(0.0) or ComplexF64(0.0,0.0) or using the complex(0.0) function. These are all type stable.
::
With the ::-operator type annotations are attached to expressions and variables in programs. See the manual section on Type Declarations.
Outside of declarations :: is used to assert that expressions and variables in programs have a given type.
Examples
≡≡≡≡≡≡≡≡≡≡
julia> (1+2)::AbstractFloat
ERROR: TypeError: typeassert: expected AbstractFloat, got a value of type Int64
julia> (1+2)::Int
3
With this in mind, obviously julia considers the declaration invalid because of operator precedence, so just put parentheses if you want to do the declaration this way
const czero = (0.0 + 0.0im) ::ComplexF64
I also second the opinion above: if you're just trying to declare zeros then what you need is zero
As an old C programmer, I use lots of asserts in my code. Now I want to globally switch them off to speed things up. What is the best practice way to do that?
There is no built-in option / command line flag to disable #asserts globally, yet(!).
For now, you can define a #myassert macro which, depending on a global switch, is a no-op or a regular #assert:
asserting() = false # when set to true, this will enable all `#myassert`s
macro mayassert(test)
esc(:(if $(#__MODULE__).asserting()
#assert($test)
end))
end
f(x) = #mayassert x < 2
(taken from https://discourse.julialang.org/t/assert-alternatives/24775/14)
You could put your #assert statements in a #debug block. Then the #assert call is desactivated, unless you activate debugging either globally (ENV["JULIA_DEBUG"] = "all") or just for your module (ENV["JULIA_DEBUG"] = "NameOfYourModule")
julia> #debug begin
#assert 1==2
end
#or
#debug #assert 1==2 # assert is not called
julia> ENV["JULIA_DEBUG"] = "all" # enable debugging
"all"
julia> #debug begin
#assert 1==2
end
┌ Error: Exception while generating log record in module Main at REPL[4]:1
│ exception =
│ AssertionError: 1 == 2
│ Stacktrace:
│ [1] top-level scope at REPL[4]:2
│ [2] top-level scope at logging.jl:319
| ...
└ # Main REPL[4]:1
Although it would be nice to have this feature, the need for #asserts in your code can be reduced by defining and dispatching on your own types. For example, suppose you have a function foo(t::TimeType) = t, but you only want to accept times that are a multiple of five minutes. You can create a new type with this requirement:
using Dates
struct FiveMinuteMultiple
t::DateTime
function FiveMinuteMultiple(y, m, d, h, mi)
if mi%5 != 0
throw(DomainError(m, "the minute argument must be a multiple of 5"))
end
new(DateTime(y, m, d, h, mi))
end
end
Now you literally can't create a FiveMinuteMultiple that is not a multiple of five minutes:
julia> t = FiveMinuteMultiple(2016, 7, 15, 4, 23)
ERROR: DomainError with 7:
the minute argument must be a multiple of 5
Stacktrace:
[1] FiveMinuteMultiple(::Int64, ::Int64, ::Int64, ::Int64, ::Int64) at ./REPL[2]:5
[2] top-level scope at none:0
julia> t = FiveMinuteMultiple(2016, 7, 15, 4, 25)
FiveMinuteMultiple(2016-07-15T04:25:00)
So if you now define foo(t::FiveMinuteMultiple) = t, you no longer need an #assert to verify that the argument is a time that is a multiple of five minutes. Sure, you still have to pay the cost of argument checking when you construct the FiveMinuteMultiple, but unless it's a hot inner loop you probably want that additional data validation anyways.
Advantages:
Method dispatch guarantees that the arguments to your functions are of the correct type.
You can avoid duplicating the same assertion across multiple functions foo(t::FiveMinuteMultiple), bar(t::FiveMinuteMultiple), and baz(t::FiveMinuteMultiple).
The more specific argument annotation alerts users and developers that the function expects a more specific type of data.
Disadvantages:
Depending on your use case, you may need to forward various methods to the data field within your struct. For example, for FiveMinuteMultiple you may need to forward methods such as day, hour, etc, to the t field of the struct.
Adding a new concept (type) to represent assertions about your data might introduce an unnecessary layer of abstraction.
When trying to clean up the code using #code_warntype I get the type instability of ::AbstractArray{T,1} when it is not expected.
A data frame is the argument of the function FUNC1, and a particular COLUMN in it is used within the function. I've defined the type for this COLUMN within the function as Array{Float64,1}. But, when I run #code_warntype on the function, ::AbstractArray{T,1} appears in the output.
function FUNC1(df::DataFrame)
df_COL=df[:COLUMN]::Array{Float64,1}
.......
end
Expected result is that there should be no type instability because the type has been specified for that column.
Actual results:
Body::Tuple{Float64,Float64}
│ 159 1 ── %1 = invoke Base.getindex(_2::DataFrame, :COLUMN::Symbol)::AbstractArray{T,1} where T
│ │ (Core.typeassert)(%1, Array{Float64,1})
│ │ %3 = π (%1, Array{Float64,1})
That's printing out exactly as I'd expect. There are three things that are happening here:
First the indexing: %1 = invoke Base.getindex — this is doing the indexing. It can return a vector of any type. This is indeed type-unstable.
Then the typeassert: (Core.typeassert)(%1, Array{Float64,1}) — this ensures that what getindex returned (in %1) is a Vector{Float64}. If it's not, Julia will throw an error.
And now the payoff: %3 = π (%1, Array{Float64,1}) — now that vector can be considered a Vector{Float64} since every other type would result in an error. From here on out, computations with the vector should be type-stable.
Adding type assertions like that don't "fix" the instability at its root, they simply patch it up so everything afterwards is fast.
I can make "literals" of type Int64 and even Uint8 in Julia:
julia> typeof(8)
Int64
julia> typeof(0x08)
Uint8
But I haven't been able to find out how to make a literal of type Int8. I have tried a few different things:
julia> 8::Int8
ERROR: type: typeassert: expected Int8, got Int64
julia> 0x08::Int8
ERROR: type: typeassert: expected Int8, got Uint8
julia> convert(Int8, 8)
8
julia> typeof(ans)
Int8
So the application of the convert function worked, but that's a somewhat wordy expression. I was wondering if there was something a little more concise, perhaps like Rust's 8i8.
I am using Julia 0.3.3, but answers for Julia 0.4.x would be fine too.
More convenient than convert(Int8, 8) is Int8(8) respective int8(8) on earlier versions. The reason that few number literal notations like 8i8 exist is that it conflicts with multiplication by juxtaposition.
julia> i8=8
8
julia> 3i8
24