Im new to c++, I'm reading the core guidelines and I came across this:
P.1: Express ideas directly in code
In this, it says to use something like Month month() const; instead of int month();
So I have 2 questions, why is there a const at the end of the function and what does that do? And how is Month defined? Can you declare new functions with any name instead of things like int, double, float etc?
Thanks in advance
The point of the guideline is what it says: to put the ideas behind the interface in the code itself.
If you have some date type, and it has a member function int month();, that expresses the idea that you can retrieve a month from the date. And presumably, the returned int value represents the month of the year as stored within that date.
But... how does it represent the month? It's an integer. Is the month of January given the integer 0, as might be expected by a long-time programmer (of most languages)? Or maybe it is given the integer 1, because that's how dates are actually written? The code itself says nothing about this; you would have to look at the documentation for the function to find out. So if you see if(date.month() == 1), you don't know if the code is asking if it is January or February.
The alternative, Month month() const; returns the type Month. Now, what that type is is not specified. Whatever it is, that type can make it unambiguous what value is represented by "January". For example:
enum class Month { January, February, ...};
How is "January" encoded? By the enum value Month::January. Therefore, if you see the test if(data.month() == Month::January), then it is clear exactly what it is saying. It is not only unambiguous, it also reads almost exactly like English: is the month of the date the month of January.
This is what it means to express an idea in the code: the entirety of the idea is unambiguously expressed by the code. Make the code say what it is doing, not-so-much how it is doing it.
Related
I have to convert some SAS code. In other programming languages I am used to < being used in comparisons e.g. in pseudo-code: If x < y then z
In SAS, what is the < operator achieving here:
intck(month,startdate,enddate)-(day(enddate)<day(startdate))
I have been able to understand the functions using the reference documentation but I can't see anything relating to how '<' is being used here.
Just to go into a little more detail about what the code you have there is doing, it's an old school method to determine the number of months from one date to the next (possibly to calculate a birthday, for example).
Originally, SAS functions intck and intnx only calculated the number of "firsts of the month" in between two dates (or similar for other intervals). So INTCK('month','31OCT2020'd, '01NOV2020'd) = 1, while INTCK('month','01OCT2020'd,'30NOV2020'd) = 1. Not ideal! So you'd add in this particular bit of code, -(day(enddate)<day(startdate)), which says "if it is not been a full month yet, subtract one". It's equivalent to this:
if day(enddate) < day(startdate) then diff = intck(month,startdate,enddate) - 1;
else diff = intck(month,startdate,enddate);
There's now a better way to do this (yay!). intck and 'intnx' are a bit different, but it's the same idea. For intck the argument is method, where c for "continuous" is what you want to compare same period in the month. For intnx it is the alignment option, where 's' means "same" (so, move to the same point in the month).
So your code now should be:
intck(month,startdate,enddate,'c')
The symbol < is an operator in that expression. It is not a function call , like INTNX() is in your expression.
SAS evaluates boolean expressions (like the less than test in your example) to 1 for TRUE and 0 for FALSE.
So your expression is subtracting 1 when the day of month of ENDDATE is smaller than the day of month of STARTDATE.
Note: You can also do the reverse, treat a number as a boolean expression. For example in a statement like:
if (BASELINE) then PERCENT_CHANGE = (VALUE-BASELINE) / BASELINE ;
A missing value or a value of zero in BASELINE will be treated as FALSE and so in those cases the assignment statement does not run.
For a dataset in SSRS reports, I've created a calculated field with below expression and it works fine.
=(Fields!SalesAmount.Value+Fields!TaxAmt.Value)*Fields!Factor.Value
But sometime we can have factor value as 0. So, I modified above expression with below:
=iif(Fields!Factor.Value = 0,(Fields!SalesAmount.Value+Fields!TaxAmt.Value)*1,(Fields!SalesAmount.Value+Fields!TaxAmt.Value)*Fields!Factor.Value)
But this throws below exception:
The Value expression for the textrun ‘Textbox2.Paragraphs[0].TextRuns[0]’ uses an aggregate function on data of varying data types. Aggregate functions other than First, Last, Previous, Count, and CountDistinct can only aggregate data of a single data type.
Can someone please help to get resolve this issue?
This doesn't seem to be an issue with the IIF, but the datatypes seem to be mismatched. I have a few suggestions to try. First, you could try to multiply the true value by 1.0 as I assume the datatypes are decimal or double. The other option would be to use something like CInt to covert the value to the correct datatype. CInt would likely be inappropriate for decimals as it would round off any decimal values, but the idea is the same. Since your expression doesn't use any aggregates and only uses normal operators, it must relate to something other than the IIF.
Here's a useful link to break down the datatypes and conversion methods. Choose the most appropriate conversion and apply it to the 1.
EDIT: The expression should be the following.
=iif(Fields!Factor.Value = 0.00,
(Fields!SalesAmount.Value+Fields!TaxAmt.Value)*CDbl(1),
(Fields!SalesAmount.Value+Fields!TaxAmt.Value)*Fields!Factor.Value)
Apologies for such an entirely uninformed question, but I don't know any SAS and just need to know what one line of code does, so I hope someone can help.
I have a loop over an array of variables, and an if clause that is based on a comparison to .Z, but this variable is defined nowhere, so I'm guessing this is some sort of SAS syntax trick. Here's the loop:
ARRAY PTYPE{*} X4216 X4316 X4416 X4816 X4916 X5016;
DO I=1 TO DIM(PTYPE);
IF (PTYPE{I}<=.Z) THEN PUT &ID= PTYPE{I}=;
END;
So on the first iteration, the loop would check whether the value in X4216 is smaller than .Z, and then...? ID is another varuable in the dataset, but I have no idea what's happening on the right hand side of that if clause. I've briefly consulted the SAS documentation to figure out that ampersands refer to macros, but my knowledge of SAS is to limited to understand what's happening.
Can anyone enlighten me?
.Z is a special missing value. In SAS a missing value (what you might call a NULL value) is indicated by a period. There are also 27 other special missing values that are indicated by a period followed by a letter or an underscore. The missing values are distinct and are all considered smaller than any actual number. .Z is the "largest". So PTYPE{I}<=.Z is basically testing if the value is missing. You could instead use MISSING(PTYPE{I}) to make the same test. The right hand side is writing out the name and the value of the variable in the array with a missing value and also the name and value of the variable named in the macro variable ID.
I want to get the offset of a struct's member. I know this has been asked multiple times and the answer is always the mighty offsetof. Well, my case is a little different: I need the offset of an unknown type. That is for example:
void fill_struct(void* unknown)
{
...
}
The only thing I will know from unknown is the order in which types are set. i.e.
int
int
float
...
string
And the main problem here is align/padding, since I don't know a way to calculate it nor if there is a way at all.
This kind of question is often replied with: why would you want to do that?
For those people: I'm implementing a JSON parser in C++, and faced a problem (representing multiple type arrays), and my solution is to map the array's values into a custom struct.
I accept feedback regarding to that solution but I'm mainly interested in my question being answered
I've got experience in a lot of other programming languages, but I'm having a lot of difficulty with Stata syntax. I've got a statement that evaluates with no problem if I put in values, but I can't figure out why it's not evaluating variables like I expect it to.
gen j=5
forvalues i = 1(1)5 {
replace TrustBusiness_local=`i' if TrustBusiness_local2==`j'
replace j=`j'-1
}
If I replace i and j with 1 and 5 respectively, like I'm expecting to happen from the code above, then it works fine, but I get an if not found error otherwise, which hasn't produced meaningful results when Googled. Does anyone see what I don't see? I hate to brute-force something that could so simply be done with a loop.
Easy to understand once you approach it the right way!
Problem 1. You never defined local macro j. That in itself is not an error, but it often leads to errors. Macros that don't exist are equivalent to empty strings, so Stata sees in this example the code
if TrustBusiness_local2==`j'
as
if TrustBusiness_local2==
which is illegal; hence the error message.
Problem 2. There is no connection of principle between a variable you called j and a local macro called j but referenced using single quotes. A variable in Stata is a variable (namely, column) in your dataset; that doesn't mean a variable otherwise in the sense of any programming language. Variables meaning single values can be held in Stata within scalars or within macros. Putting a constant into a variable, Stata sense, is legal, but usually bad style. If you have millions of observations, for example, you now have a column j with millions of values of 5 within it.
Problem 3. You could, legally, go
local j "j"
so that now the local macro j contains the text "j", which depending on how you use it could be interpreted as a variable name. It's hard to see why you would want to do that here, but it would be legal.
Problem 4. Your whole example doesn't even need a loop as it appears to mean
replace TrustBusiness_local= 6 - TrustBusiness_local2 if inlist(TrustBusiness_local2, 1,2,3,4,5)
and, depending on your data, the if qualifier could be redundant. Flipping 5(1)1 to 1(1)5 is just a matter of subtracting from 6.
Problem 5. Your example written as a loop in Stata style could be
local j = 5
forvalues i = 1/5 {
replace TrustBusiness_local=`i' if TrustBusiness_local2==`j'
local j=`j'-1
}
and it could be made more concise, but given Problem 4 that no loop is needed, I will leave it there.
Problem 6. What you talking about are, incidentally, not if statements so far as Stata is concerned, as the if qualifier used in your examples is not the same as the if command.
The problem of translating one language's jargon into another can be challenging. See my comments at http://www.stata.com/statalist/archive/2008-08/msg01258.html After experience in other languages, the macro manipulations of Stata seemed at first strange to me too; they are perhaps best understood as equivalent to shell programming.
I wouldn't try to learn Stata by Googling. Read [U] from beginning to end. (A similar point was made in the reply to your previous question at use value label in if command in Stata but you don't want to believe it!)