Рекурсивная функция с операторами If-Else в Прологе

Я пытаюсь написать рекурсивную функцию в прологе, которая вычисляет R = (2*X + Y)^N без использования оператора экспоненты. Я написал рекурсивную функцию с операторами if-else и получаю сообщение об ошибке: ) or operator expected. Мне кажется, что у меня правильный синтаксис, но я должен что-то упустить. Код ниже.

expbar(R, X, Y, N) :-
    (X =:= Y =:= N =:= 0 -> 
        write("No two variables can equal 0 at the same time.");
        (N =:= 0 ->
            R is 2 * X + Y;
            R is (2 * X + Y) * expbar(R, X, Y, N-1)
        )
    ).

person aclark    schedule 22.04.2012    source источник


Ответы (3)


Вы постоянно используете выражение 2*X+Y. Почему бы не вычислить его сначала, а затем использовать этот результат для реальных вычислений? Может быть, вы что-то упустили в постановке задачи?

Почему вы хотите исключить случай, когда X, Y и N равны 0? ... при этом вы не исключаете случай N < 0?

порядок аргументов

В Прологе принято помещать результаты после соответствующих входных аргументов. Есть исключения из этого правила, (is)/2 — самый распространенный пример, но он записывается как инфиксный оператор.

Сигнализация ошибки

Для случаев, которые вы не можете правильно обработать, в Прологе есть два варианта. Либо вы молча терпите неудачу, либо выдаете чистую ошибку. (Есть третий цикл, который, хотя и не идеален, все же лучше, чем успех.) В настоящее время вы пишете текст, а затем вам это удается. Таким образом, вы предполагаете, что кто-то прочитает ваше сообщение. Но часто программы запускаются без присмотра, и сообщение игнорируется.

Представьте, что я хочу использовать ваше определение, чтобы доказать, что ваше определение — это вопрос, на который следует ответ:

?- expbar(42, 0, 0, 0).

Вот что я получаю в SWI после перезаписи X =:= Y =:= N =:= 0 в X =:= 0, Y =:= 0, N =:= 0.

?- expbar(42, 0, 0, 0).
[78,111,32,116,119,111,32,118,97,114,105,97,98,108,101,115,32,99,97,110,32,101,113,117,97,108,32,48,32,97,116,32,116,104,101,32,115,97,109,101,32,116,105,109,101,46]
true.

Там написано true.! И эти цифры выше, безусловно, являются некоторыми сообщениями о прогрессе в таком очень сложном вычислении... Так что очень легко неправильно понять ваше сообщение. Было бы немного проще, если бы вы использовали одинарные кавычки. Подробнее об одинарных и двойных кавычках. Но даже с более читаемым сообщением его легко пропустить.

Правильный способ справиться с такой ситуацией — выдать ошибку:

    throw(error(Error_term,_More_info))

Таким образом, вычисление прерывается, и ошибка обрабатывается на верхнем уровне (или в следующем месте, где ее обрабатывает catch/3). Это снижает вероятность неправильной интерпретации ошибки.

В идеале Error_term должен быть одним из существующих условий ошибки. Вот полный список ошибок в ISO Prolog . В вашем случае это может быть evaluation_error(undefined) аналогично определению возведение в степень.

person false    schedule 22.04.2012

expbar не является функцией. Правильно

expbar(R, X, Y, N) :-
(X =:= Y =:= N =:= 0 -> 
    write("No two variables can equal 0 at the same time.");
    (N =:= 0 ->
        R is 2 * X + Y;
        N1 is N - 1,
        expbar(R1, X, Y, N1)
        R is (2 * X + Y) * R1
    )
).
person joel76    schedule 22.04.2012
comment
Я реализовал этот код, но все еще получаю ) или ожидается оператор Что это такое и как это исправить? - person aclark; 23.04.2012
comment
@aclark, пожалуйста, посмотрите другие ответы X =:= Y =:= N =:= 0 недопустимый синтаксис - person false; 23.04.2012

У вас должна быть синтаксическая ошибка в начальном состоянии. Добавление к ответу joel76:

expbar(R, X, Y, N) :-
    (   ( X =:= 0, Y =:= 0 ; X =:= 0, N =:= 0 ; Y =:= 0, N =:= 0 )
    ->  write("No two variables can equal 0 at the same time.")
    ;   (   N =:= 0
        ->  R is 2 * X + Y
        ;   N1 is N - 1,
            expbar(R1, X, Y, N1),
            R is (2 * X + Y) * R1
        )
    ).
person CapelliC    schedule 22.04.2012
comment
значение R, если N =:= 0 будет 1 больше, чем 2 * X + Y, я думаю. И выражение поддается вычислению, пока 2 * X + Y или N отличается от 0, тестовые примеры могут быть слишком широкими. - person m09; 22.04.2012