Simple nth1 predicate in Prolog

前端 未结 3 998
陌清茗
陌清茗 2020-12-21 03:50

With SWI Prolog, there\'s a predicate that finds the nth item in a list called nth1. I want to implement my own version of the predicate but SWI\'s is so complicated if you

相关标签:
3条回答
  • 2020-12-21 04:18

    The SWI code is a bit complex because the predicate can be used to generate from a variable index:

    ?- nth1(Idx,[a,b,c],X).
    Idx = 1,
    X = a ;
    Idx = 2,
    X = b ;
    Idx = 3,
    X = c ;
    false.
    

    If you don't want that behavior, nth1/3 can be implemented easily in terms of nth0:

    nth1(Idx,List,X) :-
        Idx0 is Idx-1,
        nth0(Idx0,List,X).
    

    Edit: it's also possible to do without nth0 in just a few lines of code:

    nth1(1,[X|_],X) :- !.
    nth1(Idx,[_|List],X) :-
        Idx > 1,
        Idx1 is Idx-1,
        nth1(Idx1,List,X).
    
    0 讨论(0)
  • 2020-12-21 04:29

    Consider using finite domain constraints for general (reversible) integer arithmetic:

    :- use_module(library(clpfd)).
    
    nth1(1, [E|_], E).
    nth1(N, [_|Xs], E) :-
            N #> 1,
            N #= N1 + 1,
            nth1(N1, Xs, E).
    
    0 讨论(0)
  • 2020-12-21 04:32

    I didn't mean to be contradictory or get someone else to do my work actually; I just wanted some advice, sorry for not being clearer.

    I've implemented it myself now but could you guys possibly suggest improvements or better ways of doing it? What I often find myself doing in Prolog is writing a predicate with say a counter or set of counters and getting a predicate with fewer arguments to call the clauses with extra arguments. This often ends up producing quite a bit of code. Anyway, here's my implementation I just did:

    item_at( N, L, Item ) :-
        item_at( N, 0, L, Item ).   
    item_at( N, Count, [H|_], Item ) :-
        CountNew is Count + 1,
        CountNew = N,
        Item = H.
    item_at( N, Count, [_|T], Item ) :-
        CountNew is Count + 1,
        item_at( N, CountNew, T, Item ).
    

    Any comments? Thanks :). Usage:

    ?- item_at(3,[a,b,c,d,e],Item).
    Item = c ;
    
    0 讨论(0)
提交回复
热议问题