Python, as Reviewed by a C++ Programmer
sgh1.net
sgh1.net
Several years ago I remember someone who (perhaps unwisely) wrote a C++ function with many floating-point values as parameters and a single default "bool". At some point the function was extended to have another float. The compiler did not catch calling code that failed to add an extra float; it simply allowed the formerly-flag arguments to be assigned to the new float argument instead. In fact, implicit conversion of parameters is such a common C++ problem that I occasionally define wrapping types for the sole purpose of being parameter types: then the compiler has to trip over them when they are used incorrectly and callers have to do some kind of explicit action to indicate what their values really are.
It is possible to add annotations to your code like
class Foo:
x: int
# ...
and then run type checks using `mypy`, so that for the annotated code probability of the "passes the checks => won't crash the runtime" case is much larger.So this might be helpful for code you wrote, but not anywhere it interfaces with other peoples' code (which, in my opinion, is probably the most important place to check for type errors).
IDEs like PyCharm can use those and other methods to find most typing issues. In practice this is very effective for most "boring" Python code, but if you get really clever it falls over completely.
from typing import Dict
Foo = Dict[int:str]
def __init__(self, name:str, balance=0.0):
"""Construct a Klass."""
self.myfoos = {} # type: Foo
I _think_ that's right... close anywayThe article wouldn't have been much different had it been C++ vs Ruby/Perl/etc.
On any given day, I poop you not, I'm writing either c#, java, c++ or any number of scrpting languages (perl, bash, python, JavaScript).
Do people seriously only use a single language these days!?
Yes. In what bizarro world would one assume it's not so? By thinking that all development in the world resembles the company/work they do?
Tons of programmers only write C# or Java on Windows, and don't touch any shell scripting at all.
Tons of front-end developers only write Javascript.
Tons of statistics people only use R or 1-2 other statistics packages.
Tons of systems, drivers, embedded and OS people only C or C++.
Tons of game devs only write C++.
Tons of native mobile devs only write Swift, Objective-C or Java.
Some of them do occasional need to write some script to get something done, but it's hardly like the juggle between multiple languages.
And of course larger companies have specialized programmers for different domains, not some guy doing C++ AND admin stuff in shell AND some front-end JS etc.
- Apple's Swift codebase is 54.8% c++ [0]
- Microsoft's CNTK codebase is 57.6% c++ [1]
- Bitcoin's codebase is 68.6% c++[2]
- XBMC's codebase is 84.7% c++[3]
If you work on certain or specific types of projects, like ones making the tools that others use do their projects, then you are typically working more in only 1-2 languages at a time.
[0] https://github.com/apple/swift
[1] https://github.com/Microsoft/CNTK
Their primary code base is written in Java, monitoring scripts in Python/Ruby, and tracking pixel code in JavaScript, so I would have days in which I coded in all 3, albeit for separate use-cases.
It's happening enough that there has been a series of popular conferences for it, PyHPC http://www.dlr.de/sc/desktopdefault.aspx/tabid-11992/21071_r...
Then, some systems cannot afford to have garbage collection, because it usually runs in an unpredictable amount of time. Such systems are for example real-time systems. In those cases a language like C++ is a good fit.
It's really okay to have a future where C++ and Rust are both popular, widely used languages. I'm happy to acknowledge the merits of Rust as a language and even talk about them without inserting it into every conversation about low-level computing.
I'm sure the language designers and core developers don't actively endorse this behavior, but somewhere along the way it became a core part of the culture. This world domination shit has to stop.
That said, while it might be annoying to serious c programmers, they aren't really the intended audience. It's new programmers that matter. Or people who bounce between languages anyway.
Instant classic
What I do know is that a) it's hilariously on point b) Google search now autocompletes on it for me.
It's... harder/less-defensible to enforce codes of conduct/rules like these in third-party spaces, but Rust people still do often call out incorrect assertions/ridiculous comments. Someone not familiar with the community may not recognise that the people doing the calling out are actually "prominent" voices.
My view is that Rust risks a similar track as Haskell if the community continues to grow in the way it has recently. It's not a healthy community, outside of the circles you note. Quite the opposite--I view it rather as being fairly toxic.
I want rust to take off, as even bounds checking at compile time would save me a lot of trouble.
I don't know if I'll ever be able to deal with the community, though.
On the other hand, I've never seen people get as passionate about c++ as I have python and rust, so maybe that says something about the benefits, even if its just as beginners see them.
That said for all my personal/greenfield stuff I've been using Rust and really happy with it.
That said I get your point about using the debugger less.
That says more about the particular programs you write than about the language, frankly. Writing trivial bug-free programs is easy in any language. The trick is writing complex bug-free programs.
> println debugging
This is something you should only need to do if you have a wretched debugger of if you're working on a bug where the presence of the debugger alters its behavior.
Not really. Writing programs which don't crash the first few times I run them in a dynamic language is surprisingly hard. Just having a compiler prevents having to get to that point - and then Rust ensures that I handle potential errors correctly and avoid segfaults.
> This is something you should only need to do if you have a wretched debugger of if you're working on a bug where the presence of the debugger alters its behavior.
Or if I can't be arsed configuring gdb with breakpoints for everything from the command line. I can add a println!(), save my file, and watchman will recompile and run my program in a much more reasonable (to me) workflow. I assume that I can somehow integrate gdb into my editor, but that involves a pile of learning new things.
For a so-called "trivial" app I'm most of the way through writing right now, is an OpenID Connect and SCIM server that has had to implement a decent chunk of functionality (JWTs, key fetching and caching, juggling between postgres and redis, etc) from scratch. But for most of the particularly fiddly parts, I've managed to have the type system ensure that I either outright can't have logic errors or they're detected and the program panics, which is rather nice.
Writing correct programs in JS is difficult, I agree. Writing correct trivial programs is easy, though.
> Or if I can't be arsed configuring gdb with breakpoints for everything from the command line. I can add a println!(), save my file, and watchman will recompile and run my program in a much more reasonable (to me) workflow. I assume that I can somehow integrate gdb into my editor, but that involves a pile of learning new things.
That's not a third alternative, that's just gdb being wretched, as it's always been.
1. "Call/pass by XXX" terminology usually refers to language semantics, not underlying implementation details. In that respect, the call-stack mechanism is largely orthogonal here.
2. According to this oft-cited article (in the context of Java), passing an address under the hood is not sufficient to make a language call-by-reference. http://javadude.com/articles/passbyvalue.htm - AFAIK Python would "fail" the "Litmus test".
(EDIT - clarify what's not call-by-ref)
Dog toby = new Dog("Toby");
public static void replaceDogWithToby ( Dog d )
{
d = toby;
}
public static void main ( String[] args )
{
Dog d = new Dog("Lassie");
replaceDogWithToby(d);
System.out.println(d);
}
In Pascal, this will print Toby: var
toby:tDog;
procedure replaceDogWithToby ( var d:tDog );
begin
d := toby;
end;
var
lassie:tDog;
begin
{code to initialize toby and lassie here}
d := lassie;
replaceDogWithToby(d);
writeln(getDogName(d));
end.
The first is call by object (or call by sharing, in my book). The second is call by reference. The behavior is totally different.Usually there is one global hash-table, and a local hash table. Everything (every function, every object, every string is stored once, depending on the calling situation. So passing a reference to a object is passing the reference to that one global object, until you change it, or make a local copy of it. That sounds really strange and in a way is it. It also means, that your list of objects, will not contain duplicates. It means no useless work is done to copy data.
The model involved borrows basically from the concept of lazy loading and flat copys. Do work only when needed. Super difficult to explain to new users without CS background.
Python uses references implicitly without ever defining the term, so it's essential to talk about the high level semantics in this case. A Python reference (implied) differs greatly from a C++ reference in that it can be rebound with the assignment operator. If you're thinking about references in C++ terms then Python will confuse you. It's important to call out the differences.