
Rust: A Scala Engineer's Perspective - blacksmythe
https://beachape.com/blog/2017/05/24/rust-from-scala/
======
saghm
> When handing out references of something bound with let mut, why do i need
> to do &mut instead of just & ?

Sometimes, you still want to immutably borrow a mutable variable. Otherwise,
you wouldn't be able to have multiple references to a variable declared with
`mut`, which would be an unnecessary limitation.

EDIT: Here's an example of something that wouldn't otherwise work if borrows
of mutable variables were implicitly mutable:

    
    
        struct Point {
            x: i32,
            y: i32,
        }
    
        fn add(p1: &Point, p2: &Point) -> Point {
            let x = p1.x + p2.x;
            let y = p1.y + p2.y;
    
            Point { x: x, y: y }
        }
    
        fn main() {
            let mut some_point = Point { x: 1, y: 1 };
            some_point.x = 2;
    
            // `some_point` is borrowed twice here, which wouldn't be possible if the borrows were mutable.
            let other_point = add(&some_point, &some_point);
    
            println!("({}, {})", other_point.x, other_point.y);
        }

~~~
kllrnohj
The question isn't why does the function decleration need to have &mut, it's
why does the call site need to have &mut?

as in assume you had: fn reset(p: &mut Point) { p.x = 0; p.y = 0; }

Why can't this be called like so:

reset(&some_point);

rather than needing to say

reset(&mut some_point);

To some extent it's nice that the callsite must document the behavior
visually, but its more forcing a style guide rather than anything that's
required to compile & work.

~~~
saghm
When you use `&mut some_point`, (i.e. immutably borrow "some_point"), the
compiler requires that "some_point" is not borrowed anywhere else at the same
time. In order to enforce that invariant, it needs to know what borrows are
mutable and what borrows are immutable.

Perhaps what you're wondering is "why can't the compiler infer when a borrow
needs to be mutable instead of having the programmer specify it"? I can't say
for certain what the answer to this is, but my guess is that it would be
rather expensive. Consider this example (reusing the "add" function from
above):

    
    
        let mut foo = Point { x: 1, y: 2 };
        let bar = &foo;
        add(&foo, &foo);
     
        ...
    
        // Much later
        reset(bar); 
    

Under the proposed "mutable reference inference" rules, should this compile?
It's not necessarily trivial to determine this (especially if the "..."
contains a lot of code), but it should not, since `bar` must a be mutable
borrow to be able to pass into `reset`, which means that the borrows of `foo`
to pass to `add` shouldn't be allowed. This means that the compiler would have
to a rather expensive lookahead to determine whether any borrows are valid
(and some people already complain that Rust compiles too slowly!). Forcing
users to specify when borrows are mutable makes the compilers job _much_
easier, not to mention the readability benefits that comes from making
mutability explicit.

~~~
johncolanduoni
Borrow checking happens quite late in the compilation process. It has to,
because it can't know the lifetimes of the borrows until all the functions are
resolved (borrows are allowed to leave the scope of the call via requirements
imposed by functions, even to the point of being required to be static). If
this choice was made for technical reasons, this is not why.

Considering how seriously Rust takes explicitness in general, I strongly
suspect this was done purely for readability.

------
brson
> As with Swift, I haven’t been able to find conclusive evidence nor credit
> given to suggest that there was any influence from Scala on Rust …

Scala was a significant influence on Rust. Niko did his dissertation in Scala,
and several other team members were fans. Let it be known!

~~~
kibwen
I took that to mean that Scala's influence on Rust is non-obvious. I might
describe Scala's general design philosophy as "exuberant", whereas Rust has
historically tried to have as little machinery as possible to achieve its
safety goals. Scala's much more flexible, much less explicit, and much more
TIMTOWTDI.

------
kaoD

        match some_int {
          // Why not Some(& s) => ... ???
          Some(ref s) => println!("{}",s),
          None => unreachable!()
        }
    

To me his proposed syntax looks like the exact contrary use case: pattern-
match on something that's a reference.

EDIT: And that's actually the case.

[https://play.rust-
lang.org/?gist=017740fbff2c5923dec3cc514bd...](https://play.rust-
lang.org/?gist=017740fbff2c5923dec3cc514bdba2f7&version=stable&backtrace=0)

In that case it works because `w` is copy. For non-copy types, it prevents
moving out of the borrow (as expected).

[https://play.rust-
lang.org/?gist=241728575a382c54c324b0201c5...](https://play.rust-
lang.org/?gist=241728575a382c54c324b0201c5f7ea5&version=stable&backtrace=0)

~~~
masklinn
> To me his proposed syntax looks like the exact contrary use case: pattern-
> match on something that's a reference.

> EDIT: And that's actually the case.

Yes, &s in a pattern is already valid and captures a "dereference" by value.
While ref captures a value match by reference.

~~~
sanderjd
> ref captures a value match by reference

