本文介绍了使用 SICStus 拆分原子,如 SWI 中的 atomic_list_concat/3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像 'id1,id2,id3' 这样的原子,我想把它分成列表与 SWI 中的谓词 atomic_list_concat/3 相同.

i have an atom like 'id1,id2,id3' and i want to split it into list with same way as the predicate atomic_list_concat/3 in SWI .

预期结果

?- atomic_list_concat(L, ',', 'id1,id2,id3').
L = [id1, id2,id3]

?- atomic_list_concat([id1,id2,id3], ',', A).
A = 'id1,id2,id3'

无论如何,是否可以使用DCG

anyway, is it possible to do it using DCG

推荐答案

不考虑效率,这看起来很相似

without any regard to efficiency, this seems fairly similar

atomic_list_concat_(L, Sep, Atom) :-
        ( atom(Sep), ground(L), is_list(L) )
    ->  list_atom(L, Sep, Atom)
    ;   ( atom(Sep), atom(Atom) )
    ->  atom_list(Atom, Sep, L)
    ;   instantiation_error(atomic_list_concat_(L, Sep, Atom))
    .

list_atom([Word], _Sep, Word).
list_atom([Word|L], Sep, Atom) :-
    list_atom(L, Sep, Right),
    atom_concat(Sep, Right, Right1),
    atom_concat(Word, Right1, Atom).

atom_list(Atom, Sep, [Word|L]) :-
    sub_atom(Atom, X,N,_, Sep),
    sub_atom(Atom, 0,X,_, Word),
    Z is X+N,
    sub_atom(Atom, Z,_,0, Rest),
    !, atom_list(Rest, Sep, L).
atom_list(Atom, _Sep, [Atom]).

基本原理

atomic_list_concat/3 是 SWI-Prolog 中内置的一个便利,我认为我的代码没有完全涵盖规范(主要是因为我缺少 SICStus Prolog 进行测试).一个值得注意的区别是可接受类型的限定.对于列表元素,我坚持使用 atom 而不是 atomic 类型,因为 atom_concat/3 它是 ISO 内置的,因此应该禁止 SWI 接受的某些模式-Prolog 实现.

atomic_list_concat/3 is a convenience built-in in SWI-Prolog, I think my code doesn't cover fully the specification (mainly because I lack SICStus Prolog for testing). A noteworthy difference is the qualification of acceptable types. I'm sticking to atom instead of atomic types for list' elements, because atom_concat/3 it's an ISO built-in, as such should ban some patterns accepted by SWI-Prolog implementation.

关于代码,当类型测试决定了转换的方向时,实现很简单:我在 list_atom/3 中选择了一个简单的递归连接,它可以很容易地优化,例如添加一个累加器,从而使它尾递归优化,而atom_list/3从左到右扫描寻找分隔符,找到后存入list head,得到正确的部分进行递归.

About the code, when the type testing has decided about the direction of conversion, the implementation is simple: I opted for a simple recursive concatenation in list_atom/3, that could be easily optimized, for instance adding an accumulator and thus making it tail recursion optimized, while atom_list/3 scan left to right looking for separator, and when it find it, store in list head and get the right part for recursion.

关于一个头脑简单的 DCG 实现,我用这段代码来测试一个很好的抽象列表//3 由 dcg_util,导致这个紧凑的代码:

About a simple minded DCG implementation, I used this code to test a nice abstraction list//3 implemented by dcg_util, leading to this compact code:

list_atom(L, Sep, Atom) :-
    phrase(list(atom_codes, atom_codes(Sep), L), AtomCs),
    atom_codes(Atom, AtomCs).

atom_codes(A) --> {atom_codes(A, Cs)}, Cs.

atom_list(Atom, Sep, L) :-
    atom_codes(Atom, AtomCs),
    phrase(list(any, atom_codes(Sep), LCs), AtomCs),
    !, maplist(atom_codes, L, LCs).

any([]) --> [].
any([C|Cs]) --> [C], any(Cs).

很简单,无需列表即可直接实现//3...

Would be simple enough to directly implement without list//3...

这篇关于使用 SICStus 拆分原子,如 SWI 中的 atomic_list_concat/3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-19 05:14