Function Scripting Evolved

When FileMaker 8 was released in 2005 it was a game changer for the world of FileMaker scripting. You could now pass data into scripts from buttons - added to already being able to access data from within the script. It wasn't long after its release that developers wanted to pass information to scripts in a more structured fashion. "Passing multiple parameters" is a common term in FileMaker development and there are many ways to accomplish it.

In 2006 I released a video about the topic of "Function Scripting". It was a very popular article which advanced the idea of using scripts as something similar to functions and treating them more like methods in object oriented languages.

I simply combined two different sets of custom functions from two very smart developers. Over the years, I've used the method almost exclusively for passing information into scripts. Recently, however, I've started to use an evolved method of passing information into scripts.

The method I'm now using, focuses a great deal on code readability and facilitates both strict and relaxed parameter requirements. The function is a multipurpose function which can be used in many areas of your FileMaker solution. In this video, I walk through the evolution, some of the other options you have available and why I've chosen to adopt this new method of passing parameters into scripts.

AttachmentSize
FunctionScriptingEvolved.zip237.35 KB

Comments

hello

Really nice. but I have some suggestions. And i hope i haven't missed anything before I give suggestions ;)

1.
I have functions that require MUST have parameters, and optional parameters. Would be nice if I could mark the obligatory parameters with a star '*' or something. So only required parameters are being checked.

2.
Do to the fact that your solution creates local variables, there is no need to check if the parameters come in the correct order. This has the advantage of being able to change the script later on, add additional parameters and change the order in the Scriptname.

Example: Send_Email(to, attachment) ==> Send_Email(to, cc, attatchment)

Bye and thanks

It seems like you're wanting to put all parameters in the name of the script, yet you only want certain parameters to be checked. In my own use I only put required parameters in the script name. One of those parameters can be a packed parameters.

This can certainly be done, and it looks like you've modified the function below, although you've added in dependancies. It could be modified to accept optional parameters according to the syntax of the script name. If you take a look at the older article, you'll see how Alexander Zuiev handled this in the previous incarnation of this technique - he followed the familiar syntax of using braces {}.

-- Matt Petrowsky - ISO FileMaker Magazine Editor

/*
* =====================================================
* var.eval( contents )
*
* RETURNS: (bool) True or False based on proper evaluation
* DEPENDENCIES: From http://www.briandunning.com ==> ApplyToList, ListIndex, FilterList, CustomList
* NOTES: Try to always use the List() function when passing multiple values into var.eval!
* $checkScriptName is a reserved local variable used when you wish to enforce
* that inbound parameters match the name of the script. It is reset after the
* evaluation.
* RELEASE: 100909
* =====================================================
*
* This custom function evaluates contents passed as the
* variable declaration part of a Let function. Useful for
* defining global or locally scoped variables.
*
*/

Let( [
$$ERROR.VAR.EVAL = ""; // Reset global error variable for evaluation

var.empty = IsEmpty ( contents ); // test for empty contents
var.semicolons_exist = ( ValueCount ( contents ) = PatternCount ( contents ; ";¶" ) ) or ( ValueCount ( contents ) - 1 = PatternCount ( contents ; ";¶" ) );
var.contents = If ( not var.semicolons_exist ; Substitute ( contents ; ¶ ; ";¶") ; contents ); // Add semicolons if needed
var.trailing_semicolon = Right ( var.contents ; 1 ) = ";"; // Clean off the trailing semicolon if present
var.contents = If ( var.trailing_semicolon; Left ( var.contents ; Length( var.contents ) - 1 ); var.contents );

var.script = Get ( ScriptName );
var.begin = "(" ; // beginning of parameters definition
var.break = "," ; // regular parameters separator (and)
var.end = ")" ; // end of parameters definition

var.parameters = Middle ( var.script ;
Position ( var.script ; var.begin ; 1 ; 1 ) +1;
Position ( var.script ; var.end ; Length ( var.script ) ; -1 ) - Position ( var.script ; var.begin ; 1 ; 1 ) -1
); // raw parameters
// ONLY ALLOWED CHARACTERS FOR SCRIPT NAME PARAMERS ARE THE FOLLOWING (minus the ¶)
var.parameters = Filter ( Substitute ( var.parameters ; var.break ; ¶ ) ; "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_¶*" );

var.expected = "$" & Substitute ( var.parameters ; ¶ ; "¶$" );
var.expected = FilterList ( var.expected ; "EndsWith"; "*" ; 0 );
var.expected = Filter ( var.expected; "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_¶$" );

var.matching = FilterValues ( Substitute( var.contents; "="; ¶ ) ; var.expected );
var.matching = Left ( var.matching ; Length ( var.matching) - 1) ; // replace extra return added by FilterValues function

var.expected_needed = ValueCount(var.expected);
var.expected_found = Evaluate(ApplyToList ( var.matching ;"if(ListIndex ( \""& var.expected & "\" ; [n] ; 0 ; \"¶\" );1;0)" ; "+" ));

var.missingParams =(var.expected_needed <> var.expected_found)

];

If ( Evaluate( "Let ( [" & var.contents & "]; False )" ) = "?" // generates an error or
or var.empty or var.missingParams; // empty contents or missing expected parameters
// Return error result
Let ( [
$$ERROR.VAR.EVAL =
Case (
var.empty ; "EMPTY PARAMETER SET" ;
var.missingParams ; "MISSING EXPECTED PARAMETERS PER SCRIPT NAME";
List ( "ERROR »"; var.contents )
);
$checkScriptName = "" // reset the $checkScriptName variable (after setting error)
];
False
);
Let ( $checkScriptName = "" ; True )
)

)