Jump to content

Passing Repeating Variables as Script Results


This topic is 3097 days old. Please don't post here. Open a new topic instead.

Recommended Posts

I was wondering if there was a way to pass a repeating variable as a script result, or do I have to separate it out, and then remake the repeating field in the secondary script.

 

Thank you,

 

Fed

Edited by fed
error in original post
Link to comment
Share on other sites

Hi Fed,

You can pass a repeating field by using:

List ( yourTable::yourRepeatingField_name )

This will produce a multi-line text result.

However, you can get yourself into trouble using Repetitions because it can be difficult to retrieve the data.  Can you explain what you are using this for?  We might be able to suggest better ways. 

I'm unsure what you mean by 'remake the repeating field in the secondary script' so I cannot answer without more information but it points again to my first paragraph.  Are you sure you should be using them at all?  Repetitions may be the best answer but more likely, they are not.  :-)

Edited by LaRetta
Link to comment
Share on other sites

If you mean that you later want to use the multiline variable you are passing, to set another identical repeating field, then I think you need to loop similar to:

Set Variable [ $sp ; Get ( ScriptParameter ]
# prior line holds your repeating field as multiline passed from parent script
Loop
Set Variable [ $count; Value:$count + 1 ]
Exit Loop If [ $count > ValueCount ( $sp ) ]
Set Field [ reps::newField[$count]; GetValue ( $sp ; $count ) ]
End Loop

If it is something which must happen often, you might be able to use auto-enter on the target field but still ... why go to this trouble?  Of course there may be simpler way to set the repetitions in the target field.

Edited by LaRetta
Link to comment
Share on other sites

Yeah you will have to set your repValues to delineated list in a variable, then pass the variable value to the SUB-SCRIPT via Script Parameter, then parse of the Script Parameter to your source RepField:

Let's say we have file called "PassReps" with  two fields:

SourceRep - Text Result - 6 repetitions
TargetRep - Text Result - 6 repetitions

Here are a few sample scripts:

GetReps

Set Variable [ $repsCount; Value:6 /* number of reps in your field */ ] 
Set Variable [ $counter; Value:1 ] Set Variable [ $repValues; Value:"" ] Loop
Exit Loop If [ $counter > $repsCount ] 
Set Variable [ $repValues; Value:Let([
a = GetRepetition ( PassReps::SourceRep ; $counter ) ];
List($repValues; If ( IsEmpty ( a ) ; " " ; a )) )]
Set Variable [ $counter; Value:$counter + 1 ] 
End Loop
Perform Script [ “SetReps”; Parameter: $repValues ]

Then the SUB-SCRIPT called

SetReps

Set Variable [ $repsCount; Value:6 /* number of reps in your field */ ] 
Set Variable [ $counter; Value:1 ] Loop
Exit Loop If [ $counter > $repsCount ]
Set Field [ PassReps::TargetRep[$counter]; Let([
a = GetValue ( Get(ScriptParameter) ; $counter ) ];
If ( a = " " ; "" ; a ) )] 
Set Variable [ $counter; Value:$counter + 1 ]
End Loop 

Hope this helps!

Edited by dwdata
Link to comment
Share on other sites

Yes of course ... using List() will not include empty repetitions, thanks, Don!  :)

I keep thinking we could use the variable's repetition here ... I know variable repetitions are not true repetitions but still, since this is all handled via script, we should be able to use them; heck, we are just passing variables anyway.  I am not a repetition master and a developer had better really know their stuff if they plan to use repetitions for data or they can cause you more problems than they are worth down the road.  

Link to comment
Share on other sites

Careful:
Both List ( RepeatingField ) and the scripts suggested above assume that the repeating field contains no carriage returns. If this assumption is false, another delimiter must be used when concatenating the values to a single variable.

Moreover, the script handles empty repetitions in a rather peculiar way: it converts them to spaces, in an effort to use the List function to concatenate them. As a result, if a repetition legitimately contains a single space, it will be reconstructed as an empty string on the other side of this process. The correct approach is to insert a carriage return (or another delimiter, as mentioned above) after every repetition, instead of using the List() function - which would also simplify the code significantly:

Instead of:

