I'm looking at the this thread
I'm trying to understand the following line of code:
struct Foo end
(::Type{Float64})(::Foo) = "not a Float64"
It seems like it assigns a string to a variable of type Foo, but I don't see any variable declaration on the left-hand-side.
What is going on?
There's a few things going on here.
The line is a method, not a variable assignment. f(x) = "blah" is one-line syntax for
function f(x)
"blah"
end
The (::Foo) part is actually 1 annotated argument for the method. An argument's name can be omitted, you just can't use the argument in the method body because no variable references it. The argument only dispatches the method. For example, f(::Foo) = "blah" would work for f(Foo()) but not f(Bar()).
The (::Type{Float64}) part instead of a method name indicates this is a functor. (f::F)(x) = x*f.suffix means that instances of struct F can be called like a method F(".net")("something"). The name f isn't a method name and will not exist for you to use like one, it's there to reference the instance of F to be used in the method. The name can be omitted if it's not used in the method (::F)(x) = x*".com".
Type{Float64} is a type whose only instance is Float64, so this means that you can only use this method by calling Float64(Foo()). It seems to me that defining a method Base.Float64(::Foo) = "not a Float64" would be equivalent, I don't actually know why they opted for functor syntax.
When you see annotations surrounded by parentheses, the annotation can only belong to whatever is in the parentheses and to the left. f::Foo means f is annotated with Foo, f(::Foo) means an anonymous argument is annotated with Foo.
Related
Copied this into a jupyter notebook cell but can't get it to run and the message doesn't really help. Everything looks right.
mutable struct CircularArray{T} <: AbstractArray{T,1}
data::Array{T,1}
first::Int
CircularArray{T}(length::Int) where {T} = new{T}(Array{T, 1}(undef, length), 1)
end
a = CircularArray(10)
MethodError: no method matching CircularArray(::Int64)
I think the error is clear: you need to define CircularArray(length::Int). What you implemented, however, is a parametric constructor. To call your parametric constructor, you need to pass the parameter T with your constructor call, e.g.
a = CircularArray{Float64}(10);
You can also implement non-parametric constructor for a default type of your choice. For example;
CircularArray(length::Int) = CircularArray{Float64}(length)
After this your call to this constructor, CircularArray(10);, won't give a MethodError: no method matching CircularArray(::Int64).
Note the ; at the end of the commands. You need to define other methods (like size) for your array type so that display can work. Otherwise, you may get an error in REPL if you omit ; after the evaluations that return a CircularArray.
I'm trying to figure out a way to .invoke() methods of a single arg, without knowing the type of the arg at runtime.
For example, by passing a property name to the following function, I'd like to set the property's value. For now it's hard-coded as Double/TYPE, but really the function should be allowed to take any type of value arg.
The property names, and therefore the type of arg value is not known until runtime, however it appears the method requires an array of primitives, at least for number types.
(defn set-prop-val!
"Sets property value to value. Uses reflection."
[obj prop value]
(let [methodname (str "set" prop)]
(.. obj
getClass
(getMethod methodname (into-array [Double/TYPE]))
(invoke obj (into-array [value]) ))))
(set-prop-val! (Button.) "TranslateX" 13.99)
In the above function, trying instead (getMethod methodname (into-array [(class value)])) doesn't work, and I get NoSuchMethodException javafx.scene.control.Button.setTranslateX(java.lang.Double) because it wants a double not a Double.
What I'd like to do is for numbers to get the primitive type at runtime, but all attempts at calling a static method from an instance have failed, eg (. (class 19.5) TYPE) (in this case I get IllegalArgumentException No matching field found: TYPE for class java.lang.Class)
It seems only Double/TYPE works, even though (= (class 19.5) Double) returns true.
So a few questions come out of this:
How do I call a static method, such as TYPE from an instance?
Is there a use for double-array here? That will get me the array to carry the values for the .invoke, which doesn't even appear necessary anyway, but not the Class[double] array needed for .getMethod.
Should I use clojure.reflect instead?
I found I could just use clojure.lang.Reflector/invokeInstanceMethod to do exactly what I need.
In Julia am I allowed to create & use static fields? Let me explain my problem with a simplified example. Let's say we have a type:
type Foo
bar::Dict()
baz::Int
qux::Float64
function Foo(fname,baz_value,qux_value)
dict = JLD.load(fname)["dict"] # It is a simple dictionary loading from a special file
new(dict,baz_value,quz_value)
end
end
Now, As you can see, I load a dictionary from a jld file and store it into the Foo type with the other two variables baz and qux_value. Now, let's say I will create 3 Foo object type.
vars = [ Foo("mydictfile.jld",38,37.0) for i=1:3]
Here, as you can see, all of the Foo objects load the same dictionary. This is a quite big file (~10GB)and I don't want to load it many times. So,
I simply ask that, is there any way in julia so that, I load it just once and all of there 3 types can reach it? (That's way I simply use Static keyword inside the question)
For such a simple question, my approach might look like silly, but as a next step, I make this Foo type iterable and I need to use this dictionary inside the next(d::Foo, state) function.
EDIT
Actually, I've found a way right now. But I want to ask that whether this is a correct or not.
Rather than giving the file name to the FOO constructor, If I load the dictionary into a variable before creating the objects and give the same variable into all of the constructors, I guess all the constructors just create a pointer to the same dictionary rather than creating again and again. Am I right ?
So, modified version will be like that:
dict = JLD.load("mydictfile.jld")["dict"]
vars = [ Foo(dict,38,37.0) for i=1:3]
By the way,I still want to hear if I do the same thing completely inside the Foo type (I mean constructor of it)
You are making the type "too special" by adding the inner constructor. Julia provides default constructors if you do not provide an inner constructor; these just fill in the fields in an object of the new type.
So you can do something like:
immutable Foo{K,V}
bar::Dict{K,V}
baz::Int
qux::Float64
end
dict = JLD.load("mydictfile.jld")["dict"]
vars = [Foo(dict, i, i+1) for i in 1:3]
Note that it was a syntax error to include the parentheses after Dict in the type definition.
The {K,V} makes the Foo type parametric, so that you can make different kinds of Foo type, with different Dict types inside, if necessary. Even if you only use it for a single type of Dict, this will give more efficient code, since the type parameters K and V will be inferred when you create the Foo object. See the Julia manual: http://docs.julialang.org/en/release-0.5/manual/performance-tips/#avoid-fields-with-abstract-containers
So now you can try the code without even having the JLD file available (as we do not, for example):
julia> dict = Dict("a" => 1, "b" => 2)
julia> vars = [Foo(dict, i, Float64(i+1)) for i in 1:3]
3-element Array{Foo{String,Int64},1}:
Foo{String,Int64}(Dict("b"=>2,"a"=>1),1,2.0)
Foo{String,Int64}(Dict("b"=>2,"a"=>1),2,3.0)
Foo{String,Int64}(Dict("b"=>2,"a"=>1),3,4.0)
You can see that it is indeed the same dictionary (i.e. only a reference is actually stored in the type object) by modifying one of them and seeing that the others also change, i.e. that they point to the same dictionary object:
julia> vars[1].bar["c"] = 10
10
julia> vars
3-element Array{Foo{String,Int64},1}:
Foo{String,Int64}(Dict("c"=>10,"b"=>2,"a"=>1),1,2.0)
Foo{String,Int64}(Dict("c"=>10,"b"=>2,"a"=>1),2,3.0)
Foo{String,Int64}(Dict("c"=>10,"b"=>2,"a"=>1),3,4.0)
I often see something like the following in Julia:
convert(::Type{Point{Float64}}, ::Float64)
how does the (:: work? And what is the terminology for this?
Your answer can be found in the Julia documentation for defining conversions. To quote (with types switched to make it even more straightforward to read):
The type of the first argument of this method is a singleton
type, Type{Point{Float64}}, the only instance of which is
Point{Float64}. Thus, this method is only invoked when the first
argument is the type value Point{Float64}. Notice the syntax used
for the first argument: the argument name is omitted prior to the ::
symbol, and only the type is given. This is the syntax in Julia for a
function argument whose type is specified but whose value is never
used in the function body. In this example, since the type is a
singleton, there would never be any reason to use its value within the
body.
(Emphasis mine)
You will also encounter the foo(::SomeType) syntax in error messages, when trying to invoke a function with arguments of the wrong type (after all you can't show the argument names of a variant that does not exist). E.g:
julia> foo(x::Bool) = 3
foo (generic function with 1 method)
julia> foo(5)
ERROR: `foo` has no method matching foo(::Int64)
In Julia, is there any way to get the name of a passed to a function?
x = 10
function myfunc(a)
# do something here
end
assert(myfunc(x) == "x")
Do I need to use macros or is there a native method that provides introspection?
You can grab the variable name with a macro:
julia> macro mymacro(arg)
string(arg)
end
julia> #mymacro(x)
"x"
julia> #assert(#mymacro(x) == "x")
but as others have said, I'm not sure why you'd need that.
Macros operate on the AST (code tree) during compile time, and the x is passed into the macro as the Symbol :x. You can turn a Symbol into a string and vice versa. Macros replace code with code, so the #mymacro(x) is simply pulled out and replaced with string(:x).
Ok, contradicting myself: technically this is possible in a very hacky way, under one (fairly limiting) condition: the function name must have only one method signature. The idea is very similar the answers to such questions for Python. Before the demo, I must emphasize that these are internal compiler details and are subject to change. Briefly:
julia> function foo(x)
bt = backtrace()
fobj = eval(current_module(), symbol(Profile.lookup(bt[3]).func))
Base.arg_decl_parts(fobj.env.defs)[2][1][1]
end
foo (generic function with 1 method)
julia> foo(1)
"x"
Let me re-emphasize that this is a bad idea, and should not be used for anything! (well, except for backtrace display). This is basically "stupid compiler tricks", but I'm showing it because it can be kind of educational to play with these objects, and the explanation does lead to a more useful answer to the clarifying comment by #ejang.
Explanation:
bt = backtrace() generates a ... backtrace ... from the current position. bt is an array of pointers, where each pointer is the address of a frame in the current call stack.
Profile.lookup(bt[3]) returns a LineInfo object with the function name (and several other details about each frame). Note that bt[1] and bt[2] are in the backtrace-generation function itself, so we need to go further up the stack to get the caller.
Profile.lookup(...).func returns the function name (the symbol :foo)
eval(current_module(), Profile.lookup(...)) returns the function object associated with the name :foo in the current_module(). If we modify the definition of function foo to return fobj, then note the equivalence to the foo object in the REPL:
julia> function foo(x)
bt = backtrace()
fobj = eval(current_module(), symbol(Profile.lookup(bt[3]).func))
end
foo (generic function with 1 method)
julia> foo(1) == foo
true
fobj.env.defs returns the first Method entry from the MethodTable for foo/fobj
Base.decl_arg_parts is a helper function (defined in methodshow.jl) that extracts argument information from a given Method.
the rest of the indexing drills down to the name of the argument.
Regarding the restriction that the function have only one method signature, the reason is that multiple signatures will all be listed (see defs.next) in the MethodTable. As far as I know there is no currently exposed interface to get the specific method associated with a given frame address. (as an exercise for the advanced reader: one way to do this would be to modify the address lookup functionality in jl_getFunctionInfo to also return the mangled function name, which could then be re-associated with the specific method invocation; however, I don't think we currently store a reverse mapping from mangled name -> Method).
Note also that (1) backtraces are slow (2) there is no notion of "function-local" eval in Julia, so even if one has the variable name, I believe it would be impossible to actually access the variable (and the compiler may completely elide local variables, unused or otherwise, put them in a register, etc.)
As for the IDE-style introspection use mentioned in the comments: foo.env.defs as shown above is one place to start for "object introspection". From the debugging side, Gallium.jl can inspect DWARF local variable info in a given frame. Finally, JuliaParser.jl is a pure-Julia implementation of the Julia parser that is actively used in several IDEs to introspect code blocks at a high level.
Another method is to use the function's vinfo. Here is an example:
function test(argx::Int64)
vinfo = code_lowered(test,(Int64,))
string(vinfo[1].args[1][1])
end
test (generic function with 1 method)
julia> test(10)
"argx"
The above depends on knowing the signature of the function, but this is a non-issue if it is coded within the function itself (otherwise some macro magic could be needed).