Function Scripting - A powerful scripting technique

FileMaker is an easy environment to work in. It's mostly point and click for a lot of things. It allows you to start simply then grow more complex as you learn while you develop. The work you do, however, can either become very complex or stay simple - from the start. There's always a balance to be attained when trying to build a complex solution.

Code readability is the topic I'm talking about. The goal is powerful, and often necessary, complexity, yet a level of obvious simplicity - for the sake of future understanding and possible collaboration.

In this video, I present a new method for naming your scripts and defining script variables. It's a very elegant combination of three custom functions from two VERY smart developers. I'm pleased to provide this powerful scripting technique. I've personally never seen anything like it and I love it!

AttachmentSize
FunctionScripting.zip112.15 KB

Comments

Another variation on AssignParams

Charles Ross wrote in to tell me the following...

While I love the idea, and found the execution worked, I didn't enjoy that I found the original AssignParams function so convoluted. I rewrote it for my own personal use because I didn't like the format it required for the script names. I prefer to enclose the entire parameter list in parentheses and enclose the optional parameters in square braces. A minor difference, yes, but I've been using that format for quite some time, albeit without the validation functionality that [the original] AssignParams gives. Finally, I don't like functions that are so long they can't fit on my screen. In order to rewrite it, I had to understand it fairly well, so I took it apart today and rewrote it using sub-custom functions and hopefully better commenting.

AssignParams

AssignParams =
// A rather complicated function that not only assigns parameters to local script variables, but also validates them given the template
// provided by the called script's name. Returns True if required parameters are passed and at least one of the alternative parameters
// are included. Returns False otherwise. But in the process of determining the return result, also assigns the parameters to local script
// variables.
//
// EXTERNAL REQUIREMENTS: A number of custom functions that perform many sub parts, such as actually assigning the local script
// variables and setting up the local variables needed to operate: SetAssignParamVars, WordsToList, ParamToVars, SingleParamToVar.
//
// Written by Charles Ross. Inspired by Alexander Zueiv.

Let ( [
Garbage = SetAssignParamVars; // Set up the local script variables used in this custom function set.
Garbage = ParamToVars( $ParamList ); // Convert the script parameter passed and parsed into local script variables.

Parsable = Substitute( // Ease parsing by removing spaces. We'll add the dollar sign ourselves.
$ParamTemplate;
[ " " ; "" ];
[ "$" ; "" ]
);

ReqParams = Case( // Remove optional parameters.
PatternCount( Parsable; $OptionalChar );
Left( Parsable; Position( Parsable; $OptionalChar; 1; 1 ) - 1 );
Parsable
);

Parsed = "$" & Substitute( // Enclose alternate possibilities in parentheses and prepend parameter names with the dollar sign.
ReqParams;
[ $BreakChar & $AltOpenChar ; ";( $" ]; // Enclose the optional parameters in parentheses.
[ $AltChar ; $AltChar & "$" ]; // Add dollar signs before each optional parameter after the first.
[ $AltCloseChar ; " )" ] // Close the optional parameters parentheses.
);

Parsed = Substitute( // Handle the possible special case with the break character is followed by alternative parameters.
Parsed;
[ $BreakChar & "("; "^^^^" ]; // Substitute an unlikely string for the break sequence we want to keep.
[ $BreakChar ; $BreakChar & "$" ];
[ "^^^^" ; $BreakChar & "(" ] ); // Substitute the break sequence we want to keep back in.

// Add in the FileMaker code to ensure that the appropriate strings are not empty, thus validating that each parameter that is required
// is present.
FMCode = "( not IsEmpty( " & Substitute(
Parsed;
[ $BreakChar; " ) ) and ( not IsEmpty( " ];
[ $AltChar; " & " ]
) & " ) )"

];

( FMCode = $EmptyParamTemplate ) or Evaluate( FMCode )
)

SetAssignParamVars

SetAssignParamVars =
// Store constants and other variables needed during script parameter validation.
//
// EXTERNAL REQUIREMENTS: TheWordsToList custom function.
//
// Written by Charles Ross. Inspired by Alexander Zueiv.

