These are chat archives for rust-lang/rust

28th
Sep 2017
Zakarum
@omni-viral
Sep 28 2017 09:44

@steveklabnik in this example

fn foo<'a>( ... ) { ... }

'a is defined for foo arguements and whole it's body

The same as in

fn foo<T> (...) {
    let x: T = ...
}

Tis defined in foo's body

TatriX
@TatriX
Sep 28 2017 10:10
What is the canonical way to return "success/failure" without additional info? Return bool?
Sebastian Blei
@iamsebastian
Sep 28 2017 10:10
@TatriX Result<_, _>
TatriX
@TatriX
Sep 28 2017 10:11
And then return Err(()) or Ok(())?
Jonas Platte
@jplatte
Sep 28 2017 10:12
Can't say I've seen Result<(), ()> much.. I think it is actually bool.
Zakarum
@omni-viral
Sep 28 2017 10:12
@TatriX either Option<T> where T is success result or Result<T, E> where E describes why it has failed
Rui Azevedo
@neu-rah
Sep 28 2017 10:13
any objections to use Option<T> as result success/fail? it reminds me haskell Maybe ;)
Zakarum
@omni-viral
Sep 28 2017 10:14
Option<T> is good choice if failure reason is obvious
Jonas Platte
@jplatte
Sep 28 2017 10:14
@omni-viral I think you misunderstood the question. @TatriX said "without additional info".
TatriX
@TatriX
Sep 28 2017 10:15
Thanks, I think bool is fine in my case.
Denis Lisov
@tanriol
Sep 28 2017 10:15
If you're talking about a failure then it's Result<(), ()>
Rui Azevedo
@neu-rah
Sep 28 2017 10:15
@omni-viral agree
Zakarum
@omni-viral
Sep 28 2017 10:15
@jplatte yeah Result<(), ()> looks like overkill
lemonxah
@lemonxah
Sep 28 2017 10:15
if you dont have any information then yes i would just use a bool
Denis Lisov
@tanriol
Sep 28 2017 10:15
Or, better, Result<(), MyError>
lemonxah
@lemonxah
Sep 28 2017 10:16
if you want to know what error occured
Zakarum
@omni-viral
Sep 28 2017 10:17
I remember working on the project where every function that may fail returns bool
Sebastian Blei
@iamsebastian
Sep 28 2017 10:17
But I think the handling of a returned Result is much more declarative, than matching true || false.
Zakarum
@omni-viral
Sep 28 2017 10:17
It was horrible expierence
Denis Lisov
@tanriol
Sep 28 2017 10:17
Unlike bool, if you use Result, you can, for example, propagate it with ?
Sebastian Blei
@iamsebastian
Sep 28 2017 10:18
I totally would prefer Option / Result over a bool.
Rui Azevedo
@neu-rah
Sep 28 2017 10:18
Either is a better choice if extra info is needed
Denis Lisov
@tanriol
Sep 28 2017 10:18
@TatriX Are you writing a binary or a library?
TatriX
@TatriX
Sep 28 2017 10:18
A binary
Zakarum
@omni-viral
Sep 28 2017 10:18
@neu-rah Result is almost the same as Either but with better defined use case
Denis Lisov
@tanriol
Sep 28 2017 10:19
Then it matters less... however, I'd still use Result.
Rui Azevedo
@neu-rah
Sep 28 2017 10:19
@omni-viral right again :D
Denis Lisov
@tanriol
Sep 28 2017 10:20
Especially taking into account that Result is #[must_use] and if you forget to check it you get a warning. Not so for Option or bool.
Rui Azevedo
@neu-rah
Sep 28 2017 10:20
@omni-viral just googled for Either because of my background (and rust noobness)
Zakarum
@omni-viral
Sep 28 2017 10:21
@neu-rah I'd say that haskell is a good background :smile:
Rui Azevedo
@neu-rah
Sep 28 2017 10:21
@omni-viral right again :D
@omni-viral missing custom operators a lot! it would make piping the failure much more elegant
Denis Lisov
@tanriol
Sep 28 2017 10:24
@TatriX And BTW, do you really know nothing about the failure ("no additional data")?
Zakarum
@omni-viral
Sep 28 2017 10:25
@neu-rah ? do the good job
Rui Azevedo
@neu-rah
Sep 28 2017 10:26
@tanriol sometimes its not really a failure or error, its a good way of signalling an end of line.
as solving "2+x" in symbolic processor
TatriX
@TatriX
Sep 28 2017 10:26
@tanriol well I know the reason Unit cannot move due to collision but I don't care much about why it can't move
Rui Azevedo
@neu-rah
Sep 28 2017 10:27
@omni-viral people seem to not like it: rust-lang/rfcs#818
TatriX
@TatriX
Sep 28 2017 10:27
Or maybe Speed is zero so again action wasn't taken, and it's fine.
Rui Azevedo
@neu-rah
Sep 28 2017 10:28
@TatriX yup, meaning the work is done
Denis Lisov
@tanriol
Sep 28 2017 10:32
@TatriX Well, if you consider "did not move" a failure then I'd probably pass up the reason. If you don't care, maybe not return any status at all, just modify the required variables?
@neu-rah Well, if it's not a failure but an "end of line", I'd use an Option instead. Basically the question for me is "is this, by default, an error?"
TatriX
@TatriX
Sep 28 2017 10:34
Probably when the reason will be important I'll update the code to return one. For now I'm fine with bool I guess.
CrLF0710
@crlf0710
Sep 28 2017 10:36
no, please dont... use bool instead of Result is not casual rust at all...
Jonas Platte
@jplatte
Sep 28 2017 10:36
@crlf0710 std does it. It's perfectly valid.
Meanwhile nobody has provided a real-world example where std or a popular crate uses Result<(), ()>.
Denis Lisov
@tanriol
Sep 28 2017 10:37
@jplatte Does it really return bool to distinguish a failure?
CrLF0710
@crlf0710
Sep 28 2017 10:38
@jplatte Does it? Curious where it does so...
Jonas Platte
@jplatte
Sep 28 2017 10:38
Depends on what you call a "failure". You could say it returns a bool to indicate whether inserting a value into the HashSet succeeded or failed.
Denis Lisov
@tanriol
Sep 28 2017 10:40
@jplatte Not really, the insertion succeeds in both cases (as in "the element is in the set now"). It just returns additional information ("it was the first insertion" vs "ok, it was already there"). It's perfectly ok to add an element to a set that was already present in it.
Rui Azevedo
@neu-rah
Sep 28 2017 10:41
@TatriX agree with @tanriol Option for end of line or Result for Error. Bool is the worst choice in my opinion
Denis Lisov
@tanriol
Sep 28 2017 10:41
@TatriX The question, basically, is "is this a failure". If you say "this is a failure", then use a Result. If it is a perfectly normal result then use whatever you want.
oh, it returns io::Result :-\
Jonas Platte
@jplatte
Sep 28 2017 10:43
@tanriol I think you're assuming everybody shares your very specific idea of success / failure.
Denis Lisov
@tanriol
Sep 28 2017 10:44
You can have a find_best_move method documented to return the best move, if there is any, and return an Option as it's perfectly ok to return "there are no moves"
Jonas Platte
@jplatte
Sep 28 2017 10:44
I agree with @TatriX' decision of using bool for now, and re-evaluating later. If it is actually a hard error that the caller is meant to always handle, sure, then Result is the better choice.
But then you would usually also have an Err type other than ().
@tanriol Yes but we aren't talking about the context of "there might be a result, or none". We are talking about "action might succeed (without a value to return) or not"
TatriX
@TatriX
Sep 28 2017 10:47
Ok, I have a bit more complex question
I have a turn based game for 2 players
Denis Lisov
@tanriol
Sep 28 2017 10:48
@jplatte Here I assume that a HashSet is an approximation of a mathematical set, which, for every element, either contains it or not. The set operations generally don't care whether you're re-adding an element.
TatriX
@TatriX
Sep 28 2017 10:48
And I need a way to find a current player.
I can do it quite simple with match, but there is a problem. I want to modify that player (for example move it, changing it's position vector)
Zakarum
@omni-viral
Sep 28 2017 10:49
you can do this with match
just use Variant(ref mut) => ... in arms
TatriX
@TatriX
Sep 28 2017 10:49
The problem is, I don't want to write this match in every function, so I wrote a helper function.
But it mutably borrows the parent object
Like this:
self.get_player().move_unit(dir, &self.world_map);
And it doens't compile, because self is already borrowed mutably in the get_player()
Zakarum
@omni-viral
Sep 28 2017 10:51
Make get_player method of the field of self
Jonas Platte
@jplatte
Sep 28 2017 10:51
@TatriX Can you paste the definition of get_player?
Zakarum
@omni-viral
Sep 28 2017 10:51
self.current_player.get().move_unit(dir &self.world_map)
TatriX
@TatriX
Sep 28 2017 10:51
fn get_player(&mut self) -> &mut Player {
        use CurrentPlayer::*;
        match self.current_player {
            Player1 => &mut self.player1,
            Player2 => &mut self.player2,
        }
    }
Denis Lisov
@tanriol
Sep 28 2017 10:51
Maybe just pass the current player as an argument?
TatriX
@TatriX
Sep 28 2017 10:55
I need to change several things. 1) current player Action Points 2) current player position 3) world_map data used for collision detection.
So probably I need 2 mutables references, for the player and for the map. And I can't find a simple solution on how can I do it.
Jonas Platte
@jplatte
Sep 28 2017 10:55
Hmm, my first idea to solve this would be to store the position information in / alongside the map instead of the player, but I'm not entirely sure if that's actually an improvement readability-wise (I think it should make implementing movement easier though).
TatriX
@TatriX
Sep 28 2017 10:56
Yes, it's possible, but it still don't fix my problem with boilerplate match
Denis Lisov
@tanriol
Sep 28 2017 10:57
You can pass down mutable references to two different fields, no problem.
TatriX
@TatriX
Sep 28 2017 10:57
Basically I have to write the following everywhere:
match self.current_player.clone() {
            CurrentPlayer::Player1 => {
...
            }
            CurrentPlayer::Player2 => {
...
            }
        }
