Armin's Flask was probably best experience I've ever had with a piece of software. Clean, modular, pragmatic and very well documented. I only stopped using because "websockets, Go, SPA", though I never really finished a side project with those yet.
I can't think of a single WTF moment I had with it. Several "OMG this guy thought about this too" moments.
I used Falcon for a relatively large project and enjoyed using it. It is noticeably faster than Flask and I can write code faster as well. It is very much still growing and features are being added. They call Flask "Batteries not included" but Falcon takes that to another level. There are also not very many extensions in comparison to Flask. If you are writing an API exclusively, I would choose Falcon. However, if you have any HTML/CSS/JS, Falcon is probably not suited for the project.
Flask is an awesome framework. I've used a little bit of Tornado and Django for side projects, but found how overkill those were (at least for my small use cases) as soon as I got into Flask.
Flask made a number of really questionable decisions that are not visible to someone who just followed a tutorial to make a simple app. "g" is a horrible thing that doesn't exist in other frameworks for a reason.
If you started out parodying something else you didn't like, and ended up completely emulating its interface, it means that you were either wrong earlier or you were wrong later.
Maybe he will do better things in Rust, but Flask has been heavily overrated since it came out.
I've built a number of more complex applications via Flask, and I'd love for you to elaborate more on some of the deficiencies of Flask, or provide links.
I ask not because I want to be snarky, but because I don't have the breadth of experience to identify any of the deficiencies in the Flask design. I'm curious to learn more.
Nice writeup! One thing though, I believe Rust's BTreeMap [1] is a B-Tree (not a binary tree, as suggested), i.e. it's a tree whose branch factor is generally greater than 2.
The docs say that if you don't give a branch factor, a sensible choice is made for you, probably to get nodes to fit neatly into cache lines, so seeing as we are storing 35 unsigned 64 bit integers, this would be around 16 or 32 elements in a single node, and a depth of about 2. This means that, because the current implementation of BTreeMap does linear searches at
insertion, for this particular use case, the BTreeMap isn't doing much better than a plain old array, that you are insertion sorting.
TL;DR: Storing the results in a vector and then in-placing sorting it could be faster, but not noticeably. I know this isn't the point of the article, but it was just an observation I had :)
I honestly respect the power and rapid development of Rust but I think that Nim (http://nim-lang.org) is a much better alternative to Python than Rust, as its syntax and "feeling" is much closer to Python, and also the productivity level. In Nim I get things done much faster than in Rust. Nim is easy to learn but Rust requires a certain amount of knowledge and experience for good productivity.
I consider Nim the "better Python", and Rust the "better C++".
Rust's goal is to be memory safe and high level without depending on a garbage collector, which is very important for many problems. That Rust is comparable with high level languages is a big accomplishment, as nobody compares C++ with these languages.
Nim does not have the same goals. Which IMHO makes it a lot less interesting, because if you're allowed a garbage collector, then you can talk about Java / the JVM, .NET, Haskell, Ocaml, Erlang, Go and the list can continue.
Expanding on that, I'd say that Nim is a "better" [1] Python [2], Rust is a better C, and D is a better C++.
[1] For some purposes. As a long-time Pythonista, I've looked at Nim, and I have no desire to replace Python with Nim in my daily use. But my uses for Python aren't the same as everyone else's, and Nim looks like it could be a fun language to play around with and learn, at least.
[2] Even more accurate, Nim is a better Object Pascal.
Rust is a better C++ more than a better C, it has similar goals to C++ of advanced zero-cost (at runtime) abstractions, not so much of being a portable assembly. Like C++ it can be an alternative to C in some contexts.
D intended to be a better C++, but that hasn't panned out well in practice for various reasons (one of them being the use of a GC and much of the standard library depending on it, though IIRC they're trying to fix that).
I wouldn't say Rust is an alternative to Python. But if you want to learn Rust, and you already know Python, that's the demographic this article serves.
On a completely unrelated thought, the second I saw the first three words of your paragraph, I thought of the infamous Kanye's interrupt. Not that I agree/disagree with your statement.
That was a really interesting introduction. I hadn't looked at Rust before and that gave me a good feel for it. Thanks for putting it together, Armin.
A minor peeve of mine is examples between languages that differ in ways that are unimportant (though maybe it can just justified as "idiomatic code"). It adds bias to the demonstration.
We could have written the python one like the following to wrap the lock up with the results structure (and get the automatic sorting behaviour, too):
import queue
from threading import Thread
def fib(num):
return 1 if num < 2 else fib(num - 2) + fib(num - 1)
def thread_prog(results, i):
rv = fib(i)
results.put((i, rv))
def main():
results = queue.PriorityQueue()
threads = [Thread(target=thread_prog, args=(results, i)) for i in range(35)]
[t.start() for t in threads]
[t.join() for t in threads]
while not results.empty():
i, rv = results.get()
print("fib({}) = {}".format(i, rv))
Though, I've also taken other liberties to make it shorter. I normally stay away from threading in python because the GIL makes it a bit of a waste of time in most cases, and who needs the complexity in their lives?
Consider that such examples are often not about convincing, but teaching. That is, they often not trying to convince the reader, "Language X is better than language Y." Rather, the intent is more, "You already know language X, so here's some code in X. Now here's how you would do the same thing in Y." It's a pedagogical tool, rather than an argument tactic.
You can also use a locked data structure in Rust. This was to show how to actually use mutexes. In theory (assuming a Python with GIL or locked dicts) you can get rid of the mutex as well. But this only works for such a simple example in any case.
The mutex generally works and was meant to show the relationship of the borrow checker and the mutability system to the mutex that moves checks to runtime.
Ok cool, I figured that was the case. I mostly sat down to write out the example to humour myself during my lunch break (as I said, I don't do much with threads so wanted to make sure I understood what was going on).
The ownership/borrowing system is really interesting, not something I'd seen before - though I guess other languages do it too?
Ownership/borrowing enforced at compile time doesn't exist in any other (practical) language. Though C++ has some runtime support for it and in C you would/should do it by convention.
Believe it or not, it's the first time I've used a list comprehension for execution like that (other than when working interactively in ipython)! Originally I had a comment about how it was a non-idiomatic thing to do, but I deleted it.
What's strange is that I didn't even consider writing the for loop on a single line. I just never do that. It's clearly better in this case (than a list comprehension). In real code I'd just do it on 2 lines.
Yeah, I also found weird that he'd check the type of the addend in the adding example, he just talked about protocols, and that negates their use, and instead forces inheritance.
> In Python a function can fail with any error and there is nothing you can do about that.
To be fair, the adorable `except:` black magic exists there to be used in such a case. Of course its use is extremely dangerous for obvious reasons (it even catches the `SystemExit` exception!), so I can understand why the author didn't mention this.
> This is a big change in how you think about programs but you will get used to it.
Possibly! But I have a feeling that the ownership model would be the biggest blocker to newcomers, as well as the largest innovation Rust brought to the mainstream languages. I can already hear the crowd saying Rust's just a giant mess, after struggling with the borrow checker. This may impact the success of the language. Now that Rust is post-1.0, we will see.
> the constant encoding and decoding you have to deal with in Python just to support O(1) string indexing.
Strictly speaking, Python also doesn't support a complete character indexing, because it works on code point basis. O(1) string indexing is largely a myth.[1] But I'm sure that the author definitely knows about this, considering his previous rants on Python's Unicode handling. ;)
Regarding Unicode handling, I think Swift's `String` type is arguably more complete than Rust or Python. Its internal representation is UTF-16, possibly due to the interoperability concerns with `NSString`, so it can't compete with Rust on the performance aspect. However, it indexes a string by grapheme cluster (so Swift's `Character` type is actually a slice, not an integer) and compares the characters by their normalized forms, which eliminates many mistakes that can be made by careless programmers, including me. Of course the same thing can be done in other languages using external libraries, but the official support residing in the built-in string type is very nice to have.
> To be fair, the adorable `except:` black magic exists there to be used in such a case. Of course its use is extremely dangerous for obvious reasons (it even catches the `SystemExit` exception!)
And KeyboardException. Which is why it's very strongly recommended to never write bare excepts in Python (unless you're going to rethrow immediately and just want to cleanup or log on exception), and always `except Exception` at least.
> Regarding Unicode handling, I think Swift's `String` type is arguably more complete than Rust or Python.
Very likely considering it inherits Apple's concern for internationalisation, Objective-C was one of the very few languages which exposed relatively easy grapheme cluster level manipulations. I believe Rust's string mostly tries to provide a sensible interface, not a complete one, which is why you can iterate on bytes and codepoints (decoded on the fly) but more complex unicode operations tend to be left to external libraries. Whether that's a good idea is debatable, on the one hand implementing fully unicode aware strings would make that part of the standard library much more complex and bigger, on the other hand not doing so means you still get mostly broken strings when it comes to end-user output.
>To be fair, the adorable `except:` black magic exists there to be used in such a case. Of course its use is extremely dangerous for obvious reasons (it even catches the `SystemExit` exception!), so I can understand why the author didn't mention this.
This is why you use "except Exception:" which doesn't catch system exceptions.
I think the point was (and I'm extrapolating here) that `except:` exists at all, and doesn't require any special foresight to use. That compared to Rust, which thinks about safety first.
"except Exception:" is rarely what you want IMO. It also catches SyntaxError, which is almost always a design error -- one you'd typically prefer would halt the system.
Unfortunately there's no common parent to EnvironmentError/SystemError/RuntimeError/etc that excludes SyntaxError.
SyntaxError can happen as a consequence of loading a module (hitting an import statement, etc). But for a simpler example, replace SyntaxError with NameError and it's still almost always a design error that you probably have no sane way to handle in an exception handler (other than to mask the problem).
Python's a very dynamic language and so of course you could come up with examples to the contrary (ones where the user input could trigger SyntaxError or NameError).
But the only universally good reason I know of where you should be wrapping imports in try except is 2/3 compatibility or other module/library import fallback. For these you need to be catching syntaxerror and other system errors.
Oh, I'm fairly sure my unholy abuse of decorators and dynamic __import__() trumps any time I've ever used a bare 'except:' in the past (and I think I got rid of all my old bare 'except:'s during a code cleanup anyway).
A quick question from a Rust noob: if I knew Python, why should I try Rust? What is in there that would make my life better? At first glance I see a lot of unimportant syntactic sugar or concepts I am not sure would make my life any easier (ownership tracking vs garbage collection).
As a current python & rust user, I can say that I picked up rust because I liked the idea of a systems language that could give me c-like performance, without having to use C. Rust seems, to me, like a combination of the best parts of python (traits as pseudo-duck-typing), haskell (type inference, functional concepts), and C(++) (speed, no GC).
As @mitsuhiko says in the article, it is very easy to export symbols from a Rust library so that they can be used via CFFI, so the possibility of "dropping down to Rust" instead of "dropping down to C" is very attractive to me.
I keep on messing around with Julia, but I never stick with it. I have nothing in particular against the language, but I don't do a lot of scientific computing, so my motivations to use it are not that great.
It can. However, Julia made a very strong push to target the scientific computing niche (very strong array support, ease of writing tight loops in native code, etc) - and such it has a very quickly growing ecosystem of high quality scientific packages.
In comparison, Julia has relatively few web frameworks, GUI toolkits, etc..
Sure it can. But why would I pick it up over, say, rust? Rust gives me the productivity of a dynamic language, and the speed of a systems language. Julia gives the same. So, given similar pros/cons, the choice comes down to aethsetics, and Julia just didn't give me a compelling enough reason to switch.
I think Julia gets unfairly pigeonholed. It's got a great concurrency story, for example. I know what you mean though, it always seems to be the language I'll write my "next" project in.
I've been able to call into the Nim side from Python by treating the Nim code as C functions to call. That works, but it would be interesting to come up with a more Pythonic way of doing that.
Nim requires a runtime to operate. Figuring out how to safely share the runtime between different Python extensions requires the cooperation of all of those extensions. You probably also need to move all nim code into a thread.
Just a guess, but it is probably because they each have their own GCs, and that makes it harder* to ensure that objects created in language A, from language B, haven't been collected when language B needs them again.
So there probably aren't many circumstances where you would be choosing between one and the other, but one reason you might want to keep your eye on Rust is for extension-writing. The traditional approach to dealing with stuff that needs to be fast in Python is to get it working in pure Python first, optimize as best you can, and if it's still not fast enough, profile to identify your hot loops and rewrite those bits in C as an extension. This is somewhat less necessary in the era of PyPy, but still a common way to think about things.
To me, at least, Rust provides a compelling alternative to C in the Python+C combination. Coming from Python, writing C is pretty unergonomic; it's super-easy to shoot yourself in the foot and have your program die with an inexplicable segfault, which feels pretty alien for someone used to nice pretty stack traces. Rust promises to make that a lot more pleasant by being memory-safe, while still making good performance promises.
A great writeup! A lot of the Rust community seems to have come from the Ruby side of things (with writings such as "Rust for Rubyists" by Steve Klabnik), although I feel that Rust and Python share many ideas that Ruby does not concern itself with.
I particularly like the section about string handling. There is a reason that Rust strings are hard, and I will make sure to point to that section whenever mentioned.
Throughout my experiences with both Python and Rust, I am able to use the same ideas to accomplish tasks. The Zen of Python fits both languages in my opinion also.
I think that they are both very pragmatic languages, they are not trying to be expressive in the way that Ruby does, or try to write the coolest one liner, writing Rust or Python is about writing good code.
At least in my opinion. I think both languages complement each other extremely well, and I hope to see more of the two of them meshing in the future.
Im not sure if I actually said anything here... sorry im tired. What I meant to say is that I feel that idiomatic Python can look a lot like idiomatic Rust, and that they can complement each other in code by using Rust instead of C.
Between Rust and Go (for Pythonistas) I still prefer Rust.
One thing that bothers me in Go is that, like Ruby, when you import something you don't know exactly what's being injected in the context. So it's quite bad to understand from where some things came from. I like more the Python / Rust approach for that.
Maybe it's just because Go has Google backing it, but I seem to hear way more about Go than I do about Rust. I have my doubts about whether Rust will have a viable ecosystem in 4-5 years. It's a shame because Rust seems like a more interesting language to me.
Rust is currently backed by Mozilla, Samsung, and an expanding coalition of startups. There are other large companies experimenting with Rust at the moment, but I'd rather wait for them to come out with their own announcements. The community is hugely active and growing at an increasing rate. There are four Rust books in the publishing pipeline and Rust's first conference will be held this year, with at least two conferences already planning for next year. I wouldn't worry about the state of Rust's ecosystem in five years. :)
It might also have something to do with the fact that Go has been out for five years and Rust 1.0 happened two weeks ago, or the fact that you are hearing about Go in different contexts from Rust because the two languages, despite HN's insistence to the contrary, aren't really appropriate for the same use cases.
Are there any good articles comparing the two? What are some contexts where one might be more appropriate than the other? I know Go's special focus is on concurrency. Is Rust less-good for concurrent applications?
Rust is best viewed as a replacement for C++ in performance-critical, security-critical applications that are either resource-intensive, or exist in a resource-starved environment. In particular, it eschews garbage collection while preserving memory safety, even in the presence of multiple threads, something C++ does not. It also has native, overhead-free FFI-level compatibility with C. An example of where Rust is appropriate would be an operating system kernel, a video game, a web browser (writing one, not writing code that runs within one), embedded development, a high-performance database (there aren't any existing examples yet but it strikes me as an ideal language for this purpose), or fast, native extensions to applications written in higher level languages.
Go is a relatively fast, ahead-of-time compiled, garbage-collected language; a good comparable for when you might want to use it would be OCaml (if you don't need threads) or Haskell (if you do). Java (particularly early versions of Java) or C# would also be a good comparable, in circumstances where you don't care about the JIT. Like Haskell, Go also has very good support for M:N threads, a particular threading model optimized for fast context switching and programmer ease of use (a common requirement for socket web servers). Unlike many ahead-of-time compiled languages, it also has compiler performance as an overriding concern--Go prides itself on its quick compilation.
I would not say Go is better than Rust at concurrency. While Rust used to have M:N threads as well, it abandoned them because they turned out to have unacceptable performance tradeoffs in a language without a heavy runtime and garbage collector, and also play poorly with native code not managed by the runtime. Personally, I also feel that safe concurrency is considerably easier in Rust, where common Go idioms like channels are guaranteed to be memory safe, which they are not in Go with GOMAXPROCS > 1, and where it's impossible to see data races through things like mutexes or lockless data parallel threads in safe code.
The reason to use Go over Rust would be that you can afford a garbage collector and a relatively heavy runtime, and are willing to accept some chance of data races (or don't require concurrency at all, or have a particular concurrent application where by far your biggest cost is context switching and you do very little allocation). This is the case for a large percentage of applications. Of course, there are many other languages available under these circumstances as well. I am not personally sure why people are espousing Rust for these applications, FWIW.
Rust is newer, but Go is also more relevant to the crowd here.
Most people writing web apps don't need a language where you have to worry about ownership, but they do need a language that does concurrency really well. It's the same reason you hear more about Python or Ruby than C++ here. Use cases.
Even as Rust matures, it is unlikely that people will be writing a lot of web apps in it.
Can someone explain why the parent was downvoted? Difference of opinion or is there actual reasoning. Because if there is reasoning, I'd be interested to hear it. But this seems like shaming. Stop. Or explain why he's wrong.
Other than the "Go is more relevant to the crowd here" which is a bit overarching, I don't see what's wrong here.
I'm a Python user that has my eye on Go instead of transitioning to Python3, but letting Rust/Go/Py3 all bake for a bit before doing anything (though Py3 is last on that list as I've lost faith in it at this point). I tend to agree with his viewpoint. Do go on.
I'm not sure if this is the reason, but I have noticed that there is a definite backlash against Go here and on /r/programming, especially when discussed in relation to "better" languages like Haskell and Rust.
Nothing gets imported into the namespace when you import a package in go, except a reference to the package itself. The only way to pollute the namespace is to use import "foo" . which is strongly discouraged.
I only do data analysis but cython [0] is pretty much the fastest way for me to produce fast code. I tried to do some things in Rust but my productivity fell, and I could not figure out how to fix some error messages.
[0] https://honnibal.wordpress.com/2014/10/21/writing-c-in-cytho...
I use cython extensively in my work and it's super productive for me as well, but I could see maybe toying with Rust more in the future for some really specialized things.
It makes sense if you remove "where a character"... Or change it to "where a character is a Unicode codepoint".
This is basically saying Python uses a fixed-length encoding (UTF-32) where each codepoint takes constant storage, as opposed to UTF-8 where the storage of a character depends on where it is in the Unicode plane. A useful analog, if you know C, is that Python always uses wchar_t[] where each element is a character, while rust uses char[] and then the elements are not characters but UTF-8 bytes.
There are obvious up- and downsides to both approaches.
EDIT: As suggested by two children, with Python 3.3+, the fixed-length encoding Python uses depends on the highest codepoint in the string and is often not UTF-32. With earlier versions there are "narrow" and "wide" builds which use UTF-16 and UTF-32 respectively.
On Python 2.2 through 3.2, CPython could be compiled with "narrow" or "wide" Unicode strings. On a "narrow" build, Unicode strings internally were represented using two-byte characters and surrogate pairs. On a "wide" build, Unicode strings were represented internally using four-byte characters.
On Python 3.3+, the distinction is gone, and Python uses either latin-1, UCS-2 or UCS-4 depending on the highest codepoint in the string (i.e., a string containing only codepoints in latin-1 will be stored internally as latin-1; a string containing at least one codepoint outside the BMP will be stored internally as UCS-4, etc.).
I think it's that python has become a pretty big lingua franca of the programming world - so it makes sense that a lot of tutorials relate other languages to the one tons of people know already.
IMHO they are just catchy titles to grab readers. As an example in the last sentence the author states: "I don't think there is a direct relationship between Python and Rust." That's a fair conclusion as TL; DR;
I've switched from Python to Elixir. Python was my favorite language. I fell in love with functional programming after trying out Scala and spent a fair amount of time after trying out different languages to see which one was a good fit for me. Elixir is that language for me. When I start talking about it I seem to go on and on so I'll stop there.
I'm also a fan of rust and plan to use it for more system level programming as well. I think its going to open the door to systems programming for more people and I'm excited to see what comes out of it. Also, as someone who has done a fair bit of C/C++, I'm happy to see an alternative.
Yes. I think Ruby is losing popularity or already has long ago, my guess is a lot of those guys moved to Go or JS on Node.
Python isn't really losing popularity, it's probably gaining as many users as it's losing right now. It's just that a lot of people including myself are completely turned off by Python3, so if we're going to break our old code and take on a ton of testing- may as well do rewrites in a new, potentially better language/platform.
For me, Go has problems (as Python does) but thus far I find it the most appealing of all choices. I tend to be attracted to simpler things (worse is better).
I think it's more that many language designers and/or fans don't really understand why Python is so popular, and therefore think the Python ecosystem is an easy ecosystem to draw developers from.
It isn't that there is a trend away from Python, it's that languages that are not yet very popular want to lure away some of Python's audience to augment their own.
I think it's just a generic "new language guide for the exact target audience", which, realistically, anyone who knows a current language will be able to follow.
This is a very common question, and there's two camps:
1. Learn C, then learn some C++. You won't appreciate Rust until you've felt the pain that it solves.
2. Learn Rust. Why bother going through all that trouble on your own when you can have the compiler help guide you.
and a third position:
3. Rust is still new enough that you'll find way more information with C, so you should just learn that even if Rust is better in a vacuum. Learning is easier with copious help and tutorials.
Thanks for the reply. I'm leaning towards Rust. I'm required to learn C for university next year (I do physics) so I'm going to have to go through the pain anyway. There's also the quwation of usage in physics circles.
It'll probably come down to the material I'm trying to learn each with. The Rust book looks very good, finding anything decent and modernish for C has been a nightmare.
This is a nice summary! FWIW I'm more likely 1, as I've seen many people coming from dynamic languages being frustrated about the "Rust way". Not only the ownership model, but also compiling, optimization, etc.
3 is certainly a problem, but personally I found enough materials to learn Rust even for now. However more "friendly" resources would be definitely welcome.
While I'm new to rust, and have just been dabbling in C -- as another comment mentions here: you really have to deal with the borrowing in C as well (and the compiling/optimization). If you don't deal with in C (without any real language support) -- you'll get bugs. If you're very lucky, and made a great effort in turning on warnings[1] -- you'll be aware of those bugs. Most likely you won't.
I'm in the same boat as you. I've been working through Learn C The Hard Way [1] as a way to learn some of these concepts. I've been finding it incredibly valuable/rewarding.
That said, even the author of LCTHW (Zed Shaw) recommends writing in languages other than C. He specifically mentions Go, Swift, and Rust.
Weird rant. C is not dead, especially not for really low level high performance things. But Go/Rust/Swift are more modern and easier to use for some of C and many of C++ use cases.
You already have a lot of good answers, here's some more:
C and C++ really isn't the same thing. Certainly not "modern" C++.
Unless you know of any C++ projects/frameworks/libraries you really want
to use/contribute to -- I don't think I would recommend looking to hard
at C++. It certainly isn't a dead language, and has many uses -- but at
least outside of the gaming industry, I can't think of any segment were
C++ would be the preferred language -- except when dealing with legacy
code (which of course, realistically is the biggest segment...).
Perhaps C++ paired with qt for GUI programming.
But even for games, you don't need C++ -- if you are free to start
from scratch anything will work.
> is Rust a decent place for me to learn lower-level concepts
Which lower level concepts?
C maps quite neatly to assembler -- but to appreciate that I'd recommend
learning a bit of assembler. amd64 with nasm/intel syntax is rather
pleasant[1]. It'll let you see what calling conventions/ffi, data layout
and the difference between c-strings and pascal strings are all about.
If you take a canonical hello-world from C, C++ and rust and look at the
generated assembly -- rust and c++ will be (IMNHO) closer to each other
than to C. The assembler generated by the c-compiler will be straight
forward, and quite readable -- while both C++ and rust will look a
little more convoluted. (This is also true for Nim, which compiles to C
-- but needs it's own runtime. I've not looked too hard at code
generated by go -- but given the runtime, I think that assembly would
also be much more difficult to make heads and tails of, than something
output by a C compiler).
If your goal is more to learn a low-overhead compiled language, I would
recommend rust. If your goal is to find a compiled language that is easy
to integrate with others, I think I would recommend C (for now) -- and a
bit of basic assembler.
I think after learning a bit of assembler and C -- one also gets a
better appreciation for why Pascal was so popular for a while.
With any luck, and more work -- hopefully rust will be able to sneak
into quite a few of Cs use-cases, like writing libraries for easy
consuption by python/ruby/etc. But I don't think rust is quite at a
place where it makes sense to reccomend it for that use-case to a novice
(low-level) programmer. I'd love to be wrong about that.
[1] Unfortunately, I don't really know of any good introductions to
amd64 assembly. There are a couple of great tutorials for 32bit/x86 --
but a lot of things are simpler in our amd64 world. While it might be
good to know how to write bootloaders (16bit) and 32bit code -- I'd love
for there to be a simple tutorial focused on just amd64.
I like this asm tutorial (unfortunately for 32-bit):
I may be misusing the terminology but I had in mind the sorts of things Python does for you, like memory management.
> If your goal is more to learn a low-overhead compiled language, I would recommend rust.
Now that you mention it, this is probably the main thing I want. Integration with Python would be nice though and, as mentioned in a previous comment, I have to learn C for university soon anyway.
Might add that Rust has a very new blend of concepts that are "in your face" -- and arguably a very "modern" selection of concepts. I'm not well versed in neither C, C++ or Rust (or Haskell/ML) -- but this old article by Stroustrup (creator of C++) still makes some interesting points vis-a-vis C:
Rust has great documentation that's rapidly improving, but the selection of "syntactic tools" are somewhat eclectic -- yet I think one could probably be a better C programmer by first learning Rust (just as one might be a better C programmer by first learning Pascal and/or Ada) -- precisely because Rust has gathered up what seems to me to be a very useful subset of "things" (borrow/box, strong typing, safe/unsafe etc) -- that can be useful to apply to any kind of programming.
And just as with C++, Rust will give you somewhat more complex solutions (if you look at the generated machine code) than naive C code -- but as it turns out -- the naive C code is probably incorrect, anyway!
> But I don't think rust is quite at a place where it makes sense to reccomend it for that use-case to a novice (low-level) programmer. I'd love to be wrong about that.
So a lot of this is tooling, integration and documentation.
If one might whip up something similar for rust that works cross platform, and results in code that is reasonably easy to distribute via pypi (and similar for gems for ruby etc) -- that'd be great.
So, I meant that for a novice, that wants to, say write a compiled extension/wrapper for python/ruby whatever -- a bit of C and the standard docs go a long way now.
Obviously there's a lot of work to get to the point of C (it's been ubiquitous for a while...) -- but if some parts could be made similarly accessible; interfacing with rustc, if rustc is in path/installed "properly", some magic on the host-language side etc -- that would be very good, I think.
This great! Looks like there's still a bit of a gap wrt passing arguments; like the snippet above does. After skimming the chapter on ffi as well, there appears to be the need for a bit of experimentation (for me/a novice) to get that to work (eg: passing in a string, getting it back reversed, or as a list/array of unique characters/glyps etc).
I'll have a look when I find the time - but this is a great start!
Yeah, things like "what do I do about more complex types" needs tons of more docs in general. We will get there. I'm also pretty convinced that a dedicated individual could create pretty awesome automatic binding generators for any language, especially since bindgen works pretty well for C... but we'll see how it shakes out.
Don't hesitate to email me or post in the forums if you play around with this and get stuck :)
By the way, about Rust error handling. I like the concept that any error is being returned as a function result, but there's is a huge practical problem I don't understand how to solve with this approach. Exceptions (kind of) solve it automatically.
What if the information that "computation failed" is not enough? Say, I wrote a `getItem(User) -> itemId` function, which does a lot of calls and can fail for multiple reasons. Later I will have to admit that my API is not perfect: user isn't quite ok with the fact that operation failed, he wants to know why it failed: maybe there's no items to get at the time, maybe he isn't permitted to get them, maybe that permission is computed in real-time based on how many clicks he made today or anything else. What do I do now?
If getItem was throwing exceptions, I can fix it right away. It's not my favorite solution of that problem, but it works: I catch all exceptions separately at the caller and do something. I can provide user-friendly message as the text, that the exception will carry.
But if I was using something like Maybe monad for the error mechanism, I'm pretty much fucked. Now I have to go through huge getItem function and refactor it using some custom container-type as a return value, which will carry the reason the call failed, as well as the data itself.
From what I understood, Rust's error handling is exactly such Maybe monad with a different name. Is there built-in, idiomatic way to solve that problem?
The `Option` type (what Rust calls Maybe) is rarely used for error handling. As the article describes, Result is normally used, which allows attaching arbitrary data to the error case: http://doc.rust-lang.org/std/result/
But anything more complicated than that (defining extension types etc.) isn't yet supported by the high-level bindings, and would need unsafe code using the python C API directly.
This looks like it is tied irreparably to the CPython interpreter. One probably doesn't want to do this. Export a clean C compatible API and call via CFFI. This has the being callable from other languages, CPython and PyPy.
I like the way the error handling works; it's a pattern I try and use in Python by creating custom exceptions that basically pass up whatever specific exception is caught.
Python 2 will store Unicode as either UCS-16 or UCS-32, depending on how it was compiled. The horrible monstrosity that is the default "string" (those are scare quotes; I know how the formatting on here works) in Python 2 is not Unicode, so it obviously doesn't use UCS-16 or UCS-32.
"Railway Oriented Programming" is a term coined by Scott Wlaschin, a prominent F# practitioner who popularized the term with helpful blog posts, slides, and speaking events.
Outside of the F# community (i.e. those that have not seen Wlaschin's materials) however, the term is rarely used. The larger FP community has more more general terms they use instead for the whole class of patterns surrounding this.
Rust's error handling is pretty good. First of all you see in the signature of the function that it can trigger an exception, so such a function will return Result<T, E> instead of just T. This is similar to Option, Either or Try in Scala, or to Maybe / Either in Haskell. To easily pipe such errors, Rust provides a try! macro, which just expands into a catch block.
Rust is less functional than Haskell or Scala, so I don't know how that works out, but in FP languages it ends up working great. Also, compared with Go it isn't the same thing.
Rust targets C++ programmers (Go seems to be targeting Python/Ruby web devs), the former are used to not using exceptions even when they exist in the language (for various reasons, some valid - some not so much :) )
I can't think of a single WTF moment I had with it. Several "OMG this guy thought about this too" moments.