I would like to able to define a static variable inside a Julia struct. E.g I would like to define something along the lines of:
mutable struct MyStruct
global const a = 1
b = 2
end
Then I would like to be able to access a, in a similar fashion to static constants in the Java or C++ languages, e.g:
MyStruct.a
I am very well aware that this way of writing code is not-Julian, and that I just could use a module for this purpose.
However, I am interested in whether it is possible or not for mutable structs.
E.g I am interested in in details why this is not possible and techniques to emulate this pattern of programming.
(edit since you asked for something that does not require an instance of the struct)
Another way to do this is:
julia> mutable struct MyStruct b::Int end
julia> a(::Type{MyStruct}) = 1
a (generic function with 1 method)
julia> a(MyStruct)
1
which is accessed as a(Mystruct) instead of MyStruct.a
============================================================
(first answer):
You will need one more struct, and the syntax would be x.a.a not x.a:
julia> struct A
a::Int
end
julia> A() = A(1)
A
julia> s = A()
A(1)
julia> s.a
1
julia> mutable struct MyStruct
a::A
b::Int
end
julia> MyStruct(b) = MyStruct(A(), b)
MyStruct
julia> c = MyStruct(3)
MyStruct(A(1), 3)
julia> c.a.a
1
julia> c.a.a = 5
ERROR: type A is immutable
Not sure exactly what you want, but
mutable struct MyStruct end
Base.getproperty(s::MyStruct, sym::Symbol) = (sym==:a ? 1 : getfield(s, sym))
julia> m = MyStruct()
julia> m.a
1
julia> m.a = 2
ERROR: type MyStruct has no field a
Stacktrace:
[1] setproperty!(::MyStruct, ::Symbol, ::Int64) at ./Base.jl:21
[2] top-level scope at REPL[18]:1
Or you can type MyStruct().a
You could also overload setproperty! to provide a more informative error message.
I think the answer you are actually looking for is a const variable outside of a struct. The reason static variables exist in OOP languages is that sometimes you want a variable that isn't connected to an instance of a class. In Julia, you can do that just by using a variable.
const a = 1
mutable struct Mystruct
b::Int
end
will provide the functionality you want. It won't look object oriented, because that isn't how Julia is designed.
Related
While refactoring my F# code, I found a record with a field of type bool ref:
type MyType =
{
Enabled : bool ref
// other, irrelevant fields here
}
I decided to try changing it to a mutable field instead
// Refactored version
type MyType =
{
mutable Enabled : bool
// other fields unchanged
}
Also, I applied all the changes required to make the code compile (i.e. changing := to <-, removing incr and decr functions, etc).
I noticed that after the changes some of the unit tests started to fail.
As the code is pretty large, I can't really see what exactly changed.
Is there a significant difference in implementation of the two that could change the behavior of my program?
Yes, there is a difference. Refs are first-class values, while mutable variables are a language construct.
Or, from a different perspective, you might say that ref cells are passed by reference, while mutable variables are passed by value.
Consider this:
type T = { mutable x : int }
type U = { y : int ref }
let t = { x = 5 }
let u = { y = ref 5 }
let mutable xx = t.x
xx <- 10
printfn "%d" t.x // Prints 5
let mutable yy = u.y
yy := 10
printfn "%d" !u.y // Prints 10
This happens because xx is a completely new mutable variable, unrelated to t.x, so that mutating xx has no effect on x.
But yy is a reference to the exact same ref cell as u.y, so that pushing a new value into that cell while referring to it via yy has the same effect as if referring to it via u.y.
If you "copy" a ref, the copy ends up pointing to the same ref, but if you copy a mutable variable, only its value gets copied.
You have the difference not because one is first-value, passed by reference/value or other things. It's because a ref is just a container (class) on its own.
The difference is more obvious when you implement a ref by yourself. You could do it like this:
type Reference<'a> = {
mutable Value: 'a
}
Now look at both definitions.
type MyTypeA = {
mutable Enabled: bool
}
type MyTypeB = {
Enabled: Reference<bool>
}
MyTypeA has a Enabled field that can be directly changed or with other word is mutable.
On the other-side you have MyTypeB that is theoretically immutable but has a Enabled that reference to a mutable class.
The Enabled from MyTypeB just reference to an object that is mutable like the millions of other classes in .NET. From the above type definitions, you can create objects like these.
let t = { MyTypeA.Enabled = true }
let u = { MyTypeB.Enabled = { Value = true }}
Creating the types makes it more obvious, that the first is a mutable field, and the second contains an object with a mutable field.
You find the implementation of ref in FSharp.Core/prim-types.fs it looks like this:
[<DebuggerDisplay("{contents}")>]
[<StructuralEquality; StructuralComparison>]
[<CompiledName("FSharpRef`1")>]
type Ref<'T> =
{
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
mutable contents: 'T }
member x.Value
with get() = x.contents
and set v = x.contents <- v
and 'T ref = Ref<'T>
The ref keyword in F# is just the built-in way to create such a pre-defined mutable Reference object, instead that you create your own type for this. And it has some benefits that it works well whenever you need to pass byref, in or out values in .NET. So you should use ref. But you also can use a mutable for this. For example, both code examples do the same.
With a reference
let parsed =
let result = ref 0
match System.Int32.TryParse("1234", result) with
| true -> result.Value
| false -> result.Value
With a mutable
let parsed =
let mutable result = 0
match System.Int32.TryParse("1234", &result) with
| true -> result
| false -> result
In both examples you get a 1234 as an int parsed. But the first example will create a FSharpRef and pass it to Int32.TryParse while the second example creates a field or variable and passes it with out to Int32.TryParse
I have an abstract container AbstractContainer parameterised over a type T which indicates the type of what is in the container. Every subtype (in this case FloatContainer) then specifies what's actually in the container (in this case a Float64).
Ideally I'd have a means of getting back what type is in the container if I only have the container type.
This way I could use it in another struct (in this example MultiplyBy)
I was thinking of doing it in a similar way to Julia's internal eltype function but I can't get it to work.
I always get a method error (see the last snippet for the detailed error message)
abstract type AbstractContainer{T} end
gettype(::Type{AbstractContainer{T}}) where T = T
struct FloatContainer <: AbstractContainer{Float64}
x::Float64
end
struct MultiplyBy{T<:AbstractContainer}
x::gettype(T)
end
function process(m::MultiplyBy, v::AbstractContainer)
return typeof(v)(m.x*v.x)
end
function main()
x = FloatContainer(2.0)
y = FloatContainer(3.0)
op = MultiplyBy{FloatContainer}(y)
z = process(op, x)
println(z.x)
end
main()
ERROR: LoadError: MethodError: no method matching gettype(::TypeVar)
Closest candidates are:
gettype(!Matched::Type{AbstractContainer{T}}) where T at /Users/.../test.jl:6
I must admit I'm very new to Julia but I'm very interested in learning more about it.
So any tips are appreciated - either on how to solve this problem differently or where my mistake is.
Determining element type
Your gettype does not work because it dispatches on abstract types, but your container objects will all have concrete types. You have to use the subtype operator in order to dispatch correctly.
Compare dispatch on abstract types:
julia> eltype1(::Type{AbstractContainer{T}}) where T = T
eltype1 (generic function with 1 method)
julia> eltype1(FloatContainer)
ERROR: MethodError: no method matching eltype1(::Type{FloatContainer})
Closest candidates are:
eltype1(::Type{AbstractContainer{T}}) where T at REPL[4]:1
Stacktrace:
[1] top-level scope at REPL[5]:1
julia> eltype1(AbstractContainer{Float64})
Float64
with dispatch on subtypes of abstract types:
julia> eltype2(::Type{<:AbstractContainer{T}}) where T = T
eltype2 (generic function with 1 method)
julia> eltype2(FloatContainer)
Float64
julia> eltype2(AbstractContainer{Float64})
Float64
Prefer dispatch variables to explicit eltype calls
Calling eltype directly is usually unnecessary; you can make the parametric type explicit during dispatch.
This solution uses only parametric types:
julia> struct Container{T}
x::T
end
julia> struct MultiplyBy{T}
x::T
end
julia> MulitplyBy(x::Container{T}) where T = MultiplyBy{T}(x.x)
MulitplyBy (generic function with 1 method)
julia> process(m::MultiplyBy, x::Container{T}) where T = Container{T}(m.x * x.x)
process (generic function with 1 method)
julia> a = Container(2.0)
Container{Float64}(2.0)
julia> b = Container(3.0)
Container{Float64}(3.0)
julia> op = MulitplyBy(b)
MultiplyBy{Float64}(3.0)
julia> process(op, a)
Container{Float64}(6.0)
i'm not sure about what you need, but i coded an working example with your structure:
abstract type AbstractContainer{T} end
#not necessary anymore
#gettype(a::Type{AbstractContainer{T}}) where T = T
struct FloatContainer{T<:AbstractFloat} <: AbstractContainer{T} #AbstractFloat, to include Float32, BigFloats and others
x::T
end
#you can't use functions on struct definitions, if you need more restrictions,
#use a Constructor
struct MultiplyBy{T<:AbstractContainer}
x::T
end
#example external Constructor
MultiplyBy(x::AbstractFloat) = MultiplyBy(FloatContainer(x))
value(x::AbstractContainer) = x.x #basic accesor function
value(x::MultiplyBy) = value(x.x)
function process(m::MultiplyBy, v::AbstractContainer)
return typeof(v)(value(m)*value(v)) #calling accesor functions to access the values.
end
function main()
x = FloatContainer(2.0)
y = FloatContainer(3.0)
op = MultiplyBy(y) #the parametric type is inferred automatically, no need to use Curly Braces
z = process(op, x)
println(value(x)) #better use accesor functions that direct access, as the underlying implementation can change
end
main()
In Julia, I want to have a mutable struct with an attribute which type is a Function, this function will have arguments:
mutable struct Class_example
function_with_arguments::Function
some_attribute::Int
function Class_example() new() end
function Class_example(function_wa::Function, some_a::Int)
this = new()
this.function_with_arguments = function_wa
this.some_attribute = some_a
this
end
end
I also want to do an action on this mutable struct :
function do_action_on_class(Class::Class_example)
return Class.function_with_arguments(Class.some_attribute ,2.0, true)
end
Then I define a function that aims to be my class attribute :
function do_something_function(arg1::Int, arg2::Float64, arg3::Bool)
if arg2 < 5.0
for i in 1:arg1
# Do Something Interesting
#show arg3
end
end
return 1
end
Finally, function_whith_arguments will be launch a huge number of time in my whole project, this is only a minimal example, so I want all this code to be very quick. That's why I use #code_warntype according to Julia's documentation Performance Tips
However, #code_warntype tells me this
body::Any
15 1 ─ %1 = (Base.getfield)(Class, :function_with_arguments)::Function
getproperty
%2 = (Base.getfield)(Class, :some_attribute)::Int64
%3 = (%1)(%2, 2.0, true)::Any │
return %3
Here, ::Function and the two ::Any are in red, indicating Julia can improve the performance of the code with a better implementation. So what's this correct implementation ? How should I declare my attribute function_whith_arguments as a Function type in my mutable struct ?
Whole code compilable :
mutable struct Class_example
function_with_arguments::Function
some_attribute::Int
function Class_example() new() end
function Class_example(function_wa::Function, some_a::Int)
this = new()
this.function_with_arguments = function_wa
this.some_attribute = some_a
this
end
end
function do_action_on_class(Class::Class_example)
return Class.function_with_arguments(Class.some_attribute ,2.0, true)
end
function do_something_function(arg1::Int, arg2::Float64, arg3::Bool)
if arg2 < 5.0
for i in 1:arg1
# Do Something Interesting
#show arg3
end
end
return 1
end
function main()
class::Class_example = Class_example(do_something_function, 4)
#code_warntype do_action_on_class(class)
end
main()
This will be efficient (well inferred). Note that I only modified (and renamed) the type.
mutable struct MyClass{F<:Function}
function_with_arguments::F
some_attribute::Int
end
function do_action_on_class(Class::MyClass)
return Class.function_with_arguments(Class.some_attribute ,2.0, true)
end
function do_something_function(arg1::Int, arg2::Float64, arg3::Bool)
if arg2 < 5.0
for i in 1:arg1
# Do Something Interesting
#show arg3
end
end
return 1
end
function main()
class::MyClass = MyClass(do_something_function, 4)
#code_warntype do_action_on_class(class)
end
main()
What did I do?
If you care about performance, you should never have fields of an abstract type, and isabstracttype(Function) == true. What you should do instead is parameterize on that fields type (F above, which can be any function. Note that isconcretetype(typeof(sin)) == true). This way, for any particular instance of MyCall the precise concrete type of every field is known at compile time.
Irrelevant for performance but: There is no need for a constructor that simply assigns all the arguments to all the fields. Such a constructor is defined by default implicitly.
You can read more about parametric types here.
On a side note, what you are doing looks a lot like trying to write OO-style in Julia. I'd recommend to not do this but instead use Julia the Julia way using multiple dispatch.
Basically, I am looking for something more or less equivalent to the following C code:
int theGlobalCount = 0;
int
theGlobalCount_get() { return theGlobalCount; }
void
theGlobalCount_set(int n) { theGlobalCount = n; return; }
You could use a neat trick: declare a mutable global variable, and make a ref (aka mutable reference) point to it (no GC is required to make this work!). Then, implement functions to provide access to the mutable reference.
local
var theGlobalCount_var : int = 0
val theGlobalCount = ref_make_viewptr (view# theGlobalCount_var | addr# theGlobalCount_var)
in // in of [local]
fun
theGlobalCount_get () : int = ref_get_elt (theGlobalCount)
fun
theGlobalCount_set (n: int): void = ref_set_elt (theGlobalCount, n)
end // end of [local]
Note that declarations inside local-in are visible only to code inside in-end. Therefore, neither theGlobalCount_var nor theGlobalCount are visible outside the scope of the local.
Full code: glot.io
You can also use the extvar feature to update an external global variable (declared in the target language). This is very useful if you compile ATS to a language that does not support explicit pointers (e.g., JavaScript). Here is a running example that makes use of this feature:
http://www.ats-lang.org/SERVER/MYCODE/Patsoptaas_serve.php?mycode_url=http://pastebin.com/raw/MsXhVE0A
Given the following:
use std::fmt::Debug;
#[derive(Debug)]
enum A<T: Debug> {
X,
Y(T),
}
#[derive(Debug)]
struct B;
type C = A<B>;
// use A<B> as C; // Does not compile
I can use it as:
fn main() {
let val0 = A::X::<B>;
let val1 = A::Y::<B>(B);
println!("{:?}\t{:?}", val0, val1);
}
But then for more than one generic parameter (or if A, B etc were much longer names then to alias it I tried the following but it doesn't compile:
fn main() {
let val0 = C::X;
let val1 = C::Y(B);
println!("{:?}\t{:?}", val0, val1);
}
with errors:
src/main.rs:656:16: 656:20 error: no associated item named `X` found for type `A<B>` in the current scope
src/main.rs:656 let val0 = C::X;
^~~~
src/main.rs:657:16: 657:20 error: no associated item named `Y` found for type `A<B>` in the current scope
src/main.rs:657 let val1 = C::Y(B);
As also noted i am unable to use use to solve the problem. Is there a way around it (because typing the whole thing seems to be cumbersome) ?
rustc --version
rustc 1.9.0 (e4e8b6668 2016-05-18)
Is there a way around it (because typing the whole thing seems to be cumbersome)?
You can specify C as the type of the variable so you can use A::X or A::Y without explicit specifying the type parameter:
let val0: C = A::X;
let val1: C = A::Y(B);