I share the OP's sense that this syntax is non-obvious. Could you parse what
it means to "capture a value match by reference"?

~~~
thristian
This is all part of "destructuring pattern matching". Let's say we have:

    
    
        struct Something<T>(T);
        let x = 42;
    

When we say:

    
    
        let y = Something(&x);
    

...we're _constructing_ a value of a particular type on the right-hand-side of
the `=`. Written out, it would be something like "take the value x, calculate
its address in memory, and wrap that reference in Something()".

    
    
        let Something(&z) = y;
    

...does the reverse operation. Written out, it would be something like "take
the value y, remove the Something() wrapper to get the value inside,
dereference the pointer to find the value pointed to, then assign a copy of
that value to the variable z". At the end, z == x.

Note that the last step is copying a value: it only works if value is of a
type that can be safely memcpy()'d (in Rust terminology, if the type
implements the Copy trait). In this case, the value happens to be the integer
42, and integers _are_ Copy, so it all works out. However, not all types are
Copy, so if you can't copy the value, what happens?

If the value you're destructuring _owns_ the inner value, it's easy—you just
become the new owner:

    
    
        let x = Something(123); // x owns this Something instance.
        let y = Something(x);   // the value from x is moved into y.
        let Something(z) = y;   // the value inside y is moved into z.
    

On the other hand, if the value you're destructuring _doesn 't_ own the inner
value, you can't just take ownership of it. If you want a handy name to use
when talking about that value, it's going to need to be a pointer.

    
    
        let x = Something(42); // a value that is not Copy.
        let y = Something(&x); // a reference, so we can't take ownership
        //let Something(&z) = y; // Can't take ownership of x!
        let Something(ref z) = y; // z is a reference to x
    

