How low-level is Rust?

What is Fortran like, is it as low level as C and Rust?

Fortran is...

Fortran is a bizarre demon skeleton dinosaur that simply will not die.

It is not low-level, in the bare metal sense. You could never write an operating system in FORTRAN. That said, it also completely depraved of any worthwhile high-level abstractions.

If you ask me, Fortran is no-level!


Heck, they don't even write Fortran compilers in Fortran!

6 Likes

Lol,

Why does it still exist?

What could be possibly done with Fortran then?

Basically just math and science. I'm a physics grad student, and my colleagues are enamored by it. They believe it is equivalent to C in power. (but they're not writing operating systems!)

And from what I can tell, the reason it's still so popular is because there's a lot of old code written in it that people still use to compute things. I mean, I've seen code written in the 70s.

2 Likes

To be fair to Fortran, this language has improved a lot in the 90s (even if most code written in it unfortunately still predates that era), and it has no serious competitor on the near horizon[1] when it comes to its only area of expertise: performing computations on large multidimensional arrays of numbers quickly.

If you've ever played with MATLAB or its NumPy clone, Fortran 90+ brings essentially the same ideas but with more language-level concepts (e.g. easy handling of floating-point precision, compile-time function evaluation...) and a much faster implementation.

[1] On the far horizon, I'm very curious about how the Julia experiment will evolve.

8 Likes

As with the question of Rust's "height level", I'm not sure this can be answered until you have learned C and understand exactly what elements are "cumbersome" about it. (Seriously, just learn C! It's a very simple language in the sense of having relatively few concepts, syntactic elements, and keywords. You will learn very little that won't also help you when learning Rust and/or C++.)

But even once you've learned C, the question of how cumbersome a language is relative to another is something of a matter of opinion.

Additionally, the question of whether the low level features of any language "feel" like C is kind of strange, because C is essentially just a linguistic model of (the basics of) how hardware works. It's difficult (for me at least) to imagine how a language could possibly provide the same features, with similar semantics, and not feel equally "low level." But, again, you can avoid these parts of the language quite easily if you don't actually need to do specialized things with your hardware!

3 Likes

Have you learn't Rust and C? if so which language do you personally think is more cumbersome?

If I am doing robotics in the new future, then I would be using Rust and I may have to deal with low level stuff within the language.

It depends what cumbersome means to you. At the beggining Rust tends to be cumbersome, becouse you need to bother with borrow checker, lifetimes, and other stuff which prevents you doing unsafe things. In C (and also C++), everything seems straightforward at the beggining. However when you learn the language it comes out, that all those cumbersome things in Rust, which you already used to and which aren't problems anymore, leads to structured, maintainable and safe code. On the other hand, when your C codebase grows up, nasty things comes out - bugs which were done before, but didn't show up before, dependencies between code parts becomes difficult to maintain, global states avoids you to test fancy scenarios properly, and two libraries you are using are completely incompatible with each other. Those things doesn't happen in Rust, or at least happen less often. And belive me, those things are really much more hurting you than some difficulties while learning.

There is also other thing. If you start in Rust, and you will use to all its discomforts, you will have much easier start in other languages like C/C++. Good habbits about ownership control, data and behaviour separation, and others would help you write much better C/C++ code, and possibly you would have less problems I was talking before. On the other hand, starting in C/C++ would make learning Rust more difficult in future just because of bad habbits, not because C/C++ forces them, but because it allows them, and they makes things easier at the beggining, so its easy to fall into them.

5 Likes

That's good, honestly CS students in universities should be forced to learn Rust before learning C/C++ just so people learn how to not get into bad habits.

Even though I know Rust is just as low level as C, can Rust also feel like just as low level as C?

can Rust also feel like just as low level as C?

You've asked this question in some for or another at least three times now, and it looks like most[*] versions of the answer have been given :slight_smile:

