midstring/[3,4,5,6]
The midstring/N
family has four members:
midstring(
ABC,
B,
AC,
LenA,
LenB,
LenC)
midstring(
ABC,
B,
AC,
LenA,
LenB)
midstring(
ABC,
B,
AC,
LenA)
midstring(
ABC,
B,
AC)
The principal routine for taking apart an atom is midstring/6
.
midstring/6
Either ABC or both B and AC should be instantiated.
Apart from this restriction, midstring/6
is a genuine relation, and all
the other arguments can be solved for.
How can you be expected to remember all these arguments? The arguments fall into two groups: three text objects and three integers. The three integers form a little picture of what you want.
| LenA | LenB | LenC | ABC= a a a a a a B B B B B B B c c c c c
So the order of the three integer arguments is the same as the order of the substrings whose lengths they are. Note that none of these arguments is a "position" in any string: all three of them are to be understood as lengths of strings.
The order of the text arguments was chosen to extend the order used
by substring/5
(see lib-txp-sub-substring). Generally, you are more likely
to know ABC than B or AC, and you are more likely
to know B than AC.
For example, a common use of the midstring/[3,4,5,6]
family is to ask
"if B is deleted from ABC, what results?",
which can be done by asking
| ?- midstring(this_is_abc, is, AC, _, _, _). AC = th_is_abc ; AC = this__abc ; no
Earlier in this section we saw midstring/4
used to append two
strings. Now we can see how that works:
| ?- midstring(BC, B, C, 0).
is true when BC can be broken into three parts, A, B, and C, such that 0 is the length of A, the lengths of B and C are unconstrained, and C is the concatenation of A and C.
Another way to see this is that
| ?- midstring (ABC, B, AC, N).
is true when ABC is obtained by inserting B just after the Nth character of AC.
Some other examples using the midstring/N
family:
I"m going, Tom
, retaining the first 4
characters:
| ?- midstring('I''m going, Tom', _, Answer, 4, 7). Answer = 'I''m Tom'
To search for the text ab
in abracadabra
:
| ?- midstring(abracadabra, ab, _, Offset). Offset = 0 ; Offset = 7 ; no
| ?- midstring(Whole, Front, Back, 0, FrontLength).
| ?- midstring(Whole, Front, Back, 0, _, BackLength).
| ?- midstring(Whole, Part, Fringes, Offset).
| ?- midstring(Whole, Part, Fringes, _, _, Offset).
| ?- midstring(Whole, _, Short, Offset, Drop).
| ?- midstring(Whole, _, Short, _, Drop, Offset).
| ?- midstring(Text, Text, '', 0, Length, 0).
It would not be useful to try to memorize these examples. Instead, remember the picture:
ABC, B, AC, LenA, LenB, LenC
Note that midstring/[3,4,5,6]
has been carefully designed so that you can
extract and insert from either the left or the right with equal
facility, and so that successive calls to extract related fragments
will require a minimum of arithmetic. For example, suppose we want to
break a text ABCD into four pieces, where the lengths of B and D are
known. We think about the picture
ABCD = '' (ABC) D ABC = A (B) C AC = A (C) ''
and then write
four_parts(ABCD, A, B, C, D, LenB, LenD) :- /* this is an example */ midstring(ABCD, ABC, D, 0, _, LenD), midstring(ABC, B, AC, LenA, LenB), midstring(AC, C, A, LenA, _, 0).