Hello everybody, a question about expressions and arrays here. I have

Certified Associate Developer
Hello everybody, a question about expressions and arrays here.

I have a function that takes an array of users.

I have multiple arrays of users that I want to call my function on after applying a merge (ie: I want to call my function on the first element of each array, then the second of each array, etc etc). However the apply function treats the result of a merge as individual arguments instead of a single array object when calling my expression. Wrapping the _ placeholder in the apply function with curly brackets causes a syntax error as does casting the result of the merge to a user list.

Has anyone dealt with this before and if so how did you resolve it?

OriginalPostID-138030

OriginalPostID-138030

  Discussion posts and replies are publicly visible

  • 0
    Certified Lead Developer
    From my experience, the best (and MAYBE only) solution to your issue may be to write a sub-function which you call via apply(), which then itself uses apply() to iterate over the smaller arrays it gets passed.

    So something like this maybe(?):
    apply(rule!myFunction_sub, local!mergedList);

    rule!myFunction_sub:
    apply(fn!desiredFunction, ri!smallerArray)
  • 0
    Certified Associate Developer
    Thanks for the thought Mr. Schmitt but that still leaves me with a different problem - I want to make my function work over a dynamic number of input values (ie: array of any size). In order to create a working wrapper function I will need to create different versions with 1, 2, 3, 4, etc etc inputs. Given my expected use case (20+ inputs) that won't really work for me :)
  • 0
    Certified Lead Developer
    I may be misunderstanding somewhat, then, sorry - can you slightly expand upon your use case or give an example of some sort?
  • 0
    Certified Associate Developer
    In my specific example I have a dynamic number of CDTs, each with several userIds. I need to check each CDT to determine if any of those userIDs are inactive within the system.
    Unfortunately I need perform this test on several different types of CDTs each with a different number of userIds.

    I have written a single expression which, given a dynamic number of user Ids, will return the number of active logins. My issue arises when trying to apply the function.
    Specifically I receive an error message stating that the expression expects 1 parameter but received X (where X is the number of userIDs I am testing at the moment).
  • 0
    Certified Lead Developer
    It still sounds doable to me; it sounds like you're saying your CDT has a mulitple-type integer component (let's call it CDT.UserIDs), and you'll be using an array of such CDTs.

    Your sub-rule, I think, should be doing the check across the ID array of *one* CDT, such as: "apply(rule!checkUserIDActive, ri!thisCDT.UserIDs". (this would be rule "myFunction_sub", ri!thisCDT would be "any type")

    You would then call this from a parent rule, such as this: apply(rule!myFunction_sub, local!arrayOfCDTs)

    If you need to handle an array which will contain various different CDTs, all that really matters is that they either all contain a field named "UserIDs" or at least a set of such property names that you know up-front (like one has "UserIDs" but another one has "LoginIDs"). You would simply use the property() function in myFunction_sub to check which 'IDs' property the CDT member has prior to doing the apply.
  • 0
    Certified Lead Developer
    (Note that even though I describe UserIDs as an integer array, it really doesn't matter whether it's integers, or a text array of usernames, etc - it still works the same way)
  • 0
    Certified Associate Developer
    Yes, I see how your approach would work unfortunately my particular objects store the usernames in distinct fields (regionalManager, operationalManager, etc) and there exists no commonality of fields between the various object types.

    However you're absolutely correct in that I could create a custom expression for each type of CDT I intend to check and pass the entire object instead of the fields - I was just looking to write a generic function that I could re-use on all my objects and across various projects.

    That said I feel the problem is a little more fundamental than that - How do I pass an array type argument of dynamic length to an expression via an apply function.
  • 0
    Certified Lead Developer
    Yes, you do need to pass the whole object down through the evaluating expression, but as I mentioned before, you can utilize property() to handle multiple different types of CDT in one expression (instead of one separate sub-rule for each different type).

    As far as apply() goes, in my experience it's a bit finnicky in what it accepts. For instance it'll accept the larger chunks of a list created by merge(), but it doesn't seem to like handling array-of-arrays in any other way (that i've tried).
  • 0
    Certified Lead Developer
    I'm not sure if I understand your problem entirely but have you tried something like:
    apply(rule!ruleToApply(_), 1+enumerate(length(ri!arr)), local!arr) and then inside ruleToApply index out the next array in your dynamic array of arrays object?
  • 0
    Certified Lead Developer
    accidentally used a local var and rule input in my example! should be apply(rule!ruleToApply(_), 1+enumerate(length(ri!arr)), ri!arr)