سؤال

هل هناك طريقة للقيام إذا كان في مقدمة ، على سبيل المثال إذا كان المتغير 0 ، ثم للقيام ببعض الإجراءات (اكتب نصًا إلى المحطة). ليست هناك حاجة إلى أخرى ، لكن لا يمكنني العثور على أي وثائق إذا.

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

المحلول

مسند مقدمة قياسي سوف تفعل هذا.

   isfive(5). 

سيتم تقييمها إلى True إذا اتصلت بها بـ 5 وفشلت (إرجاع خطأ) إذا قمت بتشغيله مع أي شيء آخر. لعدم تساويك تستخدم =

isNotEqual(A,B):- A\=B.

من الناحية الفنية ، لا يتوحد ، لكنه يشبه المساواة.

تعلم Prolog الآن موقع ويب جيد لتعلم مقدمة.

تحرير: لإضافة مثال آخر.

isEqual(A,A). 

نصائح أخرى

نعم ، هناك بناء تحكم مثل ISO Prolog ، يسمى ->. يمكنك استخدامه مثل هذا:

( condition -> then_clause ; else_clause )

فيما يلي مثال يستخدم سلسلة من النطاقات الأخرى:

(   X < 0 ->
    writeln('X is negative.  That's weird!  Failing now.'),
    fail
;   X =:= 0 ->
    writeln('X is zero.')
;   writeln('X is positive.')
)

لاحظ أنه إذا حذفت البلية الأخرى ، فإن فشل الحالة يعني أن كل ما إذا سيفشل الـ statement. لذلك ، أوصي دائمًا بما في ذلك البنى الأخرى (حتى لو كان الأمر كذلك true).

تقدم Prolog "Unify" -

لذلك ، في Langauge الضروري سأكتب

function bazoo(integer foo)
{
   if(foo == 5)
       doSomething();
   else
       doSomeOtherThing();
}

في مقدمة سأكتب

bazoo(5) :-  doSomething.
bazoo(Foo) :- Foo =/= 5, doSomeOtherThing.

الذي ، عندما تفهم كلا الأنقام ، هو في الواقع أكثر وضوحا.
"أنا بازو للحالة الخاصة عندما يكون FOO 5"
"أنا بازو للحالة العادية عندما لا يكون FOO 5"

لقد وجدت هذا مفيدًا لاستخدام لو بيان في القاعدة.

max(X,Y,Z) :-
    (  X =< Y
    -> Z = Y
    ;  Z = X
    ).

شكرا ل http://cs.union.edu/~striegnk/learn-prolog-now/html/node89.html

أولاً ، دعنا نتذكر بعض منطق الدرجة الأولى الكلاسيكية:

"لو ص من ثم س آخر R "يعادل" (P و س) أو (non_p و ص) ".


كيف يمكننا التعبير عن "If-then-else" مثل الذي - التي في Prolog؟

دعنا نأخذ المثال الملموس التالي:

لو X هو عضو في القائمة [1,2] من ثم X يساوي 2 آخر X يساوي 4.

يمكننا مطابقة النمط أعلاه (""لو ص من ثم س آخر ص ") إذا ...

  • شرط P هو list_member([1,2],X),
  • حالة نفي non_P هو non_member([1,2],X),
  • عاقبة Q هو X=2, ، و
  • لبديل R هو X=4.

للتعبير عن القائمة (غير) العضوية بطريقة خالصة ، نحدد:

list_memberd([E|Es],X) :-
   (  E = X
   ;  dif(E,X),
      list_memberd(Es,X)
   ).

non_member(Es,X) :-
   maplist(dif(X),Es).

دعنا نتحقق من طرق مختلفة للتعبير عن "If-then-else" في Prolog!

  1. (P,Q ; non_P,R)

    ?-      (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4).
    X = 2 ; X = 4.
    ?- X=2, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2.
    X = 2 ; ؛ خاطئة.
    ?-      (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2.
    X = 2 ; ؛ خاطئة.
    ?- X=4, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4.
    X = 4.
    ?-      (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4.
    X = 4.
    

    درجة الصواب 5/5. درجة الكفاءة 3/5.

  2. (P -> Q ; R)

    ?-      (list_memberd([1,2],X) -> X=2 ; X=4).
    خاطئة.                                                % WRONG
    ?- X=2, (list_memberd([1,2],X) -> X=2 ; X=4), X=2.
    X = 2.
    ?-      (list_memberd([1,2],X) -> X=2 ; X=4), X=2.
    خاطئة.                                                % WRONG
    ?- X=4, (list_memberd([1,2],X) -> X=2 ; X=4), X=4.
    X = 4.
    ?-      (list_memberd([1,2],X) -> X=2 ; X=4), X=4.
    خاطئة.                                                % WRONG
    

    النتيجة الصحيحة 2/5. درجة الكفاءة 2/5.

  3. (P *-> Q ; R)

    ?-      (list_memberd([1,2],X) *-> X=2 ; X=4).
    X = 2 ; ؛ خاطئة.                                        % WRONG
    ?- X=2, (list_memberd([1,2],X) *-> X=2 ; X=4), X=2.
    X = 2 ; ؛ خاطئة.
    ?-      (list_memberd([1,2],X) *-> X=2 ; X=4), X=2.
    X = 2 ; ؛ خاطئة.
    ?- X=4, (list_memberd([1,2],X) *-> X=2 ; X=4), X=4.
    X = 4.
    ?-      (list_memberd([1,2],X) *-> X=2 ; X=4), X=4.
    خاطئة.                                                % WRONG
    

    النتيجة الصحيحة 3/5. درجة الكفاءة 1/5.


(تمهيدي) ملخص:

  1. (P,Q ; non_P,R) صحيح ، ولكنه يحتاج إلى تنفيذ منفصل non_P.

  2. (P -> Q ; R) يفقد الدلالات التعريفية عندما يكون التثبيت غير كافٍ.

  3. (P *-> Q ; R) هو "أقل" غير مكتمل من (P -> Q ; R), ، ولكن لا يزال لديه مشاكل مماثلة.


لحسن الحظ بالنسبة لنا ، هناك نكون البدائل:أدخل بنية التحكم المنطقية في رتابة if_/3!

يمكننا ان نستخدم if_/3 جنبا إلى جنب مع مسند القائمة العضوية memberd_t/3 مثل ذلك:

?-      if_(memberd_t(X,[1,2]), X=2, X=4).
X = 2 ; X = 4.
?- X=2, if_(memberd_t(X,[1,2]), X=2, X=4), X=2.
X = 2.
?-      if_(memberd_t(X,[1,2]), X=2, X=4), X=2.
X = 2 ; ؛ خاطئة.
?- X=4, if_(memberd_t(X,[1,2]), X=2, X=4), X=4.
X = 4.
?-      if_(memberd_t(X,[1,2]), X=2, X=4), X=4.
X = 4.

درجة الصواب 5/5. درجة الكفاءة 4/5.

أفضل ما يجب فعله هو استخدام ما يسمى cuts, الذي لديه الرمز !.

if_then_else(Condition, Action1, Action2) :- Condition, !, Action1.  
if_then_else(Condition, Action1, Action2) :- Action2.

ما سبق هو الهيكل الأساسي لوظيفة الشرط.

لتجسيد ، إليك max وظيفة:

max(X,Y,X):-X>Y,!.  
max(X,Y,Y):-Y=<X.

أقترح قراءة المزيد من الوثائق حول التخفيضات ، ولكن بشكل عام هم مثل نقاط التوقف. على سبيل المثال: في حالة الأولى max تُرجع الوظيفة قيمة حقيقية ، لا يتم التحقق من الوظيفة الثانية.

ملاحظة: أنا جديد إلى حد ما على Prolog ، ولكن هذا ما اكتشفته.

هناك أساسًا ثلاث طرق مختلفة كيفية التعبير عن شيء مثل If-then-else في Prolog. لمقارنتهم النظر char_class/2. ل a و b يجب أن يكون الفصل ab و other لجميع الشروط الأخرى. يمكن للمرء أن يكتب هذا بشكل خرقاء مثل ذلك:

char_class(a, ab).
char_class(b, ab).
char_class(X, other) :-
   dif(X, a),
   dif(X, b).

?- char_class(Ch, Class).
   Ch = a, Class = ab
;  Ch = b, Class = ab
;  Class = other,
   dif(Ch, a), dif(Ch, b).

لكتابة الأشياء بشكل أكثر إحكاما ، هناك حاجة إلى بنية إذا كانت Else. Prolog لديه واحد مدمج:

?- ( ( Ch = a ; Ch = b ) -> Class = ab ; Class = other ).
   Ch = a, Class = ab.

في حين أن هذه الإجابة سليمة ، فهي غير مكتملة. فقط الجواب الأول من ( Ch = a ; Ch = b ) معطى. الإجابات الأخرى يتم تقطيعها. ليست علائقية للغاية ، في الواقع.

بناء أفضل ، غالبًا ما يسمى "قطع ناعم" (لا تصدق أن الاسم ، فإن القطع عبارة عن قطع) ، يعطي نتائج أفضل قليلاً (هذا في YAP):

?- ( ( Ch = a ; Ch = b ) *-> Class = ab ; Class = other ).
   Ch = a, Class = ab
;  Ch = b, Class = ab.

بدلا من ذلك ، Sicstus لديه if/3 مع دلالات مماثلة جدا:

?- if( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
   Ch = a, Class = ab
;  Ch = b, Class = ab.

لذلك لا يزال الإجابة الأخيرة مكبوتة. أدخل الآن library(reif) ل Sicstus, ياب, ، و SWI. تثبيته وقل:

?- use_module(library(reif)).

?- if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
   Ch = a, Class = ab
;  Ch = b, Class = ab
;  Class = other,
   dif(Ch, a), dif(Ch, b).

لاحظ أن كل if_/3 يتم تجميعه بعيدًا إلى متداخل If-then-else

char_class(Ch, Class) :-
   if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).

الذي يتوسع في YAP 6.3.4 إلى:

char_class(A,B) :-
   ( A\=a
   ->
     ( A\=b
     ->
       B=other
     ;
       ( A==b
       ->
         B=ab
       )
     ;
       A=b,
       B=ab
     ;
       dif(A,b),
       B=other
     )
   ;
     ( A==a
     ->
       B=ab
     )
   ;
     A=a,
     B=ab
   ;
     dif(A,a),
     ( A\=b
     ->
       B=other
     ;
       ( A==b
       ->
         B=ab
       )
     ;
       A=b,
       B=ab
     ;
       dif(A,b),
       B=other
     )
   ).

يعد برنامج Prolog في الواقع شرطًا كبيرًا لـ "if" مع "ثم" الذي يطبع "الهدف الذي تم الوصول إليه" و "آخر" الذي يطبع "لم يتم العثور على مقلوب". A, Bيعني "A صحيح و B صحيح" ، معظم أنظمة Prolog لن تحاول إرضاء "B" إذا لم يكن "A" يمكن الوصول إليه (أي X=3, write('X is 3'),nl سوف طباعة "x هي 3" عندما x = 3 ، ولن تفعل شيئًا إذا كان x = 2).

(  A == B ->
     writeln("ok")
;
     writeln("nok")
),

الجزء الآخر مطلوب

يجب أن تقرأ تعلم مقدمة الآن! الفصل 10.2 باستخدام قطع. هذا يوفر مثالاً:

max(X,Y,Z) :- X =< Y,!, Y = Z.

ليقال ،

Z يساوي Y لو ! صحيح (وهو دائمًا) و X هو <= Y.

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