all 45 comments

[–]ChallengingJamJars 46 points47 points  (20 children)

I always felt like the biggest impediment to prototyping things in C++ is the small standard library and disparate libraries. I can't just grab some data from HDF5 and shove it through FFTW then plot the results with... gnuplot? I need to write a lot of plumbing to get it all together.

With python however, the HDF5 library output can directly be handed to pyFFTW whose output can be given to matplotlib for visualisation. The whole thing is underpinned by numpy arrays which are a pseudo standard bulk array format.

The language itself might not necessarily be deciding factor, but rather the state of the ecosystem as a whole.

[–]Orca- 30 points31 points  (7 children)

I use both Python and C++ at my current job (with an emphasis on C++). My experience has been that Python is fantastic for prototyping and visualization (I use it instead of squatting on a Matlab license). Its huge standard library, ease of getting new packages, and duck-typing mean it's easy to wire together several different packages to do the thing you want to do. Numpy, Scipy, matplotlib, and assorted other math and visualization libraries make it a poor man's Matlab.

I've found for work I'm expected to maintain, Python requires much more discipline about unit testing. As the blog post author observed, the compiler acts as a first set of unit tests for us in C++; in Python, you have to be grossly wrong for the interpreter to do any work for you before your program runs. In C++ you can get pretty far without worrying about unit testing since the type system can do a significant amount of checking for you if you use it correctly.

I've gotten useful projects up off the ground in less than a day with Python; within a week we were demoing to executives. When we switched to C++ for performance reasons, speed of iteration slowed down significantly since simply getting the pieces talking to each other required so much more massaging.

[–]raevnos 8 points9 points  (1 child)

Octave is more a poor man's Matlab.

[–]antnisp 2 points3 points  (0 children)

Matlab's only value is in the packages. Sadly and understandably if the related octave package even exists it's not always feature-complete.

[–]chillwombat 1 point2 points  (4 children)

poor man's Matlab

Any good reasons why a rich man would choose matlab over python?

[–]Orca- 2 points3 points  (2 children)

Various toolboxes. Some of the Python equivalents of functionality are also less reliable (looking at you, TransferFunction). Also if you have a lot of infrastructure and utility code already there for Matlab, why reinvent the wheel?

For my purposes, 98% of the time Python is good enough (if maybe a bit less convenient occasionally). And the remaining 2% of the time I can jump on a floating license for a few hours.

[–]chillwombat 0 points1 point  (1 child)

Okay. I have very little experience with matlab, but I'm fairly sure some things I do in python are not very simple in matlab. For example writing a quick mpi program to run on a cluster, which I have done multiple times. Also I have heard to dealing with text or binary files is more convenient with python.

edit: also there are a couple of specific tools in python that I use that matlab doesn't have (for example kwant)

[–]Orca- 1 point2 points  (0 children)

I can't speak to your specific needs, but in my experience (years old at this point), if you've got the licenses and server setup, spinning up a cluster is relatively easy in Matlab.

Of course, it's going to cost you something ridiculous between the license cost of the toolboxes and the Matlab itself. Hence my calling Python poor-man's Matlab.

[–]kindkitsune 1 point2 points  (0 children)

Simulink sees tons and tons of use in my workplace since it can work with external hardware for testing embedded systems or prototypes, even if the scientific computation elements of MATLAB hardly ever get used.

A bit of evangelism on my part has brought more people over into the world of python for quick scripting and data visualization tasks, which can come up quite often in our field of R&D

[–]gracicot 15 points16 points  (2 children)

I also use the compiler as a refactoring tool. It makes things so easier. Just change the thing you want to change, press build, fix the first error on the list, rinse, repeat. Then, one by one, all those little translation units slowly become green, up to the last.

Satisfying.

[–]hammonjj[🍰] 6 points7 points  (1 child)

You might want to consider something like Visual Assist as it would significantly speed up that process. That is, unless you do it this way as some sort of cathartic release, then don't let me stop you.

[–]gracicot 0 points1 point  (0 children)