I love your excitement and enthusiasm for learning about Rust, and your questions have triggered so many well-reasoned and clear explanations (:heart: everyone!). However, I remember from my own days starting out that no amount of friendly explanations can replace actual personal experience.
There's just no substitute for your first duel with the compiler!
Probably the most educational thing you can do at this stage to get a better feel for Rust is to dive in (at least little);

  • If you haven't done so, start reading the first four chapters of The Book.
    it explains a lot of Rust's background and intentions; what does the language look like, and why is it that way.
    • Specifically chapter 4 - Understanding Ownership explains Rust's primary feature, its true innovation, the ownership model (Which also usually the biggest stumbling block for newcomers, and the source for many of the "rust is hard" complaints)
  • These golden oldies from the Rust Blog explain some more background thinking of why Rust is the way it is:
  • Have a look at Rust By Example for lots of small demo programs. The example code is interactive and editable, so you can play around with it and see what happens in the online editor (much like the Playground, which I seen you try already in other threads)
    • My personal favourite (because I wrote it :blush:) is the threaded map-reduce example.
    • For advanced credit: see if you can come up with your own example, and contribute it back; Rust-By-Example accepts pull requests!
  • If you want to try some local developing, I can recommend, also from personal experience, the Rust Exercism track. This gives you small assignments to complete (in the form of a test-suite to make pass), and is a great way to get your hands dirty in the beginning.
    • Exercism has many languages, including C and C++, so you can even solve the same problem in different languages, to get that much-desired feel for how they compare.
      Once you finish an assignment, you can also look at other people's solutions, to learn from how others are doing it (To me, that was at least as educational as the trying-it-out part).

Also, since it seems you're having some interesting discussions with your friend about this topic, feel free to invite him to drop by :slight_smile:


[*] The only additional answer I can think to add is to read Japaric's excellent "Embedded in Rust" blog; It is great to follow it from the oldest to the newest posts, and see how he builds up increasingly "high level" abstractions on top of the raw register writes. I love how he combines the different views all the way from bare metal raw assembly to high level (partially even auto-generated) Rust code; You are unlikely to find a better example of both "high level" and "low level" Rust anywhere, and the gradient is an excellent example of how "doing low level stuff" can still feel like "writing at a high abstraction level".

10 Likes

Sorry I keep asking I just want to know that is all,

Oh ok thanks for that mate, I will save this page so when I am actually able to learn Rust then I will check out the tutorials =D

and see how he builds up increasingly “high level” abstractions on top of the raw register writes.

Are there any "low level" abstractions as well and would users still need to use these low level abstractions at all? In Rust I hope that I can learn low level stuff instead of relying upon high level programming so that I can more deeply learn how low level programming works. Can this be achieved?

I can assure you there's plenty of low level stuff in Rust - you have nothing to worry about on that front :slight_smile:.

3 Likes

Thanks bro :slight_smile:

I know how I must sound saying this, but: I simply cannot take any language seriously that has no concept of lexical scope. Correct me if I am wrong, but it seems that even after decades of development, it still remains that all declarations must be at the top of the function. And in a language whose target audience is prone to writing procedures that are hundreds of lines long!

Without this basic language feature, people start looking for creative ways to avoid declaring new variables:

     allocate(t_new(3,3))
     t_new=dble(e%s_lat)     !  prepare inverse matrix
     call lu_d(t_new,t1_new)
     t_r=t1_new(1,1)*t1_new(2,2)*t1_new(3,3) ! det(e%s_lat)
     call inv_d(t_new,t_new)
     t_sc=t_new  ! inverse super cell
     t_new=dble(e%p_lat)     !  prepare inverse matrix
     call lu_d(t_new,t1_new) 
     t_r=abs(t_r/(t1_new(1,1)*t1_new(2,2)*t1_new(3,3))) ! det(e%s_lat)/det(e%p_lat)
     call inv_d(t_new,t_new)
     t_pc=t_new  ! inverse primary cell
     n_qgroup=anint(t_r) ! number of q points in the primary cell Brillouin zone

As far as I can tell from searching the web, nobody is even talking about this. It is the embodiment of the Blub paradox.

