在 swi-prolog 中使用字典
using dictionaries in swi-prolog
我正在 Prolog 中开发一个简单的 Web 服务,并希望使用格式为 JSON 的数据来响应我的用户。 reply_json_dict/1
是一个不错的工具,它接受字典并将其转换为格式正确的 JSON 正文的 HTTP 响应。
我的麻烦是构建响应字典本身似乎有点麻烦。例如,当我 return 一些数据时,我有数据 ID 但 may/may 没有数据属性(可能是未绑定变量)。目前我执行以下操作:
OutDict0 = _{ id : DataId },
( nonvar(Props) -> OutDict1 = OutDict0.put(_{ attributes : Props }) ; OutDict1 = OutDict0 ),
reply_json_dict(OutDict1)
效果很好,所以输出是 { "id" : "III" }
或 { "id" : "III", "attributes" : "AAA" }
取决于 Props
是否绑定,但是...我正在寻找更简单的方法。主要是因为如果我需要添加更多可选的 key/value 对,我最终会得到多重含义,例如:
OutDict0 = _{ id : DataId },
( nonvar(Props) -> OutDict1 = OutDict0.put(_{ attributes : Props }) ; OutDict1 = OutDict0 ),
( nonvar(Time) -> OutDict2 = OutDict1.put(_{ time : Time }) ; OutDict2 = OutDict1 ),
( nonvar(UserName) -> OutDict3 = OutDict2.put(_{ userName : UserName }) ; OutDict3 = OutDict2 ),
reply_json_dict(OutDict3)
这似乎是错误的。有没有更简单的方法?
干杯,
亚采克
在这种情况下,我的建议是使用不同的谓词来发出JSON。
,而不是乱用字典
例如,考虑 json_write/2
,它允许您发出 JSON,也可以根据 HTTP 库的要求在当前输出上发出。
假设您对 数据字段的表示 是整个 HTTP 库中用于选项处理的通用 Name(Value)
表示法:
Fields0 = [attributes(Props),time(Time),userName(UserName)],
使用 meta-predicate include/3
,您的整个示例变为:
main :-
Fields0 = [id(DataId),attributes(Props),time(Time),userName(UserName)],
include(ground, Fields0, Fields),
json_write(current_output, json(Fields)).
您可以自己尝试一下,为上面代码段中的 单例变量 的各个元素插入合适的值。
例如,我们可以(任意)使用:
Fields0 = [id(i9),attributes(_),time('12:00'),userName(_)],
产量:
?- main.
{"id":"i9", "time":"12:00"}
true.
您只需要发出合适的 Content-Type header,并具有与 reply_json_dict/1
相同的输出给你了
如果您使用列表来表示需要进入字典的所有值,则可以一步完成。
?- Props = [a,b,c], get_time(Time),
D0 = _{id:001},
include(ground, [props:Props,time:Time,user:UserName], Fs),
D = D0.put(Fs).
D0 = _17726{id:1},
Fs = [props:[a, b, c], time:1477557597.205908],
D = _17726{id:1, props:[a, b, c], time:1477557597.205908}.
这借用了 mat 的答案中的想法来使用 include(ground)
。
非常感谢 mat 和 Boris 的建议!我最终结合了你的想法:
dict_filter_vars(DictIn, DictOut) :-
findall(Key=Value, (get_dict(Key, DictIn, Value), nonvar(Value)), Pairs),
dict_create(DictOut, _, Pairs).
然后我就可以这么简单地使用:
DictWithVars = _{ id : DataId, attributes : Props, time : Time, userName : UserName },
dict_filter_vars(DictWithVars, DictOut),
reply_json_dict(DictOut)
我正在 Prolog 中开发一个简单的 Web 服务,并希望使用格式为 JSON 的数据来响应我的用户。 reply_json_dict/1
是一个不错的工具,它接受字典并将其转换为格式正确的 JSON 正文的 HTTP 响应。
我的麻烦是构建响应字典本身似乎有点麻烦。例如,当我 return 一些数据时,我有数据 ID 但 may/may 没有数据属性(可能是未绑定变量)。目前我执行以下操作:
OutDict0 = _{ id : DataId },
( nonvar(Props) -> OutDict1 = OutDict0.put(_{ attributes : Props }) ; OutDict1 = OutDict0 ),
reply_json_dict(OutDict1)
效果很好,所以输出是 { "id" : "III" }
或 { "id" : "III", "attributes" : "AAA" }
取决于 Props
是否绑定,但是...我正在寻找更简单的方法。主要是因为如果我需要添加更多可选的 key/value 对,我最终会得到多重含义,例如:
OutDict0 = _{ id : DataId },
( nonvar(Props) -> OutDict1 = OutDict0.put(_{ attributes : Props }) ; OutDict1 = OutDict0 ),
( nonvar(Time) -> OutDict2 = OutDict1.put(_{ time : Time }) ; OutDict2 = OutDict1 ),
( nonvar(UserName) -> OutDict3 = OutDict2.put(_{ userName : UserName }) ; OutDict3 = OutDict2 ),
reply_json_dict(OutDict3)
这似乎是错误的。有没有更简单的方法?
干杯, 亚采克
在这种情况下,我的建议是使用不同的谓词来发出JSON。
,而不是乱用字典例如,考虑 json_write/2
,它允许您发出 JSON,也可以根据 HTTP 库的要求在当前输出上发出。
假设您对 数据字段的表示 是整个 HTTP 库中用于选项处理的通用 Name(Value)
表示法:
Fields0 = [attributes(Props),time(Time),userName(UserName)],
使用 meta-predicate include/3
,您的整个示例变为:
main :- Fields0 = [id(DataId),attributes(Props),time(Time),userName(UserName)], include(ground, Fields0, Fields), json_write(current_output, json(Fields)).
您可以自己尝试一下,为上面代码段中的 单例变量 的各个元素插入合适的值。
例如,我们可以(任意)使用:
Fields0 = [id(i9),attributes(_),time('12:00'),userName(_)],
产量:
?- main. {"id":"i9", "time":"12:00"} true.
您只需要发出合适的 Content-Type header,并具有与 reply_json_dict/1
相同的输出给你了
如果您使用列表来表示需要进入字典的所有值,则可以一步完成。
?- Props = [a,b,c], get_time(Time),
D0 = _{id:001},
include(ground, [props:Props,time:Time,user:UserName], Fs),
D = D0.put(Fs).
D0 = _17726{id:1},
Fs = [props:[a, b, c], time:1477557597.205908],
D = _17726{id:1, props:[a, b, c], time:1477557597.205908}.
这借用了 mat 的答案中的想法来使用 include(ground)
。
非常感谢 mat 和 Boris 的建议!我最终结合了你的想法:
dict_filter_vars(DictIn, DictOut) :-
findall(Key=Value, (get_dict(Key, DictIn, Value), nonvar(Value)), Pairs),
dict_create(DictOut, _, Pairs).
然后我就可以这么简单地使用:
DictWithVars = _{ id : DataId, attributes : Props, time : Time, userName : UserName },
dict_filter_vars(DictWithVars, DictOut),
reply_json_dict(DictOut)