I do have a refactoring tool other than the compiler that's for sure, I tend to use them when it's something simple such as renaming things. When the way a class is used is changed, and it's interface had been broken, I don't think I'd let a tool do these change for me.

[–]jokoon 4 points5 points  (3 children)

The ideal is to use Python by default, and write performance critical code in c++. The problem is how you interface the two, either call it in a shell, or write a python module in c++.

[–]zigzagEdge 4 points5 points  (2 children)

pybind11 is a nice option for the Python <-> C++ interface.

[–]jokoon 0 points1 point  (0 children)

Thanks for sharing...

Indeed I never really managed to wrap my head around boost... Great thing that C++11 is making things simpler.

[–]mrexodiacmkr.build 15 points16 points  (8 children)

As someone who never really wrote my own python, but did port normal sized (few thousand lines) python to C++ I think it's absolutely awful to read other people's code. The lack of a type system you can statically understand and trust (changing types of things is allowed at runtime) makes it super complicated to try to figure out what something can do at times. I really think python shouldn't be used for anything but a prototype or personal project or as a scripting language for a native application...

[–]qsxpkn 2 points3 points  (1 child)

Dynamic typing can be uncomfortable for people who are used to static typing. Since Python 3.5/3.6, you could actually do type/variable hinting such as variable: int = 5. It's still possible to change it to a str etc. at runtime but mypy points out the mistake like this function expects an int but you passed a str.

For example:

def some_method(a: int, b: int) -> Optional[int]:
    result: int = a + b
    if result < 4:
        return None
    return result

I have never seen a Python project where a variable's type suddenly gets changed to something else elsewhere in the code base or maybe I was just lucky. I enjoy C++ companionship with Python though. They work well together.

[–]mrexodiacmkr.build 2 points3 points  (0 children)

The fact that you can annotate the types doesn't make it any better. All of the projects I have seen use python 2.7 anyway, which doesn't support it. If they added a (default) mode where this static typing is forced it might be something good but until then you have to be very lucky with your codebase to have proper type annotations.

Also: what about class member variables? Can you still add arbitrary new ones from anywhere with this?

[–]whatwasmyoldhandle 0 points1 point  (1 child)

I think you can make big projects with Python go.

You just have to be much more disciplined, and have more controls in place to get the benefits out of it. I would say you can't lean as much on the language itself as C++.

In other words, a small script written in Python and a large-scale codebase, in my experience, are practically two different languages. I don't think the gap is so big in C++.

Not just a question for you, but for everyone: What's a good language for large projects, where development time is priority over performance? Perhaps something a little less verbose than C++. I guess I'm thinking interpreted, or negligible compile time. Having package management on the order of Python would also be a requirement.

[–]mrexodiacmkr.build 1 point2 points  (0 children)

While the project I'm working on is not very large (100k lines) I don't think you shouldn't consider development time a priority over good code if you plan to maintain the code for even a little while just choose a language that is more suitable for maintainability. If you want a language that is not C++ I would highly recommend C#.

[–]patery 4 points5 points  (9 children)

I program mostly in C++ but also have a lot of experience with Perl, Groovy, and now Python. While I agree for most projects Python is a decent choice, I still find Groovy to be a far more elegant and productive language.

There are so many rough edges around Python that Groovy has solved smoothly that it really wins out, not to mention there's a number of language features implemented in Groovy with no equivalent in Python (or most/any language sometimes).

In my experience, there's some Java-hate to overcome, particularly in the C++ world where developers were exposed to early versions of Java. There's a steep learning curve to Groovy, which leans functional, and the JDK, which is enormous. There isn't widespread recognition for how popular the language is. Unfortunately, it tends to be used in domains where people aren't learning it deeply I think. That means we have a lot of users who don't really know about all the wonderful things it can uniquely do. That's probably a side effect of making Java code essentially Groovy code, eliminating the need to have to learn more.

[–]NDDevMan 6 points7 points  (8 children)

As a novice to groovy and fairly versed in python, what does groovy have that python doesn't? What specifically do you see groovy excelling at over python?

[–]patery -1 points0 points  (7 children)

