This will do it, although it’s a bit ugly – by reordering the goals depending on whether S
is a variable or not. (This can probably be done more elegantly using freeze/2 or when/2):
split_string_at_nth1(Nth,S,Start,End):-
( var(S)
-> string_codes(Start,SL),
string_codes(End,EL),
split_list_at_nth1(Nth,L,SL,EL),
string_codes(S,L)
; string_codes(S,L),
split_list_at_nth1(Nth,L,SL,EL),
string_codes(Start,SL),
string_codes(End,EL)
).
split_list_at_nth1(Nth, Long, Start, End) :-
length(Start, Nth),
append(Start, End, Long).
?- split_string_at_nth1(3, "abcde", Start, End).
Start = "abc",
End = "de".
?- split_string_at_nth1(I, X, "abc", "de").
I = 3,
X = "abcde".