# Define a new Front End Syntax for Function Argument Checking & Debugging

In this question I asked a basic question about how to check argument types such that there was useful output from the front end when calling functions. Based on elements of the nice answer by @j-m-is-computerless I have developed the following, which works but is somewhat tedious in use.

First I give an example of the usage of the goodArgQ function which does type checking in the body of function definitions; the definitions of goodArgQ and its dependencies are at the end after the discussion and question.

ClearAll[columnsExistQ];
columnsExistQ::usage="Returns a list of True/False for each column if the named column exists in the current database in the specified table.";
columnsExistQ[conn_, tableName_, cols_]:=
Module[{t, abortOnFail = True, debugPrint = True},
goodArgQ[conn, "SQLConnection","abortOnFail"->abortOnFail, "debugPrint"->debugPrint];
goodArgQ[tableName, StringQ, "abortOnFail"->abortOnFail, "debugPrint"->debugPrint];
goodArgQ[cols,ListQ, "abortOnFail"->abortOnFail, "debugPrint"->debugPrint];
goodArgQ[#,StringQ, "abortOnFail"->abortOnFail, "debugPrint"->debugPrint] & /@ cols;
(* functional code here*)
]


The advantage to me of this type checking is that by appropriate use of the abortOnFail and debugPrint options I can focus on errors progressively.

However, what I would like to do is to develop a new front end syntax, similar to the following modification of the columnsExistsQ function

columnsExistsQ[conn As SQLCOnnection, tableName As String, cols As List of String]:=...


(where case of "As"", "of" should be ignored)

But I cannot work out how to get, let alone process, such an argument list.

Questions (For the sake of brevity I have kept the question very high level) How could one define such a way of defining functions so that the "as" etc. would automatically inline the appropriate goodArgQ calls - or e.g. use Map with a single additional function passed the arguments in list form.

How else might one compactly (i.e. avoiding the extra coding of @j-m-is-computerless and my own work) achieve the aim of declaring argument types such that MMA does not just silently do nothing if there is no match to a function definition?

Note this is the first time I have used any form of Hold, and I did try various Hold types and the like in order to get the argument list, alas to no avail.

The argument checking functions

ClearAll[goodArgQ]; (* clear all values, definitions, attributes, messages, and defaults *)
ClearAll[goodArgQByQ];

Options[goodArgQ]={"abortOnFail"->True, "debugPrint"->False};
Options[goodArgQByQ]={"abortOnFail"->True, "debugPrint"->False};

SetAttributes[goodArgQ, HoldFirst];

goodArgQByQ::usage="Checks argument by Head with test value as string. Options: abortOnFail (Boolean), debugPrint (Boolean)";
Module[{},
If[OptionValue["debugPrint"]==True, Print[Style[ToString[HoldForm[paramName]] <> " does not have required head " <> paramQ,Darker[Red]]]];If[OptionValue["abortOnFail"]==True, Abort[]];,
If[OptionValue["debugPrint"]==True, Print[Style[ToString[HoldForm[paramName]] <> " has required head " <> paramQ,Darker[Green]]];];
];
];
goodArgQByQ::usage="Checks argument by Q function. Options: abortOnFail (Boolean), debugPrint (Boolean)";
goodArgQByQ[paramName_, paramQ_, OptionsPattern[]]:=
Module[{},
ReleaseHold[paramName];
If[paramQ[paramName]==False,
If[OptionValue["debugPrint"]==True, Print[Style[ToString[paramName] <> " does not satisfy " <> ToString[paramQ] <> " = True",Darker[Red]]]];If[OptionValue["abortOnFail"]==True, Abort[]];,
If[OptionValue["debugPrint"]==True, Print[Style[ToString[paramName] <> " satisfies " <> ToString[paramQ] <> " = True",Darker[Green]]];];
]
];

goodArgQ::usage="Checks argument by Q function or Head with test value as string. Options: abortOnFail (Boolean), debugPrint (Boolean)";
goodArgQ[paramName_, paramQ_, OptionsPattern[]]:=
Module[{},