Question

I have a massive record and am looking to use it in comparison. Is there a way to omit one field from the record in the comparison, or do I have to check each field individually?

example:

type Apple_T is record
  Redness_Scale : Integer;
  Weight : Natural:
  Age : Natural;
  Eaten : Boolean;
end record;

I want to compare on Redness, Weight, and age, but not on eaten. Is there a way that I can do this without having three seperate statemenets?

Was it helpful?

Solution

No, you have to write code like

return (Left.Redness_Scale = Right.Redness_Scale) and then
       (Left.Weight = Right.Weight) and then
       (Left.Age = Right.Age);

(assuming you have a function that returns Boolean to test whether the apples compare equally). Technically, those aren't three separate statements. But no, the way you've defined the record, you do have to use three equality comparisons.

However, you may want to consider that the original "characteristics" of an apple (as opposed to actions that someone has taken on the apple) might be worth turning into their own abstraction, something like

type Apple_Characteristics is record
    Redness_Scale : Integer;
    Weight : Natural:
    Age : Natural;
end record;

type Apple_T is record
    Characteristics : Apple_Characteristics;
    Eaten : boolean;
end record;

Now you could just compare the Characteristics components of the two records with one equality test. That's one benefit of separating out the characteristics, but there could be others, too; if the fields are related enough that a comparison groups those fields together and ignores other fields, chances are there are other operations that inherently treat those fields as a group too.

It does mean that you have to use A.Characteristics.Weight (for example) to get at the fields. But assuming you've done what you should do and made Apple_T a private type, and provided operations (procedures/functions) for other users of the package to use, then the need to add .Characteristics occurs only in the body of the package that defines Apple_T when it implements those operations. Separating out the Apple_Characteristics into another record type is an implementation detail that users of the package would not need to know about.

OTHER TIPS

You can always override the default "=" operation of a type.

function "=" (Left, Right : Apple_T) return Boolean is
begin
   return Left.Redness_Scale = Right.Redness_Scale and
          Left.Weight        = Right.Weight        and
          Left.Age           = Right.Age;
end "=";

Your type example is bad style. Which values are really valid for redness? Can an apple really be weightless?

For tagged record types you can declare your own equality operator.

Its declaration would have to perform each required comparison individually, or resort to ajb's more compact solution (which could be re-written as extending the Apple_Characteristics type instead of including it as a component).

So the equality operator's declaration would potentially involve three statements, but its use would be compact.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top