I think I'm using a wrong approach with that current_player "pointer", but I can't find a better way yet.
Jonas Platte
@jplatte
Sep 28 2017 10:59
There is a way of getting mutable references to distinct fields without the boilerplate of matching everywhere, but it's also a little bit weird. It might work though if you always need this specific combination of current player + map:
fn get_map_and_player(&mut self) -> (&mut Map, &mut Player) {
    use CurrentPlayer::*;
    let current_player = match self.current_player {
        Player1 => &mut self.player1,
        Player2 => &mut self.player2,
    };

    (&mut self.map, current_player)
}
TatriX
@TatriX
Sep 28 2017 11:00
Oh, it could work, thanks!
Michal 'vorner' Vaner
@vorner
Sep 28 2017 11:30
I'm not sure this is the right place to ask, but does anybody know if the workshops will be available on some kind of video later on after the RustFest? I'm going through the schedule and have hard time choosing, there are multiple I'd like to attend.
Jonas Platte
@jplatte
Sep 28 2017 11:33
@vorner I'm not sure about workshops (never been at a RustFest) but the recordings of the talks from the last RustFest can be found on YouTube
Michal 'vorner' Vaner
@vorner
Sep 28 2017 11:38
I know the talks are available, but unlike the talks, the workshops run in parallel.
Jonas Platte
@jplatte
Sep 28 2017 11:40
Ah, alright.
David Harvey-Macaulay
@alteous
Sep 28 2017 15:36
It would be great if one could have 'sub-enums'.
enum Operation {
    enum Cake {
        Bake,
        Eat,
    },
    enum Missiles {
        Launch,
    },
}

