Here is my proposal for a clpfd variant of @sharky's version using if_/3. Firstly, here is a reifying version of the greater-equal to relation using clpfd:
geq_to_t(X,Y,T) :-
(X#>=Y) #<==> B,
bool10_t(B,T).
bool10_t(1,true).
bool10_t(0,false).
With geq_to_t/3 and if_/3 the predicate can be defined like so:
% this corresponds to @sharky's slne/2:
sl_of(SL,[X1,X2|Xs]) :-
if_(geq_to_t(X1,X2),
max_sl_of_(X1,X2,Xs,SL),
max_sl_of_(X2,X1,Xs,SL)).
% this corresponds to @sharky's slne/4:
max_sl_of_(_M,SL,[],SL). % base case
max_sl_of_(M,SL,[X|Xs],R) :-
if_(geq_to_t(X,M), % if X#>=M
max_sl_of_(X,M,Xs,R), % X is new maximum
if_(geq_to_t(X,SL), % else if X#>=SL
max_sl_of_(M,X,Xs,R), % X is new 2nd largest
max_sl_of_(M,SL,Xs,R))). % else X is not of interest
Note that I flipped the order of the arguments in order to use a more desciptive naming (sl_of/2), so the list is now the second argument. As demanded in the bounty description, there are no useless choicepoints left if the second argument is ground:
?- sl_of(SL,[1,2,3,4,5,6]).
SL = 5
?-
Samples from answer by @repeat:
?- sl_of(SL,[2,4,8,3,5,8,7]).
SL = 8
?- sl_of(SL,[6,4,3,6,3,4,8,6]).
SL = 6
?- sl_of(SL,[2,3,5,4,1,6,7,3,9]).
SL = 7
?- sl_of(SL,[2,3,5,4,1,6,7,3,9,8]).
SL = 8