`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`

- is true when
`ABC`,`B`, and`AC`are all atoms.`ABC`can be broken into three pieces`A`,`B`, and`C`,`AC`is the concatenation of`A`and`C`,`LenA`is the length of`A`,`LenB`is the length of`B`, and`LenC`is the length of`C`.

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 `N`th character
of `AC`.

Some other examples using the `midstring/N`

family:

- To delete 7 characters from
`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 - To divide
`Whole`into`Front`and`Back`, where the length of`Front`is known:| ?-

`midstring(Whole, Front, Back, 0, FrontLength).` - To divide
`Whole`into`Front`and`Back`, where the length of`Back`is known:| ?-

`midstring(Whole, Front, Back, 0, _, BackLength).` - To insert
`Part`into`Fringes`at a given`Offset`from the left, yielding`Whole`:| ?-

`midstring(Whole, Part, Fringes, Offset).` - To insert
`Part`into`Fringes`at a given`Offset`from the right, yielding`Whole`:| ?-

`midstring(Whole, Part, Fringes, _, _, Offset).` - To delete
`Drop`characters from`Whole`, starting at a given`Offset`from the left, yielding Short:| ?-

`midstring(Whole, _, Short, Offset, Drop).` - To delete
`Drop`characters from`Whole`, starting at a given`Offset`from the right, yielding`Short`:| ?-

`midstring(Whole, _, Short, _, Drop, Offset).` - To determine the
`Length`of`Text`:| ?-

`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).