|
I addressed this somewhere else but, as an example, a variable arg list is possible (and often very desirable) in, for example, php (very much C-like except for no strong typing).
It allows one to create a function with a default value and still not be stuck with just that value. An ease of use thing. The example I gave in what is really a style-preference question, can be called either as whatEver(inVal) or whatEver() with the latter not giving a 'missing argument' error but rather defaulting to what was in the declaration.
An example of use: initializing a random function: with a value it uses that; without a value it can internally pick the current time of day. It's related somewhat to C++ overloading functions.
Ravings en masse^ |
---|
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein | "If you are searching for perfection in others, then you seek disappointment. If you seek perfection in yourself, then you will find failure." - Balboos HaGadol Mar 2010 |
|
|
|
|
|
TBH, if it is something we have to do a lot of, I prefer wrapping it with a #defined function...
void fx(int intVal)
{
intVal = COALESCE( intVal, intValDefault );
intVal = COALESCE( intVal, intValDefault );
intVal = COALESCE( intVal, intValDefault );
intVal = COALESCE( intVal, intValDefault );
intVal = COALESCE( intVal, intValDefault );
}
Stealing the syntax from SQL gets the point across.
Sometimes, doing something 5 times in a row, changes your interpretation of the value of the choice.
|
|
|
|
|
I agree with this. If your default parameter is only going to be replaced anyway, just go straight to the replacement.
Of course, you still need to allow for null actually being passed (assuming the parameter is of a nullable type), so you'll need the check internally.
I'm ambivalent on the question of ternary vs 'standard' here. The ternary is small and uncomplicated enough to be readable. Personal/team preference there.
|
|
|
|
|
May I inquire why you would not write "whatEver(inVal=internalDefault)" - Cheerio
|
|
|
|
|
Because of this:
whatEver(NULL);
|
|
|
|
|
I meant to agree w/ Monsieur Mircea Neacsu - Professional Profile[^] in his post The Lounge[^] I simply do not understand the purpose of passing in a value only to discard and replace it. In hopes of becoming a better programmer or is it "coder" or is it "app author" I now know it is not "progamer" a full and lengthy explanation would be most appreciated. I am afraid I am too dim witted to understand how your brief quote "whatEver(NULL)" is an explanation as to why one would not declare it as Monsier Mircea Neacsu suggested. I await your kind reply. - Cheerio
|
|
|
|
|
Function logic is really strange, but in any case, with your suggestion, result of whatEver(NULL) call is: inVal is not replaced by internalDefault and remains null, which will cause exception when this pointer is dereferenced.
|
|
|
|
|
Thank you for your reply but doesn't the original code of Monsieur Mircea Neacsu as shown below merely replace inVal w/ internalDefault when inVal is NULL ?
function whatEver(inVal=NULL) {
if(inVal==NULL)
inVal = internalDefault;
inVal = (inVal==NULL)?internalDefault:inVal;
}
|
|
|
|
|
This question is (despite the little C++ above the code snippet) meant to be considered beyond C++.
One reason for you to consider is those languages that accept a variable argument list and accept an empty argument position (php comes to mind).
So
function sample($x=7) can be invoked:
sample($inVal) or sample() with the latter assigning 7 to the internal value. NULL, however, is more common (for me at least). There's some personal conventions that are standardized that way. For example, in the cases where more than on arg has a default I can fill it's place with NULL (it cannot be empty) and assign a further argument. Often used for strings, actually, where I wish to control minor things such as delimiters, test char sets, and such.
Think of it as a sometimes variable but usually always the same value is desired.
Ravings en masse^ |
---|
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein | "If you are searching for perfection in others, then you seek disappointment. If you seek perfection in yourself, then you will find failure." - Balboos HaGadol Mar 2010 |
|
|
|
|
|
I rarely use the ternary operator unless something happens in both situations. I'd write it the first way, and even on one line unless the assignment seemed a likely spot for a breakpoint.
|
|
|
|
|
That's pretty much my attitude.
One place that's essentially always the ternary operator (for me) is testing for incoming arguments in a php file
$aVal = isset($_REQUEST['val']) ))?isset($_REQUEST['val']:some_default; There could be a flock of these, one after the other, to handle potential incoming values so (at least) I don't get undefined errors.
Further handling of default may occur later on (like not use the value). Because it's always the way I do the checking for this particular file type it falls back to being easy reading. Within the body it's not, however, the default way of doing it.
Ravings en masse^ |
---|
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein | "If you are searching for perfection in others, then you seek disappointment. If you seek perfection in yourself, then you will find failure." - Balboos HaGadol Mar 2010 |
|
|
|
|
|
I don't know PHP, but that looks like a good usage after squinting at it and reading your explanation.
|
|
|
|
|
Yeah, no, I don't use the ternary operator for that.
|
|
|
|
|
The first is definitely easier to read.
|
|
|
|
|
I think, because the THEN branch is short, the second is more natural.
EDIT: I turns into mess when the same condition evaluated many times in the "sentence". Natural languages and regexp have simple backreference to solve the problem.
|
|
|
|
|
I prefer
if(inVal==NULL) inVal = internalDefault;
Why waste a line of screen space. It's easy enough to read.
Though I actually prefer the declaration assign the argument w/ the valid default value as in
return_type whatEver(arg_type inVal=internalDefault);
I simply do not understand the logic of assigning a value to an argument only to immediately discard and replace it. I would be happy to learn of same.
Incidentally I learned from a previous post or article I don't recall which to write e.g.
void foobar(int arg)
{
if(arg != valid_value) return;
}
instead of
void foobar(int arg)
{
if(arg == valid_value)
{
}
}
so as to minimize the number of indented blocks even though in previous times I preferred minimizing the number of return statements. I find minimizing the number of indented blocks to be easier to understand. - Cheerios
|
|
|
|
|
Comments below assume C#, capabilities / syntax in other languages may vary.
My preference is, if internalDefault is not a compile-time constant, to overload the function e.g.
void whatEver() => whatEver(internalDefault);
void whatEver(sometype inVal) { } or (assuming internalDefault is a compile-time constant)
void whatEver(sometype inVal = internalDefault) { } Better than null would be to use default (type ) e.g.
void whatEver(sometype inVal = default(sometype) { } But in all of theses you should still check that inVal is not null.
Alternatively, you can use the null coalescing operator e.g.
void whatEver(sometype inVal = null)
{
inval = inval ?? internalDefault;
}
One day, perhaps, there will be a null coalescing assignment operator so you can do
inVal ??= internalDefault; - this is a feature that I have wanted in JavaScript since JS1.1 (c 1998) to change having code like
myvar = myvar || somedefault; into
myvar ||= somedefault;
|
|
|
|
|
My God in heaven. The first thing you absolutely must fix is the spacing:
inVal = (inVal == NULL) ? internalDefault : inVal; That's better. Now, what were you babbling on about?
Software Zen: delete this;
|
|
|
|
|
Gary Wheeler wrote: That's better. Now, what were you babbling on about? Shoes and Ships and Sealing Wax. Cabbages and Kings.
Ravings en masse^ |
---|
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein | "If you are searching for perfection in others, then you seek disappointment. If you seek perfection in yourself, then you will find failure." - Balboos HaGadol Mar 2010 |
|
|
|
|
|
I would completely disregard both causes, check what my developers commonly understand best, and pick that one.
As a rule:
- Never write code for an unqualified or unasked efficiency goal.
- Always write code that is cost-effective to maintain.
I've seen many many many average developers write code in a specific way because it's supposedly more efficient.
In almost all of those cases, they completely skipped measuring performance and examining the software requirements, and are picking an obtuse implementation because it makes them feel good about their code.
To be a excellent developer, you need to write excellent code for humans, and randomly add optimized of code for the compiler.
The compiler doesn't care at all, while the humans do. Write code for the latter.
|
|
|
|
|
KateAshman wrote: check what my developers commonly understand best, and pick that one. I've never considered coding to be a majority operation.
I do what I do because I think that's how it should be done. If I learn something better I'll fix it.
KateAshman wrote: I've seen many many many average developers write code in a specific way because it's supposedly more efficient. Seems to contradict your earlier (first) statement.
Don't join the herd in a stampede of "me too!" - if everyone does everything because that's how everyone else does it then nothing will change.
Ravings en masse^ |
---|
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein | "If you are searching for perfection in others, then you seek disappointment. If you seek perfection in yourself, then you will find failure." - Balboos HaGadol Mar 2010 |
|
|
|
|
|
Coding is a team sport, even when you're alone: you need to collaborate with you from the past and you from the future.
Writing code that's first and foremost efficient, while not actively improving existing code for specific performance goals, is a bad idea. I'm implying that without evidence and without specific performance goals, you should always write code that's concise and easy to understand instead. Easy to understand, however, is a moving target, which depends entirely on your team and your coding language.
I've extensively researched the topic of code quality for 20+ years. YMMV
|
|
|
|
|
I would always use the first set of code (marked by "this ?") for two reasons...
1)
I haven't bothered to learn all the new ways of coding for the simple reason that they most often make the code look arcane and difficult to read. This would result in boosting maintenance costs through difficulties with less experienced developers trying to understand what has been written.
2)
Efficiency is highly overrated in computer systems. Do you really believe that a Human Being will be able to tell the difference in speeds between the two types of code? Of course not. So why bother with it?
The reason developers bother with such concoctions is they are under the impression that what they are doing either looks "cool", they actually believe that using such arcane coding constructs will make their applications perform better, or both. As to the latter, no such coding construct will make one's code perform better except in the tiny recesses of computer memory where no one will ever notice.
Steve Naidamast
Sr. Software Engineer
Black Falcon Software, Inc.
blackfalconsoftware@outlook.com
|
|
|
|
|
Efficiency is not highly overrated, depending upon the type of coding you do.
Even early on I had some molecular modeling code that, when I changed from function (actually subroutine) return values to global values ran about 95% faster. Overnight batch runs became real-time in terms of excitation and planning the next iteration target. OK - long ago with FORTRAN and room-size computers. And time sharing. Some other optimizations were made for I/O timing, as well.
Back to now: doing it right, which means efficient coding, is even necessary for Web-Based applications: whether it's load time for a page (one second or fifteen?) or, far more importantly, optimizing SQL: something which has reared it's head, recently, as the amount of data in tables, especially joined tables, has grown. A stored procedure could even fail do to exceeding the maximum execution time set up (again, 400 users means limits).
So - if all your coding has to handle is small numbers of iterations and much time awaiting human responses it makes no perceivable difference - but good habits pay one back when they don't have to what always seems to be the inevitable future of a good application.
Ravings en masse^ |
---|
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein | "If you are searching for perfection in others, then you seek disappointment. If you seek perfection in yourself, then you will find failure." - Balboos HaGadol Mar 2010 |
|
|
|
|
|
I don't think it matters much as the compilers are pretty efficient at this.
In C#, I usually use the "null coalescing assignment operator (??=)"; so "inVal ??= internalVal;".
Here are some functions to test the various ways to assign a default value:
void FixNullArg_SimpleIf(string arg = null) {
if (arg == null)
arg = "Fix null via simple if";
Console.WriteLine(arg);
}
void FixNullArg_TernaryOp(string arg = null)
{
arg = (arg == null) ? "Fix null via ternary operator" : arg;
Console.WriteLine(arg);
}
void FixNullArg_NullCoalescingOp(string arg = null)
{
arg = arg ?? "Fix null via ?? operator";
Console.WriteLine(arg);
}
void FixNullArg_NullCoalescingAssignmentOp(string arg = null)
{
arg ??= "Fix null via ??= operator";
Console.WriteLine(arg);
}
void FixNullArg_IsNullOrWhiteSpace(string arg = null)
{
arg = string.IsNullOrWhiteSpace(arg) ? "Fix null via IsNullOrWhiteSpace" : arg;
Console.WriteLine(arg);
} And here is the decompiled Intermediate Language (IL):
FixNullArg_SimpleIf:
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldnull
IL_0003: ceq
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: brfalse.s IL_0010
IL_0009: ldstr "Fix null via simple if"
IL_000E: starg.s 01
IL_0010: ldarg.1
IL_0011: call System.Console.WriteLine
IL_0016: nop
IL_0017: ret
FixNullArg_TernaryOp:
IL_0000: nop
IL_0001: ldarg.1
IL_0002: brfalse.s IL_0007
IL_0004: ldarg.1
IL_0005: br.s IL_000C
IL_0007: ldstr "Fix null via ternary operator"
IL_000C: starg.s 01
IL_000E: ldarg.1
IL_000F: call System.Console.WriteLine
IL_0014: nop
IL_0015: ret
FixNullArg_NullCoalescingOp:
IL_0000: nop
IL_0001: ldarg.1
IL_0002: dup
IL_0003: brtrue.s IL_000B
IL_0005: pop
IL_0006: ldstr "Fix null via ?? operator"
IL_000B: starg.s 01
IL_000D: ldarg.1
IL_000E: call System.Console.WriteLine
IL_0013: nop
IL_0014: ret
FixNullArg_NullCoalescingAssignmentOp:
IL_0000: nop
IL_0001: ldarg.1
IL_0002: brtrue.s IL_000B
IL_0004: ldstr "Fix null via ??= operator"
IL_0009: starg.s 01
IL_000B: ldarg.1
IL_000C: call System.Console.WriteLine
IL_0011: nop
IL_0012: ret
FixNullArg_IsNullOrWhiteSpace:
IL_0000: nop
IL_0001: ldarg.1
IL_0002: call System.String.IsNullOrWhiteSpace
IL_0007: brtrue.s IL_000C
IL_0009: ldarg.1
IL_000A: br.s IL_0011
IL_000C: ldstr "Fix null via IsNullOrWhiteSpace"
IL_0011: starg.s 01
IL_0013: ldarg.1
IL_0014: call System.Console.WriteLine
IL_0019: nop
IL_001A: ret I'm sticking with the ??= operator for simple null tests and ternary when more involved checks are needed (e.g. see if a string is null, empty or just whitespace).
modified 5-May-21 13:19pm.
|
|
|
|