<div class="gmail_quote">On 2 February 2012 13:01, Michael Richter <span dir="ltr"><<a href="mailto:ttmrichter@gmail.com">ttmrichter@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im"><div class="gmail_quote">On 2 February 2012 05:50, Julian Fondren <span dir="ltr"><<a href="mailto:ayrnieu@gmail.com" target="_blank">ayrnieu@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<p>to make the problem clearer, you have here</p>
<p>  A = (func(X) = B, C),</p>
<p>How is this not like your definitions of named functions?<br></p>
<p></p></blockquote></div><div><br></div></div>It's got a lambda instead of a :- func body?<div><br></div><div>Maybe I'm fundamentally misunderstanding the syntax of funcs vs. preds.  (There doesn't appear to be a grammar for Mercury in the language reference so I'm only inferring what's permitted and what's not.)<br clear="all">

<div><br></div><div>Let's say I have a predicate like this:</div><div><br></div><div>a(X,Y) :- Y = X.</div><div><br></div><div>This is fine, right?  And the equivalent written as a function is this:</div><div><br></div>

<div>a(X) = X.</div><div><br></div><div>I know this is fine because I've just tested it.  The compiler doesn't vomit.  Now let's say that I want to do a calculation on X first.  Here it'll be a brain-dead calculation but the principle is the same whether it's something stupid like this or something that actually warrants breaking out the calculation into its own sub-step:</div>

<div><br></div><div>a(X,Y) :- B = X * 2, Y = B.</div><div><br></div><div>Again, the compiler doesn't puke on this and the result is as expected.  So the equivalent function is:</div><div><br></div><div>a(X) = B = X * 2, B.</div>

<div><br></div><div>Only that doesn't work because you get an operator precedence error on "=".  (It also looks pretty retarded.)  Time for plan B.</div><div><br></div><div>a(X) = (B = X * 2, B).</div><div>
<br>
</div><div>Whiiiiiiiiiiich… gives me the error that's mystified me so long.  I may be on to something here!  Let me take another crack at it.  Looking at the library source I see another way that functions are defined.  Let me see if the same kind of structure helps here.</div>

<div><br></div><div>a(X) = Y :- B = X * 2, Y = B.</div><div><br></div><div>OK, that works.  So let's see how that looks in a lambda.</div><div><br></div><div>A = (func(X) = Y :- B = X * 2, Y = B).</div><div><br></div>

<div>OK, that seems to work, so let's make B a func as well:</div><div><br></div><div><div>    A = (func(X) = Y :- </div><div>            B = (func(X) = Y :-</div><div>                    Y = X * 2</div><div>                ),</div>

