[erlang-questions] Additions to lists module

Richard O'Keefe <>
Thu Nov 27 03:30:40 CET 2008

On 27 Nov 2008, at 12:52 pm, Michael McDaniel wrote:

> Everyone works on different kinds of problems and has their solutions.
> One immediate use I thought of follows.
> Note that html_tokenise is from Joe Armstrong's www_tools-1.0 on  
> trapexit.
> {ok, H} = http:request("http://somewebsite.com") ,
> Ht      = html_tokenise:string2toks( element(3, H) ) ,
> Pos     = list_position:pos( Hal, {tagStart,"title"} ) ,
> {_, Title} = lists:nth( Pos+1, Hal ).

This is better as

	{_,Title} = lists:after({tagStart,"title"}, Hal)

	after(X, [X,Y|_]) -> Y;
	after(X, [_|Ys])  -> after(X, Ys).

which does the job in one pass.  The *order* and *adjacency*
of elements in a list often matters; the actual *positions*
far less often.

If we add

	before(X, [Y,X|_]) -> Y;
	before(X, [_|Ys])  -> before(X, Ys).

then we've matched the #after: and #before: methods in
ANSI Smalltalk's SequencedReadableCollection class.
If we add

	after(X, [X,Y|_], _) -> Y;
	after(X, [_|Ys],  D) -> after(X, Ys, D);
	after(_, [],      D) -> D.

	before(X, [Y,X|_], _) -> Y;
	before(X, [_|Ys],  D) -> before(X, Ys, D);
	before(_, [],      D) -> D.

then we've come close to matching the #after:ifAbsent:
and #before:ifAbsent: methods (which actually take funs
rather than default values).

Even simpler than after would be to adapt Lisp's (MEMBER - -)
function, and instead of returning false or true, return the
empty list or the place where the match was found.  (Funny
how the Boolean anti-pattern keeps turning up, isn't it?)

	lmember(X, Xs = [X|_]) -> X;
	lmember(X, [_ | Xs])   -> lmember(X, Xs);
	lmember(_, [])         -> [].


	[_,{_,Title}|_] = lmember({tagStart,"title"}, Hal)

and if we wanted to pick up the next two elements it would
be just as simple to do

	[_,{_,Title},Next|_] = lmember({tagStart,"title"}, Hal)

More information about the erlang-questions mailing list