Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type

2015-01-21 Thread Keith Mason
I figured out my problem.  I was pre-creating and storing 
CFunction{Float64,Float64} objects in an Array{CFunction,1}.  This was 
causing f to be a CFunction rather than a CFunction{Float64,Float64}.  So 
the Julia compiler was a bit confused as to what my return type was going 
to be.

I've got it worked out, and it does work.  Thanks!

On Tuesday, January 20, 2015 at 10:19:51 PM UTC-6, Jeff Bezanson wrote:
>
> That's surprising; I get the same speedup in 0.3 with 
>
> function test2() 
> f = CFunction{Float64,Float64}(foo) 
> for i=1:1 
> r = call(f, 1.0) 
> goo(r) 
> end 
> end 
>

-- 


Please click here 
 for 
important information regarding this e-mail communication.


Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type

2015-01-20 Thread Keith Mason
I tried that, but it was slower than my initial method of calling f().

I even tried called ccall directly, but it also didn't solve the problem of 
type instability (which makes me feel like I'm missing something 
important), and it had an additional problem of not accepting its type 
arguments as variables.

I'm going to try 0.4 tomorrow and see how it goes.

On Tuesday, January 20, 2015 at 10:06:40 PM UTC-6, Jeff Bezanson wrote:
>
> Oops, that's right, `call` only exists in 0.4. Probably the quickest 
> way to make this work in 0.3 is to write `call(f, x)` instead of 
> `f(x)` where needed. 
>
> On Tue, Jan 20, 2015 at 10:14 PM, Keith Mason  > wrote: 
> > When I try this, I get an error: 
> > 
> > ERROR: type: test2: in apply, expected Function, got 
> > CFunction{Float64,Float64} 
> > 
> > 
> > It looks like "call" doesn't exist in version 0.3.  I suppose I need 0.4 
> to 
> > make this work.  It doesn't appear from the docs that call used to be 
> named 
> > something else. 
> > 
> > 
> > On Tuesday, January 20, 2015 at 4:54:08 PM UTC-6, Jeff Bezanson wrote: 
> >> 
> >> Here is a hack that basically works by escaping through the C type 
> system: 
> >> 
> >> ``` 
> >> immutable CFunction{R,A} 
> >> f 
> >> p::Ptr{Void} 
> >> CFunction(f) = new(f, cfunction(f, R, (A,))) 
> >> end 
> >> 
> >> call{R,A}(f::CFunction{R,A}, x) = ccall(f.p, R, (A,), x) 
> >> 
> >> foo(x::Float64) = 0.0 
> >> goo(x::Float64) = x 
> >> 
> >> function test1() 
> >> for i=1:1 
> >> f = foo 
> >> r = f(1.0) 
> >> goo(r) 
> >> end 
> >> end 
> >> 
> >> function test2() 
> >> f = CFunction{Float64,Float64}(foo) 
> >> for i=1:1 
> >> r = f(1.0) 
> >> goo(r) 
> >> end 
> >> end 
> >> ``` 
> >> 
> >> I added an argument to `foo` to increase the generality somewhat. 
> >> test1() is the original test case. test2() is the new version. The 
> >> CFunction object needs to be constructed outside the loop, but this 
> >> can be stored in a data structure and reused anywhere. 
> >> 
> >> -Jeff 
> >> 
> >> 
> >> On Tue, Jan 20, 2015 at 4:34 PM, Ivar Nesje  wrote: 
> >> > Originally posted at https://github.com/JuliaLang/julia/issues/9863 
> > 
> > 
> > 
> > 
> > Please click here for important information regarding this e-mail 
> > communication. 
>

-- 


Please click here 
<http://www.e-disclaimer.com/conning/AD21D06B4CC99D2B4F24BA73FB4EED83.htm> for 
important information regarding this e-mail communication.


Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type

2015-01-20 Thread Keith Mason
When I try this, I get an error:

ERROR: type: test2: in apply, expected Function, got 
CFunction{Float64,Float64}


It looks like "call" doesn't exist in version 0.3.  I suppose I need 0.4 to 
make this work.  It doesn't appear from the docs that call used to be named 
something else.

