I'm trying to manage optional parameters (I need to know which of them are actually passed), but it seems like in the case of boolean type has([_passed],'op1') is acting weird.
Can someone explain why has([_passed],'op1') is working correctly in function f, but isn't working correctly in function g? What am I missing here?
f:=proc(x,{op1::integer:=1,op2::boolean:=false});
print(has([_passed],'op1'),has([_passed],'op2'));
end proc:
g:=proc(x,{op1::boolean:=true,op2::boolean:=false});
print(has([_passed],'op1'),has([_passed],'op2'));
end proc:
"Correct:";
f(x);
f(x,op1=1);
f(x,op2=true);
f(x,op1=1,op2=true);
"Incorrect:";
g(x);
g(x,op1=true);
g(x,op2=true); #this case gives incorrect result
g(x,op1=true,op2=true);
The output:
"Correct:"
false, false
true, false
false, true
true, true
"Incorrect:"
false, false
true, false
true, true
true, true
The idea of has([_passed],'op1') is taken from this post.
Printing out _passed[1.._npassed] reveals what has happened here.
g:=proc(x,{op1::boolean:=true,op2::boolean:=false});
print(has([_passed],'op1'),has([_passed],'op2'),[_passed[1.._npassed]]);
end proc:
g(x,op2=true);
gives true, true, [x, op2 = true]. So the first true from has([_passed],'op1') is because 'op1' is evaluated as true and not as the name op1. And indeed _passed has true, the true in op2 = true. This can be verified by using extra unevaluation quotes:
g:=proc(x,{op1::boolean:=true,op2::boolean:=false});
print(has([_passed],''op1''),has([_passed],'op2'),[_passed[1.._npassed]]);
end proc:
g(x,op2=true);
now gives the expected false, true, [x, op2 = true].
Relying on the correct number of unevaluation quotes is fragile. As noted in the comment by @Nasser, one can use default values to find when an ordered or keyword argument was passed, recognizing that the default value does not have to be the declared type. For example,
g:=proc(x,{op1::truefalse:=0,op2::truefalse:=0});
if op1=0 then
print("user passed no value")
else
print(op1)
end if
end proc:
g(x,op2=true);
gives "user passed no value". (I used truefalse rather than boolean here because the latter can include other than true or false, such as 2 > 3.)