let op = Operation::Cake::Eat;
Hans W. Uhlig
@huhlig
Sep 28 2017 15:37
hmm... how would you enumerate them
just top to bottom?
ignoring the sub type?
David Harvey-Macaulay
@alteous
Sep 28 2017 15:41
The point is it would replace patterns like this:
enum Operation {
    BakeCake,
    EatCake,
    LieAboutCake,
    LaunchMissiles,
    StowMissiles,
    DestroyMissiles,
}

enum Operation {
    Cake(CakeOperation),
    Missiles(MissileOperation),
}
The representation would be the same as the top.
The Cake variant of the original snippet would just namespace its members.
Zakarum
@omni-viral
Sep 28 2017 15:59
So what would be the type of Operation::Cake::Eat?
Cake or Opeartion?
And how to create the other one?
Hans W. Uhlig
@huhlig
Sep 28 2017 15:59
I think it would technically be both
Cake being a subtype of Operation
does rust understand subtypes
Zakarum
@omni-viral
Sep 28 2017 16:00
We don't have subtypes in rust
Hans W. Uhlig
@huhlig
Sep 28 2017 16:00
can traits extend other traits?
Zakarum
@omni-viral
Sep 28 2017 16:00
Traits are not types
Hans W. Uhlig
@huhlig
Sep 28 2017 16:01
hmm
Zakarum
@omni-viral
Sep 28 2017 16:01
And I take trait extension to be more sugar than actual thing
Hans W. Uhlig
@huhlig
Sep 28 2017 16:02
traits are just sugar
much like method pinning is
Zakarum
@omni-viral
Sep 28 2017 16:03
Well. You can indeed say that they are.
Since they can be replaced with plain functions
But than again. Types are sugar too :jack_o_lantern:
Only ones and zeroes aren't
David Harvey-Macaulay
@alteous
Sep 28 2017 16:30
Should I ever be concerned about the runtime overhead of std::sync::mpsc channels?
The async variety, that is.
Zakarum
@omni-viral
Sep 28 2017 16:32
The overhead is bigger than 0
David Harvey-Macaulay
@alteous
Sep 28 2017 16:32
I'm using them to pass thread-safe messages in a game client.
Zakarum
@omni-viral
Sep 28 2017 16:33
If you pass too many simulteneously they can collide and fight each other
David Harvey-Macaulay
@alteous
Sep 28 2017 16:33
Is the overhead significantly worse than pushing to a Vec? I currently have only one thread.
@omni-viral Noted r.e. passing many at once.
Zakarum
@omni-viral
Sep 28 2017 16:34
With one thread it is close to pushing into list
David Harvey-Macaulay
@alteous
Sep 28 2017 16:35
That's not so bad then. Thanks.
Zakarum
@omni-viral
Sep 28 2017 16:36
I think it should cost you one allocation, relaxed load and cas per message
Hey. Wait a minute.
You are using one from sync
No cas then
David Harvey-Macaulay
@alteous
Sep 28 2017 16:38
It's something I could always optimise at a later date. I'm using the asynchronous version.
If I send my messages in batches perhaps that could keep the allocation count down.
struct Batch(Vec<Message>)
Zakarum
@omni-viral
Sep 28 2017 16:40
You'll have potentially two per message
David Harvey-Macaulay
@alteous
Sep 28 2017 16:41
In the worst case. Obviously I'd have to ensure that messages are actually batched.
Zakarum
@omni-viral
Sep 28 2017 16:42
I think that using singlethreaded queue is simplier
Since you already have only on thread
For batching there is smallvec
David Harvey-Macaulay
@alteous
Sep 28 2017 16:44
I only have one thread at the moment. I'm trying to design the program so that it's simple to convert to a threaded program later down the line.
Thanks, noted. Gtg.
Zakarum
@omni-viral
Sep 28 2017 16:44
It is vec with small portion on stack
unreadable
@unreadable
Sep 28 2017 18:26
hey, what;s the fastest way to iterate a collection? for i in list or for &item in list.iter() ?
or there might be something better
Denis Lisov
@tanriol
Sep 28 2017 18:43
It depends, but generally "the fastest way" is not the correct question.
Steve Klabnik
@steveklabnik
Sep 28 2017 18:43
if item is Copy, those do the same thing
possibly
it depends on the type of list too
Denis Lisov
@tanriol
Sep 28 2017 18:45
@krypton97 What do you want to do with the items?
Felipe Seré
@felipesere
Sep 28 2017 22:08
Hi! I am going through Philip Wadlers paper on Monads and I tried to code along in Rust
I got a Monad trait working, but trying to implement it for something like Identity stumbles on a FnOnce(T) -> Monad<U> not having a statically defined size during compile time
You can see the code here: https://pastebin.com/GzdJCB7j
How do I tell rust: " I want the argument to be a function from T to anything that implements the Monad Trait for some value U"?