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?
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.
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.
Related
A nice feature in Chapel is that it distinguishes between the domain of an array and its distribution. What is the best way to check that two arrays have the same domain and distribution (which one often wants)?
The best I can see is to check D1==D2 and D1.dist==D2.dist, if D1 and D2 are both domains.
In particular, consider the following code :
const Dom = {1..5, 1..5};
const BDom = newBlockDom(Dom);
var x : [Dom] int;
var y : [BDom] int;
test(x,y);
proc test(a : [?Dom1] int, b : [Dom1] int) {
}
This compiles and runs just fine, which makes sense if the query syntax in the function declaration just tests for domain equality, but not for distribution equality (even though Dom1 also knows about how a is distributed). Is the only way to check for distribution equality in this case is to do a.domain.dist==b.domain.dist?
To check whether two domains describe the same distributed index set in Chapel, you're correct that you'd use D1 == D2 and D1.dist == D2.dist. Domain equality in Chapel checks whether two domains describe the same index set, so is independent of the domain maps / distributions. Similarly, an equality check between two domain maps / distributions checks whether they distribute indices identically.
Note that in Chapel, both domains and distributions have a notion of identity, so if you created two distributed domains as follows:
var BDom1 = newBlockDom(Dom),
BDom2 = newBlockDom(Dom);
they would pass the above equality checks, yet be distinct domain values. In some cases, it might be reasonable to wonder whether two domain expressions refer to the identical domain instance, but I believe there is no official user-facing way to do this in Chapel today. If this is of interest, it would be worth filing a feature request against on our GitHub issues page.
With respect to your code example:
const Dom = {1..5, 1..5};
const BDom = newBlockDom(Dom);
var x : [Dom] int;
var y : [BDom] int;
test(x,y);
proc test(a : [?Dom1] int, b : [Dom1] int) {
}
there is a subtlety going on here that requires some explanation. First, note that if you reverse the arguments to your test() routine, it will not compile, acting perhaps more similar to what you were expecting (TIO):
test(y,x);
The reason for this is that domains which don't have an explicit domain map are treated specially in formal array arguments. Specifically, in defining Chapel, we didn't want to have a formal argument that was declared like X here:
proc foo(X: [1..n] real) { ... }
require that the actual array argument be non-distributed / have the default domain map. In other words, we wanted the user to be able to pass in a Block- or Cyclic-distributed array indexed from 1..n so that the formal was constraining the array's index set but not its distribution. Conversely, if a formal argument's domain is defined in terms of an explicit domain map, like:
proc bar(X: [BDom] int) { ... }
(using your Block-distributed definition of BDom above), it requires the actual array argument to match that domain.
An effect of this is that in your example, since Dom1 was matched to a domain with a default domain map, b is similarly loosely constrained to have the same index set yet with any distribution. Whereas when the first actual argument is block-distributed (as in my call), Dom1 encodes that distribution and applies the constraint to b.
If your reaction to this is that it feels confusing / asymmetric, I'm inclined to agree. I believe we have discussed treating declared/named domains differently from anonymous ones in this regard (since it was the anonymity of the domain in X: [1..n] that we were focused on when adopting this rule, and its application to queried domains like Dom1 in cases like this is something of a side effect of the current implementation). Again, a GitHub issue would be completely fair game for questioning / challenging this behavior.
I am trying to build a drools rule where the fact supplied has a user supplied int value. Fact also has a list of objects that have an expected int value. I need to check if the user supplied value is less than sum of the individual objects expected value.
Here is my sample fact class -
public class Order {
private int orderId;
private List<OrderItem> orderItems;
private int usersIntegrationFee;
}
The OrderItem class contained in the fact class is -
public class OrderItem {
private int orderItemId;
private Product prod;
}
And the Product class is the one that has productIntegrationFee field-
public class Product {
private String mktProdId;
private String prodName;
private int productIntegrationFee;
}
I wish to check if Order.usersIntegrationFee is less than sum of all Order.OrderItem.Product.productIntegrationFee.
Is there a way to do this in drools? Any help would be much appreciated.
What you need to use is a drools built-in utility called accumulate. This utility allows you to iterate over a collection of objects on the right hand side while "accumulating" some sort of variable value. Some common use cases involve sums, means, counts, and so on. Basically the construct loops over each item in a collection and performs some defined action on each item.
While you can define your own custom accumulate function, Drools supports several built-in accumulate functions -- one of which is sum. This built-in function is what you need for your particular use case.
The general format of accumulate is this: accumulate( <source pattern>; <functions> [;<constraints>] ). Your rule would look something like this (psuedo-code since I don't have Drools on this computer; syntax should be close or exact but typos may exist.)
rule "Integration fee is less than sum of product fees"
when
// extract the variables from the Order
Order( $userFee: usersIntegrationFee,
$items: orderItems)
// use the accumulate function to sum up the product fees
$productFees: Integer( this > $userFee ) from
accumulate( OrderItem( $product: prod ) from $items,
Product( $fee: productIntegrationFee ) from $product;
sum($fee) )
then
// do something
end
Some things to note. In a single accumulate, you can do multiple things -- sum, average, and so on. But if you're only invoking one accumulate function like here, you can use the syntax I've shown (Integer( conditions ) from accumulate( ... ).) If you had multiple functions, you'd have to assign the outputs directly (eg. $sum: sum($fee), etc.)
Finally there's a third optional parameter to accumulate which I've omitted since your use case is quite simple and doesn't need it. The third parameter applies filtering (called 'constraints') so that the accumulate functions skip over items that don't meet this criteria. For example, you could add a constraint to ignore productIntegrationFee values that are negative like this: $fee > 0.
A final note about the syntax I chose in this rule. Since the use case was "trigger the rule if the usersIntegrationFee is less than the sum," I put the comparison directly in the Integer( ... ) from accumulate. You could, of course, do a comparison separately, for example like Integer( $productFees > this ) from $userFee or whatever other format of comparison you like. This way just seemed simplest.
The Drools documentation has more information about this utility. I've linked to the section that discusses elements in the 'when' clause; scroll down a bit to see the documentation for accumulate directly.
What's an example of a scenario where an empty string and NULL should be treated as distinct values?
(I ask because Django and Oracle consider them indistinguishable, but some databases treat the empty string and NULL as 2 distinct values.)
In short, that allows for optional unique fields.
Let's take the example of financial securities: some are identified using multiple codes. Bloomberg codes, ISIN codes, Sedol codes, Reuters codes ... But rarely would all securities have registered for all types of codes at the same time.
However if one security is already assigned one type of code, you would not want another security to reuse the same value.
Hence the need for both uniqueness and optionality, which mixing '' and NULL prevents, because the db would complain if you were trying to insert '' twice for unassigned codes.
In my mind these two values are semantically different. Empty string is a valid string instance while null means that the value has not been set at all (note that in general null is not reserved for string type only but is a general concept that applies to any nullable type and therefore I don't treat null as a string value (i.e. a value from the set of all possible string values) while empty string is specific to string type and is a string value - i.e. it belongs to the set of possible string values). To understand what I mean look at nullable integer type - is there a difference between 0 and null? Obviously there is. The difference between string and int example is that in real world 0 is much more useful than the empty string. In real world an empty string and null are also very often equivalents.
One use case when you may want empty string instead of null is when you want to remove all occurrences of a character/substring from a string. The easiest method is to replace what you want to remove with empty strings. I don't know what it would mean to replace a substring with a null value - it will probably behave differently depending on the language you are using. However, if I use the empty string I would expect the same behavior regardless of the language.
You could have a database table that represents an inheritance hierarchy (known as Table-Per-Hierarchy in .NET's Entity Framework). This means that a single table stores the state of all derived types in that hierarchy, as well as the base class.
Look at this class hierarchy:
public class Animal
{
int Id,
int NumberOfLegs
}
public class Cat : Animal
{
string FurColor;
}
The base class Animal has no string properties. However, a derived type called Cat has a string property called FurColor. If we were using Table-Per-Hierarchy, then we would have the columns:
ID | NumberOfLegs | FurColor
We would probably also have what's called a discriminator column which helps differentiate between different types, but that's not important here.
Now, if you had an instance of the Animal base class, your object would only have 2 properties. When this object is stored into the database table, there is no value for FurColor because that property has nothing to do with the Animal class. Therefore NULL is the most suitable value as it indicates that there is no explicit value for this property. Empty string on the other hand could be considered to have some meaning, which is structurally incorrect for the Animal object, as that property is non existant on it.
If you had an instance of the Cat class, then your object would have 3 properties. Saving this to the database table would conceptually require all 3 fields. If FurColor didn't have a particular value, empty string is perfectly valid and in my opinion a better option than NULL. This is because when you read the object back from the database, you don't have to specifically check the property for NULL before using it in operations such as string concatenation (which will throw something along the lines of a NULL reference exception in most statically typed languages such as C#).
So long story short, NULL can be considered 'value-less' where an empty string might be a perfectly valid value in your application.
Let's say I'm building a simple class that prints some text on the screen, and it has the possibility to change the colors of the text.
myclass a("this is the text");
a.setColor("green");
I'm still learning C++ and I recently got introduced to enum and thought I'd give it a try. I was wondering if it is a good practice to use enum types in interface functions like the above setColor?
What are the advantages or disadvantages of using enum classes in interface functions? Are there cases where they are more applicable than and are there case where they are bad to use?
What if I want to combine properties? E.g.
a.setAttribute("bold reverse");
I don't know if interface is the correct term for what I want to describe: the functions that a user of my class would end up using.
In your case, there are (at least) two advantages:
No need to parse the string at run-time, leading to higher efficiency. You can use an enum variable directly in a switch statement.
An enum is (to some extent) self-documenting, the user of your code has to work hard to provide an invalid value.
One potential "disadvantage" is in the case where the colour string has come from e.g. run-time userinput (they've typed into a textbox or something). You will need to parse this string and convert it into an enum. But it's not really a disadvantage, because you'll need to do this anyway. Best practice is for the user-interface logic to validate the string and convert to the enum at the earliest opportunity.
What if I want to combine properties?
I can think of at least three options:
Use multiple calls to setAttribute.
Pass an array of attributes.
Define each enum value to be a power-of-two, and then you can combine enums with |.
Yes, using an enum in this case seems better than an actual string.
One clear advantage - strong typing.
If setColor accepts a char*, like in your case, you could do:
a.setColor("horse");
which you can only detect as an error at runtime.
If setColor takes an eColors as parameter:
a.setColor(eGreen);
a.setColor(eRed);
would compile, but
a.setColor(eHorse);
would not.
Enums are definitely more explicit than strings for this case. As for the concatenation of values, you can use some bit fiddling to make this work. Set the values of your enum to increasing powers of two, then you can OR them together.
enum TextAttributes {
Bold = 1,
Italic = 2,
Reverse = 4,
StrikeThrough = 8,
Underline = 16
};
TextAttributes attr = Bold | Reverse;
I've got a list of number that I need to keep track of. The numbers are loosely related, but represent distinctly different items. I'd like to keep a list of the numbers but be able to refer to them by name so that I can call them and use them where needed easily. Kind of like an inventory listing, where the numbers all refer to a part ID and I'd like to call them idPart1, idPart2, idPart3 so their purpose is easily identifiable when they are used.
What would be the best way to do this?
1)Define a structure. Say, Inventory. A number of int members will be included, part1, part2 etc. To use, an instance of the structure will be created, values assigned to the members, and the numbers will be used by saying struct.member as needed.
2)Define an enumeration. Use part1, part2 as the enum literals. Store the actual values in a vector or list, each one at the index corresponding to the value of the number's name within the enum. Use the enum literals to retrieve the values, list[enumLit].
3)Something completely different
There's nothing else I need to do with the numbers - just look them up every once in a while. Since there's no processing, I kind of think a new class for them is overkill, but I'm willing to be convinced otherwise.
Any suggestions?
Let me try to rephrase what you're trying to do here. You want developers who use your code to be able to refer to a pre-defined set of numeric values:
using intuitive names
that will be validated at compile time
and that the IDE will recognize for the sake of code completion.
If the values will not change at run-time, and they are integer values, you can use an enum as Mark Ransom showed.
If the values will not change at run-time, and they are non-integer values, you can use either #define or const variables:
#define PART1 1.3
#define PART2 "1233-456"
or
namespace PartNumbers
{
const double Part1 = 1.3;
const char* Part2 = "123-456"
}
If the values may change at run-time, you can use either of the two options you identified. Both of these options have the drawback of requiring an object to be instantiated which holds the current part number values. The other options are simpler to implement and don't require any run-time lookup. Everything is resolved at compile time.
All of these options require users of your code to recompile if they are to access new part types. Your first option may require existing code to be recompiled when new part types are added, even if the existing code doesn't access them; it's more prone to memory layout changes.
You can use a map with a string as the key.
std::map<string,int> mymap;
mymap["part1"] = value1;
cout << mymap["part1"];
You could use the:
std::map<string, int> someMapName;
with the key as the string and the actual number as the int. That way you could do you could use
someMapName["idPart1"]
to grab the number.'
EDIT:
If you are ok with Enumerations then option 2 would work perfectly with the std::map just instead of string, the key would be your enum type obviously.
Based on your comments to the other answers, I'd say enums are the way to go, but I'd structure them a little differently.
namespace id {
enum {
part1 = 123,
part2 = 456,
part3 = 987,
...
};
}
cout << id::part1;
Use a database.
Specifically, a table like the following:
+------------------+-------------------+
| Item Name | Item Number |
+------------------+-------------------+
Internally, this can be represented as:
std::map<std::string, // The item name
unsigned int> // The number.
When you want the number, retrieve it using the name:
std::map<std::string, unsigned int> index_by_name;
//...
std::string part_name = "Part0123";
unsigned int part_number = 0;
part_number = index_by_name[name];
Seriously, use a database. Check out SQLite and MySQL.