Rust as high-level language such as java/kotlin

Rust as high level language such as java/kotlin

Hi rust community!

I'm here because I'm looking for a new language to learn. But I'm unsure if rust language fits usecases i daily try to solve.

Now i'm a little Kotlin developer. Mainly i develop tested microservice with Spingboot and RabbitMQ.

I'm pretty read about Rust, if i miss understood something, please correct me:

  • Rust is a language with the main purpose to write high performance and safe software thanks to amazing static verifications at compile time;
  • Borrow checker, ownership, and life time concepts permits to Rust to be a no garbage collected language and safe to write concurrent programs;
  • Parts of the language design is inspired by the most pragmatic parts of functional programming that promote code reuse, immutability, avoid global states and side effects;
  • The tooling like Cargo is modern, up and running, simply works without crazy configurations;
  • Rust is a compiled language and binary standalone programs are easy to deploy.

And now my questions:

Can Rust be used with the intent to write software that not have hard performance constraint?
Is Rust suitable if your daily needs are just write, well tested, clean, readable and maintainable code?
What involve using rust only for high level development?
What are advantages and disadvantages of this?
Do you have experience putting in production an only business logic focused program written in rust?
In this context, what characteristics does Rust have that a static typed language as Kotlin does not have? What can i learn from Rust?
In your vision, in the future of software development, is it a valuable skill for a product-oriented developer to know low-level details? Do you recommend Rust as the right compromise to improve in both things? or would you recommend in something more widely used and high level like Python?

Example of cons:
Does involve risks to have more verbose and boilerplate code?
Does involve risks to remain lot of time stucked in low level details?

Example of pros:
Does it implies having more control of concurrent code thanks to concurrent facilities and compile time validations?

if you have good material, please link it in this discourse.

Thanks for your time.

Your first impressions seem pretty accurate, and your list of pros and cons look reasonable.

One additional advantage of Rust is that it is fairly straightforward and efficient to integrate C libraries into Rust programs (and vice-versa), or to embed Rust in other languages that can use the C ABI. This can be very useful if you are working with existing code and frameworks in such languages. (On the other hand, if you need to connect to Java code, then Kotlin has the advantage.)

One additional disadvantage is that Rust can be a relatively hard language to learn. It can easily take weeks or months to feel confident in Rust, while many other languages can be quicker to pick up. (On the other hand, it has some similarities to Kotlin, so at least some parts of Rust will already feel familiar.)

Certainly. I can write poorly performing code in any language. I do it every day in Rust now. Although I find it hard to get it to perform as badly as my other favorite language, Javascript/node.js or Java. :slight_smile:

Certainly, why not?

Most of what I do in Rust can be described as "high level". I use it in the server, it speaks to databases, it speaks to messaging servers, it acts as HTTP and web socket servers, it throws JSON around. A year ago or so I would have been doing all that in Javascript or Python. All in all I don't find it much more hard work than using Javascript or Python. With the huge benefit that I can have much more confidence in the stability of what I create in Rust. And of course it performs much better.

Yes. I started learning Rust a year ago and soon had little services in Rust running in production. They proved to be trouble free so production code in Rust has been steadily growing since. See above.

The huge win for Rust over Kotlin for me is that I have no dependency on a JVM. Apart from the sordid history of Java and Oracle I see no reason to need a virtual machine.

More practically, the lack of reliance on a VM or other huge run time beans I can use Rust on our remote embedded systems (think IoT). It's nice to be able to use the same language everywhere.

That depends on what product you want to develop. At this time Rust is likely not a good choice if you want to churn out mobile apps in a hurry. For example.

On the other hand people like Microsoft, NPM, Cloudflare, not to mention Mozilla of course, are busy building Rust into their product. As am I :slight_smile:

I think it's good for a developer to learn a bunch of different languages. Preferably languages representative of the different programming paradigms we have. List, Haskell, Forth, C, C++, Rust. That get's you thinking about programming in different ways.

4 Likes

Absolutely!

At work if we ever need to make some tool (automating our complicated build process, translating GUI strings using Google Translate, etc.) it'll be written in Rust. Having a good type system means you have less unexpected errors, and when errors do occur they are often easier to understand than some NullReferenceException deep in the bowels of your code.

Rust isn't too verbose as long as you aren't trying to do fancy things with lifetimes and complicated generics. I find working in an OO language like C# to require a lot more boilerplate and verbosity than Rust.

This doesn't really have much to do with the language. I can write really low level code in Kotlin and really high level code in Rust, it really depends on how the 3rd party code you interact with is designed.

One of the nice things about Rust is that you do have access to the higher level concepts like closures, traits, and iterators. So if you want to, you can write quite high level code without much effort.

1 Like

Most certainly yes, in my opinion. In fact most of the time I don't really need high-performance code; I'm using Rust because of its awesome type system instead. In fact, I'm doing a PhD currently, which is oriented towards improving the correctness of a particular kind of abstraction, and I'm considering using Rust for it.

4 Likes

That is kind of an interesting question.

By virtue of the fact that you can get you code to even compile it is already better tested than if it were written in any other language I know. Apart from Ada perhaps. Thanks to the rigorous type checking and data aliasing checking of the compiler.