On Tuesday, January 20, 2015 at 4:54:08 PM UTC-6, Jeff Bezanson wrote:
>
> Here is a hack that basically works by escaping through the C type system: 
>
> ``` 
> immutable CFunction{R,A} 
> f 
> p::Ptr{Void} 
> CFunction(f) = new(f, cfunction(f, R, (A,))) 
> end 
>
> call{R,A}(f::CFunction{R,A}, x) = ccall(f.p, R, (A,), x) 
>
> foo(x::Float64) = 0.0 
> goo(x::Float64) = x 
>
> function test1() 
> for i=1:1 
> f = foo 
> r = f(1.0) 
> goo(r) 
> end 
> end 
>
> function test2() 
> f = CFunction{Float64,Float64}(foo) 
> for i=1:1 
> r = f(1.0) 
> goo(r) 
> end 
> end 
> ``` 
>
> I added an argument to `foo` to increase the generality somewhat. 
> test1() is the original test case. test2() is the new version. The 
> CFunction object needs to be constructed outside the loop, but this 
> can be stored in a data structure and reused anywhere. 
>
> -Jeff 
>
>
> On Tue, Jan 20, 2015 at 4:34 PM, Ivar Nesje  > wrote: 
> > Originally posted at https://github.com/JuliaLang/julia/issues/9863 
>

-- 


Please click here 
 for 
important information regarding this e-mail communication.


Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type

2015-01-20 Thread Keith Mason
It is, but I created a form that forces it to not be inlined, and that 
still runs in just 30 ms.

On Tuesday, January 20, 2015 at 4:57:00 PM UTC-6, Jeff Bezanson wrote:
>
> Oh, I should also mention that the version that calls goo(foo()) takes 
> so little time because the entire loop is probably optimized out. 
>
> On Tue, Jan 20, 2015 at 5:54 PM, Jeff Bezanson  > wrote: 
> > Here is a hack that basically works by escaping through the C type 
> system: 
> > 
> > ``` 
> > immutable CFunction{R,A} 
> > f 
> > p::Ptr{Void} 
> > CFunction(f) = new(f, cfunction(f, R, (A,))) 
> > end 
> > 
> > call{R,A}(f::CFunction{R,A}, x) = ccall(f.p, R, (A,), x) 
> > 
> > foo(x::Float64) = 0.0 
> > goo(x::Float64) = x 
> > 
> > function test1() 
> > for i=1:1 
> > f = foo 
> > r = f(1.0) 
> > goo(r) 
> > end 
> > end 
> > 
> > function test2() 
> > f = CFunction{Float64,Float64}(foo) 
> > for i=1:1 
> > r = f(1.0) 
> > goo(r) 
> > end 
> > end 
> > ``` 
> > 
> > I added an argument to `foo` to increase the generality somewhat. 
> > test1() is the original test case. test2() is the new version. The 
> > CFunction object needs to be constructed outside the loop, but this 
> > can be stored in a data structure and reused anywhere. 
> > 
> > -Jeff 
> > 
> > 
> > On Tue, Jan 20, 2015 at 4:34 PM, Ivar Nesje  > wrote: 
> >> Originally posted at https://github.com/JuliaLang/julia/issues/9863 
>

-- 


Please click here 
 for 
important information regarding this e-mail communication.


[julia-users] convincing Julia that a function call (via a variable) has a stable return type

2015-01-20 Thread Keith Mason


I am trying to make use of functions as data, where I store functions in an 
array and call them in a loop. All of my functions return Float64, but 
because I am assigning the function to a variable before calling it, Julia 
can't figure that out.

Here's some example code:

foo() = 0.0
goo(x::Float64) = x

So if I am to call goo(foo()), this is quite type stable and results in 
virtually no code. If I call it in a loop 100,000,000 times, it takes about 
a millisecond.

However, if I do this:

function test1()
  for i=1:1
f = foo
r = f()
goo(r)
  end
end

Now I'm in trouble. Even though Julia knows that foo returns a float, it 
doesn't know that f returns a float. This code in a loop of 100,000,000 
takes nearly 8 seconds and allocates 32GB of RAM. (Honestly, this strikes 
me as an optimization that just doesn't yet exist, but my use case is a 
little more complicated; in my case, f can be one of multiple functions, 
selected by a parameter. But let's set that aside for the purposes of this 
question.)

Declaring the type of the variable doesn't help; in fact, it makes it worse:

function test2()
  for i=1:1
f = foo
r::Float64 = f()
goo(r)
  end
end

But I can improve the situation a bit by casting the result of the function.

function test3()
  for i=1:1
f = foo
r = f()::Float64
goo(r)
  end
end

