1

の使用に問題がありsetof/3ます。一部の結果が表示されません。

コンテキスト:

SWI-Prolog load_xml() を使用して xml ファイルをロードし、再帰的なリスト要素を取得します (例の testelement を参照)。次に、このリスト (xml ツリー内) で特定の要素を検索します。と組み合わせて
使用​​すると、うまく機能します。しかし、 を使用すると、結果が 1 つ失われます。要素を取得/保持するための再帰呼び出しが原因で問題があると思いますか? 再帰リストから要素を取得する別の解決策を知っている人はいますか?findall/3sort/2setof/3setof/3askElement/3

私のテストコード:

testElement([element('recipeml',[version=0.5], 
    [element('recipe',[],
        [element('head',[],
            [element('title',[],['Spaghetti Bolognese']
            )]
        ),
        element('ing-div',[type=titled], 
            [element('title',[],['sauce']),
             element('ingredients',[],
                [element('ing',[],
                    [element('item',[],['hackfleisch']),
                     element('item',[],['fleischtomaten']),
                     element('item',[],['zwiebeln']),
                     element('item',[],['sellerie']
                    )]
                )]
            )]
        )]
    ),
    element('recipe',[],
        [element('head',[],
            [element('title',[],['Erbsensuppe']
            )]
        ),
        element('ing-div',[type=titled], 
            [element('title',[],['elementar']),
             element('ingredients',[],
                [element('ing',[],
                    [element('item',[],['sahne']),
                     element('item',[],['erbsen']),
                     element('item',[],['gemüsebrühe']
                    )]
                )]
            )]
        )]
    )] 
)]).

askElement(Name, Child, Parent) :-
    (
        member( element(Name,_,Child),Parent)
    ;
        member( element(_,_,NewParent),Parent),
        [_|_] = NewParent,
        askElement(Name, Child, NewParent)
    ).

allRecipes_findall(RecipeName) :-
    testElement(Knot),
    findall(TmpR,(askElement('head',HKnot,Knot),askElement('title',TmpR,HKnot)),Bag),
    sort(Bag, RecipeName).

allRecipes_setof(RecipeName) :-
    testElement(Knot),
    setof(TmpR,(askElement('head',HKnot,Knot),askElement('title',TmpR,HKnot)),RecipeName).

私の出力:

3 ?- allRecipes_findall(X).
X = [['Erbsensuppe'], ['Spaghetti Bolognese']].

4 ?- allRecipes_setof(X).
X = [['Erbsensuppe']] 

私はどちらの場合でも私が得ると思っていました

X = [['Erbsensuppe'], ['Spaghetti Bolognese']].

どうしたの?

よろしくお願いします!

PS: 私の (初めての) Prolog コードのコメント/レビューは大歓迎です :}

4

2 に答える 2

2

Paulo は、現在のコードについて既に多くのアドバイスを提供しています。XML を処理する必要がある場合にライブラリ ( xpath ) を利用することを提案するためだけにここにいます。少し運動が必要ですが、多くの機能が得られます...あなたの例では:

?- [library(xpath)].
true.

?- testElement(E), xpath(E, //head//title(text), T).
...
T = 'Spaghetti Bolognese' ;
...
T = 'Erbsensuppe' ;
false.
于 2014-08-08T12:53:22.923 に答える
1

標準のsetof/3述語は、ゴール内の自由変数の異なるインスタンス化ごとにソリューションを提供します。コードをそのまま使用すると、次のようになります。

?- allRecipes_findall(X).
X = [['Erbsensuppe'], ['Spaghetti Bolognese']].

?- allRecipes_setof(X).
X = [['Erbsensuppe']] ;
X = [['Spaghetti Bolognese']].

それが期待される結果です。ただし、演​​算子setof/3を使用して存在量化することにより、自由変数を無視することができます。^/2

allRecipes_setof(RecipeName) :-
    testElement(Knot),
    setof(TmpR,HKnot^(askElement('head',HKnot,Knot),askElement('title',TmpR,HKnot)),RecipeName).

この変更により、findall/3述語と同じ結果が得られます。

?- allRecipes_setof(X).
X = [['Erbsensuppe'], ['Spaghetti Bolognese']].

プログラミング スタイルに関するコメントについては、コードを読みやすくするために、atom 内でCamelCaseの代わりにアンダースコアを使用してください。たとえばask_element、の代わりにaskElement。一方、変数については、キャメルケースがよく使われます。

于 2014-08-08T08:49:57.397 に答える