# [mercury-users] hi & a feq queries

Peter Schachte pets at students.cs.mu.OZ.AU
Tue Aug 18 10:51:15 AEST 1998

```On Tue, 18 Aug 1998, Thomas Charles CONWAY wrote:
> Donald Syme, you write:

> >   - I'm surprised Mercury doesn't seem to support data values that
> >     are conditionals, e.g. "if <goal> then 1 else 2".  I've had to
> >     create a function and apply itt o a dummy argument to get this effect,
> >     e.g.  apply((func(X) = Y :- if <goal> then Y = 1 else Y = 2), dummy)
> >
> >     Is there an easier way of doing this?  For starters, can I say
> >     something like
> >
> >          (func = Y :- if <goal> then Y = 1 else Y = 2)
>
> I just successfully compiled the following piece of code:
>
> 	:- func f(int) = string.
>
> 	f(N) = (if N mod 2 = 0 then "foo\n" else "bar\n").

One think that may be a bit confusing is that a predicate is not, as a
functional programmer might expect, the same as a function returning a bool.
(The reason for this is that one might just as easily expect that a function
is just a predicate with a det mode; not seeing any reason to prefer one
view over the other, Mercury takes neither view.)

Anyway, this won't work:

:- func even(int) = bool.

even(X) = (X mod 2 = 1).

You'll have to write something like

even(X) = Even :- if (X mod 2 = 1) then Even = yes else Even = no.

And with that defintion, the following won't work, either:

:- func foo(int) = int.

foo(X) = if even(X) then 0 else X / (X mod 2).

You'll have to write

foo(X) = if even(X) = yes then 0 else X / (X mod 2).

> >   - Functional programming switches with default patterns seem
> >     difficult to translate into Mercury, e.g.
> >
> >         Functional                           Mercury
> >       match x with                         switch(x = [] -> ...
> >          [] -> ...                              ; ??? -> ...)
> >        | _ -> ...
> >

> The alternative clauses in a functional language are not like disjunction -
> they are more like if then else: "if this pattern matches then do *this*
> else if this pattern matches do *this* else ..." not "do *this* or do *this*
> or ....".
>
> There are two approaches you can use:
> Use an if then else (or a chained if then else), or
> Use an partial switch in the condition of an if-then-else.
>
> The second of these techniques is better than the first if there
> are many cases to cover because the compiler generates better code
> for switches than chains of if-then-elses in the case where the
> conditions are all mutually exclusive (except for the default case).

I thought the compiler now did switch detection on if-then-elses, too?  In
any case, as you say, the functional match form is much more akin to an
if-then-else, so I think this is the right way to translate it.  If the
cases overlap, as they do here, it could get pretty painful to force them
not to overlap in the generated Mercury code, in order to get it to be det.
Especially when there's no need to do that with an if-then-else.

There's no reason I can see for the compiler not to generate equally good
code for if-then-elses, other than that no one has been interested enough
yet to implement that optimization.

-Peter Schachte               | The fantastic advances in the field of
mailto:pets at cs.mu.OZ.AU       | communication constitute a grave danger to
http://www.cs.mu.oz.au/~pets/ | the privacy of the individual.
PGP: finger pets at 128.250.37.3 |     -- Earl Warren

```