1

I have read all the posts I can find here about arrays of functions - great you can do it. I figured. But none of the posts show practically how to use them (at least not what I'm trying to do). Here's what I want - they can all take the same args, but that's not a requirement.

This article is close, and will allow me to loop through to execute each function (which meets the first goal).
https://stackoverflow.com/a/24447484/11114752

But... what if I want to execute a single function by reference? In other words, how to call just the referenced Arity2 function - for example:

// None of these work (with or without the parameter labels)
funcs.Arity2(n: 2, S: "Fred)    // value of type [MyFuncs] has no member .Arity2
funcs[Arity2](n: 2, S: "Fred")  // no exact matches to call in subscript
funcs[.Arity2](n: 2, S: "Fred") // Cannot call value of non-function type...

let fn = funcs.first(where: { a whole ton of permutations here to try to match Arity2 }) -- a whole lotta frustrating nope...

Help, please! Nothing I've tried works. The pre-compiler just goes in circles making suggestions that don't pan out and it will not compile.

EDIT: The reason for the array in the first place is that I'm going to have a quite a few functions, and I don't know what they all are in advance. Essentially, I want a plugin type of architecture. Where I can add to the list of functions (ideally within an extension of the class, but that's another problem..) and not change the processing loop that executes each function in order.

9
  • Does this answer your question? How to access a Swift enum associated value outside of a switch statement Commented Sep 3, 2020 at 22:36
  • 2
    There's no need for the complexity of the answer you're following (unless you're doing something much more complicated than you're describing). Check the following answer to the same question (a lot of the answers on that page are dealing with pre-1.0 Swift): stackoverflow.com/a/26416417/97337 Write up an example of a couple of functions you're trying to call. How would you do this without an array? Just hard code them and show what you want to call, and we'll show how to turn that into an array. Commented Sep 3, 2020 at 22:39
  • I tried the pawello2222's answer - it does not work right with functions, which is my frustration. Commented Sep 3, 2020 at 22:56
  • @Rob - that's my alternative and what I'm working with now. First goal - execute all functions (in array order - first function first, second, ...). Second goal - access individually by name. So, looks like I'll need two arrays unless the named one also maintains the order they're declared (will need some testing). Commented Sep 3, 2020 at 22:59
  • Testing confirms order appears to be maintained as desired Commented Sep 4, 2020 at 15:51

2 Answers 2

1

I assume you need something like

    _ = funcs.first {
        if case let MyFuncs.Arity2(f) = $0 {
            f(2, "Fred")
            return true
        }
        return false
    }
Sign up to request clarification or add additional context in comments.

2 Comments

YES!! That's the magical incantation I was looking for - combining if, case and .first. Wow - gotta love Swift :). Given the complexity and the fact that I have to deal with a conditional, I'm rethinking my approach - but this answers the question - thank you.
Rechecked: This does seem to work even if I only know the name
0

It can be achieved in a much simpler way if you know the position of the function in the array.

Assuming you have:

func someFunc(n: Int, s: String) { 
    print("call \(n) \(s)")
}

var funcs = [MyFuncs.Arity2(someFunc)]

you can do:

if case .Arity2(let f) = funcs.first {
    f(2, "Fred")
}

By replacing funcs.first with funcs[i] you can access the i-th index (first make sure it does exist).

6 Comments

I like this. It compiles without complaint. However, I confirmed, in init(), I have: funcs.append(MyFuncs.Arity2(someFunc)) Also confirmed funcs contains Arity2 in debugger. But the if statement never fires (using either .first or [0])
@MichaelStone I assumed you know the position of your function in the array.
code var lFn = Array<MyFuncs>(). ... init(){ lFn.append(MyFuncs.Arity2(someFunc)) }. ... suggested if block above never executes the function. But this would be great if it did! I know the name (Arity2) and the position (0), but neither funcs.first, nor funcs[0] seems to satisfy the condition. Although I may not know the position in my actual usage. I was wrong, position is 1, and that does work. So, I still need .first(where; ...) if I only know the name.
@MichaelStone Yes, it only works if you know the position. Otherwise you need to search for the first matching signature as Asperi suggested.
Yeah, again - unless I'm missing something, it only seems to work if I specify the correct position (eg: if Arity2 is really the first element, or if I specify the correct position in brackets). I have as in the example Arity0 as the first element now and Arity2 in the second to ensure I am testing the correct scenario.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.