2016-11-10 2 views
1

В принципе, я пытаюсь создать стандартный предикат элемента, чтобы не загружать модули в мой проект.Проверьте, является ли элемент членом списка

Это мой код, но, к сожалению, он не работает. Что я делаю не так? Я даже поставить оператор отреза (!) Там, чтобы убедиться, что она работает, но это не ...

/** 
* Checks if an element is part of a list 
* @param [H|T] List to evaluate 
* @param Elem Elem to check 
*/ 
memberCheckSimple([], _):- !, fail.  /* stop condition */ 
memberCheckSimple([H|T], Elem):- 
    Elem \= H,       /* check if element equals head of list and negate it */ 
    memberCheckSimple(T, Elem).   /* loop */ 
memberCheckSimple(_, _).    /* only gets here if Elem belongs to list */ 
+1

Обратите внимание, что обычно аргументы: 'member (El, Els)'. – false

+1

'memberCheckSimple (non_element, non_list)' successs – false

+0

@false yes Я знаю, но все мои функции проекта теперь наоборот, и я просто испорчу вещи, если я попытаюсь изменить их все сейчас. Так может также сделать его согласованным x) Btw, вы на каждом прологе, который я вижу здесь, в stackoverflow! : p – Tirafesi

ответ

3

Один основной вопрос с логикой вашего предиката в целом является то, что она основана неудача и вас пытаются сделать успех неудачным. Это, как правило, обратное тому, что вы хотите, чтобы ваша логика была. Вы хотите, чтобы успех был основан, то есть вы хотите установить факты и правила, которые описывают, что истинно.

Вы можете воспроизвести это следующим образом. Вы знаете, что если элемент находится во главе списка, это элемент списка. Таким образом, справедливо следующее:

memberCheckSimple([H|T], H). /* H is a member of [H|T] */ 

Это также верно, что элемент является членом списка, если он состоит из хвоста списка:

memberCheckSimple([_|T], H) :- memberCheckSimple(T, H). 

Эти два правила действительно все, что вы необходимость. Запрос, который не соответствует одному из приведенных выше правил, не будет выполнен, и это то, что вы хотите.

Теперь, глядя на то, почему ваш отказ на основе предиката не работает правильно и преуспевает в случаях отказа, это из-за этого правила:

memberCheckSimple(_, _). 

Это говорит о том, что все является членом чего-либо. Вы должны признать, что это не кажется логичным (потому что это не так). Учитывая ваше предварительное условие с разрезом:

memberCheckSimple([], _) :- !, fail. 

Это предотвращает откат к вашей «универсально истинной» статье, если первый аргумент является пустым списком ([]), но если ее не пусто. Например, memberCheckSimple([a], b) в конечном итоге провалится через путь, в котором он соответствует второму предложению, а затем соответствует первому предложению. Но сокращение в первом предложении не мешает memberCheckSimple([a], b) от возврата (и последующего) по третьему предложению. Вы можете наблюдать это, делая trace.

Чтобы завершить метод, основанный на отказе (который я еще раз подчеркнуть, это неправильный подход к проблеме и другие проблемы, такие как не реляционные), вам также потребуется разрезать во втором разделе:

memberCheckSimple([H|T], Elem) :- 
    Elem \= H,     /* check if element equals head of list and negate it */ 
    !, 
    memberCheckSimple(T, Elem). /* loop */ 

Ваши комментарии в коде указывают на неотложный мыслительный процесс. Например, вы называете «цикл», например, «рекурсией». Кроме того, как упоминалось в другом комментарии, упорядочение аргументов более естественно указано как элемент, за которым следует список, поскольку вы назвали его «членом», а не «содержит».

+0

Хороший ответ. Хорошо сказано. – Enigmativity

+0

Спасибо. Вы объяснили все, что мне нужно было знать для этого, и еще кое-что :) – Tirafesi

Смежные вопросы