Implementing a Swift undo stack the impossible way

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Implementing a Swift undo stack the impossible way

Jake Bromberg
I've been trying to implement an undo stack that leverages the type system in Swift. My particular approach is to memoize both the function used and the parameters passed to that function. If I can get this to work, as I see it, it would be an improvement over the pattern described in GOF. No success yet.

public struct Command <Parameters, Results> {
    let action : (Parameters -> Results)
    let parameters : Parameters

    init(action a : Parameters -> Results, parameters p : Parameters) {            action = a
        parameters = p
    }}

let cmd1 = Command(action: { return $0 + " World" }, parameters: ("Hello"))
let cmd2 = Command(action: { return $0 + $1 + $2 }, parameters: (1, 2, 3))

let undos = [cmd1, cmd2]

Error:

'_' is not convertible to 'Command<(Int, Int, Int), Int>'
Type of expression is ambiguous without more context

I get that the generic types are not equivalent for all instances of Command, but I'm not sure what the fix for this would be given the new semantics. 

I'm not going to define equality for every type of tuple that wants to participate in the undo system (this is more annoying than GOF).

So in an attempt to get the array to accept heterogeneous types, I tried pulling the generic types into a protocol as type aliases. Problem again: this only shifts the problem around, since it's the Command that now needs nail down the type of the alias, which forces a different Command implementation for each pair of associated types. 

At this point I've run out of ideas. What am I missing?

Thanks,
—Jake

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/CA%2B5croLgY2_bueJg%3DRqF5j6XqS4whRKDA2-hjKs%3DqQSNbToovQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a Swift undo stack the impossible way

Ken Ferry
What do you want it to look like when the undos are used? Something like

    undo.invoke()

?  If that's the case, I think you want to remove the parametrized types from Command<Parameters,Results>. They're not relevant to users of resulting commands. 

You can often remove type parameters by using closures (when they're inessential). For example,

    public struct Command  {
        let invoker : ()->()
        init<Parameters, Results>(action a : Parameters -> Results, parameters p : Parameters) {
            invoker = { a(p) }
        }
    }

    let cmd1 = Command(action: { return $0 + " World" }, parameters: ("Hello"))
    let cmd2 = Command(action: { return $0 + $1 + $2 }, parameters: (1, 2, 3))

    let undos = [cmd1, cmd2]

You could also consider whether you need a custom Command type at all, or whether a closure already does the trick.

-ken



On Thu, Jul 9, 2015 at 2:41 PM, Jake Bromberg <[hidden email]> wrote:

I've been trying to implement an undo stack that leverages the type system in Swift. My particular approach is to memoize both the function used and the parameters passed to that function. If I can get this to work, as I see it, it would be an improvement over the pattern described in GOF. No success yet.

public struct Command <Parameters, Results> {
    let action : (Parameters -> Results)
    let parameters : Parameters

    init(action a : Parameters -> Results, parameters p : Parameters) {            action = a
        parameters = p
    }}

let cmd1 = Command(action: { return $0 + " World" }, parameters: ("Hello"))
let cmd2 = Command(action: { return $0 + $1 + $2 }, parameters: (1, 2, 3))

let undos = [cmd1, cmd2]

Error:

'_' is not convertible to 'Command<(Int, Int, Int), Int>'
Type of expression is ambiguous without more context

I get that the generic types are not equivalent for all instances of Command, but I'm not sure what the fix for this would be given the new semantics. 

I'm not going to define equality for every type of tuple that wants to participate in the undo system (this is more annoying than GOF).

So in an attempt to get the array to accept heterogeneous types, I tried pulling the generic types into a protocol as type aliases. Problem again: this only shifts the problem around, since it's the Command that now needs nail down the type of the alias, which forces a different Command implementation for each pair of associated types. 

At this point I've run out of ideas. What am I missing?

Thanks,
—Jake

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/CA%2B5croLgY2_bueJg%3DRqF5j6XqS4whRKDA2-hjKs%3DqQSNbToovQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/1436480650637.8ac1e51d%40Nodemailer.
For more options, visit https://groups.google.com/d/optout.