It's a breeze with expl3:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\deflist}{O{,}m}
{
\seq_set_split:Nnn \l_narebski_list_seq { #1 } { #2 }
}
\NewDocumentCommand{\el}{}
{
\seq_item:Nn \l_narebski_list_seq { 1 }
\seq_pop_left:NN \l_narebski_list_seq \l_narebski_waste_tl
}
\seq_new:N \l_narebski_list_seq
\tl_new:N \l_narebski_waste_tl
\ExplSyntaxOff
\begin{document}
\deflist{A,B,C,D}
\el{} something \el{} xx \el{}
\deflist[-]{A-B}
\el{} something \el{} xx \el{}
\end{document}

The input is split into a sequence (spaces around the separator, that can be changed as an optional argument to \deflist, are trimmed off); at each call of \el the first item is delivered and then popped off the sequence.
A check for emptyness of the sequence can be easily added:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\deflist}{O{,}m}
{
\seq_set_split:Nnn \l_narebski_list_seq { #1 } { #2 }
}
\NewDocumentCommand{\el}{}
{
\seq_pop_left:NN \l_narebski_list_seq \l_narebski_next_tl
% if the sequence is empty, the token list will contain \q_no_value
\quark_if_no_value:VTF \l_narebski_next_tl
{ $\langle$empty$\rangle$ }
{ \tl_use:N \l_narebski_next_tl }
}
\seq_new:N \l_narebski_list_seq
\tl_new:N \l_narebski_next_tl
\cs_generate_variant:Nn \quark_if_no_value:nTF { V }
\ExplSyntaxOff
\begin{document}
\deflist{A,B,C,D}
\el{} something \el{} xx \el{}
\deflist[-]{A-B}
\el{} something \el{} xx \el{}
\end{document}

Instead of printing <empty>, the “true” part can be modified to issue a warning or an error.