2
$\begingroup$

I have experience with Python and now am learning C++, I am finding the lack of an interpreter or a repl to be a serious hinderance when learning the language, as well as the ability to type help(func) in the interpreter when I get stuck.

What changes to the development environment, or to my approach to learning, can I make to increase my speed of learning?

(Is there a typical development flow that compiled language programmers use that make them efficient?)

How do they create fast feedback loops between code edits and results?

$\endgroup$
  • 1
    $\begingroup$ See: Stack Overflow question and CERN's notes on Clink. You can have a REPL for C++. $\endgroup$ – Gypsy Spellweaver Jan 6 at 9:26
  • $\begingroup$ @GypsySpellweaver I thought this site is for both teaching and learning strategies. $\endgroup$ – ctrl-alt-delor Jan 7 at 9:40
  • $\begingroup$ @ctrl-alt-delor The site is as you say, basically. The Q originally was about development strategies. It still seems more developer-oriented than education-oriented, to me, and could benefit from more "focus". $\endgroup$ – Gypsy Spellweaver Jan 7 at 16:46
  • $\begingroup$ I disagree. REPLs are extremely useful teaching tools. Java now has jshell, and I find this tool to be extremely helpful. $\endgroup$ – ncmathsadist Jan 7 at 16:53
4
$\begingroup$

Your question deserves a long discussion, but I will try to narrow it down to few points.

First, remember that you are dealing not just with a "compiled language" such as Java or C# (that could be much easier targets for you), you are dealing with C++ that was designed with backward compatibility with C as a killer feature, and C was created in late 70s. It means that C++ indeed implements numerous design decisions that look archaic/obsolete/strange for a modern learner. Say, the whole system of header files is a hacky substitute for a proper package management. Thus it would be good for you to study carefully major language features and understand the true reason why they exist. In many cases you'll find newer and better alternatives to old tools (such as std::vector objects vs. arrays)

Second, use a good IDE. For instance, if you place a cursor under printf() (or any other library function) in MS Visual Studio and hit F1, it will jump to the extensive online manual, so this is not an issue. Also you will get autocomplete features similar to those available for Python (e.g., type a variable name, then a dot, and see a list of member functions).

Third, think of a compiler as of a subsitute for REPL (and there are true REPL environments for C++, such as the one available at repl.it). When you type a Python program, you don't know anything about its correctness until you run it. In C++ you can catch many errors just by compiling. So by the time of the first run you will already eliminate all syntax errors and many other errors related to type mismatching. I was learning Python after C++, and for me a source of constant annoyance was to make sure that every single line of code is executed before I could even hope it is correct.

Thus your typical session will look like "type some lines -> compile -> type some lines -> compile -> run"). Since you are asking about "fast feedback loops", I can tell that really good C++ programmers invest considerable effort in the type system used in their code. They don't use int everywhere even if they can. They use incompatible types for incompatible entities, declare member functions as const if they shouldn't modify objects, and add static_assert statements where possible, and avoid type casting. In other words, they make the compiler do the job. In the best case, if such code compiles, it works correctly. So the real feedback loop is concentrated on the stage of compilation.

