[mercury-users] Style, Newbie decision question, "What? No X?!", Microbenchmark

Peter Schachte schachte at cs.mu.OZ.AU
Tue Nov 19 10:53:41 AEDT 2002


> given
> 
>  :- pred char_filter(character::in, character::out) is det.
> 
> the following does not work because of commutativity (the second
> clause can match even when the first would, making the determinism
> 'multi')
> 
>  char_filter('\t', '\n').
>  char_filter(C, C).

This doesn't say what you intend.  In Mercury, each clasue is
independent, so the first clause correctly says that the char_filter
of tab is newline, but the second clasue says that the char_filter of
every character, including tab, is itself.

> and neither does
> 
>  char_filter(In, Out) :-
>      (
>          In = '\t',
>          Out = '\n'
>      ;
>          In \= '\t',
>          Out = In
>      ).

OK, now it's correct.  But the Mercury mode system is not omnicient.
It's not smart enough to know that if In = '\t' succeeds, then In \=
'\t' always fails, and vice versa.

> but this doesn't scale well:
> 
>  is_whitespace(C, Bool) :-
>      (
>          C = ' ',
>      ->
>          Bool = yes
>      ;
>          (
>              C = '\t',
>          ->
>              Bool = yes
>          ;
>              (
>                  C = '\r',
>              ->
>                  Bool = yes
>              ;
>                  (
>                      C = '\n',
>                  ->
>                      Bool = yes
>                  ;
>                      Bool = no
>                  )
>              )
>          )
>     ).

disjunction (;) is right associative, so you don't need all those
parentheses.  You can instead lay this out as:

	is_whitespace(C, Bool) :-
	     (
	         C = ' '
	     ->
	         Bool = yes
	     ;
	         C = '\t'
	     ->
	         Bool = yes
	     ;
	         C = '\r'
	     ->
	         Bool = yes
	     ;
	         C = '\n'
	     ->
	         Bool = yes
	     ;
	         Bool = no
	    ).

which is better.  Personally, I'd write that as

	is_whitespace(C, Bool) :-
		 (   C = ' '  -> Bool = yes
		 ;   C = '\t' -> Bool = yes
		 ;   C = '\r' -> Bool = yes
		 ;   C = '\n' -> Bool = yes
		 ;   Bool = no
		 ).

which I think is a lot easier to read.

But for something like this, I think a semidet predicate like

	is_whitespace(' ').
	is_whitespace('\t').
	is_whitespace('\r').
	is_whitespace('\n').

is still clearer, and also easier to use.  Instead of writing

	is_whitespace(C, Bool), Bool = true -> ...

to use it, or, better,

	is_whitespace(C, true) -> ...

you just write

	is_whitespace(C) -> ...

-- 
Peter Schachte              If you only have a hammer, you tend to see every
schachte at cs.mu.OZ.AU        problem as a nail.
www.cs.mu.oz.au/~schachte/      -- Maslow 
Phone: +61 3 8344 9166      
--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list