Let([
a = GetRepetition ( PassReps::SourceRep ; $counter ) 
];
List($repValues; If ( IsEmpty ( a ) ; " " ; a )) 
)

just:

$repValues & ¶ & GetRepetition ( PassReps::SourceRep ; $counter )

 

Can you explain what you are using this for?  We might be able to suggest better ways. 

Ditto.

 

I keep thinking we could use the variable's repetition here ...

Alas, script result has no repetitions. Of course, you could use a global variable instead. With the additional responsibility to destroy it (with all of its repetitions) after use.

 

 

Edited by comment
  • Like 1
Link to comment
Share on other sites

I was wondering if there was a way to pass a repeating field as a script result, or do I have to separate it out, and then remake the repeating field in the secondary script.

 

Going back to the underlying premise: if you have stored the results already in the script, why not let the other script read what is needed instead of trying to pass around values that are already stored in the db?

Passing data around is very efficient for data that is not stored in the db, but only exists in variables.

 

Link to comment
Share on other sites

Sorry, I misstated the issue.  I am not using a repeating field, but rather a repeating variable (like an array), that I would like to pass from one script to another.

 

Thanks you your responses!

 

Link to comment
Share on other sites

 I am not using a repeating field, but rather a repeating variable (like an array), that I would like to pass from one script to another.

That doesn't make things any clearer. How exactly is this variable created? And why do you create it in the first place, if you need the results in the calling script? And how are you going to use the passed values in the calling script? Why do you even need two scripts? Without knowing the background, this is an XY problem.

Edited by comment
Link to comment
Share on other sites

That was my interpretation of various comments.  Anyhow, I got it working without using repeating variables.  I will avoid them in the future.

 

Thanks anyhow.

 

Link to comment
Share on other sites

Yes of course ... using List() will not include empty repetitions, thanks, Don!  :)

I keep thinking we could use the variable's repetition here ... I know variable repetitions are not true repetitions but still, since this is all handled via script, we should be able to use them; heck, we are just passing variables anyway.  I am not a repetition master and a developer had better really know their stuff if they plan to use repetitions for data or they can cause you more problems than they are worth down the road.  

Really? What is untrue about repeating variables? Yes, fields and variables are quite different things. But both repeating fields and repeating variables (global or script) are directly addressable, as opposed to the result of a list operation which will collapse empty values.

Link to comment
Share on other sites

I took the suggestion to avoid Repeating fields/variable.

No one made such suggestion.

That was my interpretation of various comments.

Let me stress for the benefit of future readers that such interpretation would be wrong. Repeating variables (or fields) are not a contagious disease; they are to be used (where appropriate) and not avoided.

Link to comment
Share on other sites

That was my interpretation of various comments.  Anyhow, I got it working without using repeating variables.  I will avoid them in the future.

 

Thanks anyhow.

 

Avoiding them; and understanding them; are VERY different things. And as always the case, being clear and complete when describing a problem is important. It is certainly quite misleading to put "repeating fields" in the title of your post when you did not mean repeating fields at all; but actually meant repeating variables.

Link to comment
Share on other sites

Careful:
Both List ( RepeatingField ) and the scripts suggested above assume that the repeating field contains no carriage returns. If this assumption is false, another delimiter must be used when concatenating the values to a single variable.

Moreover, the script handles empty repetitions in a rather peculiar way: it converts them to spaces, in an effort to use the List function to concatenate them. As a result, if a repetition legitimately contains a single space, it will be reconstructed as an empty string on the other side of this process. The correct approach is to insert a carriage return (or another delimiter, as mentioned above) after every repetition, instead of using the List() function - which would also simplify the code significantly:

Instead of:

Let([
a = GetRepetition ( PassReps::SourceRep ; $counter ) 
];
List($repValues; If ( IsEmpty ( a ) ; " " ; a )) 
)

just:

$repValues &  & GetRepetition ( PassReps::SourceRep ; $counter )

 

Ditto.

 

Alas, script result has no repetitions. Of course, you could use a global variable instead. With the additional responsibility to destroy it (with all of its repetitions) after use.

 

 