Again, Fortran is a domain-specific language for large-scale N-d array computations. To understand its appeal, you need to put yourself in the shoes of the target audience, not see it through the lens of a daily user of general-purpose programming languages.

Imagine that you are doing some kind of natural science and have very little interest in programming, but need to program something from time to time because computers are inescapable and engineering departments are massively under-staffed. Maybe you want to numerically integrate an equation which has no analytical solution. Maybe you want to process a big bunch of measurement data to filter it or compute some kind of simple statistic on it. In any case, you know the maths pretty well, and all you need now is to translate it into efficient code with as little effort as possible, so that you can go back on focusing on "real science".

When you come from this perspective, things like best software engineering practice or variable scoping mean nothing to you, because your programs are too simple for this kind of concerns to matter at all. You live in the 100~3000 LOC range, not the 10~100 kLOC range. If your code becomes too messy, you'll just throw it away and rewrite it from the mathematical paper anyhow. What matters more, on the other hand, is how much foreign programming knowledge and concepts you need to painfully get through before you can achieve your goal of getting things done.

From this perspective, being able to, for example, efficiently and easily pass a slice of a matrix into a function as if it were the whole 2D array without needing to think about how that can possibly be implemented efficiently, learn advanced object-oriented hackery and expression templates, hunt answers through ill-written documentation, or wade through kilometers of incomprehensible compiler error messages is a big plus. And this is where Fortran shines. It is the place where scientists who don't like programming go when MATLAB has become too slow and Python has become too confusing.

Sure, Fortran is old and full of quirks. You get strange syntax all over the place, implicit footguns, and backwards compatibility support for COMMON and fixed-format abominations. But since no one has actually expended some serious time at building something better for the target audience, the language remains the king of its small niche for now.

12 Likes

“differentiate between different types of memory addresses”
... and ...
As a C++ programmer who understands many (though not all) of the “dark corners” of the language, I don’t know what your friend means by this.

My guess is he is referring to the C++ std library data types which let you supply your own customer allocators (which can be used if you need an allocator with special characteristics, such as in multiprocessor systems where each processor has it's own fast local memory and they all share a much slower shared memory.) Alternatively, he might be referring to how Java doesn't let you allocate objects on the stack.

2 Likes

For someone that intends to write specialized embedded code for a microcontroller, say for robotics, and especially for someone new to programming/microcontrollers/etc. I would suggest choosing the language and tools most used within the community using that particular hardware and/or robotics domain. Often this will be driven by the vendor of the hardware/devices in question as they typically choose the OS for which they will write the board support package, drivers, etc. This may or may not be Rust.

Once you've got enough experience in that domain using the language/tools that are most commonly used, best supported by the community, etc only then would I consider exploring how a different language with different properties could be used instead. You might drive a switch to Rust based on how many problems you had during development that trace back to pointers/memory ownership/etc. If your difficult problems were mostly in other areas you might look to other solutions.

Of course, this recommendation is assuming that the goal is more about building a new robotics system than proving it can be done with a specific language.

2 Likes

Ah, yes, I had forgotten that Rust doesn't yet support custom allocators. That would be a fair criticism of Rust's abilities.

Custom global allocators have been stable since 1.28.0 (so not yet on "real" stable I don't think, but very usable on nightly)

That isn't entirely accurate is it?

My understanding is that lifetime checks and all type-checks still occur. The only thing "unsafe" blocks/fn's allow that is not otherwise allowed is:

  • calling "unsafe" functions
  • de-referencing arbitrary pointers
  • reading/writing mutable static variables (globals)

Additionally, you can annotate an impl(ementation) of an "unsafe" trait with "unsafe" to let the compiler know that you know that providing an implementation of the trait requires that you uphold the contract that is required by the trait that the compiler is unable to verify whether or not you've upheld it. Today, this last bit is only used for impl's of the "send" and "sync" marker traits as far as I know.

All other checks and verifications of the compiler continue to function normally even in "unsafe" blocks and fn's.

hmmm the discussion ones more turns me over the thought that Rust is still in the need for a "killer apps".