These are chat archives for rust-lang/rust

28th
Oct 2018
Denis Lisov
@tanriol
Oct 28 2018 00:02
You may want to look at something like html5ever
wang-d
@wang-d
Oct 28 2018 00:04
I expect the text output to be 1-to-1 with the real data structures. So it's just a lot faster to dump out some text, review it, and accept that as my expected output than to type out Rust literals corresponding to what I expect.
Well, that's bizarre: I googled "exploratory programming with CRAM tests" and got a description of this workflow for some other CRAM-like test framework: https://blog.janestreet.com/repeatable-exploratory-programming/ But there's a worked example.
wang-d
@wang-d
Oct 28 2018 00:12
Maybe I'm going about this wrong? How would you start writing a web scraper for an unfamiliar website?
@tanriol
Denis Lisov
@tanriol
Oct 28 2018 00:24
First, I'd select a library that can select the parts I need. Then, probably, create an integration test reading a saved copy of the page, extracting something and comparing the extracted data with a reference copy (possibly loaded from a JSON or YAML file, for example). Then I can add more data to be extracted. Most likely I'd want to save it in some format for later use, so serialization will be needed anyway.
wang-d
@wang-d
Oct 28 2018 00:28

@tanriol That sounds pretty similar to what I had in mind, except for the reference copy. How do you generate the reference copy?

In the workflow I know, the tooling supports an "accept" operation which means, whatever the code did generate, call that the expected output. And then I'd work on the code until the expected output was actually good, accept that, and commit it.

(In case it wasn't clear, the "accept" operation actually updates the source code of my test.)
Denis Lisov
@tanriol
Oct 28 2018 00:35
No experience with the workflow you describe, but it should be interesting.
If I were writing a scraper, I'd probably just extract one item manually and assert_eq that the extracting code returns the same. This probably depends on the chosen approach. You seemingly want to explore the page, while I'd first check what data I actually want to extract and only start coding the actual extractor after that.
wang-d
@wang-d
Oct 28 2018 00:38
Fair enough. I know it wasn't you who suggested this, but any idea how to make cargo run a cram test? I'd ideally like not to write a Makefile on top of cargo.
laurent bernabé
@loloof64
Oct 28 2018 12:24
Hi everyone, I'm stuck with a module organisation in my own project.
I have this folder structure for now :
.
├── Cargo.lock
├── Cargo.toml
├── LICENSE
├── README.md
├── src
│   ├── chess_position_trainer
│   │   ├── graphic.rs
│   │   └── mod.rs
│   └── main.rs
└── target
    ├── debug
    │   ├── build
    │   ├── chess_position_trainer
    │   ├── chess_position_trainer.d
    │   ├── deps
    │   ├── examples
    │   ├── incremental
    │   └── native
    └── rls
        └── debug
And the main.rs source code is (all is working before the reorganisation)
extern crate gtk;

mod chess_position_trainer;
use chess_position_trainer::graphic::{MainWindow};

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }

    let main_window = MainWindow::new();
    main_window.show();

    gtk::main();
}
What I am trying to do is that, without having to change main.rs content, reorganize modules so that graphic module is its own folder, with a mod.rs and a new file main_window.rs
But I did not manage to make such a reorganisation for now, keeping getting into namespaces errors.
laurent bernabé
@loloof64
Oct 28 2018 12:29
unresolved import `chess_position_trainer::graphic::MainWindow`
This is my chess_position_trainer mod.rs
pub mod graphic;
My graphic mod.rs is left empty because I don't know how to declare the MainWindow structure (publicly of course)
laurent bernabé
@loloof64
Oct 28 2018 12:34
Adding the following inside it does not help either, because the namespace changes
pub mod main_window;
to chess_position_trainer::graphic::main_window::{MainWindow};
Is there a way to keep the namespace use chess_position_trainer::graphic::{MainWindow}; with my new organisation ? Regards
The new File structure :
.
├── Cargo.lock
├── Cargo.toml
├── LICENSE
├── README.md
├── src
│   ├── chess_position_trainer
│   │   ├── graphic
│   │   │   ├── main_window.rs
│   │   │   └── mod.rs
│   │   └── mod.rs
│   └── main.rs
Vitaly
@Virtuos86
Oct 28 2018 12:56
.../chess_trainer/src $ ls
chess_position_trainer  main.rs
.../chess_trainer/src $ cat main.rs
mod chess_position_trainer;
use chess_position_trainer::graphic::main_window::MainWindow;