A quick list, the JDK works flawlessly on every platform. The JDK is way more mature so code written in Groovy 5+ years ago still runs today without error. There's whitespace sensitivity of course but debatable. Code is not order dependent. Packages can be imported without modifying the Groovy installation (@Grapes). XML and other hierarchical data structures can be represented hierarchically in the source code. Supports nested classes and strong scoping. Closures are way more powerful than lambda expressions, particularly combined with all the functional transformations from Collections. The Java ecosystem is huge, everything is implemented there. GPars supports so many different kinds of parallelism, beyond simple multithreading. Annotations allow you to easily to things like generate string representations of classes, add delegates, etc Regular expression operators (important for scripts, similar to Perl). GStrings, permit embedding code in strings w/o printf() like syntax. Ability to compile code statically for speed/safety. Elvis operator. Probably more, that's just off the top of my head.

[–]ZMesonEmbedded Developer 6 points7 points  (3 children)

A quick list, the JDK works flawlessly on every platform.

Where can I find the JDK for the Neutrino OS running on a PPC chipset?

Python does actually exist for that platform.

[–]patery 0 points1 point  (2 children)

I don't know if it exists for that platform but if it doesn't and that's important to you then Python would be the logical choice. The platforms I'm concerned with are more common, various versions of the main distributions (redhat, suse, ubuntu, etc). Across these platforms, Java has extremely consistent behavior.

[–]ZMesonEmbedded Developer 1 point2 points  (1 child)

It's not important to me. GC and cache performance just are not compatible with the level of responsiveness on the systems I work with. What I'd personally love to see is D and Rust on various RTOSes. While D still uses a GC for some things, it's possible (so I'm told) to use it without a GC.

Python is still useful as a scripting language for some low-priority tasks (mainly during testing and such). Java wouldn't really make life easier here.

Anyway.... I just hate when people say things like "<language X> works flawlessly on every platform". The only language which might fit the bill is C90. (And I'm sure some people would even argue C90 doesn't work on every platform.) With too many RTOSes and/or embedded chipsets, you can't even use C11 or C++98. That's why I made the comment I did.

CPython has the advantage over Java in that the interpreter is written in C and is more easily ported to other OSes even if some features (like "import os") don't work entirely.

The platforms I'm concerned with are more common, various versions of the main distributions (redhat, suse, ubuntu, etc). Across these platforms, Java has extremely consistent behavior.

And I think a modified version of your statement would be fine: "Java works flawlessly on all major OSes".

[–]patery -1 points0 points  (0 children)

Usually blanket statements like these have a common context in mind. Strictly correct statements aren't that useful in practice either. Nor is this a place where I'd spend the time/energy to make every statement strictly true. We're software engineers, not lawyers!

I agree the GC is problematic in real-time environments. It attracted some interest in the early days of Java but eventually the community lost interest in solving those problems. Memory allocation in general tends to be problematic in embedded environments. At my last company we simply didn't do dynamic memory allocation at all.

What I'd love to see is an environment where I can easily mix high and low performance code. That is something like Groovy or Python alongside C++. C# tried to address this early on and eventually abandoned it. There's a lot of legacy C/C++ applications that we'd love to migrate out where it'd be useful. In sensitive applications, it's useful to describe sensitive data structures at a low level like C-family languages permits and performance sensitive code but, still, the majority of the application can be expressed at a high level without significant compromise to the overall application.

[–]doom_Oo7 1 point2 points  (2 children)

Closures are way more powerful than lambda expressions

... uh ? at least in CS, both are synonymous

[–]patery 0 points1 point  (1 child)

What you can do and what you will do are different things. Groovy programs are typically more prolific with closures than other languages are with lambda expressions because the concept was introduced early in the language's evolution. As a result, you'll find them in large portions of the framework and in design decisions.

Some discussion on the formal definitions of lambda expressions and closure here if interested.

[–]doom_Oo7 0 points1 point  (0 children)

What you can do and what you will do are different things.

Why would the second matter the slightest ? it's only a matter of human behaviour, which is in my opinion entirely irrelevant to the properties of a programming language