📜 ⬆️ ⬇️

Make Refal on Prolog. Seven line magic

If the discriminating machine responds to the drawing of an elephant with a “mura” signal, the images of a camel are also “mura” and the portrait of a prominent scientist is again “mura”, this does not necessarily mean that it is faulty. She may just be philosophically tuned.
Vladimir Savchenko, "Opening yourself"


1. Love Refal. Immediately!



Everyone knows that there is such a programming language - Refal. Refal was developed in 1966 by our compatriot Valentin Turchin. The fate of Refal is complicated, but the language is still alive and developing. For those interested, here are some links:

')
Strongly exaggerating, we can say that Refal is a mixture of Lisp and Prolog. In the syntax of the language there is one interesting feature - the comparison with the so-called sample. "Direct conclusion".

Ie, for example, the predicate for defining a palindrome on Refal can be written as:

Palindrom { = True; s.1 = True ; s.1 e.2 s.1 = <Palindrom e.2> ; e.1 = False ; } 


Each line in braces is a pattern matching rule. The body of each rule is separated by the symbol "=". Sample elements are separated by a space. The function call is written in angle brackets. Symbols beginning with “s” and “e” are variables of a certain type. The variable name is written after the full stop.


So This definition of a palindrome can be read as follows:


It is necessary to cancel that in modern implementations of Refal the pattern matching is implemented quite effectively.

2. Prologue. The magic begins!



In Refal there is a lot of Prolog language. We will try to implement the mechanism of refal pattern matching on the Prolog.

Before we begin, we define the auxiliary predicate “prefix”. The predicate must check whether the first argument is the beginning of the second argument. The remainder of the second argument is specified in the third argument.

 prefix([], [X|Xs], [X|Xs]). prefix([X|Prefix], [X|List], Rest) :- prefix(Prefix, List, Rest). 


Call examples:

 ?- prefix([1,2], [1,2,3,4], [3,4]). true. ?- prefix([], [1,2,3,4], X). X = [1, 2, 3, 4]. 


Now everything is ready for us to define the predicate of the reference match with the sample (let's call the predicate “rf”). Let us give examples of using “rf” using the example of the same palindrome (the implementation itself will be a little later):

 palindrom([]). palindrom([_]). palindrom(List) :- rf([s(X1), e(Y), s(X1)], List), palindrom(Y). 


As you can see, this definition is similar to what we wrote earlier on Refal. We did not need the fourth rule in the Refalian example, since The prologue itself will cut off the false branches of the collation. Note that the “s” and “e” in the example are the usual terms of Prologue.

Examples of calling our palindrome:

 ?- palindrom("abc"). false. ?- palindrom("abcba"). true . ?- palindrom("aa"). true . 


We now turn, in fact, to the definition of the predicate “rf”:

 rf([X | Pattern], [X|Xs]) :- rf(Pattern, Xs). rf([s(X) | Pattern], [X|Xs]) :- rf(Pattern, Xs). rf([e(X) | Pattern], Xs) :- prefix(X, Xs, Rest), rf(Pattern, Rest). rf([e(X)], X). rf([], []). 


Let's comment on our definition line by line:


3. Examples



3.1. First example



The wonderful article “Prolog, Introduction” provides a solution to the problem proposed in the Refal community in Prolog. Task statement:

There are two ASCII strings in the input file, one consists only of capital Latin letters, the other can contain large Latin letters and two more special characters - * (asterisk) and? (question mark). Lines can be from 1 to 255 characters long, be in a file in any order (but there are only two of them, the format of the input data is correct). A string with only letters is called a word. A string with special characters - a pattern in which the "?" and "*" play the role of wildcard characters according to the rules identical to wildcards in DOS or Unix-shell file names, i.e. "?" substitutes for itself exactly one arbitrary character, and "*" replaces any number of arbitrary characters — 0 or more (that is, it can replace an empty string). The program should give the answer YES, if the word falls under the pattern (match it), or NO otherwise.


Solution to the refal:

 Match { s.1 e.2 (s.1 e.3) = <Match e.2 (e.3)>; s.1 e.2 ('?' e.3) = <Match e.2 (e.3)>; e.1 ('*' e.3) = { e.1 : e.11 e.12, <Match e.12 (e.3)>; }; /*empty*/ () = /*yes*/; }; 


Rewrite the Refal predicate on Prolog using the approach described above:

 ischar(H, [H]). match([],[]) :- !. match("*",_) :- !. match(Pattern, Word) :- rf([s(T1), e(E1)], Pattern), rf([s(T1), e(E2)],Word), match(E1, E2),!. match(Pattern, Word) :- rf([s(T1), e(E1)], Pattern), ischar(T1, "?"), rf([s(_T2), e(E2)], Word), match(E1,E2),!. match(Pattern, Word) :- rf([s(T1), e(E1)], Pattern), ischar(T1, "*"), rf([e(_E21), e(E22)], Word), match(E1,E22),!. check:- match("ASDFAASDASDAAASDASDASD", "ASDFAASDASDAAASDASDASD"), match("*", "ASDFAASDASDAAASDASDASD"), match("A?DF?A*ASD*ASDA?DASD", "ASDFAASDASDAAASDASDASD"), \+ match("ASDFAASDADAAASDASDASD", "ASDFAASASDAAASDASDASD"). 


Note that, of course, our definition is significantly less efficient than the solution from the article “Prolog, introduction” .

3.2. Second example



Let's give one more example of using our predicate. We define a trivial predicate that calculates arithmetic expressions in a string.

Example of use:

 ?- infix("2+2*2", R). R = 6. ?- infix("1+1+1+1", R). R = 4. 


Let the infix predicate "understand" only operations of addition and multiplication. Then the solution might look like this:

 ischar(H, [H]). infix(A,R) :- rf([e(X), OpPlus, e(Y)], A), ischar(OpPlus, "+"), infix(X,R1), infix(Y,R2), R is R1 + R2,!. infix(A,R) :- rf([e(X), OpMul, e(Y)], A), ischar(OpMul, "*"), infix(X,R1), infix(Y,R2), R is R1 * R2, !. infix(A,R) :- rf([e(X)], A), number_codes(R, X),!. 


We reserve the implementation of other operators for independent study.

Instead of conclusion



The code above does not claim to be unique or practical. However, we dare to hope, will push the reader to get closer to such wonderful languages ​​as Prolog and Refal.

Source: https://habr.com/ru/post/198972/


All Articles