Can I define an ordered mixed message array in proto3? - protocol-buffers

I want to define in proto3 an ordered list of unrelated classes (messages) like this:
Frog
Dirt
Air
Computer 1
Computer 2
Politics
Is it possible? I can also live with having a base class (base message) if that exists in proto3... Its not clear to mean if the feature set of proto3 allows this. Thanks!

The typical way of representing this would be
message Wrapper {
oneof Thing {
Frog frog = 1;
//...
Politics politics = 6;
}
}
and use repeated Wrapper for the list/array. There is no one-step repeated oneof.
Alternatively, you could just use
repeated Frog frogs = 1;
//...
repeated Politics politics = 6;
However this second layout cannot preserve the order between different kinds of element.

Related

Difference of proto messages with the relative positions of its attributes

what is the difference if the attribute in a protobuf message is first or second member?
The Request proto message i have, has 2 fields. i am asked to interchange the position of the attributes
message SomeRequest {
SomeMessage1 message1 = 1;
SomeMessage2 message2 = 2;
}
Changed to :
message SomeRequest {
SomeMessage2 message2 = 1;
SomeMessage1 message1 = 2;
}
What could be the possible reasons of such a advice? message2 is expected to be more predominately searched?
Also can i have few more scenarios to understand it better?
Thanks in advance!!
Ultimately, whoever asked for this change - maybe ask them for their reasons?
There are scenarios where lower field numbers are cheaper (space-wise) and so should be preferred, but fields 1 and 2 are identical in terms of space, so this this isn't a concern here.
If this was for byte compatibility with a pre-existing similar type, it might be a reasonable request.

proto3 - oneof vs fields with identifier

I am writing a proto3 class for an object which currently have around 2 variations, and will grow up to 6 or 7. Only one of them would be used in a message. These variations do not share common fields. They will be encoded as a submessage in a parent message. These messages would be written once and read tens of thousands of time.
I was wondering what would be the most performant way, memory and time of parsing wise, to achieve this so that as more variations are added, the performance is not lost.
Consider the following variations.
message B1 {
repeated string value = 1;
bool hasMeta = 2;
}
message B2 {
repeated int32 value = 1;
map<string, string> foo = 2;
}
First option: define an oneof field that refers the specific subtype.
message P1 {
oneof parents {
B1 boo = 1;
B2 baz = 2;
// add more variations here in future..
}
// other non-related fields...
}
Second option: define an integer that acts as an identifier for the available variation. At runtime this integer can be used to determine which variation has been set (another way is to null check the variations and use the first non-null).
message P1 {
int32 type = 1;
B1 boo = 2;
B2 baz = 3;
// other non-related fields...
}
I am particularly interested in the wire size and performance.
In second option, considering only one of the variations would be set (enforced in app layer), will the wire size be more than that in first? Is memory reserved for null fields as well?
The oneof method is slightly better compared to the message where you define the variable type with respect to processing power and wire size. Protobuf always serializes the tag number before a nested message. So for the oneof message it is not required to serialize a variable like type. Making it's wire size slightly smaller compared to the second message definition.
With respect to memory allocation this highly depends on the programming language you are using and how they have implemented oneof's and nested messages. If I am not mistaken the default C++ implementation dynamically allocates memory for sub messages. I suspect no difference here between either of your suggestions. Looking at NanoPB however, there oneof's are implemented as unions allocating only memory for the bigger message. This while for your second option would allocated memory for both B1 and B2.

Should I always avoid lower case class names?

The following is incompatible with the Dart Style Guide. Should I not do this? I'm extending the num class to build a unit of measure library for medical applications. Using lower case looks more elegant than Kg or Lbs. In some cases using lower case is recommended for safety i.e. mL instead of Ml.
class kg extends num {
String uom = "kg";
num _value;
lbs toLbs() => new lbs(2.20462 * _value);
}
class lbs extends num {
String uom = "lbs";
num _value;
kg toKg() => new kg(_value/2.20462);
}
For your case I might pick a unit (e.g. milligrams) and make other units multiples of it. You can use division for conversion:
const mg = 1; // The unit
const g = mg * 1000;
const kg = g * 1000;
const lb = mg * 453592;
main() {
const numPoundsPerKilogram = kg / lb;
print(numPoundsPerKilogram); // 2.20462...
const twoPounds = lb * 2;
const numGramsInTwoPounds = twoPounds / g;
print(numGramsInTwoPounds); // 907.184
}
It's best to make the unit small, so other units can be integer multiples of it (ints are arbitrary precision).
It's up to you if you use them.
There might be situations where it can be important.
One I can think of currently is when you have an open source project and you don't want to alienate potential contributors.
When you have no special reason stick with the guidelines, if you have a good reason deviate from it.
Don't use classes for units. Use them for quantities:
class Weight {
static const double LBS_PER_KG = 2.20462;
num _kg;
Weight.fromKg(this._kg);
Weight.fromLbs(lbs) {
this._kg = lbs / LBS_PER_KG;
}
get inKg => _kg;
get inLbs => LBS_PER_KG * _kg;
}
take a look at the Duration class for ideas.
Coding conventions serve to help you write quality, readable code. If you find that ignoring a certain convention helps to improve the readability, that is your decision.
However, code is rarely only seen by one pair of eyes. Other programmers will be confused when reading your code if it doesn't follow the style guide. Following coding conventions allows others to quickly dive into your code and easily understand what is going on. Of course, it is possible that you really will be the only one to ever view this code, in which case this is moot.
I would avoid deviating from the style guide in most cases, except where the advantage is very obvious. For your situation I don't the advantage outweighs the disadvantage.
I wouldn't really take those coding standards too seriously.
I think these guidelines are much more reasonable: less arbitrary, and more useful:
Java: Code Conventions
Javascript: http://javascript.crockford.com/code.html
There are many more you can choose from - pick whatever works best for you!
PS:
As long as you're talking about Dart, check out this article:
Google Dart to ultimately replace Javascript ... not!

