Tuesday, December 7, 2021

Today I (re)Learned

Mark this up as a TI(re)L:

I've been working on the Advent of Code daily puzzles with some of the people on the Working Code Podcast Discord channel, and I said that one of the challenges I've had with some of these puzzles was simply parsing the Inputs into the format I planned to work with in CFML. Tim Cunningham (t) mentioned some code that would parse a CSV file:


private function setParseSettings(
    required string localFilePath,
    required string lineSeperator=CRLF,
    required string quoteEscape="\",
    required boolean parseUnescapedQuotes=true,
    required boolean keepFirstRow=false
) { ..... }

I looked at the code and thought "Why would you have a default value if the parameter is required?", so I asked. A long time ago I learned that a required parameter couldn't have a default value; that's what optional parameters are for. At least that's what I thought. I guess I haven't ever really thought about the way it works. 

In SQL Server, functions don't really have a concept of optional parameters. Stored Procedures do, but there isn't an explicit required attribute in either one. You simply define an optional parameter by giving it an "= something". There are a few gotchas with parameters in SQL functions and sprocs, but those are beyond the scope of my thoughts here. And since most of my current work is in SQL and not CFML, I never really came across it enough to think about it.

Back to what I didn't realize I had forgotten.... 

You CAN have both required and a default value in your parameter definitions, in CFML and in many, if not most, other languages.

I knew that, conceptually, if a parameter was required, then it didn't matter if it had a default value. You had to pass the parameter, and if you did, then the default value was replaced anyway. But that's where my thinking was backwards. When the function is evaluated, if an optional value is defined, the required definition is ignored. So even though an argument is labeled as required, it doesn't have to be passed if there is a default value.

I didn't think that made any sense, so I verified it.

<cfscript>
function testme( required String param1, required Boolean param2 = false ) {
    return {"param1":param1,"param2":param2}
}

writedump( testme("Bill") )
writedump( testme("Ted",true) )
writedump( testme(param2=true, param1="Rufus") )
writedump( testme() )
</cfscript>

Which gave me: 

Huh... I stand corrected. This was something that I used to know, but had completely forgotten, or at least overwrote my original memory with my later assumption of how it all went together. 

Apparently it's perfectly fine to not pass a "required" parameter as long as it has a default value. If no parameter is passed, the default is evaluated and the required is ignored. Which is probably why I got backwards in the first place. Why label a parameter as required if it isn't really?

I'm sure the old gods of programming had a legitimate reason for doing it that way, but it escapes me. 

Oh well.



No comments:

Post a Comment