Re: [rust-dev] Specifying lifetimes in return types of overloaded operators
For one, the Index trait is in dire need of an overhaul. In respect to the operator traits in general, I have actually been thinking of submitting an RFC proposing that they take thier parameters by-value instead of by-ref. That would remove the auto-ref behaviour of the operators which is more consistent with the rest of Rust: impl'a, 'b, T Mul'b MatT, MatT for 'a MatT { fn mul('a self, other: 'b MatT) - T { ... } } let m2: Mat_ = m0 * m1; ~Brendan On 16 Apr 2014, at 3:23 pm, Artella Coding artella.cod...@googlemail.com wrote: Hi Eric, this is an example of code which gives the error : struct Cls { vec : ~[~int] } /* Does not compile, yielding error message : method `index` has an incompatible type for trait: expected concrete lifetime, but found bound lifetime parameter */ impl'a Indexuint,'a ~int for Cls { fn index('a self, i: uint) - 'a ~int { let val = 'a self.vec[*i]; return val; } } fn main(){} It is easy to write a function which does the exact same thing (for the struct above) and has a return type with a bounded lifetime, and therefore it does not make sense to me why operator overloading would be restricted in this fashion (i.e. restricted to return concrete lifetimes). Thanks. On Wed, Apr 16, 2014 at 2:48 AM, Eric Reed ecr...@cs.washington.edu wrote: Could you provide a code sample that causes this error? On Tue, Apr 15, 2014 at 6:28 AM, Artella Coding artella.cod...@googlemail.com wrote: Currently if I try to specify lifetimes in the return types of overloaded operators like Index ([]), I get an error message : method `index` has an incompatible type for trait: expected concrete lifetime, but found bound lifetime parameter Why has this restriction been placed, given that I can write custom functions which can have bounded lifetimes specifications in the return type? 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 ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Proposal: a moratorium on adding unsafe features to the safe subset of Rust
On 29 Mar 2014, at 2:12 pm, Tony Arcieri basc...@gmail.com wrote: Recently there has been a call to introduce an optional feature flag which removes bounds checks to the *safe* subset of Rust (i.e. outside of unsafe blocks) I think this sort of suggestion imperils Rust's goals as a language. I agree that our philosophy should be formalised in a design document, but I hardly think that the language is in peril. Whilst those making the mentioned proposal have been extremely vocal in the past few days, rest assured that they are a tiny minority, and in no way represent the views of those actually working on the language. ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Announcing the new Rust package manager, Cargo
This is incredible news. Thank you for agreeing to help us out in our time of need! I have a couple of questions: - For those of us who are less familiar with Bundler, could you offer a quick run-down of how it works? - Are there any things you learned from doing Bundler that you would do differently the next time round? That is, in addition to the specific changes you would make to tailor it to the Rust language. ~Brendan On 18 Mar 2014, at 12:26 pm, Yehuda Katz wyc...@gmail.com wrote: Hello Rustlers, I'll be writing here more with more details soon. For now, a few quick comments: • I'm really glad that Mozilla and the Rust team are prioritizing package management. An open source language ecosystem really lives or dies based on how easy it is to share code, and writing a world-class package manager (as brson put it) takes time, especially when you account for the inevitable and important iteration that comes from real-world usage. • There's a lot about package management that's well-understood and somewhat language agnostic. On the other hand, there are things that are specific to native code or even more specific to Rust that a Rust package manager need to account for. My goal is to use well-known best practices for the former, and avoid reinventing the wheel, without losing track of what makes Rust unique or different. Carl and I are both the creators of the predominant Ruby package manager (bundler) and day-to-day production users of Rust (really!) at the company we founded. We think that mix should enable us to balance both of those priorities. • Over the next month or two, we plan to prioritize getting to regular, working milestones with Cargo. These milestones will not always reflect our plan for the final workflow that we expect with Cargo, but having real-world working code is very important when building something the size and scope of Cargo. We plan to share design documents (both on the internal architecture and expected workflows) as we work. We started work 10 days ago, and we already have a primitive cargo compiling one of our libraries based on its Cargo manifest, but so far only via very simple plumbing commands that don't reflect the actual workflow we intend. In general, some guiding principles for the project: • It should be possible for new users of Rust to use Cargo to experiment with Rust and its library ecosystem and have success quickly. • Users of Cargo should get deterministic builds out of the box. If I build an artifact on one machine, it should be possible to build that same artifact on another machine with exactly the same source of every dependency, and exactly the same options. • Users of Cargo should be able to update dependencies with as minimal impact on other dependencies as possible. If I update a utility library, Cargo should avoid updates to other, unrelated libraries by design. • Cargo should support cross-compilation out of the box. As long as your version of Rust and its standard library are compiled for the expected targets, a single line of configuration should be enough to get builds for those targets • Cargo should support the common lifecycle for packages: a package starts out as a part of an existing project, moves to Github for easier sharing across multiple projects and eventually the open source community, and finally is published to a central repository with a version number. This means that all three kinds of sources (local file system, github, and central package repository) should be supported by the default distribution of Cargo. We plan to publish more detail really soon, as well as more information on what we've already built. Please feel free to ask questions :) Yehuda Katz (ph) 718.877.1325 On Mon, Mar 17, 2014 at 5:48 PM, Brian Anderson bander...@mozilla.com wrote: Dearest Rustlers, Today I'm super-excited to announce that Mozilla has arranged to develop a world-class package manager for Rust. Yehuda Katz and Carl Lerche, from Tilde Inc., have previously built the popular Ruby package manager, Bundler, and now they are going to build Rust's package manager, Cargo. They are *experts* at the management of packages, and will deliver a tool that builds off both their experience in Ruby and ours with pevious iterations of rustpkg. The two of them will be talking about this project in more detail very soon. Please welcome them into your hearts. Regards, Brian ___ 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] history of rust?
Would be interesting to see the repository history rendered in gource: https://code.google.com/p/gource/ (obviously with all the ugly bloom effects turned off). I had it running for a little yesterday, but I needed to do some tweaking of how the file names were shown - things were getting very busy on the screen. ~Brendan On 1 Mar 2014, at 8:24 am, Brian Anderson bander...@mozilla.com wrote: There is not. I am interested in this topic. There is a great deal of public information about Rust's development and I'd love it to be organized in an accessible way. With the right presentation it could be interesting, dramatic, and maybe even useful to other designers. On 02/28/2014 11:13 AM, Martin Matusiak wrote: Hi, I'm wondering if there is a resource somewhere that chronicles the history of Rust from its beginnings. My interest is not so much the folklore, but more the heritage that would make it easier to understand why the language is the way it is today. Thanks, Martin ___ 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] RFC: Importing/exporting macros
Agreed. Exporting macros feels like a hack. Importing macros feels like a hack. Global namespaces are a pain. Macros on the whole feel like a second class citizen of the language. I’m not talking about writing them - I’m perfectly fine about that kind of ugliness – I’m referring to the client side usability. I would steer clear from forcing them on the users of my libraries. ~Brendan On 26 Feb 2014, at 8:39 am, Sean McArthur smcart...@mozilla.com wrote: Rust now has the ability to import macros from other crates, hurray! However, I'd like to propose adjusting the current way of using them to be more like importing/exporting other symbols of a crate. 1) It's more consistent, makes it easier to find where macros came from. 2) Current usage brings name collisions. Current example: pub mod foo { // assume other macros as well #[macro_export] macro_rules! bar ( ... ) } pub mod baz { // assume other macros as well #[macro_export] macro_rules! bar ( ... ) } mod herp { // i want bar! from foo, and some other macros from baz [phase(syntax)] use super::foo; [phase(syntax)] use super::baz; pub Derp = bar!(); // which bar? is this an ICE? or logic error? } Proposed example: pub mod foo { pub marco_rules! bar ( ... ); } pub mod baz { pub marco_rules! bar ( ... ); pub marco_rules! quux ( ... ); } mod herp { use super::foo::bar!; use super::baz::quux!; // using same name macros, no problem use baz! = super::baz::bar!; pub Derp = bar!(baz!()); } ___ 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] RFC: About the library stabilization process
We should probably start using the #[deprecated] attribute more. Using it to phase things out in the std is currently annoying because we have the #[deny(deprecated)] attribute on. ~Brendan On 19 Feb 2014, at 12:40 pm, Brian Anderson bander...@mozilla.com wrote: Hey there. I'd like to start the long process of stabilizing the libraries, and this is the opening salvo. This process and the tooling to support it has been percolating on the issue tracker for a while, but this is a summary of how I expect it to work. Assuming everybody feels good about it, we'll start trying to make some simple API's stable starting later this week or next. # What is the stability index and stability attributes? The stability index is a way of tracking, at the item level, which library features are safe to use backwards-compatibly. The intent is that the checks for stability catch all backwards-incompatible uses of library features. Between feature gates and stability The stability index of any particular item can be manually applied with stability attributes, like `#[unstable]`. These definitions are taken directly from the node.js documentation. node.js additionally defines the 'locked' and 'frozen' levels, but I don't think we need them yet. * Stability: 0 - Deprecated This feature is known to be problematic, and changes are planned. Do not rely on it. Use of the feature may cause warnings. Backwards compatibility should not be expected. * Stability: 1 - Experimental This feature was introduced recently, and may change or be removed in future versions. Please try it out and provide feedback. If it addresses a use-case that is important to you, tell the node core team. * Stability: 2 - Unstable The API is in the process of settling, but has not yet had sufficient real-world testing to be considered stable. Backwards-compatibility will be maintained if reasonable. * Stability: 3 - Stable The API has proven satisfactory, but cleanup in the underlying code may cause minor changes. Backwards-compatibility is guaranteed. Crucially, once something becomes 'stable' its interface can no longer change outside of extenuating circumstances - reviewers will need to be vigilant about this. All items may have a stability index: crates, modules, structs, enums, typedefs, fns, traits, impls, extern blocks; extern statics and fns, methods (of inherent impls only). Implementations of traits may have their own stability index, but their methods have the same stability as the trait's. # How is the stability index determined and checked? First, if the node has a stability attribute then it has that stability index. Second, the AST is traversed and stability index is propagated downward to any indexable node that isn't explicitly tagged. Reexported items maintain the stability they had in their original location. By default all nodes are *stable* - library authors have to opt-in to stability index tracking. This may end up being the wrong default and we'll want to revisit. During compilation the stabilization lint does at least the following checks: * All components of all paths, in all syntactic positions are checked, including in * use statements * trait implementation and inheritance * type parameter bounds * Casts to traits - checks the trait impl * Method calls - checks the method stability Note that not all of this is implemented, and we won't have complete tool support to start with. # What's the process for promoting libraries to stable? For 1.0 we're mostly concerned with promoting large portions of std to stable; most of the other libraries can be experimental or unstable. It's going to be a lengthy process, and it's going to require some iteration to figure out how it works best. The process 'leader' for a particular module will post a stabilization RFC to the mailing list. Within, she will state the API's under discussion, offer an overview of their functionality, the patterns used, related API's and the patterns they use, and finally offer specific suggestions about how the API needs to be improved or not before it's final. If she can confidently recommend that some API's can be tagged stable as-is then that helps everybody. After a week of discussion she will summarize the consensus, tag anything as stable that already has agreement, file and nominate issues for the remaining, and ensure that *somebody makes the changes*. During this process we don't necessarily need to arrive at a plan to stabilize everything that comes up; we just need to get the most crucial features stable, and make continual progress. We'll start by establishing a stability baseline, tagging most everything experimental or unstable, then proceed to the very simplest modules, like 'mem', 'ptr', 'cast', 'raw'.
[rust-dev] RFC: New Rust channel proposal
On 15 Jan 2014, at 9:35 am, Eric Reed ecr...@cs.washington.edu wrote: I'm skeptical about combining Chan and SharedChan. Maintaining that distinction is useful for expressing the programmer's intent and would certainly make any analysis that cared to distinguish between single and multiple producers easier to implement (off the top of my head, knowing you're the only one with a Chan means you don't have to deal with potential race conditions arising from interleaving of messages from different producers). Maybe a SharedChan should be constructed by consuming a Chan and upgrading its queue rather than duplicating all of Chan constructors? Perhaps there could be a simple `UniqueChan` type like: ~~~ struct UniqueChanT { priv chan: ChanT, } implT: Send UniqueChanT { // Re-implement Chan methods here } implT Drop for UniqueChanT { fn drop(mut self) {} } ~~~ But that is the special case rather than the general case, which is why it might be better to make Chan shared by default. ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0
On 13 Jan 2014, at 12:34 am, Owen Shepherd owen.sheph...@e43.eu wrote: But I also feel that by making the unchecked ones the shorter name, the language would be implicitly sending a message that they're preferred. Custom operator time! Say hello to our checked operators: trait CheckedAdd { fn infix +| (a: Self, b: Self) - Self; } trait CheckedSub { fn infix -| (a: Self, b: Self) - Self; } trait CheckedMul { fn infix *| (a: Self, b: Self) - Self; } xD ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] general onlookers questions on rust development
On 11 Jan 2014, at 9:38 am, Don Question donquest...@rocketmail.com wrote: 2. I'm used to curly braces, but every time i have to code in C or JavaScript i miss the better readability of python's curly-free syntax. What was the reason to keep the (imho: annoying) curly braces? I must confess i was a little bit taken aback by the first sentence on rust-lang.org: Rust is a curly-brace, ... I’m pretty sure it was for familiarity’s sake. I’m not the biggest fan of curly bracket syntax, but it’s a) too far down the road to change it easily, and b) far less important to me than the semantics that Rust brings to the table. ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] What type to put for index when impl-ing Index?
struct Foo([f64, ..3]); implI: Int IndexI, f64 for Foo { fn index(self, index: I) - f64 { let index = index.to_uint().unwrap(); match self { Foo(ref v) = v[index].clone() } } } fn main() { let tmp : uint = 0; let foo = Foo([1.0, 2.0, 3.0]); println!({:?}, foo[tmp]); } On 9 Jan 2014, at 2:08 pm, Ashish Myles marci...@gmail.com wrote: The following implementation of Index for Foo works fine. struct Foo([f64, ..3]); impl Indexuint, f64 for Foo { fn index(self, index: uint) - f64 { match self { Foo(ref v) = v[*index].clone() } } } fn main() { let tmp : uint = 0; let foo = Foo([1.0, 2.0, 3.0]); println!({:?}, foo[tmp]); } But if tmp is of type int, then I get an int-uint type mismatch failure. So I tried the following. use std::num::Int; ... implIdx : Int IndexIdx, f64 for Foo { fn index(self, index: Idx) - f64 { match self { Foo(ref v) = v[*index].clone() } } } But I get error: mismatched types: expected integral type but found `Idx` with the error pointing at *index above. What's the right way to go about implementing generic operator indexing? Or does one always require conversion to uint (in the first case above) on the caller's side? Ashish ___ 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] Joe Armstrong's universal server
On 19 Dec 2013, at 10:03 pm, Felix S. Klock II pnkfe...@mozilla.com wrote: rust-dev- From reading the article, I thought the point was that a universal server could be deployed and initiated before the actual service it would offer had actually been *written*. Ah, that makes more sense - that definitely fits in with the Erlang philosophy. Tricky to do in a language like Rust. ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Joe Armstrong's universal server
On 19 Dec 2013, at 1:26 am, Benjamin Striegel ben.strie...@gmail.com wrote: Hello rusties, I was reading a blog post by Joe Armstrong recently in which he shows off his favorite tiny Erlang program, called the Universal Server: http://joearms.github.io/2013/11/21/My-favorite-erlang-program.html I know that Rust doesn't have quite the same task communication primitives as Erlang, but I'd be interested to see what the Rust equivalent of this program would look like if anyone's up to the task of translating it. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev Universal server... done! https://gist.github.com/bjz/e4d536c63900960c9e15 Here’s the code: extern mod extra; use extra::comm::DuplexStream; enum RequestT, U { Request(T), Become(extern fn(T) - U), } struct ClientT, U { priv stream: DuplexStreamRequestT, U, U } implT: Send, U: Send ClientT, U { fn request(self, x: T) - U { self.stream.send(Request(x)); self.stream.recv() } fn become(self, f: extern fn(T) - U) { self.stream.send(Become(f)); } } fn start_serverT: Send, U: Send() - ClientT, U { fn failingT, U(_: T) - U { fail!(Server not yet initialised.) } let (client, server) = DuplexStream::RequestT, U, U::new(); spawn(proc() { let mut f = failing::T, U; loop { // Need iterators for DuplexStreams! match server.recv_opt() { Some(Request(x)) = server.send(f(x)), Some(Become(g)) = f = g, None = break, } } }); Client { stream: client } } fn factorial(n: u64) - u64 { match n { 0 = 1, n = n * factorial(n - 1), } } fn main() { let client = start_server(); client.become(factorial); println!({}, client.request(50)); } This was isn’t as elegant the Erlang example due to Rust’s static type system and/or lack of local type inference. You might be interested in my port of Erlang’s `gen_server` that I’ve been working on[1]. It needs to be fixed up to work with the new updates to std::comm though, so it won’t compile. ~Brendan [1] https://gist.github.com/bjz/c2b0ce9362cf748b4193 ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Joe Armstrong's universal server
On 19 Dec 2013, at 5:17 am, Kevin Ballard ke...@sb.org wrote: That's cute, but I don't really understand the point. The sample program he gave: test() - Pid = spawn(fun universal_server/0), Pid ! {become, fun factorial_server/0}, Pid ! {self(), 50}, receive X - X end. will behave identically if you remove universal_server from the equation: test() - Pid = spawn(fun factorial_server/0), Pid ! {self(), 50}, receive X - X end. The whole point of universal_server, AFAICT, is to just demonstrate something clever about Erlang's task communication primitives. The equivalent in Rust would require passing channels back and forth, because factorial_server needs to receive different data than universal_server. The only alternative that I can think of would be to have a channel of ~Any+Send objects, which isn't very nice. To that end, I don't see the benefit of trying to reproduce the same functionality in Rust, because it's just not a good fit for Rust's task communication primitives. -Kevin On Dec 18, 2013, at 6:26 AM, Benjamin Striegel ben.strie...@gmail.com wrote: Hello rusties, I was reading a blog post by Joe Armstrong recently in which he shows off his favorite tiny Erlang program, called the Universal Server: http://joearms.github.io/2013/11/21/My-favorite-erlang-program.html I know that Rust doesn't have quite the same task communication primitives as Erlang, but I'd be interested to see what the Rust equivalent of this program would look like if anyone's up to the task of translating 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 I think one of the points was that you could update the behaviour of the server as it was running. I changed my gist to show that: https://gist.github.com/bjz/e4d536c63900960c9e15#file-universal_server-rs-L63-L67 This is where I find that the static types come in handy, despite their verbosity. It’s much easier to understand what’s going on from the types alone. ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] IRC moderation due to attacks
On 15 Dec 2013, at 1:39 am, Jack Moffitt j...@metajack.im wrote: Some botnet is picking on #rust. Until the situation is resolved[1] or the botnet gives up, we've been turning on moderation in the #rust IRC room. This means that you won't be able to join #rust or talk in the channel unless you have registered with NickServ[2]. Right now the attack seems focused on #rust, but if the others channels start getting attacked as well we will have to turn on moderation there too. It would be useful if someone who has some free time could update the IRC page on the wiki to suggest people register their nicks and point them to the instructions below. You might also mention that moderation is employed from time to time to prevent spam bot attacks and that will prevent unregistered participants from joining and/or talking. We apologize for the inconvenience, and we'll hopefully be able to go back to our previous, unmoderated setup soon. jack. [1] https://bugzilla.mozilla.org/show_bug.cgi?id=950187 [2] https://wiki.mozilla.org/IRC#Register_your_nickname ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev I was just hit by a bot spamming /querys on me using random nicks. Can’t connect to #rust. :( ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Let’s avoid having both foo() and foo_opt()
On 7 Dec 2013, at 10:47 am, Simon Sapin simon.sa...@exyr.org wrote: This is why we have methods like .map() and .and_then() I like using these higher order functions, but I run into lots of issues with moved values because we don’t have once functions. I end up having to use matches, which are awfully verbose for simple things. :( ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Higher-Kinded Types vs C++ Combos
Of course this leads (assuming we had a `Collection` trait) to the horrendously ugly `Numbers::i32, ~[i32], f32, ~[f32](...)` if you wanted to be explicit. But hopefully your code would be such that Rust could infer the bounds. This will be alleviated in the future by associated items, but that will probably be post 1.0. (I might be getting a little off-topic here) ~Brendan On 7 Dec 2013, at 5:27 pm, Brendan Zabarauskas bjz...@yahoo.com.au wrote: I’m not sure I understand everything in your post, but this is how I’d write you first C++ example: struct NumbersIV, FV { priv iv: IV,// priv so the struct can only be constructed in this module priv fv: FV, } implI: Int, IV: CollectionI, F: Float, FV: CollectionF NumbersIV, FV { pub fn new(iv: IV, fv: FV) - NumbersIV, FV { Numbers { iv: iv, fv: fv } } } You can also write type aliases with type parameters, but I don’t think you can enforce trait bounds on them afaik: type AT = (T, int); ~Brendan On 7 Dec 2013, at 5:10 pm, David Piepgrass qwertie...@gmail.com wrote: Rust newb here. I have theoretical questions. Recently I noticed that Higher-Kinded Types (HKTs) have been mentioned on the mailing list a lot, but I had no idea what a HKT was, or what it might be good for. After reading about them a little, they reminded me of C++'s template template parameters. In C++ you can almost write something like this: template template typename class collection struct Numbers { collectionint integers; collectionfloat floats; }; So then you can write Numbersvector for a structure that contains vectorT collections, and Numberslist for a structure that contains listT collections. EXCEPT that it doesn't actually work, because vectorT has two template parameters (the second one, the allocator, is normally left at its default). Let's ignore that, though. So that brings me to my first question: is this what higher-kinded types means? What is the difference, if any, between HKT and C++ template templates? However, as a C++ developer I never actually used a template template parameter because I didn't know they existed for a long time. So instead I would have written this, which has the same end-result: struct VectorTrait { templatetypename T struct collection { typedef vectorT type; }; }; struct ListTrait { templatetypename T struct collection { typedef listT type; }; }; templatetypename Traits struct Numbers { Traits::collectionint::type integers; Traits::collectionfloat::type floats; }; // Use NumbersVectorTrait for vectorT, NumbersListTrait for listT. This is clunkier, but it would have been a bit simpler if C++ supported templatized typedefs: struct VectorTrait { templatetypename T typedef vectorT collection; }; struct ListTrait { templatetypename T typedef vectorT collection; }; templatetypename Traits struct Numbers { Traits::collectionint integers; Traits::collectionfloat floats; }; // Now write NumbersVectorTrait instead of Numbersvector, // NumbersListTrait instead of Numberslist. I have found that because of the existence of typedef, template template parameters are never actually necessary; so far, I've never seen a situation where the typedef-based solution wasn't almost as good. Also, I have found that trait types filled with typedefs seem to be a more general thing than template template; they allow you to do things that would be very difficult or impossible without them. For example you can use typedefs-in-a-struct to create circular references among types that don't know about each other: // I call this a Combo; I don't know if the technique has a standard name struct MyCombo { typedef ConcreteATraits A; typedef ConcreteBTraits B; typedef ConcreteCTraits C; }; templatetypename Combo class ConcreteA { Combo::B* b; ... }; templatetypename Combo class ConcreteB { Combo::C* c; ... }; templatetypename Combo class ConcreteC { Combo::A* b; ... }; Here I've created a network of types (ConcreteAMyCombo, ConcreteBMyCombo, and ConcreteCMyCombo) that are linked together through the Combo type MyCombo, so the types can all use each other, but none of the types refer to each other directly. This design allows you to freely swap in different implementations of A, B, and C; it has similar advantages to dependency injection or inversion of control in languages like Java and C#, except that the linkages are all defined statically at compile-time, so no dynamic dispatch is required. Without the ability to define typedefs, this approach is not possible at all if there is a cyclic relationship. Also, if the combo declares more than three types, it becomes impractical to specify all those types on the classes directly as type parameters. In C# I learned that this quickly becomes
Re: [rust-dev] Interesting talk about (scala) language/compiler complexity
On 5 Dec 2013, at 1:46 pm, Patrick Walton pcwal...@mozilla.com wrote: The particular criticisms of the Scala compiler, that the front-end does too much desugaring and that code is a string, are definitely not true for the Rust compiler. (Well, OK, `for` is desugared too early, but that has to be fixed before 1.0 anyway because this desugaring is actually incorrect.) Whilst desugaring too early is indeed an issue for creating a robust compiler, would it still make sense to think of how these language features desugar on a design/theoretical level? Then once these are set in stone for 1.0, document these transformations? ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Placement new and the loss of `new` to keywords
On 30 Nov 2013, at 6:55 pm, spir denis.s...@gmail.com wrote: Since this issue is all about placing something into memory, why not use 'mem' ? Denis Some folks have suggested using `alloc`. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] do
On 30 Nov 2013, at 5:34 pm, Oren Ben-Kiki o...@ben-kiki.org wrote: I find `do` syntax form is vital for DSL-ish code. Getting rid of it makes a lot of code look downright ugly. I'd rather it used a more Ruby-ish notation though, I find that putting the `do` far away from the `{ ... }` doesn't read well. `foo() do |...| { ... }` would have made more sense for me (think of `do` as a macro-ish binary operation injecting the proc into the function on the left). But the current form is acceptable This really is an important point. I would recommend folks look at Shoes (http://shoesrb.com/) for an example of how Ruby’s block syntax can help create beautiful APIs. ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] do
On 1 Dec 2013, at 1:45 pm, Patrick Walton pcwal...@mozilla.com wrote: the experiment of using blocks in place of RAII for stuff like with_c_str or unkillable has failed: it leads to too much rightward drift. Patrick I guess I can agree with that. I remember when I first started with Rust doing: `some_c_func(“hi”.with_c_str(|s| s))`, which completely negates the safety guarantees of the closure. How would this look with RAII? By ‘rightward drift’ do you mean in terms of multiple nested closures? ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Type system thoughts
Personally I'd appreciate a type system that's able to express SI units, which C++ and Haskell are powerful enough to do[1]. I agree. This is of huge importance when it comes to providing compile time safety guarantees. And if the language is powerful enough to express SI units, then it also demonstrates that it might be powerful enough to allow users to grow the language in other directions not anticipated by the language designers. ~Brendan On 16 Nov 2013, at 3:26 pm, Isaac Dupree m...@isaac.cedarswampstudios.org wrote: On 11/15/2013 11:05 AM, Gábor Lehel wrote: Like C++, types could be parameterized over constants. Again, the syntax could mirror their declarations. For example, a function to construct a fixed-length array: fn make_nstatic N: int(n: int) - ~[int, ..N] { [n, ..N] } Interesting questions here include what types to allow, how or whether to handle literals of various types as type arguments, and the constant expression sublanguage. Personally I'd appreciate a type system that's able to express SI units, which C++ and Haskell are powerful enough to do[1]. For example, if using the right library, let velocity = distance / time; would be a compile error if the dimensions do not match up properly. I added such a system to a C++ physics simulation and it caught some of our mistakes. *scurries off to learn Rust properly* -Isaac [1] C++: Boost.Units; Haskell: http://www.haskell.org/haskellwiki/Physical_units ___ 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] typing in rust
SML also shares these semantics when it comes to bindings. That is, a subsequent binding to the same identifier can ‘mask’ those that proceed it, even if they are in the same scope and the bound values are of different types. Once a value has had its identifier masked, it can no longer be accessed. I assume this behaviour was passed on to Ocaml, and Rust inherited it from there. Rust was originally written in Ocaml, and has drawn many influences from there. I personally find it useful from time to time. ~Brendan On 14 Nov 2013, at 3:25 am, Joshua Rodgers byt...@gmail.com wrote: I'm curious as to why this is valid, though? This makes sense if you're inside a new or nested scope, but why is it valid inside the same scope as illustrated in the code example? I can understand it from the perspective that I need to mask a function name (but that's a nested scope to me, at that point). On Wed, Nov 13, 2013 at 8:54 AM, Scott Lawrence byt...@gmail.com wrote: I would think that `test()` (the function) is in scope for the duration of `let test =`, and then the new definition masks the old one. Similarly, let x = 2; let x = x + 2; If you change the last line to /call/ test(), you should get an error. On Wed, 13 Nov 2013, Philip Herron wrote: Hey all I am still learning but i just tried something which i expected to give an error but works: fn test () - int { 1 } fn main () { let test = test (); println (format! ({}, test)); } I guess on compilation the names are mangled against their types or something so you can differentiate between test the function and test the variable. Not sure would be nice to get some clarification what this behavior is. Thanks --Phil -- Scott Lawrence ___ 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] About owned pointer
On 12 Nov 2013, at 10:21 am, Gaetan gae...@xeberon.net wrote: - as a typicial rust programmer, will i see the usage of str or ~str as logic or will i have to copy paste some sample code each time because it works this way in rust” This is what I thought at first, but once you use it for a while it will become natural, and you will find the distinction very useful. Just give it a chance before you jump to conclusions - you won’t regret it! :) - the boilder plates theory. Can i avoid them? I think a good modern language should allow me to avoid writing useless code, each time the same things. That is the real mess with C++. They are not useless - `~str`, `str`, `'a str` and `'static str` all convey extremely important semantic information both to the programmer and to the compiler. Changing `~str` to `str` would cause more inconsistencies (what about the borrowed pointers?) with a loss of the afore mentioned semantic information. ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Please simplify the syntax for Great Justice
On 12 Nov 2013, at 10:12 am, John Clements cleme...@brinckerhoff.org wrote: If you had the energy to build an alternate front-end using a parenthesized syntax, I'm sure there are others that would give it a try. Me, for instance! It would be nice if we could: - A: desugar Rust into a small kernel language - B: allow rustc to take in some sort of raw AST data (not sure if that’s already possible) - C: have a way of outputting the AST data in a certain syntax. That would allow folks like me to have a nice Haskelly syntax as well as an s-expr style! Heh. ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] How would you map one vector to a vector of a different element type?
You’re trying to move the ~strs out of the vector. You’ll need to use `move_iter`: ~~~ let ports = do myvect.move_iter().map |s| { let (pport, cchan) = stream(); do spawn { cchan.send(fun(s)) } pport }.to_owned_vec(); ~~~ Also note the use of `to_owned_vec`. `map` lazily returns a `Map` iterator - you need to explicitly drain it. (Note I haven’t tried compiling this) ~Brendan On 3 Nov 2013, at 7:04 am, Leah Hanson astriea...@gmail.com wrote: Thanks, Scott, I think that's closer. However, now I'm having trouble with my pointer types. Using the element inside a spawn means that I need to capture the owned string in the right way so that the compiler allows me to give it to the other task. This version: ~~~ let ports = do myvect.iter().map |s| { let (pport, cchan) = stream(); do spawn { cchan.send(fun(*s)) } pport }; ~~~ gives me pointer-type related errors: • error: cannot move out of dereference of pointer • cchan.send(fun(*s)) • error: cannot borrow immutable local variable as mutable • when I iterate over the Ports later • error: cannot capture variable of type `~str`, which does not fulfill `Send`, in a bounded closure • cchan.send(fun(*s)) I also tried a version with |s| and cchan.send(fun(s)), which gave me different errors: • error: cannot move out of captured outer variable in a heap closure • cchan.send(fun(*s)) • error: cannot move out of dereference of pointer • on the |s| • error: cannot borrow immutable local variable as mutable • when I iterate over the Ports later I'm very new to Rust. What do I need to do to let the compiler know that I'm not going to use anything in the first vec anymore? That I just want the ~str pointers directly? (I put the |s| outside the {} because putting it inside seemed to confuse things -- in that case, rustc expected an identifier instead of the `let` that comes next, so I assumed that `do v.iter().map {|s| ...}` is a syntax error.) Thanks, Leah On Sat, Nov 2, 2013 at 3:23 PM, Scott Lawrence byt...@gmail.com wrote: I would think: let ports = do myvect.iter().map { |e| something(e) } On Sat, 2 Nov 2013, Leah Hanson wrote: Hi, I have a ~[~str]. I have code that will turn a ~str into a Portuint. I want to end up with a [Portuint]. (or ~ or @ or whatever. I just want to be able to iterate over the Ports later.) Since I'm not sure what looping construct to use, I tried with a for-each loop. ~~~ let ports = for s in myvect.iter() { let (pport, cchan) = stream(); do spawn { cchan.send(fun(*s)) } pport }; ~~~ As you might, expect I got an error: error: mismatched types: expected `()` but found `std::comm::Portuint` (expected () but found struct std::comm::Port) From this, I take it that for loops must return `()`, rather than an actual value. When I searched for a map function in the documentation, I only found a Map type. How would you map one vector to a vector of a different element type? Thanks, Leah -- Scott Lawrence ___ 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] num::cast
You can use the `--emit-llvm` flag with rustc to check out the IR. To increase the optimisation amount, you can use `--opt-level LEVEL`, or just `-O` for an optimisation level of 2. ~Brendan On 29/10/2013, at 6:00 AM, Rémi Fontan remifon...@yahoo.fr wrote: Thanks. I hope that llvm its capable optimizing the code,I wouldn't want an option struct to be created each time I call this function. What would be the way to verify that llvm did the job correctly? Cheers Remi On Oct 28, 2013 11:12 PM, Brendan Zabarauskas bjz...@yahoo.com.au wrote: Yes, it's a static cast, so llvm should optimise that out. Do note however that the API has changed in 0.9-pre, and num::cast now returns an OptionT. So your code would be: ~~~ let res: T = aVariable / num::cast(2).unwrap(); ~~~ LLVM should resolve the conditional at statically - I haven't checked though. ~Brendan On 28/10/2013, at 8:26 PM, Rémi Fontan remifon...@yahoo.fr wrote: Hi, just checking performance wise, is num::cast() doing a dynamic type cast or a static cast. I'm writing some template code that works on Real and I need sometime to divide T:Real by 2 or compate with 0 or 1. I've been using num::zero() and num::one() so far but how about dividing by 2? should I write something like this: let two = num::one::T()+ num::one::T(); let res:T = aVariable / two; or would be just as efficient? let res:T = aVariable / num::cast::float, T(2.0); or is there an even better alternative? with rust 0.8. cheers, Rémi -- Rémi Fontan : remifon...@yahoo.fr mobile: +64 21 855 351 93 Otaki Street, Miramar 6022 Wellington, New Zealand ___ 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] return type of closure
struct ntimesT(times: uint, value: T) - T; Does this syntax work at the moment? ~Brendan On 29/10/2013, at 9:33 PM, Niko Matsakis n...@alum.mit.edu wrote: Incidentally, my preferred way to return a closure is to use an impl like so: struct ntimesT(times: uint, value: T) - T; implT:Clone ntimesT { fn call(mut self) - OptionT { if self.times == 0 { None } else { self.times -= 1; Some(self.value.clone()); } } } Now you can call it like: let foo = ntimes(3, v); foo.call(); // Some(v) foo.call(); // Some(v) foo.call(); // Some(v) foo.call(); // None Niko On Mon, Oct 28, 2013 at 04:06:38PM -0400, Steven Blenkinsop wrote: On Monday, October 28, 2013, Ramakrishnan Muthukrishnan wrote: On Mon, Oct 28, 2013 at 11:48 AM, Jesse Ruderman jruder...@gmail.comjavascript:; wrote: If you don't mind changing ntimes to not return a closure: fn ntimesT(f: fn(T) - T, times: uint, x: T) - T { match times { 0u = x, _ = ntimes(|x| f(x), times - 1u, f(x)) } } fn main() { println(format!({:d}, ntimes(|k| k*2, 2u, 3))); } Thanks. That is very nice. No, I am not particular about returning a closure. I was just trying out some toy programs to learn Rust. It would have been nice to return a closure from `ntimes' though. :( You can *create* a closure from ntimes, doing `|x| ntimes(|k| k*2, 2, x)`. The idea is that closures borrow data from the stack, so passing them up the stack is difficult. If you want to use the stack as your datastructure, you have to ensure everything travels down the stack, which you can do by requiring the caller to pass in their own closure accepting your closure as an argument (a syntax extension abstracting over this pattern would be nice so the code doesn't become ungainly). Otherwise, you have to build up your own datastructure to pass up the stack, and then derive a closure from that somehow. Ultimately, if closures become a special case of trait objects, this should be really straightforward to do. ___ 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] num::cast
Yes, it's a static cast, so llvm should optimise that out. Do note however that the API has changed in 0.9-pre, and num::cast now returns an OptionT. So your code would be: ~~~ let res: T = aVariable / num::cast(2).unwrap(); ~~~ LLVM should resolve the conditional at statically - I haven't checked though. ~Brendan On 28/10/2013, at 8:26 PM, Rémi Fontan remifon...@yahoo.fr wrote: Hi, just checking performance wise, is num::cast() doing a dynamic type cast or a static cast. I'm writing some template code that works on Real and I need sometime to divide T:Real by 2 or compate with 0 or 1. I've been using num::zero() and num::one() so far but how about dividing by 2? should I write something like this: let two = num::one::T()+ num::one::T(); let res:T = aVariable / two; or would be just as efficient? let res:T = aVariable / num::cast::float, T(2.0); or is there an even better alternative? with rust 0.8. cheers, Rémi -- Rémi Fontan : remifon...@yahoo.fr mobile: +64 21 855 351 93 Otaki Street, Miramar 6022 Wellington, New Zealand ___ 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] How to use the std::path?
Using master is highly recommended. Treat the 0.* releases as snapshots as opposed to stable releases. ~Brendan On 26/10/2013, at 11:59 PM, Ramakrishnan Muthukrishnan vu3...@gmail.com wrote: On Sat, Oct 26, 2013 at 5:00 PM, Ramakrishnan Muthukrishnan vu3...@gmail.com wrote: Hi, This is my first post to the list. Had been playing with Rust for the past one week and it is very nice so far. I hope this is the list for users of Rust as well (as opposed to developers of Rust). I apologise if it is the wrong place to ask newbie questions.. I am trying to follow the documentation on std::path and am trying to create a path, just like it is described in the documentation: http://static.rust-lang.org/doc/master/std/path/index.html use std::path; fn main() { let mut path = Path::new(/tmp/path); } Okay, I could move on by doing: let mut path = Path(/tmp/path); I also should have been looking at the manual for 0.8 version instead of master, as I am running 0.8. Thanks Ramakrishnan ___ 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] mutable vs. functional APIs
chain-oriented APIs (methods like `fn frob(self) - Frob`) What about: ~~~ fn frob(self) - Frob { let mut x = self;// not sure if you need `cast::transmute_mut` here x.thing = foo(); x } ~~~ That would solve the 'copying' problem. I was actually considering doing this as a way of initialising an object in a fluent style: ~~~ let perlin = Perlin::from_seed_str(Kittens) .with_frequency(2.0) .with_octaves(3); ~~~ ~Brendan On 22/10/2013, at 9:18 AM, Erick Tryzelaar erick.tryzel...@gmail.com wrote: In my opinion, there are two main reasons why one would prefer an immutable API over a mutable one: aliasing and sharing substructures. Given that unique pointers and references have mostly solved the first one, in my opinion we should prefer mutable APIs unless the API is going to take advantage of structure sharing. I don't think it makes a lot of sense to have immutable APIs like this: fn frob(mut self) { ... } fn frobed(self) - Frob { let x = self.clone(); x.frob(); x } It's a lot more straightforward for the users to write `let y = x.clone(); y.frob();`, and it protects us from another combinatorial explosion of methods. All that being said, I feel there is an open question on whether or not to prefer statement oriented mutable APIs (methods like `fn frob(mut self)`) and chain-oriented APIs (methods like `fn frob(self) - Frob`). Does anyone have a good argument for one over the other? On Sat, Oct 19, 2013 at 9:42 AM, Eric Sampson eric.samp...@gmail.com wrote: Date: Fri, 18 Oct 2013 10:54:23 -0700 From: Jeff Petkau j...@google.com On my code (disclaimer: only toy projects to learn Rust so far), I've been pretty happy with a mut_ prefix for mutable versions. newthing = oldthing.push(foo) anything.mut_push(foo) x = bagofun.sort() bagosadness.mut_sort() etc. Advantages: - consistent meaning with the 'mut' keyword. - works with pretty much any name. - makes mutable versions just a bit uglier than immutable code. Disadvantages: - If an API is inherently mutable, it gets pretty noisy. - A bit ugly, probably turns off newcomers. - If the compiler warns on ignoring return values, and mutating methods return (), then a convention might be unnecessary. --Jeff What about establishing a convention that mutable methods start with an uppercase letter while non-mutating methods start with a lowercase letter? It would be lightweight in terms of character count/looks and at the same time give mutable methods a slight visual emphasis, which makes sense I think. I know this convention is already used by Traits, but when I looked through some code with the above proposal in mind it would be easy to distinguish between these two uses of the same convention due to the differing contexts they're used in. -Eric ___ 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] OpenGL: gl-rs updated with command line generation options
gl-rs[1] is an OpenGL function loader for Rust. It exposes the full OpenGL API, loading the function pointers at runtime to ensure portability between systems with different graphics drivers. This capability is extremely important for developers who wish to make full use of state-of-the-art graphics hardware. The recent changes by Corey Richardson allow for the specification of what is generated by the loader. This means you don't have to generate the entire spec, like you used to (which resulted in a 1.6mb file) ./generator --version 3.3 --profile core ./generator --version 2.1 --extension GL_ARB_robustness --extension GL_EXT_draw_instanced We have included a 4.3 core profile loader so that you can get up to speed quickly without having to spend time generating the loader yourself. Hopefully with future updates to rustpkg you will be able to supply the generation options at the `extern mod` line in your source code. If you have any issues, questions or suggestions, you can contact me on irc.mozilla.org #rust-gamedev[2]. My handle is 'bjz'. Hopefully this helps to give Rust an extra boost in the realm of high-performance graphics! Regards, Brendan Zabarauskas [1]: https://github.com/bjz/gl-rs [2]: http://chat.mibbit.com/?server=irc.mozilla.orgchannel=%23rust-gamedev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] average function
I normally prefer using `std::num::{cast, zero}` as its a tad more readable. So: use std::num; fn averageT:Int(values: [T]) - T { values.iter() .fold(num::zero::T(), |x, y| x.add(y)) .div(num::cast(values.len())) } fn main() { print!({}, average([1,2,3])) } On 25/09/2013, at 8:09 AM, Scott Lawrence byt...@gmail.com wrote: Use NumCast::from(count). You'll also want to be sure to initialize sum. I'd use the Zero instance. use std::num::Zero; fn averageT:Int(values:[T]) - T { let count = values.len(); let mut sum:T = Zero::zero(); for v in values.iter() { sum = sum.add(v); } return sum / NumCast::from(count); } fn main() { println(fmt!(%d, average([1,2,3]))) } On Wed, 25 Sep 2013, Andreas Zwinkau wrote: I tried to write an average function, but so far failed to convince the type checker. fn averageT:Int(values:[T]) - T { let count = values.len(); let mut sum:T; for v in values.iter() { sum = sum.add(v); } return sum / count; } error: mismatched types: expected `T` but found `uint` (expected type parameter but found uint) The problem is that sum is the generic type T, but count is uint due to the definition of the len function. Casting count as T should work, i thought, but rustc seems to have another opinion? -- Andreas Zwinkau work email: zwin...@kit.edu private email: q...@web.de homepage: http://beza1e1.tuxen.de ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Scott Lawrence ___ 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] Struct members in trait definitions
Adding struct members in traits would be… weird. Where would those members be stored when passing things around by value? This sounds like something for properties. But as Nikko says it is not a planned feature at the moment – there is enough on the table for 1.0 as it is. I'm sure they would be a controversial proposal too (although I think they would be nice). ~Brendan On 20/09/2013, at 9:02 PM, Andres Osinski andres.osin...@gmail.com wrote: Hi all, I have a question which I'm sure must have already been discussed and dealt with, but I wanted to understand the design rationale: A lot of trait-level functionality would be enhanced if a trait could specify members to be included in the struct which implements the trait. This can be solved in practice by wrapping member access in accessor methods, but I fail to see why that would be preferable. The reason I'm asking is because I'm trying to design data structures which contain a couple of arrays, and I wanted to define the trait by not only a set of supported operations but by the existence of both arrays so that a default method could deal with any struct which implements the trait, instead of having to define for every struct an accessor method for each structure and then have to call the accessors in the trait to do anything. Thanks -- Andrés Osinski http://www.andresosinski.com.ar/ ___ 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's newest full-time Engineer
Congratulations! You've already made some significant contributions to Rust, and we greatly appreciate your efforts. Could think of nobody better to be working on Rust full time. ~Brendan On 17/09/2013, at 6:43 AM, Alex Crichton acrich...@mozilla.com wrote: Greetings rust-dev! I wanted to announce to everyone that today is my first day at Mozilla as an engineer working on Rust! I started using Rust last December for a project of mine, and once I got fed up with compiler errors I decided to try my hand at improving the compiler itself. The community was incredibly helpful in getting me on my feet contributing to rust, and it's been awesome seeing how rust and the community around it have evolved since I started working on it. I'm incredibly excited to have the opportunity to work on Rust with everyone who's been contributing, and I can't wait to help Rust reach 1.0 even faster. ___ 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] Formatting complex trait definitions and impls
Has anybody worked out a decent way to lay out complex definitions? This is what I'm starting to do: pub trait AffineSpace S: Field, V: VectorSpaceS : Eq + Zero + AddV, Self + SubSelf, V + ScalarMulS { // ... } impls are harder though: implS: Field SubPoint3S, Vec3S for Point3S { … } Any ideas? This is one way maybe, but it looks terrible: impl S: Field Sub Point3S, Vec3S for Point3S { // ... } Stacking it is probably overkill for that impl, but there a most likely going to be worse ones. Maybe this is more of a problem with the current syntax? ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Mozilla using Go
My understanding is that Rust is meant more for real-time, performance/security critical applications, such as user-facing guis and rendering engines. This also fits nicely with games and graphics applications. There is also the real possibility of it being useful in embedded systems. Go is designed more for large, server-side applications. The core devs have said many times that they don't consider Go to be a competitor. ~Brendan On 01/09/2013, at 6:48 PM, John Mija jon...@proinbox.com wrote: Hi! I've seen that Mozilla has used Go to build Heka (https://github.com/mozilla-services/heka). And although Go was meant to build servers while Rust was meant to build concurrent applications, Rust is better engineered that Go (much safer, more modular, optional GC). Then, when is better intended use case of Rust respect to Go? I expect Rust to be the next language for desktop applications if it gains as much maturity as Go but I'm unsure respect to the server side. ___ 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] Doc comment conventions + straw poll
I definitely find this very lovely. Lining up with the tab stops perfectly is a big plus. ~Brendan On 26/08/2013, at 11:21 PM, Armin Ronacher armin.ronac...@active-4.com wrote: Hi, On 26/08/2013 02:59, Corey Richardson wrote: C: The nice thing about this solution is that with the whitespace after the three slashes it lines up perfectly with 4 spaces which means the tab key continues working properly with the current rust style of 4 space indentation. This is very useful for nested code in comments. Regards, Armin ___ 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] parameterizing types and functions by integers
This would be amazing. At the moment the [T,..n] types are pretty damn useless when it comes to generics. Mathematics, science and units of measure libs would find constant parametrisation most useful. I could imagine something like: fn dotT: Ring, N: uint(a: [T, ..N], b: [T, ..N]) - T { … } or // Forgive me if I get these dimensions around the wrong way! fn mul_matT: Ring, M: uint, N: uint, O: uint(a: [[T, ..N], ..M], b: [[T, ..O], ..M]) - [[T, ..N],..O] { … } fn transposeT: Ring, M: uint, N: uint(a: [[T, ..N], ..M]) - [[T, ..M], ..N] { … } ~Brendan On 23/08/2013, at 3:22 PM, Geoffrey Irving irv...@naml.us wrote: Does rust have compile time sized arrays, equivalent to the following C++ definition? templateint d,class T struct array { T x[d]; }; More generally, is it possible to parameterize types by integers, so that types like the above can be built up? Finally, is it possible to parameterize functions over integers, as in fn concatT,a,b(x : arraya,T, y : arrayb,T) - arraya+b,T { ... } If integer type arguments aren't built in, is it possible to type the concat function using a type-based encoding of naturals? Thanks! Geoffrey ___ 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] Order of appearance in files of extern mod, mod and use
That was my understanding. Without knowing much about the compiler, `mod` seems to declare an item. It would be weird to allow imports between item declarations. ~Brendan On 06/08/2013, at 5:53 AM, Gareth Smith garethdanielsm...@gmail.com wrote: On 05/08/13 19:56, Dov Reshef wrote: If I understand correctly mod foo import the foo module into the current module, and use foo::bar bring bar from foo module into the current scope, so it seems more logical that use should follow mod, not the other way around. My understanding is that mod foo; is kind of like mod foo { ... } except that with mod foo; the body of the module comes from a different file, so it is more like a definition than an import. Gareth ___ 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] Java versus .NET style for acronyms in type names
On 03/08/2013, at 12:25 PM, Jeaye je...@arrownext.com wrote: To be fair, and I like being fair, both of these are inconsistent within Rust. If functions_are_like_this then types Should_Be_Like_This or Maybe_like_this. Having different significantly different styles for types, functions and constants aids code comprehension. They are inconsistent for ergonomic reasons. ~B ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Function definition syntax
On 31/07/2013, at 7:29 AM, Graydon Hoare gray...@mozilla.com wrote: we used to use [T,U,V] like Scala, but user feedback decisively rejected it. My kingdom for a few extra bracket characters! Maybe I should be more dictatorial and less democratic when it comes to such things; I'm a bit of a pushover. Damn, that's a shame. Feel free to use your Benevolent Dictator For Life role in future! The users will thank you in the end :) *shudders at the issues caused by delimeters* ~Brendan ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Function definition syntax
This would make function signatures harder to read in some instances, particularly when using closures and higher-order functions: let f: fn(T): T = …; fn hofT(x: T, f: fn(T): T): fn(T): T { … } Compare to the current syntax: let f: fn(T) - T = …; fn hofT(x: T, f: fn(T) - T) - fn(T) - T { … } ~Brendan On 30/07/2013, at 9:29 AM, Wojciech Miłkowski milkow...@gmail.com wrote: Hi, I'm observing rust development for some time, and I must say it slowly encourages me to use it. Especially the progress from Perl-like syntax to more sane and quiet form is enjoyable. That said I wonder why the function definition has form: fn name(var: type, ...) - return_type {...} instead of more unified: fn name(var: type, ...): return_type {...} Is it constructed to mimic mathematical form f(x)-y or is there other reason i.e. syntax ambiguity? Cheers, W. ___ 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] read_byte and sentinel values
On 25/07/2013, at 2:15 AM, Evan Martin mart...@danga.com wrote: Is an Optionu8 implemented as a pair of (type, value) or is it packed into a single word? A quick test shows: rusti std::sys::size_of::Optionu8() 16 ~Brendan___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] OpenCL-style accessors, casts.
Just so folks have the heads up, here is the discussion of the blog post on reddit: http://www.reddit.com/r/rust/comments/1igvye/vision_for_rust_simd/ ~Brendan On 16/07/2013, at 2:27 PM, Jens Nockert j...@nockert.se wrote: Hello rust-dev! I implemented OpenCL-style[0] accessors for SIMD types in Rust[1], the code quality isn't near /merge-worthy yet, but I wanted some input. For some code-examples, go to https://github.com/jensnockert/rust/tree/simd/src/test/run-pass/simd-test and check it out, you should be able to get the idea of how they work. Note that I didn't add any actual syntax for vector types yet (since it would be highly controversial and I don't know what would be the best option), so I just added a simd!(name: T * n) syntax extension that declares a new type that maps down to a LLVM n * T. My preference for syntax right now would be simd!(n x T) if I can get that to parse, or simd!(T, ..n). And then you would declare a type with type f32x4 = simd(4 x f32); and it would magically work. Another option would be some variant of the [T, ..n] syntax used for fixed-length vectors. Introducing a new t, ty_simd_vec(t, uint), instead of using the current #[simd] struct { … }, is yet another thing that is controversial about the patch and this needs a bit of explanation of the problem with #[simd] struct { … }. To be able to make these accessors work, you unfortunately need to be able to generate anonymous types in the compiler, x.even for example (take the even-indexed elements of a vector) may be a type that is undeclared. And if you want to be able to pretty-print that, you need to be able to generate a type without a name, which makes #[simd] struct { … } impossible. You could just pre-declare all possible options up to 256-bit long, which probably would only be a hundred types or so, but would feel a bit silly. There are also other operations that could generate (possibly) unnamed types, like a == b, which should generate a i1-vector, or a shufflevector intrinsic that could generate vectors of any length. Ps. I didn't think of #[simd] (T, T, T, T) c. before implementing (sanxiyn gave me that idea), but I still think that is probably a worse idea than adding SIMD as an additional type with actual syntax. [0]: http://www.khronos.org/files/opencl-quick-reference-card.pdf, page 2, Vector Component Addressing [1]: https://github.com/jensnockert/rust/tree/simd ___ 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] OpenCL-style accessors, casts.
Introducing a new t, ty_simd_vec(t, uint), instead of using the current #[simd] struct { … }, is yet another thing that is controversial about the patch This is indeed a shame because named fields are very nice for clean, self-documenting apis. Perhaps properties solve this, but I don't think there would be much will to add more features considering all the work that still has to be done (I could be wrong though). ~Brendan On 16/07/2013, at 2:27 PM, Jens Nockert j...@nockert.se wrote: Hello rust-dev! I implemented OpenCL-style[0] accessors for SIMD types in Rust[1], the code quality isn't near /merge-worthy yet, but I wanted some input. For some code-examples, go to https://github.com/jensnockert/rust/tree/simd/src/test/run-pass/simd-test and check it out, you should be able to get the idea of how they work. Note that I didn't add any actual syntax for vector types yet (since it would be highly controversial and I don't know what would be the best option), so I just added a simd!(name: T * n) syntax extension that declares a new type that maps down to a LLVM n * T. My preference for syntax right now would be simd!(n x T) if I can get that to parse, or simd!(T, ..n). And then you would declare a type with type f32x4 = simd(4 x f32); and it would magically work. Another option would be some variant of the [T, ..n] syntax used for fixed-length vectors. Introducing a new t, ty_simd_vec(t, uint), instead of using the current #[simd] struct { … }, is yet another thing that is controversial about the patch and this needs a bit of explanation of the problem with #[simd] struct { … }. To be able to make these accessors work, you unfortunately need to be able to generate anonymous types in the compiler, x.even for example (take the even-indexed elements of a vector) may be a type that is undeclared. And if you want to be able to pretty-print that, you need to be able to generate a type without a name, which makes #[simd] struct { … } impossible. You could just pre-declare all possible options up to 256-bit long, which probably would only be a hundred types or so, but would feel a bit silly. There are also other operations that could generate (possibly) unnamed types, like a == b, which should generate a i1-vector, or a shufflevector intrinsic that could generate vectors of any length. Ps. I didn't think of #[simd] (T, T, T, T) c. before implementing (sanxiyn gave me that idea), but I still think that is probably a worse idea than adding SIMD as an additional type with actual syntax. [0]: http://www.khronos.org/files/opencl-quick-reference-card.pdf, page 2, Vector Component Addressing [1]: https://github.com/jensnockert/rust/tree/simd ___ 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] OpenCL-style accessors, casts.
I'm not saying that the shuffles would have to be generated using the field names - that would be near impossible. For example: ~~~ #[simd] struct RGB T { r: T, g: T, b: T, a: T } ~~~ Shuffling would still use the CL syntax: ~~~ let v2 = v.s3201 ~~~ I would be really interested to hear what sanxiyn had in mind for #[simd] when he added it. Relevant PRs with discussions: https://github.com/mozilla/rust/pull/5841 https://github.com/mozilla/rust/pull/6214 https://github.com/mozilla/rust/pull/7705 ~Brendan On 16/07/2013, at 9:06 PM, Jens Nockert j...@nockert.se wrote: On H.25/07/16, at 12:13, Brendan Zabarauskas bjz...@yahoo.com.au wrote: Introducing a new t, ty_simd_vec(t, uint), instead of using the current #[simd] struct { … }, is yet another thing that is controversial about the patch This is indeed a shame because named fields are very nice for clean, self-documenting apis. Perhaps properties solve this, but I don't think there would be much will to add more features considering all the work that still has to be done (I could be wrong though). While nice, I don't think this is a good idea. It leads to very complex shuffle-syntax, and makes intrinsics and anything else with a T1 (x T1) - T2 type signature (comparisons, non-bitwise casts) much harder to call and implement. It would also mean that all intrinsics would have to be generic. And that you need to pattern-match match in trans to generate shufflevector operations. Examples, ~~~ OpenCL shuffle let v2 = v.abgr; ~~~ Named property shuffle let v2 = match v1 { rgba { r:r, b:b, g:g, a:a } = rgba { r:a, g:b, b:g, a:r } }; ~~~ And that isn't even the degenerate case of wanting to replace the order of a subset of the elements of a u8x16-like type which succintly can be described in OpenCl-like syntax. ~~~ v1.s89 = v1.s98; // or for complex arithmetic let i0 = a * b; r.even = i0.even - i0.odd; r.odd = a.odd * b.even + a.even * b.odd; ~~~ And these I cannot write the named-property variants of on my phone, so you will have to imagine what they would look like. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] bikeshedding println() and friends
I'm not wedded to the precise C conventions. Yes, the discussions with aatch, dbaupp, kimundi etc. were discussing possible options for the format syntax. https://mail.mozilla.org/pipermail/rust-dev/2013-May/003999.html ~Brendan On 16/07/2013, at 12:00 AM, Niko Matsakis n...@alum.mit.edu wrote: On Sun, Jul 14, 2013 at 03:51:25PM +1000, Brendan Zabarauskas wrote: I'm a fan of sticking with the fmt! style - it separates the data from the representation as opposed to mixing the two. But maybe I'm just an old fuddy-duddy. +1 for format strings, though I'm not wedded to the precise C conventions. I particularly dislike intermixing expressions and the string. I often have things like this: debug!(fmt!(Entering %s: foo=%s bar=%s, some_long_expression.id.to_str(), foo.repr(tcx, ...), ...)); When expressions get long, it's very ugly for them to be mixed in with the string. Niko ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Renamed print/println
print!()/println!() and printf!()/printfln!() sounds good to me. Adding an extra 'f' isn't much of a hassle for fmt! functionality. ~Brendan On 16/07/2013, at 7:25 AM, Steven Ashley ste...@ashley.net.nz wrote: A possible use case for printfln may be to ensure that a new line is always written in the case where the format string comes from a .po file and is translated into many different languages. ___ 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] Renamed print/println
Indeed. `println(fmt!(%?, foo));` requires great deal of keyboard gymnastics. And yes the most common use case will most likely be for debugging, so the ergonomics should fit with that. ~Brendan On 16/07/2013, at 9:38 AM, Corey Richardson co...@octayn.net wrote: On Mon, Jul 15, 2013 at 7:33 PM, Brendan Zabarauskas bjz...@yahoo.com.au wrote: print!()/println!() and printf!()/printfln!() sounds good to me. Adding an extra 'f' isn't much of a hassle for fmt! functionality. Way I see it is if I can type less than `println(fmt!(%?, foo));`, I'm happy :) That is basically the only time I use fmt!, for debugging. I haven't really written anything that needs interaction with user that isn't done with command arguments. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] bikeshedding println() and friends
Actually, your suggestion would actually be quite nice for quit print debugging. often I doe want to just do: `println(x)`. What about: - print!, println! - comma separated list of values, converted to a string - printf!, printfln! - wraps fmt! Simples. ~Brendan On 14/07/2013, at 12:39 PM, Jack Moffitt j...@metajack.im wrote: I saw https://github.com/mozilla/rust/pull/7779 come up today and commented on it. I got to thinking about it some, and since the bug doesn't seem the right place for such discussion, I wanted to bring it up here. The PR proposes to rename print!() and println!() to printf!() and printfln!(). The original macros exist to replace uses of print() and println() that look like: println(fmt!(blah blah %s, s)); Having a good default way to print things is very important, and it's one of the first things people will see of the language. I think it's worth bikeshedding it a bit to see if we can't come up with something better than the status quo. I propose instead: 1) Do away with the formatting stuff as the default. print!() and println!() should just take a variable number of arguments, and each one should be printed in its default string representation with a space between each one. This is how Clojure's (and Python's?) print and println work. This would change code like this: println!(The result is %f, foo); to this: println!(The result is, foo) It's much easier. There are no formatting codes to remember and it does exaclty what you want in most cases. Consider: println!(a, ,b, c, d=, d); This seems great for the standard printf-style debugging. If formatting is needed, it's easy to get to: println!(My name is, name, and I scored, fmt!(%0.2f, score)); 2) Since println!() is likely to be used the most often, I feel like it should have a shorter name. Ie, we should call it just print!(), and have a newline-less version with a different name, or perhaps a different style of invocation of the macro. As some data to ponder, I went through the Servo code and all its dependencies: - The dependencies of servo use println 42 times, 24 of which also use fmt!(). None of these need to use fmt!() at all, they could just use the default string representation. - Servo itself uses println about 10 times, only two of which need fmt!(). These two uses are both fancy formatted output for the profiler. Changing all these uses to print!() in the codebase (aside from the two profiler fmt!()s) would make things much nicer looking. jack. ___ 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] bikeshedding println() and friends
.. no new languages have used it in ages http://golang.org/pkg/fmt/ On 14/07/2013, at 4:29 PM, Bennie Kloosteman bkloo...@gmail.com wrote: The C printf way is very primative .. no new languages have used it in ages and even C++ tried to replace it with cout and overloading . I prefer the Java /C# way which is best from a coding simplicity and safety point of view but can handle different cases. stream.Write ( str1 + str2 +string3) ( you can go Console.WriteLine or File but these use a stream underneath so i dont think it would make a huge difference in performance ) I dont like print (str1 , str2 ,str3 ) as much because its not as obvious what the method does eg in C# if str1+str2 ..etc etc is too slow in a big loop you go to var str =string.Format ( This is a long string with many inserts {0} at different points {1} , val0 , val1 ...) ; stream.Write (str); and if that is still too slow use stringbuilder to write direcly to the stream. and if that is still too slow build your own char array It may be needed for the lib to give ok performance but i would call it somehing obscure like internal_print so its not the default option for every c programmer ..the default / easiest option needs to be the easiest and safest one to program .. which c printf style is not.. ___ 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] bikeshedding println() and friends
Not to mention all the allocation that goes on in num::strconv :/ Some work on that could possibly result in a speed up. I'm a fan of sticking with the fmt! style - it separates the data from the representation as opposed to mixing the two. But maybe I'm just an old fuddy-duddy. ~Brendan On 14/07/2013, at 1:08 PM, Patrick Walton pwal...@mozilla.com wrote: Keep in mind that fmt!'s interface is misdesigned at the moment: with the current interface the result is allocated on the heap even when the output is destined for a file or the screen. This is one of the bugs that resulted in poor performance (an order of magnitude slower than Python) on Chris Leary's benchmark. Fixing this will probably require having something like writefln or printfln. Jack Moffitt j...@metajack.im wrote: I saw https://github.com/mozilla/rust/pull/7779 come up today and commented on it. I got to thinking about it some, and since the bug doesn't seem the right place for such discussion, I wanted to bring it up here. The PR proposes to rename print!() and println!() to printf!() and printfln!(). The original macros exist to replace uses of print() and println() that look like: println(fmt!(blah blah %s, s)); Having a good default way to print things is very important, and it's one of the first things people will see of the language. I think it's worth bikeshedding it a bit to see if we can't come up with something better than the status quo. I propose instead: 1) Do away with the formatting stuff as the default. print!() and println!() sh ould just take a variable number of arguments, and each one should be printed in its default string representation with a space between each one. This is how Clojure's (and Python's?) print and println work. This would change code like this: println!(The result is %f, foo); to this: println!(The result is, foo) It's much easier. There are no formatting codes to remember and it does exaclty what you want in most cases. Consider: println!(a, ,b, c, d=, d); This seems great for the standard printf-style debugging. If formatting is needed, it's easy to get to: println!(My name is, name, and I scored, fmt!(%0.2f, score)); 2) Since println!() is likely to be used the most often, I feel like it should have a shorter name. Ie, we should call it just print!(), and have a newline-less version with a different name, or perhaps a different style of invocation of the macro. As some data to ponder, I went through the Servo code and all its dependencies: - The dependencies of servo use println 42 times, 24 of which also use fmt!(). None of these need to use fmt!() at all, they could just use the default string representation. - Servo itself uses println about 10 times, only two of which need fmt!(). These two uses are both fancy formatted output for the profiler. Changing all these uses to print!() in the codebase (aside from the two profiler fmt!()s) would make things much nicer looking. jack. Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sent from my Android phone with K-9 Mail. Please excuse my brevity. ___ 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