سؤال

لذلك عامل UNIV. أنا لا أفهم ذلك بالضبط.

على سبيل المثال هذا:

foo(PredList,[H|_]) :- bar(PredList,H).
foo(PredList,[_|T]) :- foo(PredList,T),!.

bar([H|_],Item) :- G =.. [H,Item],G.
bar([_|T],Item) :- bar(T,Item).

ماذا يفعل هذا؟ هذا يبدو لمعرفة ما إذا كان مسند آخر صحيح. لا أفهم ما يفعله "..".

كيف يمكنك إعادة كتابة هذا بدون مشغل UNIV؟

هل كانت مفيدة؟

المحلول

الجامعة (=..) يقسم مصطلح إلى قائمة من المكونات ، أو يبني مصطلح من هذه القائمة. محاولة:

?- f(x,y) =.. L.
L = [f, x, y].

?- f(x,y,z) =.. [f|Args].
Args = [x, y, z].

?- Term =.. [g,x,y].
Term = g(x, y).

bar يبدو أنه يتصل بكل مسند PredList على Item, ، مع foo التراجع عن Itemس. (باستخدام متغير كمسند غير محمول ؛ call يجب أن يفضل المسند.)

يحرر: Kaarel على حق ، يمكن استبدال جامعة functor/3 و arg/3, ، كالآتي:

bar([H|_],Item) :-
    functor(Goal,H,1),   % unifies Goal with H(_)
    arg(1,Goal,Item),    % unifies first argument of Goal with Item
    call(Goal).          % use this for portability

نصائح أخرى

الأنسب إعادة كتابة في رأيي هي:

 bar( [H|_], Item ) :- call(H, Item).

call/n ليست بعد جزءًا من معيار ISO Core ، لكنها قد تصبح في المستقبل القريب (*). الكثير من أنظمة المقدمة تدعمهم بالفعل.

هناك سبب واحد لماذا call/n يجب أن تكون مفضلة على البسيط (=..)/2 و functor/3 + arg/3 حلول. ال call/n الحل قادر على التعامل مع الإغلاق (**).

مع البسيط (=..)/2 و functor/3 + arg/3 الحل يمكن للمرء أن يستدعي bar/2 فقط مع الذرات في حجة القائمة الأولى. فمثلا:

 p1(1).
 p2(2).
 ?- bar( [p1, p2], 1 ).
 Yes
 ?- bar( [p1, p2], 2 ).
 Yes
 ?- bar( [p1, p2], 3 ).
 No

مع الإغلاق ، لسنا مقيدين بالذرات ، وقد نوفر بعض جهود الترميز. على سبيل المثال ، يمكننا القيام بما يلي مباشرة:

 ?- bar( [=(1), =(2)], 1 ).
 Yes
 ?- bar( [=(1), =(2)], 2 ).
 Yes
 ?- bar( [=(1), =(2)], 3 ).
 No

تحياتي الحارة

(*)
مشروع التصوير الفني 2
http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#call

(**)
من إخترعها؟: call/n المتوقع
http://www.complang.tuwien.ac.at/ulrich/prolog-inedit/naish.html

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top