This cuts run time and memory allocation in half. But it is still taking 
too long because it has to check if f returns a float before assigning it 
to t. @code_lowered shows that a call to typeassert is the culprit here. Is 
there any way I can promise Julia that f returns float so it doesn't have 
to call typeassert? I tried

f::Function{Float64} = foo

and

f::Function::Float64

but I can't find any syntax that works. I know there is a macro @inbounds 
 to turn off bounds checking; is there 
something similar that turns off type checking?

-- 


Please click here 
 for 
important information regarding this e-mail communication.


Re: [julia-users] function hook into variable changes

2014-03-26 Thread Keith Mason

>
> I'll expand on my iphone post with some pseudo-code. 


This is interesting; not something I was aware was possible.  I'll dig into 
it a bit deeper, thanks!

On Tuesday, March 25, 2014 10:22:48 PM UTC-5, Jameson wrote:
>
> I'll expand on my iphone post with some pseudo-code. 
>
> do blocks make a convenient way to express the concept of a group of 
> actions. using this, we can implement simple, behind-the-scenes atomic 
> storage semantics. note that I'm (mis)treating saveable as both some 
> reference into the database, and it's value. 
>
> function atomic_action(callable, saveable) 
>old_row = copy(saveable) 
>lock_row(saveable) 
>try 
>  callable(saveable) 
>  save_row(saveable - old_row) 
>finally 
>  unlock_row(saveable) 
>end 
> end 
> function eager_atomic_action(callable, saveable) 
> old_saveable = get_current(saveable) 
> callable(saveable) 
> lock_row(saveable) 
> try 
>assert_that( old_saveable == get_current(saveable)) 
>save_row(saveable) 
> finally 
>unlock_row(savable) 
> end 
> end 
>
> atomic_action(a) do b 
>   b.x += 2 
> end # b.x is saved here, unless we threw an error 
>
>
> On Tue, Mar 25, 2014 at 10:57 PM, Stefan Karpinski 
> > 
> wrote: 
> > On Tue, Mar 25, 2014 at 8:11 PM, Keith Mason 
> > > 
> wrote: 
> >> 
> >> Got it, thanks. In these terms, I guess I wish that there was an option 
> >> for mutable composite types to be stored inline rather than heap 
> allocated. 
> > 
> > 
> > That's often called a (mutable) value type. E.g. C# distinguishes 
> reference 
> > types – objects that are passed and assigned by reference/sharing – from 
> > value types, which are like C structs and are passed and assigned by 
> > copying. (If you think of reference types as pointers to objects, you're 
> > basically right). Rather than introducing two radically semantically 
> > different kinds of types, we opted for mutable versus immutable which 
> have 
> > the same semantics except for the obvious difference that you can't 
> mutate 
> > an immutable value. This distinction is much simpler to understand and 
> nice 
> > for lots of things, but it is occasionally limiting. 
> > 
> >> Anyway, this has been helpful, if only to confirm that there isn't a 
> great 
> >> way to do what I want. I need to rethink the problem space. 
> > 
> > 
> > Have you considered column-oriented storage where each column is 
> homogenous 
> > and can be mmapped? 
>


Re: [julia-users] function hook into variable changes

2014-03-26 Thread Keith Mason

>
> Have you considered column-oriented storage where each column is 
> homogenous and can be mmapped?
>
 
That is actually the direction I am going in.  It doesn't make sense for 
all of my tables, but I think it might be the right approach for most of 
them.

On Tuesday, March 25, 2014 9:57:08 PM UTC-5, Stefan Karpinski wrote:
>
> On Tue, Mar 25, 2014 at 8:11 PM, Keith Mason 
> > wrote:
>
>> Got it, thanks. In these terms, I guess I wish that there was an option 
>> for mutable composite types to be stored inline rather than heap allocated.
>>
>
> That's often called a (mutable) value type. E.g. C# distinguishes 
> reference types – objects that are passed and assigned by reference/sharing 
> – from value types, which are like C structs and are passed and assigned by 
> copying. (If you think of reference types as pointers to objects, you're 
> basically right). Rather than introducing two radically semantically 
> different kinds of types, we opted for mutable versus immutable which have 
> the same semantics except for the obvious difference that you can't mutate 
> an immutable value. This distinction is much simpler to understand and nice 
> for lots of things, but it is occasionally limiting.
>
> Anyway, this has been helpful, if only to confirm that there isn't a great 
>> way to do what I want. I need to rethink the problem space.
>>
>
> Have you considered column-oriented storage where each column is 
> homogenous and can be mmapped?
>


Re: [julia-users] function hook into variable changes