fn main() {
    let main_window = MainWindow {};
}
.../chess_trainer/src $ cd chess_position_trainer/
.../chess_trainer/src/chess_position_trainer $ ls
graphic  mod.rs
.../chess_trainer/src/chess_position_trainer $ cat mod.rs
pub mod graphic;
.../chess_trainer/src/chess_position_trainer $ cd graphic/
.../chess_trainer/src/chess_position_trainer/graphic $ ls
main_window.rs  mod.rs
.../chess_trainer/src/chess_position_trainer/graphic $ cat mod.rs
pub mod main_window;
.../chess_trainer/src/chess_position_trainer/graphic $ cat main_window.rs 
pub struct MainWindow;
laurent bernabé
@loloof64
Oct 28 2018 12:57
Thanks @Virtuos86 . But what I tryied to do is to remove the middle main_window namespace when keeping the same structure : but it seems that I can't. So decided to rename main_window in windows and to put all window related code there. Thanks anyway :smiley:
Vitaly
@Virtuos86
Oct 28 2018 13:04
For use chess_position_trainer::graphic::{MainWindow};need to add to graphic::mod.rs a linepub use self::main_window::MainWindow;
laurent bernabé
@loloof64
Oct 28 2018 13:04
Yes, I try it right now :smiley:
Vitaly
@Virtuos86
Oct 28 2018 13:05
OK :smile:
laurent bernabé
@loloof64
Oct 28 2018 13:07
I got new errors :
$ cargo run
   Compiling chess_position_trainer v0.1.0 (/home/laurent-bernabe/Documents/Programmation/ProjetsPersos/Rust/chess_position_trainer)
error[E0432]: unresolved import `self::main_window`                            
 --> src/chess_position_trainer/graphic/mod.rs:1:15                            
  |                                                                            
1 | pub use self::main_window::MainWindow;                                     
  |               ^^^^^^^^^^^ Could not find `main_window` in `self`           

error[E0432]: unresolved import `chess_position_trainer::graphic::main_window` 
 --> src/main.rs:4:38                                                          
  |                                                                            
4 | use chess_position_trainer::graphic::main_window::{MainWindow};            
  |                                      ^^^^^^^^^^^ Could not find `main_window` in `graphic`

error: aborting due to 2 previous errors                                       

For more information about this error, try `rustc --explain E0432`.            
error: Could not compile `chess_position_trainer`.                             

To learn more, run the command again with --verbose.
I should have missed something :cry:
Vitaly
@Virtuos86
Oct 28 2018 13:11
Obviously, do you forgotten to add a line pub mod main_window; before pub use ...?
laurent bernabé
@loloof64
Oct 28 2018 13:13
Yes, chances are that this is because of this forgotten line
Yes success ! :smile: Thank you very much :smile:
I have to get used to modules yet :smiley:
If I've well understood, the first line declares the submodule, and the second line makes its MainWindow struct into the current scope (graphic).
laurent bernabé
@loloof64
Oct 28 2018 13:48
Is there a simple way to use a kind of spread operator for arrays ?
I mean
func(...arr)
Instead of
func(arr[0], arr[1], ...)
red75prime
@red75prime
Oct 28 2018 13:54
fn foo([a, b, c]: [u32; 3])
Functions with variable number of arguments aren't supported in Rust.
laurent bernabé
@loloof64
Oct 28 2018 14:00
Thank you very much :smile: So I write all 3 parameters, as it is an already defined GTK function
red75prime
@red75prime
Oct 28 2018 14:05
You can always define a macro. macro_rules! spread2{ ($func:ident($arr:ident)) => {$func($arr[0], $arr[1])} }
Ichoran
@Ichoran
Oct 28 2018 14:07
It would be nice if the macro automatically filled in all the arguments that the function had instead of you needing to know how many there were, but I couldn't find out if there was a way to know the arity of the function or recurse over the argument list.
red75prime
@red75prime
Oct 28 2018 14:09
@Ichoran As far as I know it is impossible. Unless there's some incredibly clever trick. I doubt it though, macros are purely syntactical, there's no feedback from a compiler.
Ichoran
@Ichoran
Oct 28 2018 14:11
That's not entirely true or custom derive would be impossible. (It's a different type of macro, though.)
red75prime
@red75prime
Oct 28 2018 14:12
Yes, macros-by-example (AKA 1.0) are syntactical
Ichoran
@Ichoran
Oct 28 2018 14:15
There aren't enough docs on function-like procedural macros for me to be able to figure out whether that could work.
laurent bernabé
@loloof64
Oct 28 2018 14:15
Thank you, for now I won't write macro as I did not covered them yet
Ichoran
@Ichoran
Oct 28 2018 14:16
(Then again they've been in stable for all of two days, so I guess that's not too surprising!)
laurent bernabé
@loloof64
Oct 28 2018 14:16
I have a lifetime issue with a custom struct method, and I did not figured out how to handle simply
use gtk::prelude::*;
use gtk::{DrawingArea};

