What protocol to start with and where?

So I have a bit of an insane "calculator" application. This question/idea came up while using this static function on my Position type to find what percentage a position will be liquidated (closed):

public static func calculateCutLossPct(_ orders: [Order]) -> Double

However, upon realizing I needed to take segments of orders: [Order] and run those calculations on arbitrary parts or slices of the array, I thought I might be lucky but as I guessed this doesn't work:

func calculateCutLossPct(using indices: Range<Int>) -> Double {
        Position.calculateCutLossPct(position.orders[indices]
}

My first thought was "Ok, let's make Position.calculateCutLossPct generic!"

Now I think I don't like function overloading because that's (again I think) leaving swift to figure out what function to call at runtime. I'm open to suggestions for using overloading but I need efficient power consumption, speed, and lightweight. This application is going to be running a lot of computations over long arrays of orders so I assumed generics to be the right choice. And yes I totally realize most of my overhead will be in my implementation of the algorithms however, these calculations do get a little hairy and some functions call other functions to find the values they need so they can get started on their calculation and you probably get the gist, this doesn't seem to be the environment for utilizing overloading.

But now I'm very curious, what Collection Protocols should I use? Because....

This works:

static public func calculateCutLossPct<T: Sequence>(_ orders: T)

This works:

static public func calculateCutLossPct<T: RandomAccessCollection>(_ orders: T)

And this also works:

static public func calculateCutLossPct<T: Collection>(_ orders: T)

I guess my core issue is...how do I figure out what protocol to start generalizing functions and types with so that I have the option to specialize them further when the use cases arise?

TLDR: What collections protocol is most fundamental so I can continue to specialize code in the future for the use case as it appears and not focus too narrowly too soon?

There's a great graph showing the hierarchy of all the collection protocols at https://www.objc.io/blog/2019/03/26/collection-protocols/

The most general one is Sequence

1 Like

Thanks! :slight_smile:

1 Like

In addition, these 2 talks from WWDC 2018 might help as well:

Session 229: Using Collections Effectively

Session 406: Swift Generics (Expanded)

1 Like

If you're really only interested in slices of arrays then you probably want ArraySlice.

This happens at compile time not runtime, so there's no runtime penalty.

1 Like

I think you looking at this problem in the wrong direction. You don't need to make your function generic until you have to, and at that time you'll know what is common among the callers and will be able to find the protocol that fits between them. Trying to optimize early like this is classic over-optimization. I'm sure you're own time will be better spent writing the body of the function instead of figuring out how it might possibly be used. Most likely the real optimization will come later when you realize there's something to fix at a much higher level that would change everything.

For your specific problem, I don't understand how generics would relate to "long array" or why using generics would be better in that case. All a generic really provides is a way for the compiler to know that the type has the function available to it, it's really just to help the programmer and not for the program itself. And here, I don't see it helping you.

If you want speed and efficiency then stick to immutable types, use structs instead of classes whenever you can. You will find great speed ups if you can split the computation into parallel processing and immutability helps ensure the success of that.

Terms of Service

Privacy Policy

Cookie Policy