I have no idea what is meant by "clean" but the Rust compiler and clippy are always warning me to clean up any unused junk I leave lying around.

"readable" is down to the author. One can write confusing code in any language.

I would say the "maintainability" of Rust is likely better than most other languages. For sure when someone comes to your code in the future to make changes or additions the compiler will not let them accidentally introduce memory misuse errors, memory leaks, type check errors, race conditions etc. As is so easy to do when tinkering with code one does not know so well in most other languages.

1 Like

You are right!
Clean code is reasonably a subjective thing, can be applied to any language and depends on the sensibility of the single developer.
Now, for me clean code is the maximum application of the 4 rules of simple design.

A specific question about this can be:
If i write very simple code, the design/semantic of the language risk to force me to handle low-level details and over-complicate my solutions?

Can be interesting here analyse the culture of the Rust users:
The performance-driven capabilities of the language can instaurate an over-engineering tendency in the daily development? Are you note an over-engineering culture in the Rust community?

I don't think so. Rust is a high-level language – the whole point of it is exactly that you don't need to get down to the bare metal in order to write performant code. Furthermore, how simple you can get your code primarily depends on your experience. For example, knowing the standard library APIs well helps a ton. You can write, for example:

let mut values = Vec::new();
for i in 0..10 {
    for j in 0..10 {
        values.push(j);
    }
}

but if you know about iterator adaptors, this whole thing simplifies to the one-liner cycle(0..10).take(100).collect().

4 Likes

Hmm...

  • Passes the tests
  • Reveals intention
  • No duplication
  • Fewest elements

It amazes me that people write books and become famous when it all boils down to 4 ideas we all had in our heads as young teenagers after a few weeks of writing BASIC decades ago :slight_smile:

Rust certainly helps with item 1. As I mentioned above the fact that Rust is so fussy about types, data aliasing etc means that the compiler has already covered a ton of stuff one should write tests for in lesser languages. After that Rust/Cargo has great features for for writing and running tests built right into the build system.

Well, let's take a specific example of a task people do a lot in high level languages, querying data from a SQL database. In Rust it can typically look like this example from the postgres crate:

extern crate postgres;

use postgres::{Connection, TlsMode};

struct Person {
    id: i32,
    name: String,
    data: Option<Vec<u8>>
}

fn main() {
    let conn = Connection::connect("postgresql://postgres@localhost:5433", TlsMode::None)
            .unwrap();

    conn.execute("CREATE TABLE person (
                    id              SERIAL PRIMARY KEY,
                    name            VARCHAR NOT NULL,
                    data            BYTEA
                  )", &[]).unwrap();
    let me = Person {
        id: 0,
        name: "Steven".to_owned(),
        data: None
    };
    conn.execute("INSERT INTO person (name, data) VALUES ($1, $2)",
                 &[&me.name, &me.data]).unwrap();

    for row in &conn.query("SELECT id, name, data FROM person", &[]).unwrap() {
        let person = Person {
            id: row.get(0),
            name: row.get(1),
            data: row.get(2)
        };
        println!("Found person {}", person.name);
    }
}

In Python it might look like this tutorial example found on the net:

import psycopg2

try:
   connection = psycopg2.connect(user="sysadmin",
                                  password="pynative@#29",
                                  host="127.0.0.1",
                                  port="5432",
                                  database="postgres_db")
   cursor = connection.cursor()
   postgreSQL_select_Query = "select * from mobile"

   cursor.execute(postgreSQL_select_Query)
   print("Selecting rows from mobile table using cursor.fetchall")
   mobile_records = cursor.fetchall() 
   
   print("Print each row and it's columns values")
   for row in mobile_records:
       print("Id = ", row[0], )
       print("Model = ", row[1])
       print("Price  = ", row[2], "\n")

except (Exception, psycopg2.Error) as error :
    print ("Error while fetching data from PostgreSQL", error)

finally:
    #closing database connection.
    if(connection):
        cursor.close()
        connection.close()
        print("PostgreSQL connection is closed")

Judge for yourself. Is there too much low level detail and over-complication in the Rust solution?

Personally I don't think so.

The Rust is 26 lines of statements vs 25 in Python. Some would say I should count the closing "}" that Rust tends to have on a line by themselves. That only adds five lines that are basically whitespace, hardly worth worrying about.

Yes there can be more detail in those Rust statements than Python, what with type specifications and such. But that is what we want to save us having to write tests for all that type checking.

See also: "Writing Javascript In Rust, almost": Writing Javascript in Rust ... almost

I'm not sure why you think there should be.

Personally I'm lazy. After I have put enough effort in to convince the compiler to compile my code and run it through some tests I'm done. Nothing gets reengineered, let alone over-engineered unless some pressing need arises. Like boosting performance or adding a big new feature.

The beauty of all this is that Rust provides for fiddling with low level detail and complexity when you need it. For example: I have some server side code in Rust that has to decode incoming streams of binary data. There is a lot of fiddling with bits and bytes, checking header sequences, checksums etc going on in there. If my service were written in Python or JS or whatever I would have to create a module in C/C++ for them to use to get that job done with good performance. In Rust, well, I just do it in Rust. Sweet!

2 Likes