pub struct ChessBoard
{
    drawing_area: DrawingArea,
    cells_size: u32,
}

impl ChessBoard
{
    pub fn new(cells_size: u32) -> ChessBoard
    {
        let drawing_area = DrawingArea::new();
        drawing_area.connect_draw(|_, cr|{
            let pink_color = [255.0/255.0, 204.0/255.0, 221.0/255.0];
            let white_cell_color = [255.0/255.0, 255.0/255.0, 179.0/255.0];
            cr.set_source_rgb(
                pink_color[0],
                pink_color[1],
                pink_color[2],
            );
            cr.paint();

            let half_cells_size = (cells_size as f64) * 0.5;
            let other_bound = (cells_size as f64) * 8.5;

            cr.rectangle(
                half_cells_size,
                half_cells_size,
                other_bound,
                other_bound,
            );
            cr.set_source_rgb(
                white_cell_color[0],
                white_cell_color[1],
                white_cell_color[2],
            );
            cr.paint();

            Inhibit(false)
        });

        ChessBoard {
            drawing_area: drawing_area,
            cells_size: cells_size,
        }
    }

    pub fn get_drawing_area(&self) -> &DrawingArea
    {
        &self.drawing_area
    }
}
$ cargo run
   Compiling chess_position_trainer v0.1.0 (/home/laurent-bernabe/Documents/Programmation/ProjetsPersos/Rust/chess_position_trainer)
error[E0373]: closure may outlive the current function, but it borrows `cells_size`, which is owned by the current function
  --> src/chess_position_trainer/graphic/chessboard.rs:15:35                   
   |                                                                           
15 |         drawing_area.connect_draw(|_, cr|{                                
   |                                   ^^^^^^^ may outlive borrowed value `cells_size`
...                                                                            
25 |             let half_cells_size = (cells_size as f64) * 0.5;              
   |                                    ---------- `cells_size` is borrowed here
help: to force the closure to take ownership of `cells_size` (and any other referenced variables), use the `move` keyword
   |                                                                           
15 |         drawing_area.connect_draw(move |_, cr|{                           
   |                                   ^^^^^^^^^^^^                            

error: aborting due to previous error                                          

For more information about this error, try `rustc --explain E0373`.            
error: Could not compile `chess_position_trainer`.                             

To learn more, run the command again with --verbose.
Because it just a function parameter for the object initialisation, I am trying to solve it without the move keyword
I need the parameter after the closure definition, so move is not adequate here
As I am still a great Noob regarding lifetimes, can I safely add a static lifetime to the parameter cells_size ?
Ichoran
@Ichoran
Oct 28 2018 14:21
Can't you just .clone() it?
I.e. (cells_size.clone() as f64) * 0.5
laurent bernabé
@loloof64
Oct 28 2018 14:23
Thanks :smile:
Did not thought about this solution
Ichoran
@Ichoran
Oct 28 2018 14:24
Since you only want the value, not, say, to permanently retain a reference to the value, cloning should do what you want.
laurent bernabé
@loloof64
Oct 28 2018 14:25
Yes, it would be great, be the compiler still reject it
I suppose it is because we still try to call clone on the original reference, which is not static and has no sufficient lifetime
red75prime
@red75prime
Oct 28 2018 14:30
Use move |_, cr|, or copy cells_size explicitly |_, cr| { let cells_size = cells_size; ...
Non-move closures capture variable by reference
laurent bernabé
@loloof64
Oct 28 2018 14:31
Thank you :smile: I'll try these solutions.
I understand better the reference problem, in my original code, it tries to pass it by reference
Ichoran
@Ichoran
Oct 28 2018 14:32
Oh, whoops, I didn't read your code carefully enough to notice the closure. Sorry!
laurent bernabé
@loloof64
Oct 28 2018 14:32
No problem :smiley:
Thank you again :smile: It worked with the cells_size redefinition inside the new method let cells_size = cells_size
And the move keyword for the closure
laurent bernabé
@loloof64
Oct 28 2018 14:38
In fact, just using the move keyword works, but I did not thought it would worked as I have to reuse the cells_size variable in the last line. My bet is that it is because the move keyword make the closure capture by value and not reference, as you just pointed me
And that cells_size already implements the Copy trait as an Integer
Ichoran
@Ichoran
Oct 28 2018 14:51
Yeah
I really didn't pay enough attention to the details, sorry again!
laurent bernabé
@loloof64
Oct 28 2018 15:00
No problem :smile: