Это как-то "отражение" в Прологе?
Поэтому в основном я пытаюсь использовать некоторый код Пролога для имитации поведения, подобного указателю.
Я задал соответствующий вопрос здесь, и примерно через месяц у меня наконец-то появилось время для начала.
Вот простой пример в C:
int a = 1;
int* p = &a;
int b = *p;
И я хочу перевести этот код в Пролог, как это (или другие лучшие стратегии?):
A is 1,
assert(ref(p, a)), <- this can be dynamic fact gene
ref(p, TEMP), <- now I want to use a!!
to_lowercase(TEMP, TEMP1), <- I don't know how to implement to_low
B is TEMP1. <- reflection?
Так что в приведенном выше коде, я запутался с
В моем понимании после
ref(p, TEMP)
, затемTEMP
будет равно"a"
, и это просто строка, тогда как я могу использовать ее как имя переменной, звучит как отражение...?Как реализовать функцию to_lowercase?
Я чист?
3 ответа
Если вы действительно решили имитировать компьютер из Prolog, вы должны принять во внимание ответы на свои предыдущие вопросы, прежде чем двигаться дальше. В любом случае, этот ответ делает много предположений о том, какова ваша конечная цель. Я предполагаю, что вы пытаетесь симулировать машину и пишете симулятор, который берет исходный код, написанный на языке C-стиля, и выполняет его.
Допустим, у вас очень простой процессор с плоским пространством памяти (некоторые маленькие встроенные микроконтроллеры похожи на это). Тогда вся ваша память будет представлять собой один кусок 16-битных адресов, скажем, 1000 из них:
functor(Memory, memory, 1000).
Взяв ваш C-код выше, компилятор может придумать:
- Выберите адрес
Addr1
заa
, который являетсяint
и напишите значение1
по этому адресу - Выберите адрес
Addr2
заp
, который являетсяint *
и напишите значение адресаa
по этому адресу - Выберите адрес
Addr3
заb
, который являетсяint
и запишите в него значение, которое находится в памяти, к которой относится значение вp
указывает на.
Это может привести к машинному коду для компьютера, который вы моделируете (при условии, что фактические адреса уже были соответствующим образом выбраны компилятором):
arg(Addr1, Memory, 1), % int a = 1;
arg(Addr2, Memory, Addr1), % int *p = &a;
arg(Addr2, Memory, Tmp1), %% put the value at p in Tmp1; this is an address
arg(Tmp1, Memory, Tmp2), %% read the value at the address Tmp1 into Tmp2
arg(Addr3, Memory, Tmp2). % int b = *p;
Поэтому, конечно, все адреса должны быть в пределах вашей памяти. Некоторые из звонков arg/3
выше - чтение, а некоторые - запись; должно быть понятно, что есть что. Обратите внимание, что в этом конкретном сочетании все три аргумента к термину memory/1000
все еще свободные переменные. Чтобы изменить значения по адресу, который уже был установлен, вам необходимо соответствующим образом скопировать его, освобождая адрес, который необходимо использовать повторно.
Пожалуйста, внимательно прочитайте все ответы на ваши вопросы, прежде чем нажимать на.
Вам нужно прочитать хорошую книгу по Прологу. Я бы предложил Искусство Пролога.
У Пролога нет ничего похожего на указатели, адреса или переменные. У него есть условия. Несвязанный термин является переменным, потому что он еще не связан. Однажды связанная (объединенная), она перестает быть переменной и становится той, с которой она объединяется. Ему не может быть присвоено новое значение - если объединение не отменено путем обратного отслеживания и не выбран альтернативный путь. Отсюда и термин объединение.
Попытка отобразить концепцию указателей и адресов памяти на прологе сродни посадке рыбьих жабр на велосипед.
Что касается реализации предиката для преобразования сильного в нижний регистр, вы должны понимать, что на самом деле у Пролога нет строк: строка Пролога "ABC"
точно совпадает со списком [65,66,67]
, список целых чисел, представляющих кодовые точки ASCII/Unicode. Это то, что называется синтаксическим сахаром. Итак... учитывая эту идентичность...
Что-то вроде
to_lower( [] , [] ).
to_lower( [C|Cs] , [L|Ls] ) :-
char_code('A',A),
char_code('Z',Z),
C >= A ,
C =< Z ,
! ,
char_code(a,Base),
Offset = C - A ,
L is Base+Offset,
to_lower(Cs,Ls).
to_lower([C|Cs],[C|Ls]) :-
to_lower(Cs,Ls).
Должен ли ты сделать.
Поскольку вы помечаете вопрос SWI-Prolog, я предполагаю, что у вас есть string
Концепция претерпела некоторые важные изменения в последнее время, в основном из соображений эффективности.
Посмотрите на downcase_atom / 2 или string_lower / 2, в зависимости от вашего предполагаемого использования (я ссылался на страницу обработки строк, потому что у string_lower есть опечатка).
Для хранения объектов типа "указатели" я предлагаю использовать глобальные переменные nb_setval/2, nb_getval/2, nb_current/2 вместо assert/retract. Во-первых, они намного более эффективны (я измерял время в 3 раза в пользу семейства предикатов nb_) и проясняют предполагаемое использование. assert/retract лучше использовать для обновления динамической базы знаний.