2014-03-25 Thread Keith Mason
Got it, thanks. In these terms, I guess I wish that there was an option for 
mutable composite types to be stored inline rather than heap allocated.

Anyway, this has been helpful, if only to confirm that there isn't a great way 
to do what I want. I need to rethink the problem space.

> On Mar 25, 2014, at 6:20 PM, Stefan Karpinski  wrote:
> 
>> On Tue, Mar 25, 2014 at 6:32 PM, Keith Mason  wrote:
>> Why not foos[1].bar instead of the 'convert / unsafe_load' code?
> 
> Because I wanted to show that the values are stored inline, rather than heap 
> allocated. That may have been clear to me but perhaps not so clear to anyone 
> else. Consider, for comparison, the mutable version of the same code:
> 
> julia> type Foo
>  bar::Int
>  baz::Float64
>end
> 
> julia> foos = Array(Foo,10)
> 10-element Array{Foo,1}:
>  #undef
>  #undef
>  #undef
>  #undef
>  #undef
>  #undef
>  #undef
>  #undef
>  #undef
>  #undef
> 
> julia> foos[1] = Foo(1,2)
> Foo(1,2.0)
> 
> julia> p = convert(Ptr{Int}, pointer(foos))
> Ptr{Int64} @0x7ff47514f030
> 
> julia> unsafe_load(p,1)
> 140687914392808
> 
> julia> unsafe_load(p,2)
> 0
> 
> There are a number of differences, all stemming from the fact that mutable 
> Foos must be individually heap allocated, rather than stored inline in the 
> array. Thus, an uninitialized slot in an Array{Foo} is #undef (null pointers 
> under the hood), rather than whatever junk happens to be the memory that is 
> allocated, as happens in the immutable version. When you get the first 64-bit 
> value at the offset of the array, you get a pointer to a heap-allocated Foo 
> value, rather than the data of that Foo value. The next value after that is a 
> null pointer. We can poke a bit further by following the pointer:
> 
> julia> pp = convert(Ptr{Int},unsafe_load(p,1))
> Ptr{Int64} @0x7ff475295ce8
> 
> julia> unsafe_load(pp,1)
> 140687913054080
> 
> julia> unsafe_load(pp,2)
> 1
> 
> julia> unsafe_load(pp,3)
> 4611686018427387904
> 
> The first 64-bit value at the pointer location are a type tag indicating what 
> kind of value this thing is; the second and third 64-bit blobs are the values 
> of the .bar and .baz fields.


Re: [julia-users] function hook into variable changes

2014-03-25 Thread Keith Mason
Why not foos[1].bar instead of the 'convert / unsafe_load' code?

While my data really isn't immutable, this might be ok if there is a relatively 
cheap way to create a copy of an immutable object while changing one or two 
values.  For example,

immutable Foo
  x::Int
  y::Float64
  Foo(old::Foo; x = old.x, y = old.y) = new(x,y)
end
map[1] = Foo(map[1], x = 1)

But this seems expensive, particularly with many more than two fields (I'm 
thinking between 8 and 20). And it seems to be getting back to ugly, since it 
isn't much different than setfield(foo, :x, 1).

Plus, unlike with setfield, I don't see a way of passing x=1 programmatically, 
like by passing a tuple or something containing (:x,1) to Foo's constructor.

Can I safely use pointer conversion to overwrite the data inside an immutable 
object, thereby making it mutable? I would think not; it seems dangerous.

Is there any documentation on the internal functions like unsafe_load in your 
example? Or even just a list of them? I don't mind playing under the covers, 
even if that means my code breaks between versions of Julia.

