Need an example of Record Syntax in mercury - mercury

I am new to mercury and am trying to wrap my head around Record Syntax, but the Reference Manual is the only place I have encountered it and it leaves me mystified:
Term ^ field1(Arg1) ^ field2(Arg2, Arg3) is equivalent to field2(Arg2, Arg3, field1(Arg1, Term)).
Could someone please help with a real-world example?

Record syntax is a syntax sugar, and the manual is trying to explain how the
transformation from record syntax into Mercury's normal syntax works. This
is fine if you're trying to find out how to implement record syntax, but not
very helpful if you want to learn how to use it.
I recommend ignoring the (Arg1, ...) stuff in the parenthesis - I'm not
sure if it's actually part of the syntax and I've never seen anyone use it.
Lets create a structure representing points on a Cartesian plane.
:- type point
---> point(
pt_x :: int,
pt_y :: int
).
pt_x and pt_y are field names they allow us to retrieve the values of a
point's fields. For example:
format("The point's X coordinate is: %d\n", [i(Point ^ pt_x)], !IO),
format("The point's Y coordinate is: %d\n", [i(Point ^ pt_y)], !IO),
We can retrieve a value and assign it to a new variable.
X = Point ^ pt_x,
And we can also update one field without having to write out the whole point
again.
NewPoint = OldPoint ^ pt_y := NewY,
Where things get a little bit more complicated is when this is used with
state variable notation, there's an extra syntax sugar that occurs.
move_up(D, !Point) :-
NewY = !.Point ^ pt_y + D,
!Point ^ pt_y := NewY.
Note that when we read a value we use !.Point, which is the state variable
for "the current value". And when we updated it we could have written:
!:Point = !.Point ^ pt_y := NewY.
However this extra syntax sugar allows us to write:
!Point ^ pt_y := NewY.
I hope this helps. There are many more examples throughout the Mercury
source code:
https://github.com/Mercury-Language/mercury
and ohther Mercury projects, note that the github language tagging is
broken, many Objective-C files are detected as Mercury and many Mercury
things are detected as other files:
https://github.com/search?utf8=%E2%9C%93&q=language%3AMercury&type=Repositories&ref=advsearch&l=Mercury

Related

Concatenate 2 Enumerated type variable sets

enum sup;
sup=['a','b','c'];
enum sup2;
sup2=['d','e','f'];
enum sup3;
sup3=sup++sup2;
I want to get an new enumerated type sup3 with all a,b,c,d,e,f.Is there any way in minizinc we can do this.
The short answer is no, this is currently not supported. The main issue with the concatenation of enumerated types comes from the fact we are not just concatenating two lists of things, but we are combining types. Take your example:
enum sup = {A, B, C};
enum sup2 = {D, E, F};
enum sup3 = sup ++ sup2;
When I now write E somewhere in an expression, I no longer know if it has type sup2 or sup3. As you might imagine, there is no guarantee that E would have the same value (for the solver) in the two enumerated types, so this can be a big problem.
To shine a glimmer of hope, the MiniZinc team has been working on a similar approach to make this possible (but not yet formally announced). Instead of your syntax, one would write:
enum X = {A, B, C};
enum Y = {D, E, F} ++ F(X);
The idea behind this is that F(X) now gives a constructor for the usage of X in Y. This means that if we see just A, we know it's of type X, but if we see F(A), then it's of type Y. Again, this is not yet possible, but will hopefully end up in the language soon.
More of a comment but here is my example of my need. When doing code coverage and FSM transition analysis I am forced to use exclusion to not analyze some transitions for the return_to_state, in the code below. If instead I could use concatenated types as shown, I would have more control over the tools reporting missing transitions.
type Read_states is (ST1);
type Write_states is (ST2, ST3, ST4);
type SPI_states is (SPI_write);
type All_States is Read_states & Write_states & SPI_states;
I could make return_to_state of type Write_states and FRAM_state of type All_states and then not have to put in exclusions in my FSM analysis.

How can i know if a variable is a number or a letter with Pascal?

I'm trying to make a (very) little code to determine whether a given variable x is a number or a letter. It has to be done by hand without things like type(x) -assuming there is such thing in Pascal-.
My plan was to verify that x is not a number one by one, then i wrote this:
(*let ischar be a boolean and let x be a letter or a number.*)
for i:=0 to 9 do
begin
if (x=i) then
ischar = false;
end;
if ischar then
write('x is a number!');
else
write('x is a letter');
I was hoping that the test "x=i" would return false if x is a letter, but here i don't even get to compile because of the following error: "Got char, expected long int". It seems that i can't compare x and i, i knew that but i tought that under that circumstances if would return false.
Is there another way to do this 'by hand'?
It's generally not possible to directly compare variables of different types. The compilation error suggests x is declared as a char, while i is a longint.
The available options may depend on what Pascal compiler you use.
My only experience is with the Borland (later CodeGear and Embarcadero) products "Turbo Pascal" and "Delphi".
Those compilers have the ord function which gives the numeric value of an ordinal type.
In the case of a char, the ord function should give you the ASCII code of the character, which you can test to see if it's in the code range of '0'..'9'.
You don't need the for loop. This should work:
if (ord(x)<48) or (ord(x)>57) then ischar:=true else ischar:=false;
Edit: Here's the Free Pascal documentation for the ord function:
http://www.freepascal.org/docs-html/rtl/system/ord.html