Let ( [
$Script = Get( ScriptName );
$Params = Get( ScriptParameter );

$OpenChar = "(" ; // beginning of parameters definition
$CloseChar = ")"; // end of parameters definition
$BreakChar = ";" ; // regular parameters separator (and)
$AltOpenChar = "["; // beginning of alternative parameters definition.
$AltCloseChar = "]"; // end of alternative parameters definition.
$AltChar = "|" ; // alternative parameters separator (or)
$OptionalChar = "{" ; // beginning of optional parameters section

StartPos = Position( $Script; $OpenChar; 1; 1 ) + 1;
ParamLen = Position( $Script; $CloseChar; Length( $Script ); -1 ) - Position( $Script; $OpenChar; 1; 1 ) - 1;
$ParamTemplate = Middle( $Script; StartPos; ParamLen );

// Convert the parameters to a list that can be interated through.
$ParamList = WordsToList( $ParamTemplate );

$EmptyParameterTemplate = "( not IsEmpty ( $ ) )"

]; "" )

WordsToList( Words ) =
// Converts the text passed into a list of words. For example, WordsToList( "one two>three;four" ) = "one¶two¶three¶four¶".
//
// Written by Charles Ross

Case(
WordCount( Words ) = 0;
"";
LeftWords( Words; 1 ) & "¶" & WordsToList( RightWords( Words; WordCount( Words ) - 1 ) )
)

ParamToVars

ParamToVars =
// A recursive function that declares as local script variables each of the named varaibles in ParamList. ParamList is calculated from the
// name of the script.
//
// EXTERNAL REQUIREMENTS: The FirstListItem and RestOfList custom functions (list operations) and the SingleParamToVar custom
// function.
//
// Written by Charles Ross. Inspired by Alexander Zueiv.

Case(
ValueCount( ParamList ) = 0;
"";
SingleParamToVar( FirstListItem( ParamList ) ) & ParamToVars( RestOfList( ParamList ) )
)

SingleParamToVar( ParamName ) =
// Assigns the single parameter named to a local script variable. $Params is a variable declared in the custom function SetAssignParamVars.
// It's value is simply Get( ScriptParameter ). The ParamName may not have been passed (it may be optional to the script), so we check for
// its existence before doing anything. The function doesn't actually return anything useful, but after it's run, the variable named in
// ParamName should have a local script variable declared with that name if the caller of the script passed such a parameter.
//
// EXTERNAL REQUIREMENTS: The SetAssignParamVars custom function (to declare the $Params script variable).
//
// Written by Charles Ross. Inspired by Alexander Zueiv.

Case(
PatternCount( $Params; ParamName ); // Does the parameter exist in the arguments to the script?
Let( [
// Get the value of the named parameter by evaluating within a Let function the passed parameter and returning in that statement the
// named parameter.
Value = Evaluate ( "Let ( [ " & $Params & "] ; " & ParamName & " )" );

// Construct a local script variable and assign it the value found above.
Garbage = Evaluate( "Let( [ $" & ParamName & " = \"" & Value & "\" ]; \"\" )" )
];

// Return the value of the local script variable. This is a debugging feature to make sure it works correctly.
Evaluate( "$" & ParamName )
);

"" // Empty string returned if the parameter doesn't exist.
)

-- Matt Petrowsky - ISO FileMaker Magazine Editor

I neglected to send the code for two custom functions I use to iterate through lists: FirstListItem and RestOfList

FirstListItem( TheList )

// Returns the first value in a list, including the ending paragraph mark. Often used to loop through a list of items. Returns the item
// without the trailing carriage return.
//
// Written by Charles Ross

Let(
[
RawValue = LeftValues( TheList; 1 )
];

Left( RawValue; Length( RawValue ) - 1 )
)

RestOfList( TheList )

// Returns the list without the first item. Usually used to loop through a list of items.
//
// Written by Charles Ross

RightValues( TheList; ValueCount( TheList ) - 1 )

Also, I build parameters by using the following Param( VarName; ParamValue ) function.

// Encapsulates the building of parameter/value pairs used by the AssignParams function.
//
// Written by Charles Ross.

VarName & " = " & Quote( ParamValue ) & "; "

Multiple parameters are sent by using the "&" text concatenation operator between calls to Param.