<div>            Y = B</div><div>        ).</div></div><div><br></div><div>And…  Now I'm even more confused.  Yesterday when I tried that very structure I got lots of whining from the compiler about syntax errors on the :-. Damn.</div>
</div></blockquote><div><br></div><div>Oops.  I spoke too soon.  I forgot to save the file before compiling.</div><div><br></div><div>This vomits up a whole bunch of garbage (the lambda in question starts on line 19):</div>
<div><br></div><div><div>junk.m:019: In clause for predicate `junk.main'/2:</div><div>junk.m:019:   warning: variable `A' occurs only once in this scope.</div><div>junk.m:019: In clause for predicate `junk.main'/2:</div>
<div>junk.m:019:   warning: variable `X' occurs only once in this scope.</div><div>junk.m:020: In clause for predicate `junk.main'/2:</div><div>junk.m:020:   warning: variable `X' has overlapping scopes.</div>
<div>junk.m:023: In clause for predicate `main'/2:</div><div>junk.m:023:   type error in unification of variable `Y'</div><div>junk.m:023:   and variable `B'.</div><div>junk.m:023:   `Y' has type `int',</div>
<div>junk.m:023:   `B' has type `((func int) = int)'.</div><div>junk.m:023:   The partial type assignment was:</div><div>junk.m:023:     A_4: ((func V_1) = V_2)</div><div>junk.m:023:     Y_6: int</div><div>junk.m:023:     B_7: ((func int) = int)</div>
<div>junk.m:023:     STATE_VARIABLE_IO_0_8: io.state</div><div>junk.m:023:     STATE_VARIABLE_IO_9: io.state</div><div>junk.m:023:     V_10: V_1</div><div>junk.m:023:     V_11: V_2</div><div>junk.m:023:     V_12: int</div>
<div>junk.m:023:     V_13: int</div><div>junk.m:023:     V_14: int</div><div>junk.m:023:     X_17: V_1</div><div>junk.m:023:     X_18: int</div></div><div><br></div><div>One of the problems I see is that I'm returning B instead of calling it and returning its value.  Let's change that:</div>
<div><br></div><div><div>    A = (func(X) = Y :- </div><div>            B = (func(X) = Y :-</div><div>                    Y = X * 2</div><div>                ),</div><div>            Y = apply(B, X)</div><div>        ).</div>
</div><div><br></div><div>This gives me different consistencies of compiler vomit:</div><div><br></div><div><div>junk.m:019: In clause for predicate `junk.main'/2:</div><div>junk.m:019:   warning: variable `A' occurs only once in this scope.</div>
<div>junk.m:019: In clause for `main(di, uo)':</div><div>junk.m:019:   mode error in conjunction. The next 3 error messages indicate</div><div>junk.m:019:   possible causes of this error.</div><div>junk.m:020:   In clause for `main(di, uo)':</div>
<div>junk.m:020:   mode error: variable `Y' has instantiatedness `free',</div><div>junk.m:020:   expected instantiatedness for non-local variables of lambda goals</div><div>junk.m:020:   is `ground'.</div><div>
junk.m:023:   In clause for `main(di, uo)':</div><div>junk.m:023:   in argument 1 (i.e. the function term) of higher-order function</div><div>junk.m:023:   call:</div><div>junk.m:023:   mode error: variable `B' has instantiatedness `free',</div>
<div>junk.m:023:   expecting higher-order func inst (of arity 1).</div><div>junk.m:019:   In clause for `main(di, uo)':</div><div>junk.m:019:   in argument 1 of clause head:</div><div>junk.m:019:   mode error in unification of `V_11' and `Y'.</div>
<div>junk.m:019:   Variable `V_11' has instantiatedness `free',</div><div>junk.m:019:   variable `Y' has instantiatedness `free'.</div><div>junk.m:020: In clause for predicate `junk.main'/2:</div><div>
junk.m:020:   warning: variable `X' has overlapping scopes.</div></div><div><br></div><div>Hmmm....  Seems to be a clash of variable name scopes.  Maybe a some?</div><div><br></div><div><div><div>    A = (func(X) = Y :- </div>
<div>            some [X,Y] (</div><div>                B = (func(X) = Y :-</div><div>                        Y = X * 2</div><div>                    )</div><div>            ),</div><div>            Y = apply(B, X)</div><div>
        ),</div></div></div><div><br></div><div>Eh.... no.  That tosses up lots as well:</div><div><br></div><div><div>junk.m:019: In clause for predicate `junk.main'/2:</div><div>junk.m:019:   warning: variable `A' occurs only once in this scope.</div>
<div>junk.m:019: In clause for `main(di, uo)':</div><div>junk.m:019:   mode error in conjunction. The next 3 error messages indicate</div><div>junk.m:019:   possible causes of this error.</div><div>junk.m:021:   In clause for `main(di, uo)':</div>
<div>junk.m:021:   mode error: variable `Y' has instantiatedness `free',</div><div>junk.m:021:   expected instantiatedness for non-local variables of lambda goals</div><div>junk.m:021:   is `ground'.</div><div>
junk.m:025:   In clause for `main(di, uo)':</div><div>junk.m:025:   in argument 1 (i.e. the function term) of higher-order function</div><div>junk.m:025:   call:</div><div>junk.m:025:   mode error: variable `B' has instantiatedness `free',</div>
<div>junk.m:025:   expecting higher-order func inst (of arity 1).</div><div>junk.m:019:   In clause for `main(di, uo)':</div><div>junk.m:019:   in argument 1 of clause head:</div><div>junk.m:019:   mode error in unification of `V_11' and `Y'.</div>
<div>junk.m:019:   Variable `V_11' has instantiatedness `free',</div><div>junk.m:019:   variable `Y' has instantiatedness `free'.</div><div>junk.m:020: In clause for predicate `junk.main'/2:</div><div>
junk.m:020:   warning: variables `X, Y' each have overlapping scopes.</div><div>junk.m:021: In clause for predicate `junk.main'/2:</div><div>junk.m:021:   warning: variable `X' has overlapping scopes.</div></div>
<div><br></div><div>And at this point I'm lost.  How does X have overlapping scope when I've explicitly built a new scope for the second X?  Again I have to ask, how do I do what I'm trying to do?  Equivalent code in almost any other language I have that supports higher-order programming is trivial.  Why am I wrestling so much with Mercury to do the same?  What am I missing?</div>
<div><br></div></div>-- <br>"Perhaps people don't believe this, but throughout all of the discussions of entering China our focus has really been what's best for the Chinese people. It's not been about our revenue or profit or whatnot."<br>
--Sergey Brin, demonstrating the emptiness of the "don't be evil" mantra.<br>