How to Connect Logic with Objects

I have a system that contains x number of strings. These string are shown in a UI based on some logic. For example string number 1 should only show if the current time is past midday and string 3 only shows if a randomly generated number between 0-1 is less than 0.5.
How would be the best way to model this?
Should the logic just be in code and be linked to a string by some sort or ID?
Should the logic be some how stored with the strings?
NOTE The above is a theoretical example before people start questioning my logic.
It's usually better to keep resources (such as strings) separate from logic. So referring strings by IDs is a good idea.
It seems that you have a bunch of rules which you have to link to the display of strings. I'd keep all three as separate entities: rules, strings, and the linking between them.
An illustration in Python, necessarily simplified:
STRINGS = {
'morning': 'Good morning',
'afternoon': 'Good afternoon',
'luck': 'you must be lucky today',
}
# predicates
import datetime, random
def showMorning():
return datetime.datetime.now().hour < 12
def showAfternoon():
return datetime.datetime.now().hour >= 12
def showLuck():
return random.random() > 0.5
# interconnection
RULES = {
'morning': showMorning,
'afternoon': showAfternoon,
'luck': showLuck,
}
# usage
for string_id, predicate in RULES.items():
if predicate():
print STRINGS[string_id]

How to choose all possible combinations?

Let's assume that we have the list of loans user has like below:
loan1
loan2
loan3
...
loan10
And we have the function which can accept from 2 to 10 loans:
function(loans).
For ex., the following is possible:
function(loan1, loan2)
function(loan1, loan3)
function(loan1, loan4)
function(loan1, loan2, loan3)
function(loan1, loan2, loan4)
function(loan1, loan2, loan3, loan4, loan5, loan6, loan7, loan8, loan9, loan10)
How to write the code to pass all possible combinations to that function?
On RosettaCode you have implemented generating combinations in many languages, choose yourself.
Here's how we could do it in ruby :
loans= ['loan1','loan2', ... , 'loan10']
def my_function(loans)
array_of_loan_combinations = (0..arr.length).to_a.combination(2).map{|i,j| arr[i...j]}
array_of_loan_combinations.each do |combination|
//do something
end
end
To call :
my_function(loans);
I have written a class to handle common functions for working with the binomial coefficient, which is the type of problem that your problem falls under. It performs the following tasks:
Outputs all the K-indexes in a nice format for any N choose K to a file. The K-indexes can be substituted with more descriptive strings or letters. This method makes solving this type of problem quite trivial.
Converts the K-indexes to the proper index of an entry in the sorted binomial coefficient table. This technique is much faster than older published techniques that rely on iteration. It does this by using a mathematical property inherent in Pascal's Triangle. My paper talks about this. I believe I am the first to discover and publish this technique, but I could be wrong.
Converts the index in a sorted binomial coefficient table to the corresponding K-indexes. I believe it might be faster than the link you have found.
Uses Mark Dominus method to calculate the binomial coefficient, which is much less likely to overflow and works with larger numbers.
The class is written in .NET C# and provides a way to manage the objects related to the problem (if any) by using a generic list. The constructor of this class takes a bool value called InitTable that when true will create a generic list to hold the objects to be managed. If this value is false, then it will not create the table. The table does not need to be created in order to perform the 4 above methods. Accessor methods are provided to access the table.
There is an associated test class which shows how to use the class and its methods. It has been extensively tested with 2 cases and there are no known bugs.
To read about this class and download the code, see Tablizing The Binomial Coeffieicent.
It should not be hard to convert this class to the language of your choice.
To solve your problem, you might want to write a new loans function that takes as input an array of loan objects and works on those objects with the BinCoeff class. In C#, to obtain the array of loans for each unique combination, something like the following example code could be used:
void LoanCombinations(Loan[] Loans)
{
// The Loans array contains all of the loan objects that need
// to be handled.
int LoansCount = Loans.Length;
// Loop though all possible combinations of loan objects.
// Start with 2 loan objects, then 3, 4, and so forth.
for (int N = 2; N <= N; N++)
{
// Loop thru all the possible groups of combinations.
for (int K = N - 1; K < N; K++)
{
// Create the bin coeff object required to get all
// the combos for this N choose K combination.
BinCoeff<int> BC = new BinCoeff<int>(N, K, false);
int NumCombos = BinCoeff<int>.GetBinCoeff(N, K);
int[] KIndexes = new int[K];
// Loop thru all the combinations for this N choose K.
for (int Combo = 0; Combo < NumCombos; Combo++)
{
// Get the k-indexes for this combination, which in this case
// are the indexes to each loan in Loans.
BC.GetKIndexes(Loop, KIndexes);
// Create a new array of Loan objects that correspond to
// this combination group.
Loan[] ComboLoans = new Loan[K];
for (int Loop = 0; Loop < K; Loop++)
ComboLoans[Loop] = Loans[KIndexes[Loop]];
// Call the ProcessLoans function with the loans to be processed.
ProcessLoans(ComboLoans);
}
}
}
}
I have not tested the above code, but in general it should solve your problem.

Resources