In any case, remember that C++ is a complex hardware-oriented language with long history (just look at the sheer size of Stroustup's definitive guide), so approach it with patience. Mastering it takes time, indeed, be persistent and don't expect fast results.

$\endgroup$
  • $\begingroup$ I really appreciate your answer, I've been looking for awhile for a discussion like this one but haven't seemed to come across a good one. Your points are really insightful, all three of them. I really like your first point especially, that c++ has a long history and that it makes sense to "study carefully major language features and understand the true reason why they exist". I also didn't realize that experienced c++ programmers spend so much time thinking about types. Do they use typedef very often? $\endgroup$ – Allen Wang Jan 12 at 4:26
  • $\begingroup$ One thing I forgot to mention is unit tests: if you write them, this is an additional mechanism for fast feedback loop. Typedefs are useful indeed, but in practice they are less useful since they don't introduce new types. Even if you say "typedef int MyInt;", you still can mix int and MyInt everywhere, so here compiler won't help to find inconsistencies. $\endgroup$ – rg_software Jan 12 at 8:52
  • 1
    $\begingroup$ @AllenWang typedef isn't very common because it only creates a new name for a type. This can be useful as a mneumonic device, but the compiler won't catch mistakes. If you need a new type, define it as a class or a struct with the proper member functions. Also: look into templates. Templates are far more powerful than generics in Java, and they preserve type information (so you can call overloaded functions). In many cases templates can completely replace the need for an inheritance heirarchy $\endgroup$ – J. Antonio Perez Feb 19 at 7:32
1
$\begingroup$

You can find REPLs for C++ with an online search, but my advice would be different. I do the following with Java, but equivalent tools for C++ exist.

First, I use a sophisticated IDE (Eclipse) that, among other things, does error highlighting as I type. A typed language like C++ permits many errors to be caught early, normally in the compiler, but they can be pushed back into the development environment prior to formal compilation. That works for most syntax errors and for many structural errors, such as omitting a declaration.

Second, I use Test Driven Development to build serious code. I just JUnit, which is tailored for Java, of course, but there are equivalent "units" (TDD frameworks) for most languages. The rule here is "no code without a failing test". The idea is that before you write any code you write a test for it based on the specification you have or that you create on the fly. The test captures your intent directly. You write the test for a function before you begin to write the function. It fails of course, since it can't even compile. But the IDE can automatically insert the stub for the function into the code. You then provide the function body and run the test again. If it fails you need to think again.

But TDD is even better than that, since when you run the "test" you are actually running all of the tests; the test suite. So, if something used to work and now an earlier test breaks you get immediate feedback on it and, since the only thing you changed is that one method body, the source of error is usually pretty obvious. Moreover, tests are run independently of each other so that a failure of one test doesn't cascade into other failures that obscure the problem.

This is a workflow quite different from that of a REPL, so it takes some practice. But the IDE can do many things for you in addition to what is described here. The best of them have a plugin architecture in which you can easily add additional tools as needed.

Two additional notes. First, is that I use the same tools and techniques when programming Python and Ruby.

Second, having built many compilers, you should understand that the actual difference between a processor for a compiled language and an interpreted one is surprisingly small. The processing for the interpreted language has everything but the final stage code generator. But if it is to be efficient, it still creates an intermediate form of the program, possibly a tree or even an abstract assembler language version. Some of the optimization can be omitted, but only the late-stage optimizations, normally. So, an IDE for an interpreted language isn't so odd.

$\endgroup$
  • $\begingroup$ Your point about TDD is well taken. It is hard, however, for a newcomer to begin writing tests when one doesn't know very much about how the language works. $\endgroup$ – Allen Wang Jan 12 at 4:30
  • $\begingroup$ You have to teach test writing, of course, preferably with in-class demonstrations. Initially the tests can't be very sophisticated, but they shouldn't be in any case. Prefer lots of simple tests over a few complex ones. This makes them easier to write and more useful as they give fine-grained error reporting. Note that tests are run as suites, not individually. The tests in a suite are independent of one another. In Eclipse, if you have a test for a non-existent method, the IDE will write the stub for you, so it makes things simpler. $\endgroup$ – Buffy Jan 12 at 20:33
1
$\begingroup$

I would say that you need to learn a completely different (old fashioned, perhaps archaic) programming paradigm, non-interactive coding. In Ye Olden Ancient days, a programmer would often write out a complete program (or at least large parts) on paper, before even going near a computer (or punch card machine).

Try it as an exercise. See how much code (how many lines) you can write (on paper, or into a plain text editor), and have it run correctly when first compiled and run. You might learn to think more about certain aspects of the code, before typing, and perhaps end up a better programmer (even after going back to helpful interactive IDEs). Compared to coders who only know how to compose within fast feedback loops.

This will also prevent learning the bad habits from randomized hack-and-slash trial-and-error coding (that, while possibly helpful in certain exploratory and learning situations) which can become a problematical practice within many high quality/reliability coding paradigms (those that don't include 100% provable unit test coverage).

$\endgroup$
  • 1
    $\begingroup$ Hmmm. Perhaps as a thought experiment, but not in the real world. I lived in the time of 24 hour turn-around and coding on a key-punch. No one should have to do anything like that. Fast turn around is a universally good thing for learning, but you need different techniques today, such as Test First. I've done it both ways. Don't even think about going back. That said, I don't use a REPL, not because it is too fast, but because it keeps an insufficient record of my work. $\endgroup$ – Buffy Jan 10 at 21:54
  • $\begingroup$ Since you programmed in the time of key-punches, you've already learned those lessons, and don't need to go back. $\endgroup$ – hotpaw2 Jan 10 at 22:30
  • $\begingroup$ But I don't program "like that" in the modern age. I actually learned something in the modern world. $\endgroup$ – Buffy Jan 10 at 22:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.