Re: [rust-dev] Destructuring and references
Hi, Daniel, Consider this example: let vec = vec![(1u, 2u)]; for (a, b) in vec.iter() { println!({}: {}, a, b); } a and b here are of type uint, which is implicitly copyable. It is not natural to take references to it when passing around its values. That is, variables under pattern are not *always* taken as a reference. Another reason is consistency. Patterns and corresponding constructor expressions are meant to be inverses of each other: let x = (1u, 2i); match x { (a, b) = ... } See how nicely `(a, b)` and `(1, 2)` correspond to each other. `a` is of type uint, just like the literal 1u, and `b` is int, like 2i. This expands to other types too, including complex ones like `Box`. With automatic references there won't be such consistency. 2014-11-10 20:29 GMT+03:00 Daniel Trstenjak daniel.trsten...@gmail.com: Dear rust devs, let vec = vec![(a.to_string(), b.to_string())]; for (ref a, ref b) in vec.iter() { println!({}: {}, a, b); } I understand that the '' and 'ref' are needed here, because otherwise the 'String' could be moved out of the 'Vec'. I don't quite understand, why there's the need for these explicit refs, why isn't the outer '' enough to indicate that everything inside of the pattern is also referenced? Why isn't it possible to just have (with the same semantics): for (a, b) in vec.iter() { println!({}: {}, a, b); } Without these refs pattern matching would be aesthetically more in sync with the types, which I would consider very pleasing. Greetings, Daniel ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] String capitalization
Hi, Ollie, This variant is terser, but it could be even more readable if there were some kind of connect() for iterators. It surprised me that there is no such thing in Rust iterators. It would be possible to use some kind of interleave() for iterators for the same purpose, but there is no such thing as well. Hence I had to use fold() and then pop_char() which is rather nasty as it breaks method chain. On the other hand, this variant performs less allocations than your original version because the resulting string is allocated in advance. use std::char; fn name_from_file(file: String) - String { let mut r = file.as_slice().split('-') .map(|w| char::to_uppercase(w.char_at(0)).to_string().append(w.slice_chars(1, w.len( .fold( String::with_capacity(file.len()+1), |r, w| r.append(w.as_slice()).append( ) ); r.pop_char(); r } fn main() { let hypenated_string = hello-there.to_string(); let capitalized_string = name_from_file(hypenated_string); println!({}, capitalized_string); } See it in action here: http://is.gd/UKKB96 BTW, I suggest you to use Stackoverflow [1] (preferred) or Reddit [2] to ask questions like this. The active community there is much larger than here, so you can get an answer quicker. [1]: http://stackoverflow.com/questions/tagged/rust [2]: http://www.reddit.com/r/rust/ On 12 сент. 2014 г., at 15:35, Oldřich Vetešník oldrich.vetes...@gmail.com wrote: Hello, this is probably going to sound silly, but can this be written better? I’d like to turn “hello-there” into “Hello There”. I was thinking about something along the lines of split - map - capitalize - join but the capitalization seems kind of awful to me. use std::char; fn name_from_file(file: String) - String { let mut words: Vecstr = file.as_slice().split('-').collect(); let mut cap_words= Vec::new(); for word in words.mut_iter() { let first = char::to_uppercase(word.char_at(0)).to_string(); let rest = word.slice_chars(1, word.len()); let cap_word = first.append(rest); cap_words.push(cap_word); } cap_words.connect( ) } fn main() { let hypenated_string = hello-there.to_string(); let capitalized_string = name_from_file(hypenated_string); println!({}, capitalized_string); } Thanks, Ollie ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Closures with owned environments
Hi, Allen! In fact, it is possible to do it now without DST, using unboxed closures only: #![feature(unboxed_closures, unboxed_closure_sugar)] fn make_adder(x: int) - Box|: int| - int { box |: y: int| x + y } fn main() { let f = make_adder(3); println!({}, f.call((4i,))); } Test it here: http://is.gd/mCJ6Dh This code employs the idea that unboxed closure is just an instance of some anonymous struct implementing one of Fn* traits, so we can just return a boxed trait object representing the closure. The call syntax is ugly, however, but this should change in the nearest future (though explicit dereferencing, like (*f)(x), will likely be needed anyway). 2014-09-10 0:39 GMT+04:00 Allen Welkie allen.wel...@gmail.com: In this stackoverflow question: http://stackoverflow.com/questions/21130272/return-a-closure-from-a-function Chris Morgan mentions the possibility of adding closures with owned environments with the DST implementation. Is this being done with the current DST effort? If not, are there plans to add it? ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Is there a PNG lib?
Hi! These libraries may be interesting for you: * https://github.com/servo/rust-png * https://github.com/PistonDevelopers/rust-image It is also very simple to run external tools like ImageMagick from Rust. You will need Command [1] API for that. [1]: http://doc.rust-lang.org/std/io/process/struct.Command.html On 08 сент. 2014 г., at 17:44, Oldřich Vetešník oldrich.vetes...@gmail.com wrote: Hello, I’m curious - is there a PNG processing lib for Rust? I’d like to write a tiny client tool for processing a directory of images into HTML and I’ll need to resize those big images. I tried searching but wasn’t very successful. :-) Thank you, Ollie ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Is there a PNG lib?
You’re welcome :) Cargo will provide a central repository in the future, but in the meantime you can use these sites [1][2] to search for packages. Also, as Github is the main repository hosting used by the Rust community, you can search there and you can be fairly confident that if you can’t find something there then it probably does not exists :) [1]: http://www.rust-ci.org/ [2]: http://rustkit.io/ On 08 сент. 2014 г., at 18:03, Oldřich Vetešník oldrich.vetes...@gmail.com wrote: Awesome, thank you guys! I’m really looking forward to “cargo search”. :-) Ollie On Monday 8 September 2014 at 15:57, Vladimir Matveev wrote: Hi! These libraries may be interesting for you: * https://github.com/servo/rust-png * https://github.com/PistonDevelopers/rust-image It is also very simple to run external tools like ImageMagick from Rust. You will need Command [1] API for that. [1]: http://doc.rust-lang.org/std/io/process/struct.Command.html On 08 сент. 2014 г., at 17:44, Oldřich Vetešník oldrich.vetes...@gmail.com (mailto:oldrich.vetes...@gmail.com) wrote: Hello, I’m curious - is there a PNG processing lib for Rust? I’d like to write a tiny client tool for processing a directory of images into HTML and I’ll need to resize those big images. I tried searching but wasn’t very successful. :-) Thank you, Ollie ___ Rust-dev mailing list Rust-dev@mozilla.org (mailto:Rust-dev@mozilla.org) https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] [ANN] Iobuf
Hi! I’ve noticed this piece of code in your library: #[inline] fn as_mut_slice(self) - mut [u8] { unsafe { match self { OwnedBuffer(ref v) = { let mut_v: mut Vecu8 = mem::transmute(v); mut_v.as_mut_slice() }, BorrowedBuffer(ref s) = { let mut_s: mut mut [u8] = mem::transmute(s); mut_s.as_mut_slice() }, } } } I was under impression that transmuting to mut is undefined behavior in Rust, and you need to use RefCell (or UnsafeCell) for this. Am I wrong? On 04 сент. 2014 г., at 9:17, Clark Gaebel cg.wowus...@gmail.com wrote: Hey everyone! Have you ever needed to communicate with the outside world from a rust application? Do you need to send data through a network interface, or touch a disk? Then you need Iobufs! An Iobuf is a nifty abstraction over an array of bytes, which makes writing things like highly efficient zero-copy speculative network protocol parsers easy! Any time I need to do I/O, I reach for an Iobuf to do the heavy lifting. https://github.com/cgaebel/iobuf Enjoy, - Clark ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Implementing a clone trait on mut struct.
Forgot to send a copy to mailing list. 2014-08-04 10:30 GMT+04:00 Vladimir Matveev dpx.infin...@gmail.com: Hi, Paul, The problem with Clone implementation for mutable reference is not that it does not make sense at all; after all, it is just an integer value behind the fancy name, and, for example, plain references [are cloneable](http://doc.rust-lang.org/std/clone/trait.Clone.html). However, Clone can't be implemented for mutable references because mut is unaliasable - there can't be more than one mutable reference pointing to the same thing at the same time, but Clone does exactly this. Moreover, you say that `PoolT` is an abstraction over `ArcRWLockT`, right? This means that `T` should also be Share + Send, and while references are Share, they are not Send - you can't send a reference to another task because it can point to original task's stack, and if that original task exits, the reference may become invalid. So it is likely that your overall design is incorrect. It's hard to say more without more details on what you want to do. 2014-08-04 6:02 GMT+04:00 Paul Nathan pnathan.softw...@gmail.com: Hi, I've gotten myself in a bit of a bind. As part of my work with shared memory with workers, I've implemented a (relatively leaky at the moment) abstraction over ArcRWLockT, called Pool. Part of my abstraction requires the Clone trait be implemented for T. However, up in the user layer, I have something that looks roughly like this struct Agent { ... } struct Tracker { Pool'r mut Agent } At which point, the type checker complains and asks me to implement something of this signature: impl'r Clone for 'r mut Agent { Which seems quite patently ridiculous - as if I understand things something, I'm being asked to return a reference to something on the *stack* of the fn clone() function. Something smells fishy here... Some assistance and clarification would be appreciated. Regards, Paul ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Rust Executable size
Hi, Adrian, Currently Rust uses static linking to build executables. This means that the simplest «hello world» program utilizing standard library will take all of this library and all dependent libraries, including Rust runtime, into itself. That’s why the binary is large. If you want to use dynamic linking, you can invoke rustc with `-C prefer-dynamic` arguments, this will link the program dynamically, and it will be much smaller (8 KB in my case): % cat main.rs fn main() { println!(Hello world) } % rustc -C prefer-dynamic main.rs % ls -lh main -rwxr-xr-x 1 dpx-infinity dpx-infinity 8,0K июл 11 12:14 main However, this will mean that the binary is no longer portable; you can’t compile it yourself and distribute it to other machines unless these machines also have the same version of Rust installed. Disk size is cheap these days, and portability really do matter, so that’s why the static linkage is default. BTW, Go does exactly the same thing. On 11 июля 2014 г., at 12:07, Adrian Mercieca amerci...@gmail.com wrote: Hi all, I am just starting out looking at Rust and am following the tutorial. I have compiled the sample 'hello world' program (code below - copied from the tutorial) and compiled it. I was somewhat taken aback at the size of the executable size for such a small program. On my Ubuntu 13.10 machine, the resultant executable was a whopping 1054476 bytes. I stripped the program and the resultant file was still 806816 bytes. Why is the executable so large? Is there anything I might be doing wrong? Perhaps I need to use some compiler switches? Thanks for any pointers in this regard. - Adrian. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Cargo multiple targets
Hi, Isak! According to manifest documentation [1] you can specify crate type (dynamic or static lib or rlib) using crate_type option: [[lib]] … crate_type = [dylib, staticlib] The above configuration should build you both .a and .so files. [1]: http://crates.io/manifest.html, search for crate_type w/o quotes On 02 июля 2014 г., at 15:58, Isak Andersson cont...@bitpuffin.com wrote: Hi! Thanks for the reply! Apparently multiple targets does in fact work. Just that you can't rely on the default path anymore, so I had to add the path = ... to both the [[lib]] and [[bin]]. Not sure if this is a bug or not. However the library compiles as an rlib and I'm not sure how to change it to build a C library instead (a .a or .so on *nix or .lib I think on windows). Actually I'm not even sure how to make rustc build a C library so I guess that's what I will start looking at. On Wed, Jul 2, 2014 at 1:37 PM, Sebastian Gesemann s.gesem...@gmail.com wrote: On Wed, Jul 2, 2014 at 12:49 PM, Isak Andersson wrote: Hello Rust folks! I am using Cargo and I am trying to specify mulitple targets in my Cargo.toml file. First of all is this even possible? ... [package] name = hmproof version = 0.1.0 authors = [ i...@houstonmedia.se ] [[bin]] name = hmwhoami [[lib]] name = proof (I also tried adding a path) path = src/proof.rs [dependencies.rust-http] git = https://github.com/chris-morgan/rust-http.git; I also tried putting the [[lib]] part after the dependencies part. The error I get is this: error: couldn't read src/bin/hmwhoami.rs: couldn't open file (no such file or directory [...] Whiich doesn't make any sense at all to me. Why does it suddenly start looking in src/bin? According to http://crates.io/manifest.html the default path for a binary is src (if there is no other lib) and src/bin (if there is also a lib target). You should be able to override this with path = src/hmwhoami. Do I have to put my bin code in src/bin and my lib code in src lib or what? Currently, only a single lib per package is supported and it seems, judging by the document about the manifest format, that Cargo always looks for src/lib.rs for a library unless you override this using a path=something. As for how to tell Cargo to invoke rustc with the appropriate -L option: I don't know. HTH, sg ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Fwd: self/mut self in traits considered harmful(?)
Overloading Mul for matrix multiplication would be a mistake, since that operator does not act the same way multiplication acts for scalars. I think that one of the main reasons for overloading operators is not their genericity but their usage in the code. let a = Matrix::new(…); let x = Vector::new(…); let b = Vector::new(…); let result = a * x + b; Looks much nicer than let result = a.times(x).plus(b); In mathematical computations you usually use concrete types, and having overloadable operators just makes your code nicer to read. That said, for mathematicians it is absolutely not a problem that multiplication for matrices works differently than for scalars. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Porting a small DSP test from C++ to Rust: Comments and performance observations
Hi, Kevin! * What would be the replacement for a struct-scoped static constant, so I could put a static inside a struct instead of making it a global? It is not possible now. There are some suggestions on associated items, but I don’t think they are active. Currently Rust module system is used to control scopes of statics. * Rust doesn't have prefix/postfix increment? Or, I just didn't find the right syntax of using it? Yes, Rust doesn’t have it. You should use composite assignment: x += 1. It is not an expression, though. * My biggest problem was figuring out how to use arrays. Originally, things just weren't working and I think it's because I was inadvertently copying an array instead of referring to the original. t just couldn't figure out how to create a mutable alias to an array passed into a function by reference. Well, you have correctly figured out that it is done using slices :) * I understand the reasoning behind explicit integer conversions, but depending on what one is doing, it can add to a lot of explicit conversions, and I also didn't figure out a way to do an unsigned for loop. Yes, explicit conversions may sometimes be too verbose. As for unsigned for loop, it is easy. Remember, Rust uses type inference to find out correct types of all local variables. `range()` function which creates range iterators is generic and looks like this: fn rangeT(from: T, until: T) - RangeT { … } (actual definition is different because T is not arbitrary but bounded with some traits) The `T` type parameter is determined automatically from the use site of the function. In your case it is deduced as `int` because of `length` variable (which is of `int` type). So you can just cast `length` to `uint`: for i in range(0, length as uint) { … } and `i` variable will be unsigned. BTW, why did you define `length` parameter as `int` at all? You can make it `uint` and you won’t need to do this cast. * When creating / using arrays, there is sometimes duplication of the size parameter. Is there a way to reduce that? I don’t think so. They are statically sized arrays, so they just need their size specified. When you don’t care about their size, you usually use slices anyway. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] 7 high priority Rust libraries that need to be written
Well, JSR-310 is implemented here [1], and it is licensed under GPL2 license. As far as I remember, in that case Google reproduced some internal Java API, so this seems to be a different thing. BTW, one of the implementors of JSR-310 suggested [3] looking into an older implementation which is now a backport of JSR-310 to JavaSE 7 [2]. It is licensed under BSD license, which is even more permissive. Also because Rust is a different language with completely different idioms and approaches to API design, I think we’ll have no problems in this regard - the actual API is going to be quite different from the original JSR-310. [1]: http://hg.openjdk.java.net/threeten/threeten/jdk [2]: https://github.com/ThreeTen/threetenbp [3]: https://github.com/mozilla/rust/issues/14657#issuecomment-45240889 On 10 июня 2014 г., at 20:47, Matthieu Monrocq matthieu.monr...@gmail.com wrote: Could there be a risk in using JSR310 as a basis seeing the recent judgement of the Federal Circuit Court that judged that APIs were copyrightable (in the Google vs Oracle fight over the Java API) ? -- Matthieu On Sat, Jun 7, 2014 at 6:01 PM, Bardur Arantsson s...@scientician.net wrote: On 2014-06-05 01:01, Brian Anderson wrote: # Date/Time (https://github.com/mozilla/rust/issues/14657) Our time crate is very minimal, and the API looks dated. This is a hard problem and JodaTime seems to be well regarded so let's just copy it. JSR310 has already been mentioned in the thread, but I didn't see anyone mentioning that it was accepted into the (relatively) recently finalized JDK8: http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html The important thing to note is basically that it was simplified quite a lot relative to JodaTime, in particular by removing non-Gregorian chronologies. Regards, ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Generic Database Bindings
There is also rustsqlite[1]. It would be great to have generic bindings for databases, like in Go or in Java. In Rust, however, reflective approaches of these won’t work because Rust lacks structural reflection. I guess, generic bindings will have to follow type classes approach, like Encodable/Decodable (maybe even use them, taking advantage of automatic deriving). [1]: https://github.com/linuxfood/rustsqlite On 08 июня 2014 г., at 16:19, Steve Klabnik st...@steveklabnik.com wrote: There isn't no. If you want to build a binding, just do it! The only one I'm really aware of right now is https://github.com/sfackler/rust-postgres ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Deprecating rustpkg
Hi, Fredrik, Currently a new package manager designed specifically for Rust is under active development. It is called Cargo, and you can find it here [1]. It is pretty much in very alpha stage now, but one day it will become a full package manager and build system for Rust. [1]: https://github.com/carlhuda/cargo On 07 июня 2014 г., at 23:28, Fredrik Ekholdt fre...@gmail.com wrote: Hi! Seems like this thread has been dead for a while. I am new to rust, but was playing with it today, looking for rustpkg and ended up reading this thread. I have tried to read through this thread, but it is possible that there is a newer more relevant thread covering this topic in which case I excuse myself. I am currently working on a language agnostic dependency/package manager and I was wondering whether it might suit Rusts requirements. Right now we are targeting it as a replacement to Maven/Ivy on the JVM, but the idea all along is to make it platform independent (and native) by having a small and predicable algorithm for resolution. The resolution engine is written 200 LOCs, and the overall logic (excluding metadata reading and so on) is about 400 LOCs more. (I wonder if the Rust implementation will be faster than the one in Scala? :) If there is interest I might start looking more into how to port it (I will need help though) - if not, I guess it was worth a shot! :) It is called Adept (https://github.com/adept-dm/adept) and it is in alpha for the Scala/JVM. The docs (listed below) are still unfortunately a bit scattered so I am summarising here. Some features that might be of interest: - Fast and reliable resolution of metadata using versioned metadata (which is easily safely cacheable). - Fast and reliable artifact (binary files/sources) downloads, i.e. can download from multiple sources in parallel. - Authors can describe compatibility matrixes of their modules. The short story is that authors can rank modules and thereby define which ones are compatible (or can be replaced) and in multiple files thereby having many “series” of compatible modules. Using this scheme we can emulate: “normal” versioning, (what is called) semantic” versioning and backward compatibility matrixes, but also other, more exotic, version schemes as well. AdeptHub (see below) will make it easy for authors to use the standard ones, but also make it possible to customise this. - Adept’s engine is flexible enough so that authors can publish multiple packages to multiple platforms and based on user input figure out which package platform a user should get. - Adept’s engine is flexible enough to emulate the concept of scopes/configurations/views so an author can publish different scopes/configurations/views of the same package: one for compile, one for runtime, one for testing, etc etc. - Supports resolution through multiple attributes author-defined attributes. You can require a specific version, a binary-version, but also “maturity” (or release-type”) or whatever other attribute that might be relevant. - Does not require a user to resolve (figure out which packages you need), when they check out code a project. The way this works is that Adept generates a file after resolution that contains all artifacts (their locations, their hashes, filenames) that is required, as well as current requirements and the context (which metadata and where it should be downloaded from). Users/build server will therefore get exactly the same artifacts each time they build (using the SHA-256 hashes), but using compatibility matrixes it is possible to upgrade to a later compatible version easily/programmatically. This file currently called the lockfile , but it is not to be confused with Rubygem lockfiles. Note the name ‘lockfile' will change of because of this confusion. - Is decentralized (as Git), but has a central hub, adepthub.com, (as GitHub) so first-time users can easily find things. - Decentralization makes it possible for users to change metadata (and contribute it or put it somewhere else), but also makes it possible to support a dsl/api in the build tool, where users can create requirements on build time (version ranges is supported through this). - Works offline (i.e not connected to the intertubes) provided that metadata/artifacts is locally available. It knows exactly what it needs so if something is not available it can give easy-to-understand error messages for when something is missing (which is different from Ivy/Maven although I am not sure what the story for cargo or rustpkg was…). - Supports sandboxed projects reliably (no global/changing artifacts). When you checkout a project that uses Adept, you can be sure it has the same artifacts as the one you used on your dev machine. - CLI-like search for packages (through Scalas sbt, but can be extended to a pure CLI tool). Works locally and on online repositories. -
Re: [rust-dev] Passing arguments bu reference
Aw, Gmail makes it so easy to press Reply instead of Reply to all. See below :) Hi, Christophe, Because `Vec` looks like this: struct VecT { len: uint, cap: uint, data: *mut T } its actual size is just three words, so you can freely pass it around regardless of number of items in it. So, the correct signature is this one: fn my_func(src: Vecu8) - Vecu8 However, it actually depends on your actual use case. Passing a vector by value means that the function you pass it to will consume it, and you won't be able to use it again in the calling code: let v = vec!(1, 2, 3); my_func(v); v.push(4); // error: use of moved value `v` If you don't need this (and it happens very rarely, in fact), you should use references. Whether they are mutable or not depends on what you want to do with the vector. fn modify_vector_somehow(v: mut Vecu8) { ... } let v = vec!(1, 2, 3); modify_vector_somehow(mut v); v.push(4); // all is fine 2014-06-01 12:34 GMT+04:00 Christophe Pedretti christophe.pedre...@gmail.com: Hello all, I've read this : http://words.steveklabnik.com/pointers-in-rust-a-guide I am coming from Java where everything is passed and returned by reference (except for primitive data types), no choice. I know that with C, you have to use pointers to avoid passing and returning by value. When i read the mentionned guide, things are not so evident with Rust. So, to be precise, imagine i need to write à fonction which takes à big Vecu8 (In my case it´s an SQL BLOB) as argument and returns a big Vecu8 Should i use Fn my_func(src : Vecu8) - Vecu8 Fn my_func(src : Vecu8) - ~Vecu8 Fn my_func(src : Vecu8) -Vecu8 Fn my_func(src : Vecu8) - Vecu8 Fn my_func(src : ~Vecu8) - ~Vecu8 Any other combination ? Thanks PS : i know that i have to use lifetimes and that ~ are now Box, i've omitted them to simplify my demand PS2 : genrally with a language you can accomplish the same thing with different methods, but there are also common usages, even if Rust is young, what is the usage for passing and returning large data values ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev 2014-06-01 12:34 GMT+04:00 Christophe Pedretti christophe.pedre...@gmail.com: Hello all, I've read this : http://words.steveklabnik.com/pointers-in-rust-a-guide I am coming from Java where everything is passed and returned by reference (except for primitive data types), no choice. I know that with C, you have to use pointers to avoid passing and returning by value. When i read the mentionned guide, things are not so evident with Rust. So, to be precise, imagine i need to write à fonction which takes à big Vecu8 (In my case it´s an SQL BLOB) as argument and returns a big Vecu8 Should i use Fn my_func(src : Vecu8) - Vecu8 Fn my_func(src : Vecu8) - ~Vecu8 Fn my_func(src : Vecu8) -Vecu8 Fn my_func(src : Vecu8) - Vecu8 Fn my_func(src : ~Vecu8) - ~Vecu8 Any other combination ? Thanks PS : i know that i have to use lifetimes and that ~ are now Box, i've omitted them to simplify my demand PS2 : genrally with a language you can accomplish the same thing with different methods, but there are also common usages, even if Rust is young, what is the usage for passing and returning large data values ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] failed to find an implementation of trait core::cmp::TotalEq for ~str
Hi, Christophe, You shouldn't be using `~str` at all, you should use `String`. Also, `box ` is not a replacement for `~`, they have different types. The proper replacement is `String::new()` or `.to_string(). Your code in modern Rust will look like this: /// Contains a list of properties. A property is a key-value pair. pub struct Properties { props: HashMapString, String } impl MapString, String for Properties { /// Get a property value giving its name. Return None if property does not exist. fn find'a('a self, key: String) - Option'a String { self.props.find(key) } /// Return true if a property value exists for the specified key fn contains_key(self, key: String) - bool { self.props.contains_key(key) } } 2014-05-31 22:21 GMT+04:00 Christophe Pedretti christophe.pedre...@gmail.com: Hi all, i have updated my rust compiler, i have several compilations errors on my project StrBuf does not exist any more, no problem, i now use String ~ is obsolete, no problem, i use box The last isssue is failed to find an implementation of trait core::cmp::TotalEq for ~str util\properties.rs:12 self.props.find(key) ^~~~ My code is very simple and was compiling before ///Contains a list of properties. A property is a key-value pair. pub struct Properties { props : HashMap~str, ~str } impl Map~str, ~str for Properties { ///Get a property value giving its name. Return None if property does not exist. fn find'a('a self, key : ~str) - Option'a ~str { self.props.find(key) } ///Return true if a property value exists for the specified key fn contains_key(self, key: ~str) - bool { self.props.contains_key(key) } } what i am doing wrong ? Thanks ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] cannot borrow `st` as mutable more than once at a time
2014-05-30 5:37 GMT+04:00 Kevin Ballard ke...@sb.org: It shouldn't. The for-loop desugaring looks like match mut st.execute_query() { __i = loop { match __i.next() { None = break, Some(mut __value) = { let i = __value; { // for loop body goes here } } } } } It's done with a match statement like this specifically to make the mut binding of the iterator end after the for loop. Great, didn't know it. Last time I asked (on StackOverflow, I think; that was some time ago though) there were no `match`. Then from that code alone it does look like a bug to me. Note that it refers to `st.set_string(%e%)` and `for` loop ten lines above, that is, the first one. If mutable borrow of the iterator aren't escaping the loop, then this error should not appear, right? ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] A few random questions
It happens even for this: struct Test { a: int } impl ToStr for Test { fn to_str(self) - String { self.a.to_str() } } As you can see, Test is not implementing Show, so I assumed that I could implement ToStr instead. I suspect that there is somewhere an implementation implT: ToStr Show for T and after I implemented ToStr, Test automatically became an implementation of Show, which in turn led to conflict. I might be wrong though. I'd like to note that if there was a sane implementation of overloaded functions, this could be resolved. Yes, that's how trait resolution currently works. There is an RFC on that which turns traits into something resembling type classes in Haskell, with proper resolution of overlapping instances: https://github.com/rust-lang/rfcs/pull/48, however, I'm not sure if it will help in this case. Currently if you want to implement `ToStr` manually, you should implement `std::fmt::Show` instead: use std::fmt; impl fmt::Show for Test { fn fmt(self, f: mut fmt::Formatter) - fmt::Result { write!(f, {}, self.a) } } Now you can use `to_str()`: let t = Test { a: 10 } println!({}, t.to_str()); // 10 2014-05-29 6:17 GMT+04:00 Oleg Eterevsky o...@eterevsky.com: Thanks for your answers. Can't say I understand or agree with all the decisions. 1. Not everyone prefers overloaded functions, or default arguments. Suppose, I want to add a new argument to a function in a backwards-compatible way. In Python I provide a default and everything works fine. In C++ or Java I write something like fn test(old_arg: int, new_arg: int) { ... } fn test(old_arg: int) { test(old_arg, 0) } and everything is still good. What should I do in Rust? 2. Design decision. Basically, we take Erlang's philosophy: recovering from errors is tricky and error-prone. So basically this mean that you could emulate exceptions by running a co-routing and catching its state? It makes sense, though it sounds like it overcomplicates things a bit from programmer's perspective. Also I'm a bit worried about the number of unwrap's. 4. It looks like vectors can be concatenated with + operations, but strings can't. Is it deliberate? 4. I believe so, yes. We try not to be overload-heavy. In my experience + is much more often used for strings than for vectors. Is it not? 6. I believe there is a default implementation, yes. It happens even for this: struct Test { a: int } impl ToStr for Test { fn to_str(self) - String { self.a.to_str() } } As you can see, Test is not implementing Show, so I assumed that I could implement ToStr instead. I suspect that there is somewhere an implementation implT: ToStr Show for T and after I implemented ToStr, Test automatically became an implementation of Show, which in turn led to conflict. I might be wrong though. I'd like to note that if there was a sane implementation of overloaded functions, this could be resolved. On Wed, May 28, 2014 at 5:47 PM, Steve Klabnik st...@steveklabnik.com wrote: A few quick intro answers. Just the high level, not comprehensive. 1. Not everyone prefers overloaded functions, or default arguments. I know pcwalton has strong feelings about the first, so I'll leave him to that :) 2. Design decision. Basically, we take Erlang's philosophy: recovering from errors is tricky and error-prone. Better to let a task fail and start a new one rather than to try to re-start one in the middle of whatever it's doing. 3. No opinions, but know that all of this has been changing a _lot_ recently, this may even be planned. 4. I believe so, yes. We try not to be overload-heavy. 5. This is being worked on. Vec is a new construct anyway. 6. I believe there is a default implementation, yes. 7. I'm not even getting into this one. There's been a toon of discussion about this lately. https://github.com/rust-lang/rfcs/search?q=mutabilityref=cmdformtype=Issues Hope that starts to kick off some good discussion. :) ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] cannot borrow `st` as mutable more than once at a time
Hi, Christophe, Won't wrapping the first `for` loop into curly braces help? I suspect this happens because of `for` loop desugaring, which kind of leaves the iterator created by `execute_query()` in scope (not really, but only for borrow checker). 2014-05-29 19:38 GMT+04:00 Christophe Pedretti christophe.pedre...@gmail.com: Hello all, i know that this issue is already covered by issues #9113 #6393 and #9113 but actually i have no solution. My code is a library for accessing databases. In my example, the database represented by db containes a table t with columns i:integer, f:float, t:text, b:blob. Everything works fine except the following code used to test my library match db.prepare_statement(SELECT i,f,t,b FROM t where t like ?;) { Ok(mut st) = { st.set_string(1, %o%); for i in st.execute_query() { match i { Ok(s) = println!({}:{}:{}:{}, s.get_long(0), s.get_double(1), s.get_string(2), s.get_blob(3) ), Err(e) = match e.detail { Some(s) = println!({}, s), None = () } } } st.set_string(1, %e%); - PROBLEM HERE for i in st.execute_query() { - PROBLEM HERE ... } }, Err(e) = match e.detail { None = (), Some(s) = println!({}, s) } } The compilation error says test-db.rs:71:8: 71:10 error: cannot borrow `st` as mutable more than once at a time test-db.rs:71 st.set_string(1, %e%); ^~ test-db.rs:61:17: 61:19 note: previous borrow of `st` occurs here; the mutable borrow prevents subse quent moves, borrows, or modification of `st` until the borrow ends test-db.rs:61 for i in st.execute_query() { ^~ test-db.rs:88:7: 88:7 note: previous borrow ends here test-db.rs:58 match db.prepare_statement(SELECT i,f,t,b FROM t wh ere t like ?;) { ... test-db.rs:88 } ^ error: aborting due to previous error do we have a solution for #6393 ? Thanks -- Christophe http://chris-pe.github.io/Rustic/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] StrBuf and regular expressions
And hopefully in the future the regular expression library will be updated to work on StrBuf instead of str This is very unlikely. See, you can go from `StrBuf` to `str` without allocation - `as_slice()` returns a view into the `StrBuf`. This is very cheap operation. But you cannot go from `str` to `StrBuf` without allocation and copying, which are much more expensive than slicing. Hence you should always try to use `str` where possible, only resorting to `StrBuf` when absolutely necessary (for example, when you need to accumulate a string dynamically). All APIs should also take `str` when possible. 2014-05-26 11:31 GMT+04:00 Urban Hafner cont...@urbanhafner.com: Thanks guys, I now use as_slice() when necessary. And hopefully in the future the regular expression library will be updated to work on StrBuf instead of str as this seems to be the main use case (read in file, run regexp on it). Urban On Mon, May 26, 2014 at 8:58 AM, Vladimir Matveev dpx.infin...@gmail.com wrote: My suspicion is that the automatic conversion will come back at some point, but I'm not sure. I think it will be possible to make `String` implement `Derefstr` when DST land. Then it will be possible to convert from `String` to `str` using explicit reborrowing: let sgf_slice = *sgf; I'm not sure this will be fully automatic when `String` is an arbitrary actual argument to arbitrary function, however. 2014-05-26 10:36 GMT+04:00 Andrew Gallant jams...@gmail.com: Try using `self.sgf.as_slice()` instead. The change is necessary, AFAIK, because `~str` would automatically be converted to a borrowed reference without having to explicitly call the `as_slice` method. This doesn't happen for the StrBuf (and what is now String, I think) type. My suspicion is that the automatic conversion will come back at some point, but I'm not sure. - Andrew On Mon, May 26, 2014 at 2:32 AM, Urban Hafner cont...@urbanhafner.com wrote: Hello there, I just updated the compiler (I use the git master branch) and now when I read in a file I get a StrBuf instead of a ~str. That is easy enough to change, but how do I use regular expressions now? I have the following in my code: let re = regex!(rSZ\[(\d+)\]); let captures = re.captures(self.sgf).unwrap(); And it fails now because self.sgf is a StrBuf instead of a str. Do I have just a Rust compiler that is somewhere in between (i.e. not everything has been changed to StrBuf) or is this intentional? And if so, what's the best way to use regular expressions now? Urban -- Freelancer Available for hire for Ruby, Ruby on Rails, and JavaScript projects More at http://urbanhafner.com ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Freelancer Available for hire for Ruby, Ruby on Rails, and JavaScript projects More at http://urbanhafner.com ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] *c_char and *c_uchar
Hi! First of all, if you are writing custom bindings to sqlite not only to learn Rust, I'd suggest using already existing bindings [1]. That way you probably won't have to deal with low-level C integration stuff. However, if you want to learn how to write C bindings, you should probably start with reading an official tutorial [2] on foreign function interface. That way you will learn that Rust strings are not C-compatible, they are not terminated by zero byte, so you can't get a pointer from a string and pass it to a C routine directly. In order to properly convert str to *c_char you have to use various conversion utilities, the most simple one being with_c_str() method: let s = some_string; let result = s.with_c_str(|char_ptr| { // call C functions, char_ptr is a *c_char pointer // after this block finishes, a buffer pointed to by char_ptr will be freed some_result }); Here [3] is the relevant piece of documentation on C strings conversions. Your second example is also incorrect. Converting C strings to static slices is highly unsafe, for example, it will crash your program if the string is not a valid UTF-8 sequence, not to mention lifetime issues. There is a reason why it is placed in such inconvenient place as `std::str::raw`. You shouldn't use it. Instead you should use std::c_str::CString structure to wrap C strings. BTW, this structure also forces you to think about ownership. I don't know much about sqlite API, but if you're not supposed to free a string returned by sqlite3_errmsg() function, you should create CString like this CString::new(sqlite3_errmsg(*ppDb), false) false means that this CString won't own the buffer and won't free it when it goes out of scope. When you have CString structure, you can get a string slice out of it using as_str() method. This all is documented here [4]. [1]: https://github.com/linuxfood/rustsqlite. [2]: http://static.rust-lang.org/doc/master/guide-ffi.html [3]: http://static.rust-lang.org/doc/master/std/c_str/index.html [4]: http://static.rust-lang.org/doc/master/std/c_str/struct.CString.html 2014-05-10 18:14 GMT+04:00 Christophe Pedretti christophe.pedre...@gmail.com: Hi all, i am writing a wrapper to an SQLite database. If i use : extern { fn sqlite3_open(filename: *c_char, ppDb : **mut ()) - c_int; } i can not use : let ppDb : **mut () = RawPtr::null(); unsafe { res=sqlite3_open(filename.as_ptr(), ppDb); because as_ptr() returns an *u8 and c_char is a i8, so i have to use extern { fn sqlite3_open(filename: *c_uchar, ppDb : **mut ()) - c_int; } Now, suppose i use : extern { fn sqlite3_errmsg(pDb : *mut ()) - *c_uchar; } i can not use : let mut desc=; { unsafe { desc = c_str_to_static_slice(sqlite3_errmsg(*ppDb)); } } because c_str_to_static_slice taks a *c_char (so an i8) as argument, so i have to use extern { fn sqlite3_errmsg(pDb : *mut ()) - *c_char; } If the second example is quite logical, what about the first one ? how to convert str - *c_char ? thanks -- Christophe http://chris-pe.github.io/Rustic/ ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] 3 ways to do, which is the best one in terms of Rust philosophy ?
Christophe, Indeed, the idiomatic way is to use Result enum [1]. Note that you are not limited to IoResult, you can use any custom error type, for example, ResultT, 'static str. The documentation (a link to which is below) is very nice, it contains a lot of examples and use patterns. So, your constructor method will look like this: pub fn new() - ResultConnection, SomeErrorType { ... } Usually library-specific ResultT, SomeErrorType is abbreviated via a type alias: type YourLibraryResultT = ResultT, SomeErrorType; IoResult is defined exactly like this: type IoResultT = ResultT, IoError; [1]: http://static.rust-lang.org/doc/master/std/result/index.html 2014-05-10 21:38 GMT+04:00 Christophe Pedretti christophe.pedre...@gmail.com: Hi all, thanks to Vladimir and Valerii for their previous detailed answer to my email, now i have a more general question. My Connection struct has a new method with open a connection to a database. This connection can fails. Three possiblities : 1/ new returns an IoResultConnection. The connection must be unwrapped from the IoResult before using it 2/ new returns a Connection; after the instantiation, a test must be made using a method like getIoResult - OptionIoResult 3/ any other way to do For me, the 1/ is the best one, the connection can not be used until it is returned by new. With 2/, the test can be forgotten. Any suggestion ? Thanks -- Christophe http://chris-pe.github.io/Rustic ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] References to trait objects are not cloneable
Hi all, I posted this question on [Stack Overflow][1], but it is yet to be answered there, so I ask here too. Why reference to traits are not cloneable? The following code compiles: struct Test; fn clone_vec'a(v: Vec'a Test) - Vec'a Test { v.clone() } But this one doesn't: trait Test { fn do_smt(self); } fn clone_vec'a(v: Vec'a Test) - Vec'a Test { v.clone() } It spits this error: main3.rs:7:5: 7:14 error: failed to find an implementation of trait std::clone::Clone for 'a Testno-bounds main3.rs:7 v.clone() ^ However, Clone trait is implemented for all kinds of references, as far as I can see. I just don't see why 'a Test where Test is a trait is not cloneable. This is very strange provided that I can implement clone_vec() myself, without using Clone: fn clone_vec'a(v: Vec'a Test) - Vec'a Test { let mut result = Vec::new(); for e in v.iter() { result.push(e); } result } It works just fine. If this is a bug, I would gladly submit it to the tracker, but I'm not sure that I'm not doing something wrong. [1]: http://stackoverflow.com/questions/23426545/references-to-trait-objects-are-not-cloneable ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Alternative to Option types
Hi, Tobias, Yes, there is. A monad is a functor by definition, so it has to accept a type to produce another type. It can't be represented in another way, at least in Haskell. You can't come up with a sensible definition of a functor without HKT: class Functor (f :: *) probably something else where fmap :: (a - b) - f - f -- ??? The above does not make sense at all: you can't specify relationship between a and b in f's codomain, and additional parameters to the type class won't help. Similarly, you cannot make a monad without HKT too. MPTCs with functional dependencies are used in Haskell only to create monad *transformers*. In fact, it is possible to create transformers without MPTCs+FDs (and without type families), but they will be very inconvenient to use - you won't be to obtain transformer operations like (get :: StateT s m a - s), (ask :: ReaderT r m a - r) and others for your monad stack for free. 2014-03-01 2:54 GMT+04:00 Tobias Müller trop...@bluewin.ch: Eric Reed ecr...@cs.washington.edu wrote: In general, monads require higher-kinded types because for a type to be a monad it must take a type variable. That is, OptionT and ListT could be monads, but int and TcpSocket can't be monads. So imagine we wanted to define a trait Monad in Rust. Just for my understanding. Is there an inherent reason that a monad has to be a higher kinded type (type constructor)? Couldn't it also be represented somehow as a multiparam trait/typeclass? AFAIK, higher kinded types are standard haskell, while MPTCs are not, so it's the obvious choice for haskell. Is it also for rust? Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Deprecating rustpkg
2014-02-02 Thomas Leonard tal...@gmail.com: [ I don't want to start another argument, but since you guys are discussing 0install, maybe I can provide some useful input... ] I don't follow this. Whether the developer uses 0install to get the build dependencies doesn't make any difference to the generated binary. Of course, you *can* distribute the binary using 0install too, but you're not required to. I probably have left this part in that formulation by accident. I apologize for that, I had been writing this message in several passes. Yes, of course it does not matter for the developer where he gets build dependencies from, provided these dependencies are readily available for the build process and are easily managed. 0install doesn't automatically check out Git repositories (although that would be handy). Here's how we currently do it: - Your program depends on libfoo = 1.0-post - The latest released version of libfoo is only 1.0 - You git clone the libfoo repository yourself and register the metadata (feed) file inside it: $ git clone git://.../libfoo $ 0install add-feed libfoo/feed.xml - 0install now sees that libfoo 1.0 and 1.0-post are both available. Since your program requires libfoo = 1.0-post, it will select the Git checkout version. Seems to be a lot of manual work. This could be automated by Rust package/build manager, though. Given a set of requirements, 0install will tell you where some suitable versions of the dependencies are. For example: $ cd /tmp $ git clone https://github.com/0install/hello-scons.git $ cd hello-scons $ 0install download Hello-scons.xml --source --show - URI: /tmp/hello-scons/Hello-scons.xml Version: 1.1-post Path: /tmp/hello-scons - URI: http://0install.net/2006/3rd-party/SCons.xml Version: 2.0.1 Path: /var/cache/0install.net/implementations/sha1new=86311df9d410de36d75bc51762d2927f2f045ebf - URI: http://repo.roscidus.com/python/python Version: 2.7.6-1 Path: (package:arch:python2:2.7.6-1:x86_64) This says that the build dependencies are: - This package's source code (in /tmp/hello-scons) - The SCons build tool (which 0install has placed in /var/cache) - Python (provided by the distribution) The source could also specify library dependencies. How do you get this information to the build tool? The usual way is to tell 0install how to run the build tool in the XML. In this case, by running SCons on the project's SConstruct file. But you could get the information to it some other way. For example, a rustpkg tool that invokes 0install download ... --source --xml behind the scenes and does something with the machine-readable selections document produced. Thanks for the explanation, I didn't know that 0install can run build tools and that it could provide the information about libraries locations. This certainly answers my question. How should I specify build dependencies for people who want to hack on my package? List them in the XML file that is in your project's source repository. Users should then be able to clone your git repository and build, with build dependencies handled for them. Again, didn't know that 0install can handle build dependencies. This is all about run time dependencies, but I think the discussion here is about build time, right? You'll have the same issues with any system. Usually build dependencies are a superset of runtime dependencies, aren't they? Nonetheless, this was not about runtime dependencies, this was about general approach. But I think given your explanation of 0install operation this point can be discarded. I think any build tool (including go, cabal, pip, rustpkg) will have this problem. Ideally, you want distributions to be able to turn upstream packages into their preferred format automatically. Whatever system you settle on this should be possible, as long as you have some kind of machine-readable dependency information. Yes, you're quite correct on that ideally upstream packages should be converted to distribution packages automatically. For the new hypothetical build system I see it like the following: a maintainer downloads sources for a package, invokes some distro-specific tool which in turn invokes `rustpkg` to build the package and assemble dependency information, which is then converted to a distribution package. Then the maintainer manually adds external dependencies to the list. Something like that is already done for Haskell in Arch Linux, for example. It seems that it could be done with 0install, at least, to some extent. Zero install may have integration with package systems, but looks like it is very brittle. According to [this page](http://0install.net/distribution-integration.html) it is package owner's duty to specify how native package dependencies should be resolved in each distribution. This is extremely fragile. I don't use Debian, for example,
Re: [rust-dev] Deprecating rustpkg
Is it possible at all to find the latest version of a library which is still compatible completely automatically? Incompatibilites can be present on logic level, so the compilation wiith incompatible version will succeed, but the program will work incorrectly. I don't think that this can be solved without assumptions about versioning (like semver) and/or without manual intervention. Couldn't we just use more loose variant of version pinning inside semantic versioning, with manual user intervention when it is needed? For example, assuming there is something like semantic versioning adopted, packages specify dependencies on certain major version, and the dependency resolver downloads latest available package inside this major version. If for some reason automatically selected dependency is incompatible with our package or other dependencies of our package, the user can manually override this selection, maybe even with another major version. This is, as far as I understand, the system of slots used by Portage as Vladimir Lushnikov described. Slots correspond to major versions in semver terms, and other packages depend on concrete slot. But the user has ultimate power to select whichever version they need, overriding automatic choice. In short, we allow dependency resolver to use the latest possible packages which should be compatible according to semantic versioning, and if it fails, we provide the user with ability to override dependency resolver choices. 2014-02-01 Tony Arcieri basc...@gmail.com: On Fri, Jan 31, 2014 at 3:59 PM, Jack Moffitt j...@metajack.im wrote: The algorithm here is rather simple. We try to satisfy rust-logger and rust-rest. rust-rest has a version (or could be a tag like 1.x) so we go get that. It depends on rust-json 2.0 so we get that. Then we try to look for rust-logger, whatever version is latest (in rustpkg this would mean current master since no version or tag is given). This pulls in rust-json 1.0 since 1.0 != 2.0 and those have specific tags. Everything is built and linked as normal. Whether rust-json's constraints are exact revisions or they are intervals ( 2.0 and = 2.0 for example), makes little difference I think. To reiterate, it sounds like you're describing every package pinning its dependencies to a specific version, which I'd consider an antipattern. What is to prevent a program using this (still extremely handwavey) algorithm from depending on rust-json 1.0, 1.1, 1.2, 1.3, 1.4, 2.0, 2.1, and 2.2 simultaneously? What if some of these are buggy, but the fixed versions aren't used due to version pinning? What if rust-json 1.0 has a security issue? -- Tony Arcieri ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Deprecating rustpkg
You can do that within a major version, except for one case - multiple developers creating diverged versions of 2.13, based on 2.12, each with their own features. ... But doing it per major version recursively raises the question of which major version is authorised: what if you have a single library at 19.x, and TWO people create 20.0 independently? Again, you have incompatibility. So, you're back to the question of (a): is it the same library, or should an author simply stay within the bounds of a library's API, and fork a new CONCEPTUALLY DIFFERENT new lib (most likely with a new name) when they break that API? I think that forks should be considered as completely different libraries. This shouldn't be a problem when certain naming scheme is used, for example, two-level names like in Java world. Central repository will certainly help, because each entry in it will be controlled by concrete user. These entries can also be linked with version control stream which represents main development line. No ambiguities here. It may be desirable then to use specific fork instead of the mainline project. This can be a feature of overriding system, which will be present anyway. If the user wants to use a fork instead of a library (all its versions or a specific version), he/she will be able to specify this requirement somehow, and dependency resolver will take it into account. Obviously, package authors will be able to choose default fork which they want to use. But what does the user know about library APIs? He needs to dig into the logic of the program, and worse, the logic of underlying libraries, to figure out that: somelib::begin() from github://somelib/someplace/v23.2/src/module1/submod2/utils.rs, line 24 does not mean the same as: somelib::begin() from github://somelib/otherplace/v23.2/src/module1/submod2/utils.rs, line 35 ! ;) When this API is used directly by the package, then the user *should* know about it. He's using it, after all. If this API belongs to a transitive dependency, then I don't think there is an ideal solution. Either the version is pinned (like in Java world), or it is chosen by the dependency resolver. In the former case all transitive dependencies are guaranteed to be intercompatible, because these pinned versions were deliberately chosen by libraries developers. In the latter case there is always a possibility of compatibility problems, because it is impossible to guarantee complete compatibility - libraries are written by people, after all. Then it is the user's responsibility to resolve these problems, no one else will be able to do this. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Deprecating rustpkg
To clarify, when I was writing user I meant the developer who uses this package, not the end user of complete program. On 01/02/14 19:32, Vladimir Matveev wrote: When this API is used directly by the package, then the user *should* know about it. He's using it, after all. There are developers (direct library users), and then distro maintainers/admins/users who need to manage libraries installed on their system. The former should know, but the others shouldn't have to think about it, yet should (must) be able to override the defaults if they need to, at least for shared libraries. Presumably we want shared libraries and static libraries to function similarly, except for whether the user chooses static or dynamic linkage. Well, it seems that working for a long time with a code targeting virtual machines is corrupting :) I completely forgot about different models of compilation. I see your point. But I think that developing and distributing should be considered separately. Package manager for developers should be a part of language infrastructure (like rustpkg is now for Rust and, for example, go tool for Go language or cabal for Haskell). This package manager allows flexible management of Rust libraries and their dependencies, and it should be integrated with the build system (or *be* this build system). It is used by developers to create applications and libraries and by maintainers to prepare these applications and libraries for integration with the distribution system for end users. Package manager for general users (I'll call it system package manager), however, depends on the OS, and it is maintainer's task to determine correct dependencies for each package. Rust package manager should not depend in any way on the system package manager and its packages, because each system has its own package manager, and it is just impossible to support them all. Rust also should not force usage of concrete user-level package manager (like 0install, for example), because this means additional unrelated software on the user installation. Go and Haskell do not have this problem because they are linked statically, and their binary packages do not have any library dependencies at all. Rust is a different story as it supports and encourages dynamic linkage. I think that maintainers should choose standard set of Rust libraries which is OK for most applications, and support and update them and their dependent applications. If there are conflicts between versions (for example, some application started to depend on another fork of a library), then maintainers should resolve this in the standard way of their distribution system (e.g. slots for Portage, name suffixes in apt and so on). Essentially there is a large graph of packages in the Rust world, consisting of packages under Rust package manager control (main graph). Developers are only working with this graph. Then for each distribution system maintainers of this system pull packages from the main graph and adapt it to their system in a way this system allows and encourages. I don't think that it is possible to achieve anything better than this. We cannot and should not force end users to use something other than their packaging system. If this API belongs to a transitive dependency, then I don't think there is an ideal solution. Either the version is pinned (like in Java world), or it is chosen by the dependency resolver. If we're talking about pinning to an absolute version (no upgrades), then I think that's a security / bugfix issue, unless we're also talking about static linkage in that case (which is reasonable because then the bug is essentially part of the black box that is the software the user is installing, and in that case, the software maintainer is also responsible for releasing updates to fix bugs within the statically linked code. In the former case all transitive dependencies are guaranteed to be intercompatible Are they? What if the statically pinned version of a scanner library doesn't support the user's new scanner, there's an update to support his scanner, but it's ignored because the software allows only an absolute version number? I don't think your example is related. By guaranteed intercompatibility I meant something like the following. Suppose your package is called `package`. It depends on `foo-x` who in turn depends on `bar-y`. When versions are always pinned by their developers, `foo` author deliberately has chosen `bar-y` version, and he knows that `foo-x` library will work properly with `bar-y`. This is how Java ecosystem works now. New scanner, however, is not an API feature. Your example seems to support the general point about outdated dependencies, and I generally agree with it. because these pinned versions were deliberately chosen by libraries developers. Who are not infallible, and do/should not get to choose everything about the target system's libraries
Re: [rust-dev] Avoiding partially moved values error when consuming a struct with multiple fields
Oh, great! I completely forgot that I can destructure structs in let bindings too. Indeed it works. Thanks! 2014-01-26 Alex Crichton a...@crichton.co: You'll want to do destructuring assignment here. This means that you take ownership of all fields in parallel: fn into_test2(self) - Test2 { let Test1 { a, b } = self; Test2 { c: a, d: b as f64 } } On Sun, Jan 26, 2014 at 9:32 AM, Vladimir Matveev dpx.infin...@gmail.com wrote: Hi all, Consider this code: struct Test1 { a: ~str, b: f32, } struct Test2 { c: ~str, d: f64 } impl Test1 { fn into_test2(self) - Test2 { Test2 { c: self.a, d: self.b as f64 } } } In into_test2() method I want to consume Test1 struct completely. But because ~str is not implicitly copyable, self.a is moved out of self, and on Test2.d field assignment I get the following error: main.rs:15:16: 15:21 error: use of partially moved value: `self` main.rs:15 d: self.b as f64 ^ main.rs:14:16: 14:22 note: `self.a` moved here because it has type `~str`, which is non-copyable (perhaps you meant to use clone()?) main.rs:14 c: self.a, ^~ I know that I can, say, do self.a.clone() to avoid moving, but I don't want extra allocations. And it is also possible to reorder Test2 fields assignments and it will work, but it won't if both fields are not copyable. So, the question is: how to correctly correctly move several pieces of data out from a struct without using clone()? Is it possible at all? Thanks, Vladimir. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Lifetime help
In general it is likely that type annotations will be needed. But in this case you're quite correct. I have updated the gist, it now has significantly less noise. 2014/1/20 Evan G eg1...@gmail.com: Do you need to type annotate the intermediate variable? Shouldn't let sprites = assets.iter() be sufficient? Or is it because of the lifetimes? On Jan 20, 2014 1:41 AM, Vladimir Matveev dpx.infin...@gmail.com wrote: Hi, In fact, you're almost there. You only need to add lifetime annotations on `Sprite` in the intermediate HashMap variable and in return type. See here: https://gist.github.com/dpx-infinity/8516387 I tried to emulate rust-sfml types. This gist compiles, and the test is successful. BTW, you don't have to write `return` unless you want to exit early, for example, from inside a loop. Just leave out semicolon at the last line. Simple hint to detect mistakes in lifetime annotations: if you only have lifetime annotations on parameters or return values but not on both parameters and return values, then it is likely that something is wrong. 2014/1/20 benjamin adamson adamson.benja...@gmail.com: Hi all! I having a little trouble resolving this issue on my own, and I think it's an issue of syntax, not so much comprehending life times. What I'm doing is, using the RSFML library to try and write a pong clone in rust. So far it's been going awesome! I'm running into a small problem with lifetimes though. To give some context, SFML separates textures from sprites, and sprites can be created with a borrowed pointer to a texture. I first load all the textures into a HashMap, and pass that hashmap to a function which (is supposed to) will return a HashMap of Sprites. These sprites I would like to initialize inside the function with references to the textures in the input HashMap of textures. Based on my understanding of borrowed pointers, this should be able to work. In fact, I wrote a simpler version of my function just to make sure I understand what I am not understanding. I wrote a version of the function which takes the same HashMap of textures, and returns a single sprite (not a hashmap). The single sprite is created with a reference to the first texture in the hashmap. I was able to figure out the syntax to express this. However I can't seem to figure out the syntax for the more complicated case, returning the hashmap of Sprites. I created a gist for easy viewing of the code I am having trouble with, and I think I've made it very obvious what's happening in the gist link, hopefully somebody can help me sort this out :D https://gist.github.com/ShortStomp/8513368 also the link to the full file, if it helps. https://github.com/ShortStomp/pong-rust/blob/master/main.rs Thanks in advance!! ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] Failure stacktraces
Hi, Is it possible to view full stacktraces when task fails? Currently only the last item in the stacktrace is printed to the terminal when I run a failing program. I'm very surprised that I was not able to find any information on this. It looks like that the problem is nonexistent. However, the ability of getting full failure stacktraces is of colossal importance. Failures mean stack unwinding, so it shouldn't be a problem, should it? Thanks, Vladimir. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Failure stacktraces
Thanks for explanation! I guess gdb will do for me. 2014/1/19 Corey Richardson co...@octayn.net: You're not actually seeing a stack entry, you're seeing the string that was given to `fail!()`. You can get a real backtrace with gdb, break on `rust_fail`. You can also get a super crappy backtrace using the backtrace function, see prototype https://gist.github.com/cmr/8192817. We used to use it, but it only really works for dynamic linking (which we discourage for a variety of reasons right now), and doesn't work on OS X. Getting a real backtrace when unwinding would be possible, but we'd need to start parsing DWARF etc. Not trivial. On Sun, Jan 19, 2014 at 12:58 PM, Vladimir Matveev dpx.infin...@gmail.com wrote: Hi, Is it possible to view full stacktraces when task fails? Currently only the last item in the stacktrace is printed to the terminal when I run a failing program. I'm very surprised that I was not able to find any information on this. It looks like that the problem is nonexistent. However, the ability of getting full failure stacktraces is of colossal importance. Failures mean stack unwinding, so it shouldn't be a problem, should it? Thanks, Vladimir. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Lifetime help
Hi, In fact, you're almost there. You only need to add lifetime annotations on `Sprite` in the intermediate HashMap variable and in return type. See here: https://gist.github.com/dpx-infinity/8516387 I tried to emulate rust-sfml types. This gist compiles, and the test is successful. BTW, you don't have to write `return` unless you want to exit early, for example, from inside a loop. Just leave out semicolon at the last line. Simple hint to detect mistakes in lifetime annotations: if you only have lifetime annotations on parameters or return values but not on both parameters and return values, then it is likely that something is wrong. 2014/1/20 benjamin adamson adamson.benja...@gmail.com: Hi all! I having a little trouble resolving this issue on my own, and I think it's an issue of syntax, not so much comprehending life times. What I'm doing is, using the RSFML library to try and write a pong clone in rust. So far it's been going awesome! I'm running into a small problem with lifetimes though. To give some context, SFML separates textures from sprites, and sprites can be created with a borrowed pointer to a texture. I first load all the textures into a HashMap, and pass that hashmap to a function which (is supposed to) will return a HashMap of Sprites. These sprites I would like to initialize inside the function with references to the textures in the input HashMap of textures. Based on my understanding of borrowed pointers, this should be able to work. In fact, I wrote a simpler version of my function just to make sure I understand what I am not understanding. I wrote a version of the function which takes the same HashMap of textures, and returns a single sprite (not a hashmap). The single sprite is created with a reference to the first texture in the hashmap. I was able to figure out the syntax to express this. However I can't seem to figure out the syntax for the more complicated case, returning the hashmap of Sprites. I created a gist for easy viewing of the code I am having trouble with, and I think I've made it very obvious what's happening in the gist link, hopefully somebody can help me sort this out :D https://gist.github.com/ShortStomp/8513368 also the link to the full file, if it helps. https://github.com/ShortStomp/pong-rust/blob/master/main.rs Thanks in advance!! ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Exporting macros: #[macro_escape] usage
Oh, thanks. It does work now. Are macro scoping rules documented somewhere except the compiler source code? 2014/1/11 Chris Morgan chris.morgani...@gmail.com: The macro is being defined after the module is defined. You need to move the macro definition before the pub mod submod; line. Also due to the scoping rules of macros, you don't need #[macro_escape] there---it's a child, so it gets the macro. Only siblings, parents, uncles, aunts, cousins, c. would need it. On Jan 11, 2014 9:46 AM, Vladimir Matveev dpx.infin...@gmail.com wrote: Hi, As far as I understand, the current way to export macros is to annotate the module with macro_rules definition with #[macro_escape] annotation. But I just can't get it right, and my macro is not visible in other module :( Here is what I have: - START - /lib.rs: #[feature(macro_rules)]; pub mod m1; -- /m1/mod.rs: #[macro_escape]; pub mod submod; macro_rules! example_rule( () = (mod test;) ) -- /m1/submod.rs: use m1; example_rule!() - END - I have assumed that putting #[macro_escape] annotation to a module makes all macros from that module available in all modules which import this module, but apparently I'm wrong because the code above does not work with 'macro undefined' error. Could please someone explain how #[macro_escape] works in detail? I couldn't find any documentation on it, and looking through standard libs was not helpful. Thanks, Vladimir. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] Exporting macros: #[macro_escape] usage
Hi, As far as I understand, the current way to export macros is to annotate the module with macro_rules definition with #[macro_escape] annotation. But I just can't get it right, and my macro is not visible in other module :( Here is what I have: - START - /lib.rs: #[feature(macro_rules)]; pub mod m1; -- /m1/mod.rs: #[macro_escape]; pub mod submod; macro_rules! example_rule( () = (mod test;) ) -- /m1/submod.rs: use m1; example_rule!() - END - I have assumed that putting #[macro_escape] annotation to a module makes all macros from that module available in all modules which import this module, but apparently I'm wrong because the code above does not work with 'macro undefined' error. Could please someone explain how #[macro_escape] works in detail? I couldn't find any documentation on it, and looking through standard libs was not helpful. Thanks, Vladimir. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation
I think I should have put my code to gist to track changes easily. Amending: https://gist.github.com/dpx-infinity/6751843 2013/9/29 Vladimir Matveev dpx.infin...@gmail.com: Yes, this is what I have observed too, see issue https://github.com/mozilla/rust/issues/9597. I didn't know that using extra parameter with lifetime will help though. It indeed works. But I think that polluting traits-interfaces with lifetime annotation is wrong. Why the trait should have lifetime annotation? It is implementation detail. I just managed to do what I wanted with some kind of hack. The following code compiles and works: // Some business-logic trait trait Walker { fn walk(self); // Just self, without pointers } // ReaderContainer implementation remains the same // A struct which is intended to be an implementor of Walker trait // Note that it has lifetime parameter in order to work for any kind // of pointer to a Reader struct ReaderContainer'self { priv reader: 'self Reader, priv counter: int } // Some auxiliary structure for ReaderContainer // It may be anything but it should have a reference to ReaderContainer // We have to use lifetime parameter because this structure is 'attached' // to ReaderContainer, hence it must be of the same lifetime struct ReaderContainerIterator'self { priv container: 'self mut ReaderContainer'self } // Some made-up implementation of iterator protocol for our // auxiliary structure, it does not really matter impl'self Iteratoru8 for ReaderContainerIterator'self { fn next(mut self) - Optionu8 { if self.container.counter 10 { self.container.counter += 1; Some(self.container.reader.read_byte() as u8) } else { None } } } impl'self ReaderContainer'self { // A constructor for ReaderContainer, nothing special fn new'a(reader: 'a Reader) - ReaderContainer'a { ReaderContainer { reader: reader, counter: 0 } } // A method which returns our auxiliary structure, i.e. iterator // Note that self parameter has lifetime 'self, otherwise this naturally // does not compile fn iter('self mut self) - ReaderContainerIterator'self { ReaderContainerIterator { container: self } } } // And here are the changes // We implement Walker for a reference of the specific type! impl'self Walker for 'self mut ReaderContainer'self { // Here self automatically is 'self mut reference, so we can safely // use iter() method fn walk(self) { for b in self.iter() { println(fmt!(byte %?, b)); } } } fn main() { use std::io; let r = io::stdin(); let mut c = ReaderContainer::new(r); c.walk(); // No extra parameters } In short, I'm implementing `Walker` trait not for `ReaderContainer'self` but for `'self mut ReaderContainer'self`. This does not feel right, but I do not see immediate problems with this solution. Maybe someone who knows more about lifetimes could comment on this. 2013/9/29 David Renshaw dwrens...@gmail.com: If I drop the unused parameter, I get an internal compiler error: 'assertion failed: self.variance.is_some()' ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation
As far as I understand, you're mostly right, except the structures bit. Disregarding that it is not possible to use several lifetime parameters yet, I see only one slight mistake: `s: MyStruct'a` does not imply that `s` variable has any specific lifetime. If it is a local variable, then it has 'lexical' lifetime; if it is a field in a structure, it has lifetime of the structure instance. I guess what you meant is this: s: 'a MyStruct'a Here `s` pointer have lifetime 'a, as well as `s.r_int`. BTW, you came up with very nice math-like analogy, it helped me understand this thing even more. Thanks :) 2013/9/29 Gábor Lehel illiss...@gmail.com: 'self is not special in any way, except that the compiler has historical baggage such that 'self is the only name it lets you use for a lifetime parameter on a struct. But that's a bug. In the ideal platonic Rust in the sky, you can have any number of lifetime parameters on a struct with whatever names you prefer. The way I've found to think about lifetimes is that if you have: r_int: 'a int then 'a refers to a span of time (a scope, a lifetime) such that lifetime_of(r_int) = 'a = lifetime_of(*r_int). (Where *r_int is intended metaphorically to refer to the original object r_int was created from, not the result of the *r_int expression itself.) So 'a is a kind of stand between to ensure that r_int does not outlive the object it refers to. If you have fn foo'a(r_int: 'a int) - 'a int then just like any other generics argument, the lifetime 'a is chosen by the caller of `foo` (as inferred by the compiler). Typically the caller will have an int object (i: int), then borrow a reference to it (r_int: 'a int = i) which it passes to `foo`, and then 'a will be the lifetime of the int. `foo` will then have to return a reference to (an int that lives at least as long). In practice this could either be the r_int it got as argument, or a static int. `fn foo(arg: int)` is shorthand for an anonymous lifetime parameter: `fn foo'a(arg: 'a int)` In the return type position `fn foo() - int` is short for `fn foo'a() - 'a int`, meaning `foo` has to return a reference to (an int that lives as long as any lifetime the caller could choose), which in practice means that it has to be 'static. I believe you are or will be required to write 'static explicitly in these cases to avoid confusion. With a struct it's not much different. s: MyStruct'a means lifetime_of(s) = 'a s: MyStruct'a, 'b means lifetime_of(s) = 'a lifetime_of(s) = 'b If you have struct MyStruct'self { r_int: 'self int } s: MyStruct'a then lifetime_of(s) = 'a lifetime_of(s.r_int) = 'a. (Which is trivial because lifetime_of(s) == lifetime_of(s.r_int).) Basically, every object has a lifetime - from its creation to its destruction - but a lifetime parameter or argument typically refers to the lifetime of something else, which the object itself must not or does not outlive. (Please yell at me if I got any of this wrong.) On Sun, Sep 29, 2013 at 5:23 PM, Oren Ben-Kiki o...@ben-kiki.org wrote: Ok, color me confused... perhaps there's somewhere that explains 'self on more detail? For example, _why_ does the example below not work without the explicit 'self? It seems like it should. I have yet to truly understand the whole 'self thing. When I first read about lifetimes, my naive expectations were that: - Every struct has a 'self lifetime, which is basically as long as this struct exists. It doesn't matter if I have a @ of the struct or a ~ of the struct or just a local variable with the struct... when the struct is dropped, the lifetime ends. - It follows there's no need to ever annotate structs as generic with a 'self parameter - it always exists. - Any in a struct is either 'self or 'static. A simple should be 'self as that makes more sense (but if Rust wants me to be explicit, fine). This were my least surprise expectations, but things don't work this way... the problem is I don't have a simple mental model to replace the above with, so I struggle. What _is_ 'self, exactly? Isn't a function fn foo(self) - T the same as returning a 'self T? Why would I want to say fn foo'a('a self) in the 1st place - 'a is by definition the same as 'self? How come David's Foo example fails the borrow check? Besides failing (my) least surprise expectations, the current rules also seem to be a leaky abstraction. If I have a struct that holds a ComplexT member, it needs no 'self parameter. If I then add a private member to my struct to hold some 'self PartOfT (say, cached access to an internal member), then boom, all uses of my struct now have to say 'self, I can no longer put it in thread-local-storage, etc. I'd expect keeping these sort of cached borrowed pointers should be an internal implementation detail which does not affect the users of the struct at all. I suppose there's a good reason for all this, and a reasonable mental model I
[rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation
Hi all, The problem I'm writing about in this message follows from the one I have described in my other message: https://mail.mozilla.org/pipermail/rust-dev/2013-August/005281.html . I believe I'm now able to formulate it more clearly. Consider the following example code: trait Walker { // Some business-logic trait fn walk(mut self); } // A struct which is intended to be an implementor of Walker trait // Note that it has lifetime parameter in order to work for any kind // of pointer to a Reader struct ReaderContainer'self { priv reader: 'self Reader, priv counter: int } // Some auxiliary structure for ReaderContainer // It may be anything but it should have a reference to ReaderContainer // We have to use lifetime parameter because this structure is 'attached' // to ReaderContainer, hence it must be of the same lifetime struct ReaderContainerIterator'self { priv container: 'self mut ReaderContainer'self } // Some made-up implementation of iterator protocol for our // auxiliary structure, it does not really matter impl'self Iteratoru8 for ReaderContainerIterator'self { fn next(mut self) - Optionu8 { if self.container.counter 10 { self.container.counter += 1; Some(self.container.reader.read_byte() as u8) } else { None } } } impl'self ReaderContainer'self { // A constructor for ReaderContainer, nothing special fn new'a(reader: 'a Reader) - ReaderContainer'a { ReaderContainer { reader: reader, counter: 0 } } // A method which returns our auxiliary structure, i.e. iterator // Note that self parameter has lifetime 'self, otherwise this naturally // does not compile fn iter('self mut self) - ReaderContainerIterator'self { ReaderContainerIterator { container: self } } } // Here is the problem: we cannot implement Walker trait! impl'self Walker for ReaderContainer'self { // See below for concrete errors description fn walk(mut self) { // for b in self.iter() { println(fmt!(byte %?, b)); } } } fn main() { use std::io; let r = io::stdin(); let mut c = ReaderContainer::new(r); c.walk(); } This program does not compile with the following error: temp.rs:52:17: 52:30 error: cannot infer an appropriate lifetime due to conflicting requirements temp.rs:52 for b in self.iter() { ^ temp.rs:52:17: 52:22 note: first, the lifetime cannot outlive the expression at 52:17... temp.rs:52 for b in self.iter() { ^ temp.rs:52:17: 52:22 note: ...due to the following expression temp.rs:52 for b in self.iter() { ^ temp.rs:52:17: 52:30 note: but, the lifetime must be valid for the method call at 52:17... temp.rs:52 for b in self.iter() { ^ temp.rs:52:17: 52:22 note: ...due to the following expression temp.rs:52 for b in self.iter() { ^ error: aborting due to previous error This is somewhat expected, because `self` in `walk()` method implementation does not have 'self lifetime, so it is impossible to call `iter()` method which needs concrete 'self lifetime. But I cannot mark it with 'self lifetime either! If I do mark it with 'self: fn walk('self mut self) { // for b in self.iter() { println(fmt!(byte %?, b)); } } Then the program fails to compile with another message: temp.rs:51:4: 55:5 error: method `walk` has an incompatible type: expected concrete lifetime, but found bound lifetime parameter temp.rs:51 fn walk('self mut self) { // temp.rs:52 for b in self.iter() { temp.rs:53 println(fmt!(byte %?, b)); temp.rs:54 } temp.rs:55 } temp.rs:51:29: 55:5 note: expected concrete lifetime is the lifetime 'self as defined on the block at 51:29 temp.rs:51 fn walk('self mut self) { // temp.rs:52 for b in self.iter() { temp.rs:53 println(fmt!(byte %?, b)); temp.rs:54 } temp.rs:55 } error: aborting due to previous error This is also expected: adding 'self lifetime violates `Walker` trait signature, in which `walk()` method has plain `mut self` parameter. So, this is kind of dead end. I think this problem may be formulated in short as follows: how to implement generic traits for structures which have lifetime parameters which are used for `self` parameter in structure methods implementations? How to do what I want to do? Is it possible at all? Regards, Vladimir. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Borrowed pointers with lifetime in structures cause weird errors
Hi Niko, Thank you for your response. I forgot to put it in the original message, but here is a link to bitbucket repository with all the code I got so far: https://bitbucket.org/googolplex/algo/src, see module io. Maybe it will be helpful. I'm still inclined to think that this is a bug, and I really do not see how can I do what I want to with two lifetime parameters. There really should be one lifetime (the one of the Reader), or maybe I'm missing something? As for internal iterators, yes, I tried to do that first, but since it is impossible to break out or return from inside of the iterator loop directly via `break` or `return` it quickly becomes pretty unfeasible since I have to use a lot of boilerplate boolean parameters and check them in many places. This may be not so apparent for finite structures, but for potentially infinite ones (like a wrapper for `Reader`) it is. Nonetheless, as far as I understand, external iterators are the future of iteration in Rust (generators won't appear in the nearest future, will they?), so I want to use the most idiomatic style. 2013/8/20 Niko Matsakis n...@alum.mit.edu: Hi, Sorry for not responding more quickly. I've been wanting to sit down and work out your example; I am confident that it can be made to work, although from reading it quickly it sounds like a case that might be better served with two lifetime parameters, which are not yet supported (on my list...). However, I did want to briefly point out that you can continue to use internal iterators, you just don't get the `for` syntax anymore. Just write a higher-order function as you always did, possibly returning bool to indicate whether to break or continue. Niko On Sat, Aug 17, 2013 at 01:54:09PM +0400, Vladimir Matveev wrote: Hello, I'm writing a simple tokenizer which is defined by this trait: trait Tokenizer { fn next_token(mut self) - ~str; fn eof(self) - bool; } Obvious application for a tokenizer is splitting a stream going from Reader, so I have the following structure which should implement Tokenizer: pub struct ReaderTokenizer'self { priv inner: 'self Reader, priv buffer: ~CyclicBuffer, priv seps: ~[~str] } I have used 'self lifetime parameter since I want for the tokenizer work for any Reader. CyclicBuffer is another structure which essentially is an array of u8 with special read/write operations. Implementation of a Tokenizer for ReaderTokenizer involves reading from the Reader one byte at a time. I decided to use buffering to improve performance. But I still want to keep the useful abstraction of single byte reading, so I decided to implement Iteratoru8 for my Reader+CyclicBuffer pair. BTW, internal iterators in 0.7 were much better for this, because internal iterator code was very simple and didn't use explicit lifetimes at all, but 0.7 compiler suffers from several errors related to pointers to traits which prevented my program from compiling (I couldn't pass a reference to Reader to CyclicBuffer method; there were other errors I've encountered too). I So, I decided to use trunk version of the compiler in which these errors are resolved according to github, but trunk version does not allow internal iterators, which is very sad since now I'm forced to create intermediate structures to achieve the same thing. So, I came up with the following iterator structure: struct RTBytesIterator'self { tokenizer: 'self mut ReaderTokenizer'self } impl'self Iteratoru8 for RTBytesIterator'self { fn next(mut self) - Optionu8 { if self.tokenizer.eof() { return None; } if self.tokenizer.buffer.readable_bytes() 0 || self.tokenizer.buffer.fill_from_reader(self.tokenizer.inner) 0 { return Some(self.tokenizer.buffer.read_unsafe()); } else { return None; } } } Note that tokenizer field is 'self mut since CyclicBuffer is mutable. buffer.fill_from_reader() function reads as much as possible from the reader (returning a number of bytes read), and buffer.read_unsafe() returns next byte from the cyclic buffer. Then I've added the following method to ReaderTokenizer: impl'self ReaderTokenizer'self { ... fn bytes_iter(mut self) - RTBytesIterator'self { RTBytesIterator { tokenizer: self } } ... } This does not compile with the following error: io/convert_io.rs:98:37: 98:43 error: cannot infer an appropriate lifetime due to conflicting requirements io/convert_io.rs:98 RTBytesIterator { tokenizer: self } ^~ io/convert_io.rs:97:55: 99:5 note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the block at 97:55... io/convert_io.rs:97 fn bytes_iter(mut self) - RTBytesIterator'self { io/convert_io.rs:98 RTBytesIterator { tokenizer: self } io/convert_io.rs:99 } io/convert_io.rs:98:37: 98
[rust-dev] Borrowed pointers with lifetime in structures cause weird errors
Hello, I'm writing a simple tokenizer which is defined by this trait: trait Tokenizer { fn next_token(mut self) - ~str; fn eof(self) - bool; } Obvious application for a tokenizer is splitting a stream going from Reader, so I have the following structure which should implement Tokenizer: pub struct ReaderTokenizer'self { priv inner: 'self Reader, priv buffer: ~CyclicBuffer, priv seps: ~[~str] } I have used 'self lifetime parameter since I want for the tokenizer work for any Reader. CyclicBuffer is another structure which essentially is an array of u8 with special read/write operations. Implementation of a Tokenizer for ReaderTokenizer involves reading from the Reader one byte at a time. I decided to use buffering to improve performance. But I still want to keep the useful abstraction of single byte reading, so I decided to implement Iteratoru8 for my Reader+CyclicBuffer pair. BTW, internal iterators in 0.7 were much better for this, because internal iterator code was very simple and didn't use explicit lifetimes at all, but 0.7 compiler suffers from several errors related to pointers to traits which prevented my program from compiling (I couldn't pass a reference to Reader to CyclicBuffer method; there were other errors I've encountered too). I So, I decided to use trunk version of the compiler in which these errors are resolved according to github, but trunk version does not allow internal iterators, which is very sad since now I'm forced to create intermediate structures to achieve the same thing. So, I came up with the following iterator structure: struct RTBytesIterator'self { tokenizer: 'self mut ReaderTokenizer'self } impl'self Iteratoru8 for RTBytesIterator'self { fn next(mut self) - Optionu8 { if self.tokenizer.eof() { return None; } if self.tokenizer.buffer.readable_bytes() 0 || self.tokenizer.buffer.fill_from_reader(self.tokenizer.inner) 0 { return Some(self.tokenizer.buffer.read_unsafe()); } else { return None; } } } Note that tokenizer field is 'self mut since CyclicBuffer is mutable. buffer.fill_from_reader() function reads as much as possible from the reader (returning a number of bytes read), and buffer.read_unsafe() returns next byte from the cyclic buffer. Then I've added the following method to ReaderTokenizer: impl'self ReaderTokenizer'self { ... fn bytes_iter(mut self) - RTBytesIterator'self { RTBytesIterator { tokenizer: self } } ... } This does not compile with the following error: io/convert_io.rs:98:37: 98:43 error: cannot infer an appropriate lifetime due to conflicting requirements io/convert_io.rs:98 RTBytesIterator { tokenizer: self } ^~ io/convert_io.rs:97:55: 99:5 note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the block at 97:55... io/convert_io.rs:97 fn bytes_iter(mut self) - RTBytesIterator'self { io/convert_io.rs:98 RTBytesIterator { tokenizer: self } io/convert_io.rs:99 } io/convert_io.rs:98:37: 98:43 note: ...due to the following expression io/convert_io.rs:98 RTBytesIterator { tokenizer: self } ^~ io/convert_io.rs:97:55: 99:5 note: but, the lifetime must be valid for the lifetime 'self as defined on the block at 97:55... io/convert_io.rs:97 fn bytes_iter(mut self) - RTBytesIterator'self { io/convert_io.rs:98 RTBytesIterator { tokenizer: self } io/convert_io.rs:99 } io/convert_io.rs:98:8: 98:23 note: ...due to the following expression io/convert_io.rs:98 RTBytesIterator { tokenizer: self } ^~~ error: aborting due to previous error OK, fair enough, I guess I have to annotate self parameter with 'self lifetime: fn bytes_iter('self mut self) - RTBytesIterator'self { RTBytesIterator { tokenizer: self } } This compiles, but now I'm getting another error at bytes_iter() usage site, for example, the following code: fn try_read_sep(mut self, first: u8) - (~[u8], bool) { let mut part = ~[first]; for b in self.bytes_iter() { part.push(b); if !self.is_sep_prefix(part) { return (part, false); } if self.is_sep(part) { break; } } return (part, true); } fails to compile with this error: io/convert_io.rs:117:17: 117:36 error: cannot infer an appropriate lifetime due to conflicting requirements io/convert_io.rs:117 for b in self.bytes_iter() { ^~~ io/convert_io.rs:117:17: 117:22 note: first, the lifetime cannot outlive the expression at 117:17... io/convert_io.rs:117 for b in self.bytes_iter() { ^ io/convert_io.rs:117:17: 117:22 note: