[Pitch] Memos for Struct Calculated Properties


(Jon Hull) #1

I saw a message come across about Memoization, and I thought of using a slightly different approach for similar benefit.

I commonly want to store the result of a complex calculation in a private variable in a struct to avoid recalculation cost… but now I have to mark that calculation as *mutating* even though it isn’t really mutating in the semantic sense (since it will have the same value). It is an implementation detail leaking out… the caller shouldn’t care if I am memoizing.

Also, my attempt to speed things up may have actually slowed things down, since a bunch of other stuff had to be copied...

It would be nice to mark a calculated property of a struct as “memo" so that the calculation result is stored… but the calculation shouldn’t need to be marked as mutable (unless it actually mutates other things). That memo should be automatically cleared whenever an actual mutating method is called on the struct.

Ideally, the compiler would eventually be smart enough to only clear the memos when properties used in the calculations change, but I think just clearing it whenever the struct is mutated is a good first step.

struct MyStruct {
    var a:Int
    var b:Int

    memo var c {
  //Complex calculation here
    }
}

let s = MyStruct(a:2, b:3)
print(s.c) // result of c is automatically memoized
print(s.c) // returns memoized result
s.a = 5 //This clears the memo for c as it may affect the calculation
print(s.c) // New result of c is automatically memoized

The other alternative is to do things manually. Letting the programmer declare special private variables on a struct that are allowed to mutate without the “mutating” key word. That is potentially more powerful, but also more error prone. I prefer the set-it-and-forget-it approach.

If “memo" is the wrong word for this, I am completely open to calling it something else. I would really like to see this functionality in Swift 3 though (whatever it is called).

Thanks,
Jon


(Wallacy) #2

We already have lazy properties to get what you are describing. But we need
to wait for the Properties Behavior for the ability to clean a precomputed
lazy var.

···

Em sáb, 7 de mai de 2016 11:27, Jonathan Hull via swift-evolution < swift-evolution@swift.org> escreveu:

I saw a message come across about Memoization, and I thought of using a
slightly different approach for similar benefit.

I commonly want to store the result of a complex calculation in a private
variable in a struct to avoid recalculation cost… but now I have to mark
that calculation as *mutating* even though it isn’t really mutating in the
semantic sense (since it will have the same value). It is an implementation
detail leaking out… the caller shouldn’t care if I am memoizing.

Also, my attempt to speed things up may have actually slowed things down,
since a bunch of other stuff had to be copied...

It would be nice to mark a calculated property of a struct as “memo" so
that the calculation result is stored… but the calculation shouldn’t need
to be marked as mutable (unless it actually mutates other things). That
memo should be automatically cleared whenever an actual mutating method is
called on the struct.

Ideally, the compiler would eventually be smart enough to only clear the
memos when properties used in the calculations change, but I think just
clearing it whenever the struct is mutated is a good first step.

struct MyStruct {
    var a:Int
    var b:Int

    memo var c {
//Complex calculation here
    }
}

let s = MyStruct(a:2, b:3)
print(s.c) // result of c is automatically memoized
print(s.c) // returns memoized result
s.a = 5 //This clears the memo for c as it may affect the calculation
print(s.c) // New result of c is automatically memoized

The other alternative is to do things manually. Letting the programmer
declare special private variables on a struct that are allowed to mutate
without the “mutating” key word. That is potentially more powerful, but
also more error prone. I prefer the set-it-and-forget-it approach.

If “memo" is the wrong word for this, I am completely open to calling it
something else. I would really like to see this functionality in Swift 3
though (whatever it is called).

Thanks,
Jon
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Jon Hull) #3

There is a subtle, but very important difference. Lazy properties let you defer a calculation until it is needed, but once it is set, it is set. Changing it to clear it would be a mutation.

The auto clearing behavior (on mutation of any part of the struct) of the memo proposal allows the calculation to lazily update as the struct is mutated. The key bit is that setting the memo doesn’t trip the mutation wires.

I am completely ok calling this feature “lazy” if that is a better fit/word, though it has a slightly different connotation to me.

Thanks,
Jon

···

On May 7, 2016, at 7:54 AM, Wallacy <wallacyf@gmail.com> wrote:

We already have lazy properties to get what you are describing. But we need to wait for the Properties Behavior for the ability to clean a precomputed lazy var.

Em sáb, 7 de mai de 2016 11:27, Jonathan Hull via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> escreveu:
I saw a message come across about Memoization, and I thought of using a slightly different approach for similar benefit.

I commonly want to store the result of a complex calculation in a private variable in a struct to avoid recalculation cost… but now I have to mark that calculation as *mutating* even though it isn’t really mutating in the semantic sense (since it will have the same value). It is an implementation detail leaking out… the caller shouldn’t care if I am memoizing.

Also, my attempt to speed things up may have actually slowed things down, since a bunch of other stuff had to be copied...

It would be nice to mark a calculated property of a struct as “memo" so that the calculation result is stored… but the calculation shouldn’t need to be marked as mutable (unless it actually mutates other things). That memo should be automatically cleared whenever an actual mutating method is called on the struct.

Ideally, the compiler would eventually be smart enough to only clear the memos when properties used in the calculations change, but I think just clearing it whenever the struct is mutated is a good first step.

struct MyStruct {
    var a:Int
    var b:Int

    memo var c {
  //Complex calculation here
    }
}

let s = MyStruct(a:2, b:3)
print(s.c) // result of c is automatically memoized
print(s.c) // returns memoized result
s.a = 5 //This clears the memo for c as it may affect the calculation
print(s.c) // New result of c is automatically memoized

The other alternative is to do things manually. Letting the programmer declare special private variables on a struct that are allowed to mutate without the “mutating” key word. That is potentially more powerful, but also more error prone. I prefer the set-it-and-forget-it approach.

If “memo" is the wrong word for this, I am completely open to calling it something else. I would really like to see this functionality in Swift 3 though (whatever it is called).

Thanks,
Jon
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution