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

Julian Fondren cleverjulian at hotmail.com
Tue Nov 19 04:31:34 AEDT 2002


------------------------------------------------------------------------
-- Style

I'm a bit confused about the presence of 'func'

  :- func foo(int) = int.

and 'pred'

  :- pred foo(int, int).

in Mercury; when should you supposed to use one or the other?
Is one preferred over the other?  I suppose that functions make
for more terse code (foo(bar(Baz)) vs. bar(Baz,Quux), foo(Quux)),
and that predicates more naturally extend to multiple modes...

------------------------------------------------------------------------
-- Newbie decision question

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).

and neither does

  char_filter(In, Out) :-
      (
          In = '\t',
          Out = '\n'
      ;
          In \= '\t',
          Out = In
      ).

work because, apparently, both of these clauses can fail at
once (though I don't see how), making the determinism 'semidet'.
The following, I've discovered, *does* work:

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

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
                  )
              )
          )
     ).

... a lot less clear than

is_whitespace(' ', yes).
is_whitespace('\t', yes).
is_whitespace('\r', yes).
is_whitespace('\n', yes).
is_whitespace(C, no).

which, as I've said, doesn't work because any of the first
four matches can also match the fifth.  So how can I consisely
write predicates that switch over multiple values of some huge
type (like integers, or characters)?  I have to cover all the
posibilities, and I have to make each match unique, and I can't,
so far as I know, say 'match if nothing else can'.

------------------------------------------------------------------------
-- "What?  No X?!"

No directory access, no concurrency (though I see allusions to an
experimental multithreaded Mercury: does it use OS threads or something
lighter?  How can I experiment with it?), no networking -- but the
first and the last seem potentially well-covered by the foreign language
access.

Does anyone have a directory-stream/networking library handy?  If not,
how can I contribute mine when I finish them?  Is anyone thinking about
Erlang/Concurrent-Haskell -style concurrency (with independent
lightweight processes and message-passing, as opposed to evil Posix
threads with mutexes and semaphores)?

Also, is there a 'remove line terminator' in the library that I don't
see?  If not, how does anyone get io__read_line_as_string (which
returns a string with a newline) to string__to_int ?  I've written

:- pred char_list_to_nice_string(list(character)::in,
                                 string::out) is det.

char_list_to_nice_string(CL, String) :-
    chomp_char_list(list__reverse(CL), Chomped),
    string__from_rev_char_list(Chomped).

:- pred chomp_char_list(list(character)::in,
                        list(character)::out) is det.

chomp_char_list([], []).
chomp_char_list([H|T], Chomped) :-
    (
        H = '\r'
    ->
        chomp_char_list(T, Chomped)
    ;
        (
            H = '\n'
        ->
            chomp_char_list(T, Chomped)
        ;
            Chomped = [H|T]
        )
    ).

Which I hate.

------------------------------------------------------------------------
-- Microbenchmark

Yesterday I noticed that a text file had evil paragraphs (tab
indenting, no interparagraph seperation, entire-paragraph-as-one-line)
so I wrote a little Erlang program and had it simply take two arguments
(input-file and output-file) and translate tabs to newlines... and then
I watched in horror (until I got bored).  The Erlang program takes
several minutes to convert a ~400k file.  I started writing the
Mercury version before the Erlang version completed and made a program
with identical interface that converted the file in a little under two
seconds.  Yay Mercury!

(What's more: a little later I wanted to translate a unix-style text
file to a DOS-style text file, and I'd converted the aforementioned
Mercury program to a unix2dos and had it compiled in less than a
minute.  Maybe I should turn this into a unix_filter module?)


_________________________________________________________________
MSN 8 with e-mail virus protection service: 2 months FREE* 
http://join.msn.com/?page=features/virus
--------------------------------------------------------------------------
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