Prolog HTTP динамически добавляет ссылки в html

Я новичок в прологе и декларативном программировании, и я изо всех сил пытаюсь добиться следующего.

Я следую этому руководству и теперь хотел бы показать несколько ссылок на странице. Какие ссылки должны отображаться, зависит от определенных фактов/переменных.

Вот мой текущий код:

link_collection(Request) :-
http_parameters(Request,
[
    foo(Foo, [optional(true)])
]),
reply_html_page(
    [title('Dynamic Link Collection')],
    [
        a([href='/questionalice'], 'Question Alice'),       /* Should only show if has(investigate, body) is true */
        a([href='/questionbob'], 'Question Bob'),          /* Should only show if Foo = bar */
        a([href='/investigatebody'], 'Investigate Body')   /* Show always */
    ]
).

обратите внимание, что количество «перестановок» не позволяет мне просто «или» операторы link_collection. Также хотелось бы, чтобы условия были сколь угодно сложными.


person Xaser    schedule 04.11.2017    source источник
comment
При написании тегов HTML, таких как a, вам нужно заключить их в html//1. Попробуйте html([a(href='...', ...), ...]), у вас это работает?   -  person Wouter Beek    schedule 04.11.2017
comment
нет - answer_html_page автоматически оборачивает его в html//1.. этот код работает нормально, но ссылки статичны и отображаются всегда, независимо от условий.   -  person Xaser    schedule 05.11.2017


Ответы (1)


На ваш вопрос можно ответить в достаточно общем контексте, то есть даже без учета конкретного варианта использования HTTP.

Общий вопрос выглядит следующим образом: как я могу динамически выбрать подмножество некоторых доступных параметров.

Для этого предположим, что вы представляете каждую ссылку не просто как «саму себя», а скорее как пару формы Link-Condition с интерпретацией, что Link следует включать только если Condition правда.

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

is_true_with_foo(_, has(investigate, body)) :- has(investigate, body).
is_true_with_foo(Foo, Foo = bar)            :- Foo = bar.
is_true_with_foo(_, true).

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

Теперь условия примера можно представить следующим образом:

links_conditions(Foo,
    [
        a([href='/questionalice'], 'Question Alice')-has(investigate, body),
        a([href='/questionbob'], 'Question Bob')-(Foo = bar),
        a([href='/investigatebody'], 'Investigate Body')-true
    ]).

Чтобы описать подпоследовательность списка, рассмотрите возможность использования DCG (dcg).

Например:

links_subset([], _) --> [].
links_subset([L-Cond|Ls], Foo) -->
        (   { is_true_with_foo(Foo, Cond) } ->
            [L]
        ;   []
        ),
        links_subset(Ls, Foo).

Теперь вы можете позвонить:

?- links_conditions(Foo, LCs0),
   phrase(links_subset(LCs0, no), LCs).

и получить в LCs остальные ссылки. В этом случае:

LCs = [a([href='/questionalice'], 'Question Alice'),
a([href='/investigatebody'], 'Investigate Body')].

Итак, мы можем использовать полученные ссылки в нашем ответе:

link_collection(Request) :-
        http_parameters(Request, [foo(Foo, [optional(true)])]),
        links_conditions(Foo, LCs0),
        phrase(links_subset(LCs0, Foo), LCs),
        reply_html_page([title('Dynamic Link Collection')], LCs).

Обратите внимание, как в этих предикатах передается Foo.

P.S.: В вашем фрагменте примера есть элементарные синтаксические ошибки, поэтому я сомневаюсь, что ваш код хоть как-то работает.

person mat    schedule 05.11.2017
comment
очень интересная попытка, завтра подробно изучу и оценю. Просто интересно: на какие синтаксические ошибки в моем фрагменте вы ссылаетесь? Я внимательно следил за учебным пособием, и мой код, который представляет собой менее общую версию исходного фрагмента, который я опубликовал, работает отлично. На самом деле я уже сталкивался с решением, использующим DCG, и html включает использование \include, однако ваши решения кажутся более элегантными. - person Xaser; 05.11.2017
comment
В вашем фрагменте есть 2 синтаксические ошибки, во втором и третьем представлении ссылки. Первая синтаксическая ошибка возникает по адресу: a([href='/questionbob']), 'Question Bob'). Обратите внимание на (второе) закрывающее ), которому не соответствует (! Такая же ошибка присутствует и в представлении третьего звена. - person mat; 05.11.2017
comment
упс, да, это, должно быть, проскользнуло из-за копирования и вставки при разработке фрагмента примера. - person Xaser; 06.11.2017
comment
Попробовав решение, мне интересно, видите ли вы способ использовать произвольное количество условных переменных, таких как Foo? - person Xaser; 06.11.2017
comment
Конечно! Пожалуйста, задайте отдельный вопрос для этого, я отвечу на него там. - person mat; 06.11.2017
comment
на самом деле мне удалось разработать DCG, которая принимает условие формы (Cond1; Cond2, Cond3) в качестве аргумента. Будет истинным, если cond2 и cond3 или cond1 истинны. Мне даже не нужно передавать переменные условий в DCG. Я не уверен на 100%, почему это работает или имеет ли это какие-либо побочные эффекты, но, похоже, на данный момент он делает все, что мне нужно. Я принимаю этот ответ. - person Xaser; 06.11.2017
comment
Найдите мета-интерпретатор Prolog, чтобы понять, почему это работает! Думаю, систематическое и всестороннее знакомство с современным Прологом будет вам полезно для решения таких более сложных задач. - person mat; 06.11.2017