I was messing around with some data and needed to convert some date/time strings to different formats and found the need to prefix certain sequences with a leading ‘0’: anything with a single character should get a leading zero; anything with two characters shouldn’t.
I became curious about more general cases, like what about prepending a leading zero to any string (really just a list, I’m not worried about the quotes and environment and all that) containing a single character, and leaving any string longer than 1 character as-is. I also wanted it to be deterministic.
I wrote this DCG rule:
with_leading_zero(X) -->
( { length(X,L), L > 1 }
-> X
; [0|X] ).
I can call phrase/2 in these ways with success:
?- phrase(with_leading_zero([1]), X).
X = [0, 1].
?- phrase(with_leading_zero([1,2,3]), X).
X = [1, 2, 3].
?- phrase(with_leading_zero(X), [1,0]).
X = [1, 0].
?- phrase(with_leading_zero(X), [0,1]).
X = [0, 1].
This fails, which makes sense:
?- phrase(with_leading_zero(X), [1]).
false.
But what I don’t understand is why does this fail unless I call phrase/3 with the remainder?
?- phrase(with_leading_zero(X), [1,2,3]).
false.