在 Prolog 中处理可选的 HTTP 参数
Handling optional HTTP parameters in Prolog
我一直在尝试在 Prolog 中编写一个简单的 Web 服务,并且想知道如何处理可选参数。我认为使用 library(http/http_parameters)
可能就这么简单:
my_request_handler(Request) :-
http_parameters(Request, [ param_1(Param1, []), param_2(Param2, []) ]),
... ### handle both parameters
my_request_handler(Request) :-
http_parameters(Request, [ param_1(Param1, []) ]),
... ### handle only param_1
因此,如果未提供 param_2
,引擎将回溯到第二条规则。但在 SWI-Prolog http_parameters
中,如果参数与规范不匹配,则会引发异常,因此代码会在第一条规则上中断,而不是尝试评估第二条规则。
不幸的是,将 optional(true)
添加到 param_2
规范使其不受约束并迫使我使用这样的条件检查:
my_request_handler(Request) :-
http_parameters(Request, [ param_1(Param1, []), param_2(Param2, [optional(true)]) ]),
(error:text(Param2) ->
... ### handle both parameters
;
... ### handle only param_1
).
这是最好的做事方式还是我遗漏了什么?我想,如果有多个参数是可选的,条件语句会变得更丑陋...
干杯,
总结
至少有两条出路:
您可以将 optional/1
与 default/1
组合,并指定一个不会出现的值。
可以指定list/1
得到一个列表,使用模式匹配区分大小写
详情见下文。
使用default/1
例如,要实现选项 1,您可以这样写:
my_request_handler(Request) :-
http_parameters(Request, [ param_1(Param1, []),
param_2(Param2, [optional(true),
default(none)])
]),
handle_parameters_(Param1, Param2).
区分大小写:
handle_parameters_(Param1, Param2) :-
if_(Param2 = none,
Then,
Else).
主要缺点:要通过 模式匹配 真正区分大小写,您必须将其转换为 clean 表示。否则,您还会冒其中一个属性与您用来表示 "not specified" 的值合法重叠的风险。一种合适的表示形式可能如下所示:
none
对于 "not specified"
atom(A)
为 atom A
.
但是,此转换再次需要您手动实现区分,例如使用您发布的示例中的 var/1
。
使用list/1
选项 (2) 不太容易出错,尽管稍微间接一些。
你可以这样应用:
my_request_handler(Request) :-
http_parameters(Request, [ param_1(Param1, []),
param_2(Param2, [list(atom)])
]),
handle_parameters_(Param1, Param2).
然后,你可以通过模式匹配来区分大小写:
handle_parameters_(Param1, []) :-
...
handle_parameters_(Param1, [Param2]) :-
...
我觉得这还不错。
我一直在尝试在 Prolog 中编写一个简单的 Web 服务,并且想知道如何处理可选参数。我认为使用 library(http/http_parameters)
可能就这么简单:
my_request_handler(Request) :-
http_parameters(Request, [ param_1(Param1, []), param_2(Param2, []) ]),
... ### handle both parameters
my_request_handler(Request) :-
http_parameters(Request, [ param_1(Param1, []) ]),
... ### handle only param_1
因此,如果未提供 param_2
,引擎将回溯到第二条规则。但在 SWI-Prolog http_parameters
中,如果参数与规范不匹配,则会引发异常,因此代码会在第一条规则上中断,而不是尝试评估第二条规则。
不幸的是,将 optional(true)
添加到 param_2
规范使其不受约束并迫使我使用这样的条件检查:
my_request_handler(Request) :-
http_parameters(Request, [ param_1(Param1, []), param_2(Param2, [optional(true)]) ]),
(error:text(Param2) ->
... ### handle both parameters
;
... ### handle only param_1
).
这是最好的做事方式还是我遗漏了什么?我想,如果有多个参数是可选的,条件语句会变得更丑陋...
干杯,
总结
至少有两条出路:
您可以将
optional/1
与default/1
组合,并指定一个不会出现的值。可以指定
list/1
得到一个列表,使用模式匹配区分大小写
详情见下文。
使用default/1
例如,要实现选项 1,您可以这样写:
my_request_handler(Request) :- http_parameters(Request, [ param_1(Param1, []), param_2(Param2, [optional(true), default(none)]) ]), handle_parameters_(Param1, Param2).
区分大小写
handle_parameters_(Param1, Param2) :- if_(Param2 = none, Then, Else).
主要缺点:要通过 模式匹配 真正区分大小写,您必须将其转换为 clean 表示。否则,您还会冒其中一个属性与您用来表示 "not specified" 的值合法重叠的风险。一种合适的表示形式可能如下所示:
none
对于 "not specified"atom(A)
为 atomA
.
但是,此转换再次需要您手动实现区分,例如使用您发布的示例中的 var/1
。
使用list/1
选项 (2) 不太容易出错,尽管稍微间接一些。
你可以这样应用:
my_request_handler(Request) :- http_parameters(Request, [ param_1(Param1, []), param_2(Param2, [list(atom)]) ]), handle_parameters_(Param1, Param2).
然后,你可以通过模式匹配来区分大小写:
handle_parameters_(Param1, []) :- ... handle_parameters_(Param1, [Param2]) :- ...
我觉得这还不错。