How do I define a new numeric constant in Mathematica?

What is the best way to define a numerical constant in Mathematica?
For example, say I want g to be the approximate acceleration due to gravity on the surface of the Earth. I give it a numerical value (in m/s^2), tell Mathematica it's numeric, positive and a constant using
Unprotect[g];
ClearAll[g]
N[g] = 9.81;
NumericQ[g] ^= True;
Positive[g] ^= True;
SetAttributes[g, Constant];
Protect[g];
Then I can use it as a symbol in symbolic calculations that will automatically evaluate to 9.81 when numerical results are called for. For example 1.0 g evaluates to 9.81.
This does not seem as well tied into Mathematica as built in numerical constants. For example Pi > 0 will evaluate to True, but g > 0 will not. (I could add g > 0 to the global $Assumptions but even then I need a call to Simplify for it to take effect.)
Also, Positive[g] returns True, but Positive[g^2] does not evaluate - compare this with the equivalent statements using Pi.
So my question is, what else should I do to define a numerical constant? What other attributes/properties can be set? Is there an easier way to go about this? Etc...
I'd recommend using a zero-argument "function". That way it can be given both the NumericFunction attribute and a numeric evaluation rule. that latter is important for predicates such as Positive.
SetAttributes[gravUnit, NumericFunction]
N[gravUnit[], prec_: $MachinePrecision] := N[981/100, prec]
In[121]:= NumericQ[gravitUnit[]]
Out[121]= True
In[122]:= Positive[gravUnit[]^2 - 30]
Out[122]= True
Daniel Lichtblau
May be I am naive, but to my mind your definitions are a good start. Things like g > 0->True can be added via UpValues. For Positive[g^2] to return True, you probably have to overload Positive, because of the depth-1 limitation for UpValues. Generally, I think the exact set of auto-evaluated expressions involving a constant is a moving target, even for built-in constants. In other words, those extra built-in rules seem to be determined from convenience and frequent uses, on a case-by-case basis, rather than from the first principles. I would just add new rules as you go, whenever you feel that you need them. You probably can not expect your constants to be as well integrated in the system as built-ins, but I think you can get pretty close. You will probably have to overload a number of built-in functions on these symbols, but again, which ones those will be, will depend on what you need from your symbol.
EDIT
I was hesitating to include this, since the code below is a hack, but it may be useful in some circumstances. Here is the code:
Clear[evalFunction];
evalFunction[fun_Symbol, HoldComplete[sym_Symbol]] := False;
Clear[defineAutoNValue];
defineAutoNValue[s_Symbol] :=
Module[{inSUpValue},
s /: expr : f_[left___, s, right___] :=
Block[{inSUpValue = True},
With[{stack = Stack[_]},
If[
expr === Unevaluated[expr] &&
(evalFunction[f, HoldComplete[s]] ||
MemberQ[
stack,
HoldForm[(op_Symbol /; evalFunction[op, HoldComplete[s]])
[___, x_ /; ! FreeQ[Unevaluated[x], HoldPattern#expr], ___]],
Infinity
]
),
f[left, N[s], right],
(* else *)
expr
]]] /; ! TrueQ[inSUpValue]];
ClearAll[substituteNumeric];
SetAttributes[substituteNumeric, HoldFirst];
substituteNumeric[code_, rules : {(_Symbol :> {__Symbol}) ..}] :=
Internal`InheritedBlock[{evalFunction},
MapThread[
Map[Function[f, evalFunction[f, HoldComplete[#]] = True], #2] &,
Transpose[List ### rules]
];
code]
With this, you may enable a symbol to auto-substitute its numerical value in places where we indicate some some functions surrounding those function calls may benefit from it. Here is an example:
ClearAll[g, f];
SetAttributes[g, Constant];
N[g] = 9.81;
NumericQ[g] ^= True;
defineAutoNValue[g];
f[g] := "Do something with g";
Here we will try to compute some expressions involving g, first normally:
In[391]:= {f[g],g^2,g^2>0, 2 g, Positive[2 g+1],Positive[2g-a],g^2+a^2,g^2+a^2>0,g<0,g^2+a^2<0}
Out[391]= {Do something with g,g^2,g^2>0,2 g,Positive[1+2 g],
Positive[-a+2 g],a^2+g^2,a^2+g^2>0,g<0,a^2+g^2<0}
And now inside our wrapper (the second argument gives a list of rules, to indicate for which symbols which functions, when wrapped around the code containing those symbols, should lead to those symbols being replaced with their numerical values):
In[392]:=
substituteNumeric[{f[g],g^2,g^2>0, 2 g, Positive[2 g+1],Positive[2g-a],g^2+a^2,g^2+a^2>0,
g<0,g^2+a^2<0},
{g:>{Positive,Negative,Greater}}]
Out[392]= {Do something with g,g^2,True,2 g,True,Positive[19.62\[VeryThinSpace]-a],
a^2+g^2,96.2361\[VeryThinSpace]+a^2>0,g<0,a^2+g^2<0}
Since the above is a hack, I can not guarantee anything about it. It may be useful in some cases, but that must be decided on a case-by-case basis.
You may want to consider working with units rather than just constants. There are a few options available in Mathematica
Units
Automatic Units
Designer units
There are quite a few technical issues and subtleties about working with units. I found the backgrounder at Designer Units very useful. There are also some interesting discussions on MathGroup. (e.g. here).

variable is only used once

I am using ancient Turbo Prolog since it is included in our curriculum. Why is this program not working?
domains
disease, indication = symbol
Patient = string
Fe,Ra,He,Ch,Vo,Ru = char
predicates
hypothesis(Patient,disease)
symptom(Patient,indication,char)
response(char)
go
clauses
go:-
write("What is patient's name?"),
readln(Patient),
symptom(Patient,fever,Fe),
symptom(Patient,rash,Ra),
symptom(Patient,head_ache,He),
symptom(Patient,chills,Ch),
symptom(Patient,runny_nose,Ru),
symptom(Patient,head_ache,He),
symptom(Patient,vomit,Vo),
hypothesis(Patient,Disease),
write(Patient," probably has ", Disease , "."),nl.
go:-
write("Sorry unable to seem to be diagnose disease"),nl.
symptom(Patient,Fever,Feedback) :-
Write("Does " , Patient , " have " , Fever , "(y/n) ?"),
response(Reply),
Feedback = Reply.
hypothesis(Patient, chicken_pox) :-
Fe = Ra = He = Ch = 'y'.
hypothesis(Patient, caner) :-
Ru = Ra = He = Vo = 'y'.
hypothesis(Patient, measles) :-
Vo = Ra = Ch = Fe = He = 'y'.
response(Reply):-
readchar(Reply),
write(Reply),nl.
I get the warning variable is only used at all lines which contains symtoms. Isn't the parameter passing call by reference? When i pass Fe to symptoms the value should be copied to Fe and when i compare it in hypothesis it should work accordingly. = operator in Turbo Prolog works very strangely. When it is not bound to any variable, the statement a = 3 will assign 3 to a and when a already contains a value a = 5 will check whether a's value is 5 or not.
Kindly help me why is the program not working?
Thanks in advance :)
The trouble is not with your symptoms/3 predicate, they will bind (unify) their 3rd argument to what response/1 gives. The problem is that these values are never passed into your hypothesis/2 procedure in go/0 so they are never used to try and generate a hypothesis. Prolog doesn't have global variables so you have to explicitly pass all values, though you can keep things in the database which can easily cause problems if you are not careful.
This means that in hypothesis/2 you are not testing the values of Fe, Ra, He, etc but binding local variables with the same names. This is also why you get warnings of the variables only being referenced once, you bind them but never use them. Remember they are local, all variables are local to the clause in which they occur.
All this applies to standard prolog, I have never used Turbo Prolog.

how to use units along function parameter values in Mathematica

I would like to pass the parameter values in meters or kilometers (both possible) and get the result in meters/second.
I've tried to do this in the following example:
u = 3.986*10^14 Meter^3/Second^2;
v[r_, a_] := Sqrt[u (2/r - 1/a)];
Convert[r, Meter];
Convert[a, Meter];
If I try to use the defined function and conversion:
a = 24503 Kilo Meter;
s = 10198.5 Meter/Second;
r = 6620 Kilo Meter;
Solve[v[r, x] == s, x]
The function returns the following:
{x -> (3310. Kilo Meter^3)/(Meter^2 - 0.000863701 Kilo Meter^2)}
which is not the user-friendly format.
Anyway I would like to define a and r in meters or kilometers and get the result s in meters/second (Meter/Second).
I would be very thankful if anyone of you could correct the given function definition and other statements in order to get the wanted result.
Here's one way of doing it, where you use the fact that Solve returns a list of rules to substitute a value for x into v[r, x], and then use Convert, which will do the necessary simplification of the resulting algebraic expression as well:
With[{rule = First#Solve[v[r,x]==s,x]
(* Solve always returns a list of rules, because algebraic
equations may have multiple solutions. *)},
Convert[v[r,x] /. rule, Meter/Second]]
This will return (10198.5 Meter)/Second as your answer.
You just need to tell Mathematica to simplify the expression assuming that the units are "possitive", which is the reason why it doesn't do the simplifications itself. So, something like
SimplifyWithUnits[blabla_, unit_List]:= Simplify[blalba, (#>0)&/#unit];
So if you get that ugly thing, you then just type %~SimplifyWithUnits~{Meter} or whatever.

Resources