Time to try turning an R function into the equivalent C++ function. Let’s start by copy & pasting the brute.force function from problem 1 into the C++ text editor, and seeing what R code is legit in C++. Gotta start somewhere, right?
Lucky for us, the Tinn-R editor and Code::Blocks both have syntax highlighting, which colour-code various kinds of objects/variables etc.
So, it doesn’t look like a complete travesty, but it ain’t great either. The double equals-sign, ‘for’, ‘if’, and ‘or’ (the vertical bar on line 6) are all logical operators in both languages. Which, you know, is pretty logical (oho!), considering logic is a computer’s bread and butter. We can see that ‘print’ and ‘sum’ and ‘append’ don’t look like they’re recognized though. And we already know based on the Hello world program that the first line isn’t in the right format. Just for shits and giggles, let’s see what errors come up (bottom of the screen) when we try and compile the code.
- Right. We forgot to specify the type of value we want the function to return. We’re just adding whole numbers, so add ‘int’ before brute.force, and try compiling again.
- I have no idea what an initializer is. But we now know that ‘.’ is a special object reserved for particular situations (we’ll actually end up using it in our finished function, but I won’t explain how yet. All in good time, grasshopper). So let’s just remove it and see what happens:
- But seriously:
Initializer again? And another fancy token lying in wait for the unsuspecting? I’m putting my foot down.
Aside from still getting used to the grammar and syntax, there’s another issue: that first line of code works for an interpreted language where we don’t need to specify what the n1, n2 and thresh arguments are until we decide to call the function. But in C++, it seems they have to actually appear as a number at some point for the code to work. Since the optimist in me still thinks that stuff in the curly braces looks pretty salvageable, let’s just whack that stuff into the ‘Hello world’ style of program, and explicitly tell it what n1, n2 and thresh are from inside the function. When we get the code to a point where it compiles and works, then we can work out how to give it arbitrary values for the three arguments. Capisce?
6 errors. Not great. But! That first line above the first error says “In function ‘int main()’: ” so we’ve gotten it to recognize that it is a function, huzzah! As for the errors, 4 of them are that a particular object/variable has not been declared in this scope. It’s asking us to declare the type of each variable. (Short reason: if C++ knows what type of variable something is, it knows how much space it can potentially take in memory, and so it can allocate memory in a clever and efficient fashion, which makes things faster to run. Aha). n1, n2 and thresh are integers, so that’s straightforward. But we want multvect to be a vector so it can store lots of integers.
Trying doesn’t work. Now would be a good time to make use of the interwebs. Voila: a very confusing page from the reference section at cplusplus.com, which nonetheless still contains the info we’re looking for:
That makes sense. #include the code for using vectors. And <int> specifies what type of variable the vector contains. Can’t argue with that.
[Aaaand it’s digression time. We’ve been including the line ‘using namespace std;’ so that the standard namespace is used. As I mentioned in the last post, this is so that C++ knows what function you mean when you use a certain name. So far, we haven’t been using anything fancy. But for big projects, where you use functions from different namespaces, rather than importing the entirety of each namespace at the start, some people prefer to define the name space each time they use a particular function, thus: std::vector<int> instead of just vector<int>. I’m gonna keep doing it the uncouth/lazy way, but if we encounter something in the future where we need to mix namespaces, then I’ll do it the gentlemanly way.]
And there’s two errors reminding us that we need to put semicolons at the end of lines. While we’re nitpicking, we already know from ‘Hello world’ that we use ‘cout’ instead of ‘print’. And since we used the Hello world template, we already have that header line at the top making sure we include the code that can make sense of ‘cout’. So, tidied up and compiled again:
Oops, forgot about <-, which is used for assigning things in R. I’ll remove it from line 11 and just put a semicolon, since vector<int> should be all multvect needs to work. On line 15, I’ll replace it with an equals sign instead.
7 error messages now. But that’s a good thing, as they start on line 12, which means that line 11 where we declared the multvect vector, works properly! Now it seems to be having trouble with the line which sets up the for-loop. ‘i’ was not declared, it should just be a number running from 1 to 999, so we’ll make that: int i.
- Still a problem with that for-loop. The cplusplus site has a helpful page about control structures though, giving the format of this line as:
- for (initialization; condition; increase) statement;
- Initialization is initial value, condition is some logical condition that value should have. If that condition is true, you execute the statement, and then increase the initialization value by some amount . And in C++, you increase a value by 1, with ++ (or decrease it by 1 with – – ). Compare:
- Same sentence, just with a different dialect.
- We compile again, and this time it has a problem with the %% symbols in line 14 (we’re almost at the end!). Looking up the wiki page on logical operators in C++, this is probably the easiest fix so far. C++ uses only a single percent symbol to find the remainder of a division. No probs. Compile again.
- Oh yeah, append. All we need to do is find a function that adds an element to a vector. That cplusplus reference page on vectors has a list of operations you can perform on vectors. Which is where that period comes in. object.function means apply function to object. Neat. And it seems the function we want is push_back:
- So very close! Only thing left to find is something which adds up elements from vectors. The function we’re looking for is ‘accumulate’. The two arguments of .begin() and .end(), applied to the name of your vector, specify the range on which to work. The third argument is the initial constant value you want accumulate to have, which more often than not is just gonna be 0. (I don’t see the necessity of it, either). And, with accumulate, you need to have the #include <numeric> header at the top of the file. Anyway:
- No more errors! Now just go to Build, Build and run (or press F9), and it’ll execute all that code. Does it run? Does it give the right answer?
Fucking finally. I realise it’s slow going, but it’ll get quicker as we learn more and build on what we already know. In the next post, I’ll work out how to give a function user-defined inputs, not just ones hard-coded into the program. Hopefully.