> On Mar 25, 2014, at 4:44 PM, Jameson Nash  wrote:
> 
> Or you could make a do block, to create a scope for an explicit finalization 
> step
> 
>> On Tuesday, March 25, 2014, Stefan Karpinski  wrote:
>> If you use an immutable type and replace whole records, then you can mmap it:
>> 
>> julia> immutable Foo
>>  bar::Int
>>  baz::Float64
>>end
>> 
>> julia> foos = Array(Foo,10)
>> 10-element Array{Foo,1}:
>>  Foo(0,0.0)
>>  Foo(0,0.0)
>>  Foo(0,0.0)
>>  Foo(0,0.0)
>>  Foo(0,0.0)
>>  Foo(0,0.0)
>>  Foo(0,0.0)
>>  Foo(0,0.0)
>>  Foo(0,0.0)
>>  Foo(0,0.0)
>> 
>> julia> foos[1] = Foo(1,2)
>> Foo(1,2.0)
>> 
>> julia> p = convert(Ptr{Int},pointer(foos))
>> Ptr{Int64} @0x7ff36d436af0
>> 
>> julia> unsafe_load(p,1)
>> 1
>> 
>> julia> unsafe_load(p,2)
>> 4611686018427387904
>> 
>> julia> reinterpret(Float64,unsafe_load(p,2))
>> 2.0
>> 
>> Not as convenient as mutating these in place, but maybe ok.
>> 
>> 
>>> On Tue, Mar 25, 2014 at 5:35 PM, Keith Mason  wrote:
>>> This is a database application, with a large number of rows per table. So 
>>> probably not, for two reasons.
>>> 
>>> One, in the event the application crashes, I would like the data to be 
>>> updated to disk on a per transaction basis. I can deal with the problem of 
>>> when to call flush() separately.
>>> 
>>> Two, I would still need to keep track of which data had been updated, so I 
>>> only have to write the data that had been changed. Same problem applies.
>>> 
>>> Keith
>>> 
>>>> On Mar 25, 2014, at 4:14 PM, Jameson Nash  wrote:
>>>> 
>>>> Could you do all of the work in a finalizer ?
>>>> 
>>>>> On Tuesday, March 25, 2014, Keith Mason  wrote:
>>>>> I definitely understand that.  I would honestly prefer to be able to 
>>>>> memory map directly to the disk file and let the OS do the writes behind 
>>>>> the scenes.  Less potential for performance penalties that way.  But I 
>>>>> haven't found a way in Julia to do that.  mmap_array obviously only takes 
>>>>> arrays and not singular objects.  I could, of course, mmap_array a type 
>>>>> into an array of length 1.  But the real problem is that composite types 
>>>>> are handled as pointers, so mmap_array on a composite type results in the 
>>>>> pointers being written to disk and not the actual data. Obvious problems 
>>>>> abound with that.
>>>>> 
>>>>> I have had success in using mmap_array on immutable types, but the 
>>>>> problem with that is that they are immutable.  I need to be able to 
>>>>> modify individual fields.
>>>>> 
>>>>> In C, I can declare a struct, and then cast the pointer of the mmap 
>>>>> function to the struct pointer.  That doesn't seem to be an option in 
>>>>> Julia.
>>>>> 
>>>>> If there is another solution I haven't thought of yet, I'm all ears!
>>>>> 
>>>>>> On Tuesday, March 25, 2014 4:02:09 PM UTC-5, Patrick O'Leary wrote:
>>>>>>> On Tuesday, March 25, 2014 3:48:22 PM UTC-5, Keith Mason wrote:
>>>>>>> I have a number of variables based on composite types. I want the 
>>>>>>> fields of these variables synced to disk, so that every time I modify a 
>>>>>>> field, the data is written to disk. Is there any way to do this with 
>>>>>>> assignment notation?
>>>>>> 
>>>>>> As a more general note, hiding something as expensive as disk access 
>>>>>> behind an overloaded `setfield!()` may make performance characteristics 
>>>>>> less intuitive, and make tuning that performance--say, by batching 
>>>>>> operations together--more difficult. Something to think about.


Re: [julia-users] function hook into variable changes

2014-03-25 Thread Keith Mason
This is a database application, with a large number of rows per table. So 
probably not, for two reasons.

One, in the event the application crashes, I would like the data to be updated 
to disk on a per transaction basis. I can deal with the problem of when to call 
flush() separately.

Two, I would still need to keep track of which data had been updated, so I only 
have to write the data that had been changed. Same problem applies.

Keith