Comment - I like my version because it deals with the empty "$repValues" when starting the loop. Using your optimized code offset the target REP +1. Of course you can add a test for empty. which is very close to what I did.

Anyway - my end result is fine and not much of a performance hit. Thanks!

Link to comment
Share on other sites

Using your optimized code offset the target REP +1.

You are right about that - it should have been:

$repValues & GetRepetition ( PassReps::SourceRep ; $counter ) & ¶

 

Of course you can add a test for empty.

No, that's not necessary.

 

Anyway - my end result is fine

No, it is not. As I said, you are converting spaces to empty strings. That's not fine when the purpose is to transmit the values without modifying them.

Link to comment
Share on other sites

What is useful is to describe the differences and practical uses and examples. 

For instance you can set and iterate over repeating fields or variables.

Set Variable [$k; 0]

Set Variable [$max; 10]

Loop

Exit loop if [ Let[ $k = 1 + $k; $k > $max]

Set Field [table::repField[$k]; $k]

Set Variable [ $rep[$k]; $k]

End Loop

A difference between repeating variables and repeating fields is that the declaration of a repeating field to have say, 10 reps is something that you do when defining the field. The existence of the 10 reps is guaranteed and (in this case) there is no rep 11 or rep[0] or rep[-24]

Whereas with repeating variables, the declaration of $rep[10] does not mean that $rep 1 through 9 exist.

Nevertheless, you can still read; or populate; $rep[N] for 1 through 9.

And at any time, you can declare; populate; or read; $rep[11] or $rep[0] or $rep[-24]

 

Link to comment
Share on other sites

What is useful is to describe the differences and practical uses and examples.

I don't think there's a single fact about repeating variables that LaRetta, you and I will disagree on.

In my opinion, the fact that aggregate functions cannot be applied to a repeating variable, and that each repetition of a repeating variable needs to be created and destroyed individually, make them so drastically different from repeating fields that it is not useful to think of both as being in the same category.

Link to comment
Share on other sites

 

No, it is not. As I said, you are converting spaces to empty strings. That's not fine when the purpose is to transmit the values without modifying them.

LOL - Okay Comment :-)  So...   if in the Source field there is a SINGLE SPACE as the value (in any rep), and that SINGLE SPACE needs to transfer to the Target Field, then you are correct. If not, then I call this helpful house cleaning ;-)

I think I will retire from this thread. Seems the original poster has plenty to chew on and just enough to data to distract them from getting to the solution to their issue. 

Thanks all.


 

Link to comment
Share on other sites

Thanks everyone.  I corrected the original post to 'variable' instead of 'field'.  Sorry again for the confusion.  My confusion was because my variable's name in my script was 'Field'.  Funny.

I have avoided the repeating variable, as it seems you cannot pass it in the script result.  All is well for me now.

I understand that repeating variables and fields may have their usefulness, but as they seem to be a bit tricky, I will avoid them in the future.  I prefer things I can debug myself.

Just for academic reasons, what would be a situation where a repeating variable would be better than just using a variable, and using 'values' (ie lines). I suppose if some entries are more than 1 line in size...

Link to comment
Share on other sites

 

Just for academic reasons, what would be a situation where a repeating variable would be better than just using a variable, and using 'values' (ie lines). I suppose if some entries are more than 1 line in size...

There literally thousands of uses for them and if you are going to avoid repeating variables you are going to cut yourself short.

One interesting one to get your interest.  Do a google for "filemaker named buckets"

 

 

Link to comment
Share on other sites

I have avoided the repeating variable, as it seems you cannot pass it in the script result.  All is well for me now.

 

Well, there is no native, common, agreed-on way of passing any kind of multi-valued data in script results. You can't pass a record; or records; or fields; or repeating fields or repeating variables. 

You can pass text; and you can create or adopt any kind of scheme you like to give structure and meaning to the the text. You can delimit it with returns; or pipe characters; or structure it as XML or JSON; or "Let" variables; etc. Script Results are great, and it is extremely common to need to collect multiple chunks of data, pass it back as a script result, and then know how the chunks are structured.

Link to comment
Share on other sites

I have avoided the repeating variable, as it seems you cannot pass it in the script result.  All is well for me now.

