mercury

Need an example of Record Syntax in 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?


Solution

  • 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