> On Mar 25, 2014, at 4:14 PM, Jameson Nash  wrote:
> 
> Could you do all of the work in a finalizer ?
> 
>> On Tuesday, March 25, 2014, Keith Mason  wrote:
>> I definitely understand that.  I would honestly prefer to be able to memory 
>> map directly to the disk file and let the OS do the writes behind the 
>> scenes.  Less potential for performance penalties that way.  But I haven't 
>> found a way in Julia to do that.  mmap_array obviously only takes arrays and 
>> not singular objects.  I could, of course, mmap_array a type into an array 
>> of length 1.  But the real problem is that composite types are handled as 
>> pointers, so mmap_array on a composite type results in the pointers being 
>> written to disk and not the actual data. Obvious problems abound with that.
>> 
>> I have had success in using mmap_array on immutable types, but the problem 
>> with that is that they are immutable.  I need to be able to modify 
>> individual fields.
>> 
>> In C, I can declare a struct, and then cast the pointer of the mmap function 
>> to the struct pointer.  That doesn't seem to be an option in Julia.
>> 
>> If there is another solution I haven't thought of yet, I'm all ears!
>> 
>>> On Tuesday, March 25, 2014 4:02:09 PM UTC-5, Patrick O'Leary wrote:
>>>> On Tuesday, March 25, 2014 3:48:22 PM UTC-5, Keith Mason wrote:
>>>> I have a number of variables based on composite types. I want the fields 
>>>> of these variables synced to disk, so that every time I modify a field, 
>>>> the data is written to disk. Is there any way to do this with assignment 
>>>> notation?
>>> 
>>> As a more general note, hiding something as expensive as disk access behind 
>>> an overloaded `setfield!()` may make performance characteristics less 
>>> intuitive, and make tuning that performance--say, by batching operations 
>>> together--more difficult. Something to think about.


[julia-users] Re: function hook into variable changes

2014-03-25 Thread Keith Mason
I definitely understand that.  I would honestly prefer to be able to memory 
map directly to the disk file and let the OS do the writes behind the 
scenes.  Less potential for performance penalties that way.  But I haven't 
found a way in Julia to do that.  mmap_array obviously only takes arrays 
and not singular objects.  I could, of course, mmap_array a type into an 
array of length 1.  But the real problem is that composite types are 
handled as pointers, so mmap_array on a composite type results in the 
pointers being written to disk and not the actual data. Obvious problems 
abound with that.

I have had success in using mmap_array on immutable types, but the problem 
with that is that they are immutable.  I need to be able to modify 
individual fields.

In C, I can declare a struct, and then cast the pointer of the mmap 
function to the struct pointer.  That doesn't seem to be an option in Julia.

If there is another solution I haven't thought of yet, I'm all ears!

On Tuesday, March 25, 2014 4:02:09 PM UTC-5, Patrick O'Leary wrote:
>
> On Tuesday, March 25, 2014 3:48:22 PM UTC-5, Keith Mason wrote:
>>
>> I have a number of variables based on composite types. I want the fields 
>> of these variables synced to disk, so that every time I modify a field, the 
>> data is written to disk. Is there any way to do this with assignment 
>> notation?
>>
>
> As a more general note, hiding something as expensive as disk access 
> behind an overloaded `setfield!()` may make performance characteristics 
> less intuitive, and make tuning that performance--say, by batching 
> operations together--more difficult. Something to think about.
>


[julia-users] function hook into variable changes

2014-03-25 Thread Keith Mason
I have a number of variables based on composite types. I want the fields of 
these variables synced to disk, so that every time I modify a field, the 
data is written to disk. Is there any way to do this with assignment 
notation?

For example,

type Foo
  x::Int32
  y::Int16
  z::Int16

  function Foo(x,y,z)
s = stream("foo",true, true, true, false, false)
write(s, x)
write(s, y)
write(s, z)
  end
end

f=Foo(1,2,3)
...
f.z = 4


The constructor will write the initial values to disk.  What kind of code 
can I add to this program so that the assignment of f.z seeks to the disk 
location where z is stored and writes the new value.  I don't mind 
implementing a function like

function update(value, name::Symbol, x)

  T = type(value) 

  index = indexin([:x], convert(Array{Symbol,1},names(T))) 

  seek(s, fieldoffsets(T)[index])
  write(s, x)
  setfield(value, name, x)

end


but I don't want to have to call update(f, :z, 4) everywhere in the code 
that wants to change f.  I want to write f.z=4. Otherwise, the user of my 
type may forget and cause inconsistency between data in memory and data on 
disk.

I know that some languages have triggers, where a function can be called 
when a variable is modified, and I know that I can write functions to 
replace operators in Julia.  But I cannot find any such trigger 
functionality in Julia, nor can I seem to override the assignment operator 
(=).

function =(x, v)  

...

end

 


doesn't work; it tells me "syntax: unexpected =".

The docs state that there is a setfield! function that is called for a.b = 
c, but the language disagrees.  Apparently it's actually named setfield (no 
exclamation point).  And it's not a function I can replace.

setfield(x, name::Symbol, value) = println("$name")


reports "invalid method definition: not a generic function".  So, setfield 
cannot be overridden.

Do I have any options?

Thanks,
Keith