I understand that repeating variables and fields may have their usefulness, but as they seem to be a bit tricky, I will avoid them in the future.  I prefer things I can debug myself.

Just for academic reasons, what would be a situation where a repeating variable would be better than just using a variable, and using 'values' (ie lines). I suppose if some entries are more than 1 line in size...

I recommend giving repeating variables another chance next time the possibility arises. Looping through a series of repeating variables is always faster than parsing the same data out of a return-delimited list. For those with any background in computer science, the former is a O(n) operation, whereas the latter is O(n^2).

Repeating variables can be passed as parameters and results almost as easily as a return-delimited list if you use Let Notation to format your parameters, such as if you use these custom functions.

Link to comment
Share on other sites

This threads seems to take the most peculiar twists and turns...

Looping through a series of repeating variables is always faster than parsing the same data out of a return-delimited list.

Why would there be any difference?

 

Repeating variables can be passed as parameters and results almost as easily as a return-delimited list if you use Let Notation to format your parameters, such as if you use these custom functions.

I find this to be a rather misleading statement. It seems to suggest that you can send multiple values as a parameter/result. This is of course not so. As BruceR noted, there are various techniques to "pack" multiple values into a single string for the transit and "unpack" them on the other side - yours is just another one of these.

Link to comment
Share on other sites

Why would there be any difference?

Each repetition of a repeating variable is basically a separate variable. The contents of each can be extracted separately without additional work, (in O(1) time). The values in a return-delimited list must each be parsed out (in n/2 time, on average). So looping through a series of n values takes n * 1 => O(n) time for repeating variables, and n/2 * n => O(n^2) for return-delimited lists. The time for large return-delimited lists can be reduced to O(n^1.5) by breaking them into Sqrt(n) smaller lists and parsing from those, but the repeating variables' O(n) is still faster than return-delimited lists' O(n^1.5).

Link to comment
Share on other sites

Comment: have you looked at the HyperList demo on modularfilemaker.org?  Some of this theory has been shown to be true in the FM space and is nicely commented in those scripts.

Edited by Wim Decorte
Link to comment
Share on other sites

Comment: exactly so. That is why I generally recommend repeating variables for virtual lists with large record counts, for instance.

Maybe we also need to come up with a different term for repeating variable; such as ISV; Integer Suffixed Variables. Though mostly I think that everybody understands the current term.

Link to comment
Share on other sites

You are making some assumptions that may or may not be true. Would it be correct to say that under your theory GetValue() gets progressively slower as n increases?

I am inferring based on the empirical observations made independently by myself and others. Like anthropogenic climate change, this is old news. To help persuade anyone who is not satisfied with the reputations of the contributors here (healthy skeptics) or who does not have the resources to spare to test on their own (healthy laziness), I whipped up a standalone test file.

First, yes, GetValue does get slower as it extracts higher-numbered values in a list.

Second, the timing measurements of iterating through repeating variables, and iterating through return-delimited lists using simple and square-root-pre-chunking methods for various sizes of lists are consistent with O(n), O(n^2), and O(n^1.5) performance, respectively.

For very small lists (n < 20), it can be difficult to distinguish between the performances of repeating variables and simple parsing of return-delimited lists due to random interference by other processes on the computer, but measured times for repeating variables are faster than for return delimited lists more often than not. For anything larger, repeating variables are unambiguously much faster to work through.

When repeating variables are not an option for whatever reason, simple repeated application of GetValue appears to be best for small-to-medium-size lists (n < 150). Roughly between lists with 150-200 elements, simple GetValue and square-root-pre-chunking are roughly tied. For larger lists, square-root-pre-chunking rapidly becomes much faster.

I'm curious to see if other folks run the same tests on different machines and get different crossover points.

ListPerformanceComparison.fmp12.zip

Screen Shot 2015-09-06 at 19.47.21.png

Screen Shot 2015-09-06 at 19.11.29.png

Screen Shot 2015-09-06 at 19.07.09.png

Screen Shot 2015-09-06 at 19.15.20.png

Edited by jbante
Link to comment
Share on other sites

This topic is 3097 days old. Please don't post here. Open a new topic instead.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.