处理多个可选参数

Dealing with more than one Optional parameter

我有程序

f:=proc(x,option1,option2) ... end proc;

在我的例子中,option1 总是一个整数,option2 是一个列表或其他东西(包括整数)。这两个选项都是可选的,因此这些命令按预期工作:

f(x);
f(x,3);
f(x,4,[1,2]);
f(x,5,3);
f(x,6,expand);

但是如果没有指定 option1 那么我不知道一个简单的方法来处理它,因为 Maple 不允许像

这样的用法
f(x,,3);
f(x,,[1,2]);

我可以让它明白

f(x,[1,2]);

但我还是有问题

f(x,3);

因为不清楚 3option1 还是 option2。我可以重写代码来理解这种格式的函数调用

f(x,[1,option1],[2,option2]);
f(x,[1,option1]);
f(x,[2,option2]);

但我很好奇是否有更简单的方法来实现这一点,因为对于某些 Maple 函数(如 plot),大多数选项的顺序无关紧要。

使用关键字参数。

f:=proc(x,{op1::integer:=0,op2::{list,integer}:={}},$)

   if has([_passed],'op1') then
      print("op1 =",op1);
   else
      print("op1 not passed");
   fi;

   if has([_passed],'op2') then
      print("op2 =",op2);
   else
      print("op2 not passed");
   fi;

    #rest of code
end proc;

现在你可以做

f(x,'op2'=[1,2,3])    
                        "op1 not passed"    
                       "op2 =", [1, 2, 3]

f(x,'op1'=99)
                          "op1 =", 99
                        "op2 not passed"

f(x)
                        "op1 not passed"    
                        "op2 not passed"

f(x,'op1'=99,'op2'=[1,2,3])
                          "op1 =", 99
                       "op2 =", [1, 2, 3]

f(x,'op1'=99,'op2'=19827)
                          "op1 =", 99
                         "op2 =", 19827

确保调用时使用'op1'=value,而不是op1=value

大多数绘图命令使用 Maple 的更现代的 argument-processing 来管理程序选项。

特别是大多数绘图命令选项都作为 so-called keyword 选项提供。这会自动提供(此类选项的)位置无关紧要的功能。

例如,

f:=proc(v, 
        {ord::{integer,NoUserValue}:=':-NoUserValue'},
        {special::{integer,list,NoUserValue}:=':-NoUserValue'});

  print(':-ord'=ord, ':-special'=special);

end proc:

f(x);

    ord = NoUserValue, special = NoUserValue

f(x,ord=3);

         ord = 3, special = NoUserValue

f(x,special=5);

         ord = NoUserValue, special = 5

f(x,special=5,ord=3);

               ord = 3, special = 5

f(x,ord=3,special=5);

               ord = 3, special = 5

如您所见,您[逻辑上]不能使用多个 *positional/ordered" 参数,如果它们具有相同的类型并且缺少一些较早的参数。

如果您真的想要,可以将这些选项之一变成 positional parameter,尽管这自然会失去任意放置的灵活性。例如,

restart;
f2:=proc(v, 
        ord::{integer,NoUserValue}:=':-NoUserValue',
        {special::{integer,list,NoUserValue}:=':-NoUserValue'});

  print(':-ord'=ord, ':-special'=special);

end proc:
f2(x);
f2(x,3);
f2(x,special=5);
f2(x,special=5,3);
f2(x,3,special=5);

restart;
f3:=proc(v, 
         special::{integer,list,NoUserValue}:=':-NoUserValue',
         {ord::{integer,NoUserValue}:=':-NoUserValue'});

  print(':-ord'=ord, ':-special'=special);

end proc:
f3(x);
f3(x,5);
f3(x,ord=3);
f3(x,ord=3,5);
f3(x,5,ord=3);

变体太多,无法在此处一一展示。

您不必使用名称“NoUserValue”作为默认值。

正如其他人已经提到的,一种解决方案是使用“kwarg”(关键字参数)。您也可以使用 _passed_rest。您可以在 Maple 帮助页面或 Maple 编程指南 (https://www.maplesoft.com/documentation_center/Maple2021/ProgrammingGuide.pdf) 中阅读更多内容。

这只是您如何使用它们的示例。 _passed 用于当您想说出传递给您的过程的任何内容时,_rest 用于传递给您的过程的任何内容,除了已经分配给您在里面提到的参数的那些proc 前面的括号。假设我们要定义一个过程,其中包含 1 个必要参数和 2 个可能的可选参数。如果给出了两个可选参数,我们假设第一个总是option1,第二个是option2,但是如果只给出一个可选参数,那么取决于它是否是[=]类型18=] 或不是它分别是 option1option2

要询问传递的参数数量或剩余的传递参数,您可以使用 _npassed_nrest。命令 assigned() 检查是否为某物分配了值。您可以通过 type(-,-)- :: - 检查某物是否属于特定类型。所以这是简单的代码。

test := proc( x )
    local option1, option2:
    if _nrest = 2 then
        option1 := _rest[1]:
        option2 := _rest[2]:
    elif _nrest = 1 then
        if _rest[1] :: integer then
            option1 := _rest[1]:
        else
            option2 := _rest[1]:
        end if:
    end if:
    printf( "necessary argument is %a\n", x ):
    if assigned( option1 ) then
        printf( "option 1 is given and is %d\n", option1 ):
    end if:
    if assigned( option2 ) then
        printf( "option 2 is given and is %a\n", option2 ):
    end if:
end proc:

下面是上述程序针对不同输入的输出截图。