You can play with these examples in the Rust Playground:
[https://is.gd/LhrphO](https://is.gd/LhrphO)

~~~
Veedrac

        let x = Something(42); // a value that is not Copy.
        let y = Something(&x); // a reference, so we can't take ownership
        let Something(ref z) = y; // z is a reference to x
    

z is a reference to &x, and is thus of type &&i32. You should normally just do

    
    
        let Something(z) = y;

------
corn_dog
Having done scala for a few years and only dabbled in rust, I also get the
impression that the rust community is trying to have good default answers to
questions like how to do json, or which web framework to use. As opposed to
scala-land where if you ask three scala devs those questions you'll get five
answers.

~~~
tekacs
[https://www.scala-lang.org/blog/2016/11/28/spp.html](https://www.scala-
lang.org/blog/2016/11/28/spp.html) is probably what you would call the Scala
folks' attempt at this.

That said, it seems more common in Rust for there to be a consensus about
which library to use. Perhaps this is simply due to its age? I've seen a few
libraries recommend you migrate to others because the pace of Rust conceptual
evolution made the first library outdated in short order This is somewhat less
so now, though very recent features like custom derive and even impl Trait can
affect dramatically the aesthetics of a library and how someone chooses to
implement it.

------
Others
Concerning cross compiling, one useful tool the author may of missed is
[xargo]([https://github.com/japaric/xargo](https://github.com/japaric/xargo)).

------
qsymmachus
> If you lean more towards the functional programming paradigm side of Scala
> then you’ll probably love the following about Rust’s type system

Some of the more popular functional languages have advanced type systems, but
not all functional languages are statically typed. Lisp, the granddaddy of all
FP languages, is dynamically typed. So is Elixir.

Can we stop conflating FP with static typing?

~~~
kibwen
_> Can we stop conflating FP with static typing?_

I'm all for that, but first we probably need to actually define what
"functional programming" means, which seems to be one of the great
unresolveable debates of computer science. :P

To wit, I can think of no reasonable definition of functional programming that
includes Lisp, Scheme, ML, and Haskell that does not also include every
popular language aside from C. Even Java has first-class functions these days,
sort of...

~~~
lmkg
I tend to use the term "function-oriented" rather than "functional" since I
think it fits the spirit of the phrase better. You're right that language
features alone won't distinguish enough, and that means that functional
programming is more about culture and standard practices. Once you embrace
that, it's a bit easier to wrangle out a definition.

The definition I have in my head is something along the lines of "functions
are the tool that the language prefers to address common software design
concerns." So for example, Encapsulation is a big deal when designing
software. Object-oriented languages will address this concern with their
object system (via accessibility modifiers), while function-oriented languages
tend to address this with functions, via lexical scoping and closures. OOP
languages use their object system to achieve runtime-dynamic behavior through
inheritance or composition or interfaces, while function-oriented languages
will more often try to pass first-class functions as arguments. And so forth.

It's not a 100% thing. Common Lips will solve some of its problems with macros
or its module system, and ML will solve some of its problems with types. But
you do find the languages (or communities) prefer functions over their object
systems, while e.g. Python or Ruby prefer the reverse.

Although, I do find myself wondering if Haskell should actually be considered
a type-oriented language. Again, it's not just about the features of the type
system, it's the fact that the type system is the main tool that it tries to
use to solve every problem about designing software.

~~~
jholman
I strongly agree.

We see a lot of definitions of functional bandied about, often conflating
functional with Haskell or with Scala. Those definitions seem to ignore the
history of functional programming, including Lisp, as qsymmachus noted. So
that's silly. And conversely, one sees a lot of definitions of OO that appear
to mean "Java" or "C++". Again, nonsensical when one considers Self, or to a
lesser degree Smalltalk.

I do like your conception wherein a language is function to the degree to
which it prefers functions as its favourite tool for solving problems, and/or
OO to the degree to which it prefers objects as its favourite tool.

Regarding encapsulation as your particular example, OO is clearly fairly
obsessed with encapsulation, being almost the definition of an object: a
bundle of encapsulated state with the externally-facing behaviour that that
object affords. I think that many functional communities/practitioners see
this as a much less urgent issue, often going so far as to make no active
effort toward encapsulation at all (i.e. not everyone bothers with the
lexical-scopes-and-closures solution). Thus we get ideas like "smart
functions, dumb data", an idea which makes no sense in OO land.

------
doug1001
thanks for doing this

two questions: from the perspective of a Scala dev, does Rust have a solid
collections library (including persistent structures such as Scala's Vector
type) with mutable counterparts (eg, ListBuffer)?

second, from a quick glance it seems Rust's top-level concurrency model
(locks, thread ownership) is the polar opposite of Scala's (Actor-based)--is
this correct? Scala's concurrency model (based on Erlang), along with trait-
based multiple inheritance, were Scala's initial selling points for me

~~~
logicfiction
Is actor-based really considered top level for Scala? Akka is still a
framework and not in the language itself, I'd argue the core concurrency is
Java-based thread pooling enriched with Scala's Future type.

That said, I do agree that Akka is heavily favored as the ideal in Scala
development as part of Lightbend's take on the Scala ecosystem, and maybe that
was mostly your point.

~~~
evacchi
Actors (not akka's) used to ship as part of the standard library. I'd argue
it's been the killer app that drove many people in, in Scala's early days. At
some point Akka grew bigger and matured so the original actor library was spun
off in its own library, basically deprecating it in favor of akka.

------
knavely
Is there a Rust Console ? As a Scala/Haskell programmer, this is my biggest
wish right now.

~~~
cptroot
I'm guessing you're asking if Rust has a REPL? Currently there is no REPL
included in the standard language, but you can download the rusti project [1]
using cargo.

[1] [https://github.com/murarth/rusti](https://github.com/murarth/rusti)

~~~
knavely
yes, REPL. bummer.

------
flavio81

       TL;DR:
    

He is happy.

Better toolchain (environment manager, package manager, etc)

Macros are easier to do with Rust (than in Scala).

IDE: happy with MS Visual Studio Code

Syntax is not too different.

Type system: He likes it.

Calls C code with a similar syntax than doing it with Scala

Rust allows you more control on how to use your memory allocation. (Or forces
you to take control).

\-------

My own take on Rust (haven't used the language yet, only looked at specs) is
that it appears to be a more "sane", state-of-the-art version of C++,
streamlined, without all the cruft and all the legacy. And with a much better
object oriented system based on Traits.

~~~
phkahler
>> it appears to be a more "sane", state-of-the-art version of C++

Some time ago I commented on how horrible C++ has become and said it would be
nice if someone made a new language with all the efficiency and features of
C++ but nicer to program in. Someone said essentially "that's Rust". You are
another confirmation of that. I have yet to take the plunge but hope to some
day.

~~~
saghm
I had a similar conversation with someone who I consider an expert in C++
after a few months of working in C++ for the first time, and I said basically
the same thing you did (only already having Rust in mind when I made my
comment). To my surprise, he mentioned Rust immediately, instead of my having
to bring it up. Having learned C++ after Rust, I had kind of assumed that my
view of Rust as a sort of reboot of C++ wasn't going to be shared by someone
with so much C++ experience.

~~~
epage
Reboot is a good way to put it. I feel like Rust goes back to C and says "with
what we've learned how should C do OOP".

I'm excited about Rust. As a 15+ year C++ developer.

~~~
flavio81
To be fair, Objective-C has existed since 1984 and it adds nice OOP to C, that
is, Smalltalk-style OOP.

However, i must say that when I was first introduced to C++, having been
totally familiar with C, i thought that Bjarne Strostrostrostrostrostro

    
    
        *** - Program stack overflow. RESET
    

... Strostroup was a genius. I think C++ was a nice idea, but ended up
suffering from the "yeah, let's add this feature too" syndrome. I really
wonder if there is one person in the earth that actually knows the whole of
the C++14 language.

