From peter.ronnquist at gmail.com Mon Oct 1 01:30:25 2012 From: peter.ronnquist at gmail.com (Peter Ronnquist) Date: Mon, 1 Oct 2012 10:30:25 +0200 Subject: [rust-dev] increase in time for shootout-nbody buildbot test. Message-ID: Hi, I've been keeping an eye on the buildbot (http://bot.rust-lang.org/) and noticed that the "shootout-nbody.stage2-x86_64-unknown-linux-gnu task-clock-msecs" test have increased its clock from 1.3K to 1.9K. Is this time increase expected or something that is worth looking into? Regards Peter From banderson at mozilla.com Mon Oct 1 12:35:07 2012 From: banderson at mozilla.com (Brian Anderson) Date: Mon, 01 Oct 2012 12:35:07 -0700 Subject: [rust-dev] increase in time for shootout-nbody buildbot test. In-Reply-To: References: Message-ID: <5069F06B.1050501@mozilla.com> On 10/01/2012 01:30 AM, Peter Ronnquist wrote: > Hi, > > I've been keeping an eye on the buildbot (http://bot.rust-lang.org/) > and noticed that the > "shootout-nbody.stage2-x86_64-unknown-linux-gnu task-clock-msecs" test > have increased its clock from 1.3K to 1.9K. > > Is this time increase expected or something that is worth looking into? > I don't know specifically about this regression, but there is an issue with stack growth that makes microbenchmarks troublesome at the moment. Essentially, stack growth is fairly slow, and minor changes in code generation change how programs hit the stack boundaries, causing major performance changes. Perf in general has not improved this development cycle I think, particularly compiler perf. We have some catching up to do. It looks like the commit range for this nbody regression is ee7fa..954eee if somebody wants to bisect and investigate. There's some discussion about some recent regressions (not this one) https://github.com/mozilla/rust/issues/3402 A possible solution to the stack growth microbenchmark issue: https://github.com/mozilla/rust/issues/3405 Here's the ticket for optimizing stack growth https://github.com/mozilla/rust/issues/3565 The regression I am most worried about is this big one for task spawning https://github.com/mozilla/rust/issues/3353 From peter.ronnquist at gmail.com Mon Oct 1 14:13:05 2012 From: peter.ronnquist at gmail.com (Peter Ronnquist) Date: Mon, 1 Oct 2012 23:13:05 +0200 Subject: [rust-dev] increase in time for shootout-nbody buildbot test. In-Reply-To: <5069F06B.1050501@mozilla.com> References: <5069F06B.1050501@mozilla.com> Message-ID: On Mon, Oct 1, 2012 at 9:35 PM, Brian Anderson wrote: > On 10/01/2012 01:30 AM, Peter Ronnquist wrote: >> >> Hi, >> >> I've been keeping an eye on the buildbot (http://bot.rust-lang.org/) >> and noticed that the >> "shootout-nbody.stage2-x86_64-unknown-linux-gnu task-clock-msecs" test >> have increased its clock from 1.3K to 1.9K. >> >> Is this time increase expected or something that is worth looking into? >> > > I don't know specifically about this regression, but there is an issue with > stack growth that makes microbenchmarks troublesome at the moment. > Essentially, stack growth is fairly slow, and minor changes in code > generation change how programs hit the stack boundaries, causing major > performance changes. > > Perf in general has not improved this development cycle I think, > particularly compiler perf. We have some catching up to do. > > It looks like the commit range for this nbody regression is ee7fa..954eee if > somebody wants to bisect and investigate. > > There's some discussion about some recent regressions (not this one) > > https://github.com/mozilla/rust/issues/3402 > > A possible solution to the stack growth microbenchmark issue: > > https://github.com/mozilla/rust/issues/3405 > > Here's the ticket for optimizing stack growth > > https://github.com/mozilla/rust/issues/3565 > > The regression I am most worried about is this big one for task spawning > > https://github.com/mozilla/rust/issues/3353 Thank you, I love that you keep the development process so transparent and I hope that I some day will be able to contribute to your language. From niko at alum.mit.edu Mon Oct 1 20:42:48 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 01 Oct 2012 20:42:48 -0700 Subject: [rust-dev] moving/copying based on type Message-ID: <506A62B8.3070707@alum.mit.edu> I posted something on my blog I hope we can discuss at the meeting tomorrow: http://smallcultfollowing.com/babysteps/blog/2012/10/01/moves-based-on-type/ Sorry it's late. Maybe better to wait till next week. Niko From niko at alum.mit.edu Wed Oct 3 11:38:04 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 03 Oct 2012 11:38:04 -0700 Subject: [rust-dev] 0.5 priorities and beyond Message-ID: <506C860C.10601@alum.mit.edu> With 0.4 nearly complete, I have been thinking a lot about planning for 0.5 and beyond. A common refrain around MV, at least, is "oh, let's fix that in 0.5". At this point I think we plan to do everything from fixing some outstanding bugs in the regions type system to porting the windows build over to visual studio to complete traits to implementing partial compilation. In other words, a lot of stuff we'll never actually finish in a month or two. To that end, I was thinking that perhaps we could try to plan a bit more up-front our 0.5 priorities. I made a wiki page: https://github.com/mozilla/rust/wiki/Note-0.5-priorities where I was hoping that we could note down things that perhaps ought to be priorities. I figure people can add what they think is important and we can hash out at the next meeting what ought to be 0.5 and what ought to come later. Things that should come later can then be added to the roadmap as necessary. Niko From banderson at mozilla.com Wed Oct 3 15:11:47 2012 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 03 Oct 2012 15:11:47 -0700 Subject: [rust-dev] Rust 0.4 call for testing Message-ID: <506CB823.7070203@mozilla.com> Heya. The Rust folks are putting the final touches on Rust 0.4, and it's going to be a thing to behold. Unfortunately, the number of operating systems we test on is somewhat limited. This is where you can help! Please! We've got a preliminary [tarball] and Windows [exe] built (this is not the final build but it is a known working build). If you are so inclined, then please give it an install on any machine you have available and see that it works correctly, where 'works' probably means 'installs rustc, cargo, rustdoc and the man page and can build and run hello.rs'. Please report problems on the [issue tracker] (or here if you like). The operating systems we currently have coverage on are OS X 10.6 (Snow Leopard), 10.7 (Lion), 10.8 (Mountain Lion), Centos 6, Ubuntu (various), Windows 2008 R2 (64-bit), Windows 7 (64-bit). Our OS X coverage is good, Windows is not excellent, and Linuxes other than Ubuntu are less exercised. Some specific systems that we would like to know more about: Arch - Arch installs python3 as the default and this has caused problems with the llvm build. It should be resolved now (in some way, maybe just by properly detecting python3 and aborting) but isn't verified. #[2720] Debian Wheezy - We have a report that the snapshot compiler doesn't work here (may be 64-bit specific). #[3641] Ubuntu 12.10 - Do we still work on the next Ubuntu? Any other Windows or Linuxes. Regards, Brian [tarball]: http://dl.rust-lang.org/dist/rust-0.4.tar.gz [exe]: http://dl.rust-lang.org/dist/rust-0.4-install.exe [issue tracker]: https://github.com/mozilla/rust/issues [2720]: https://github.com/mozilla/rust/issues/2720 [3641]: https://github.com/mozilla/rust/issues/3641 From sebastian.sylvan at gmail.com Wed Oct 3 17:49:13 2012 From: sebastian.sylvan at gmail.com (Sebastian Sylvan) Date: Wed, 3 Oct 2012 17:49:13 -0700 Subject: [rust-dev] Rust 0.4 call for testing In-Reply-To: <506CB823.7070203@mozilla.com> References: <506CB823.7070203@mozilla.com> Message-ID: On Wed, Oct 3, 2012 at 3:11 PM, Brian Anderson wrote: > Heya. > > The Rust folks are putting the final touches on Rust 0.4, and it's going to > be a thing to behold. Unfortunately, the number of operating systems we test > on is somewhat limited. This is where you can help! Please! > Consider this a very preliminary bug report, I only gave it about two minutes because I have to run, so I could probably track this down further with some process monitor logging. In case this is useful as is I'll just tell you here. On 64-bit Windows 8 RTM I get this in a message box when running the executable produced by compiling the example on rust-lang.org. --------------------------- helloworld.exe - Entry Point Not Found --------------------------- The procedure entry point _ZN4rand14__extensions__10meth_1235514gen_uint_range17_be256aac3933fdb73_04E could not be located in the dynamic link library D:\Programming\rust\helloworld.exe. --------------------------- OK --------------------------- -- Sebastian Sylvan From lespea at gmail.com Wed Oct 3 18:16:05 2012 From: lespea at gmail.com (Adam) Date: Wed, 3 Oct 2012 20:16:05 -0500 Subject: [rust-dev] Rust 0.4 call for testing In-Reply-To: <506CB823.7070203@mozilla.com> References: <506CB823.7070203@mozilla.com> Message-ID: I'm on Windows 8 64-bit RTM as well, however when I run rustc I get a prompted that "libgcc_s_dw2-1.dll is missing from your computer". ~Adam~ -------------- next part -------------- An HTML attachment was scrubbed... URL: From banderson at mozilla.com Wed Oct 3 18:36:32 2012 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 03 Oct 2012 18:36:32 -0700 Subject: [rust-dev] Rust 0.4 call for testing In-Reply-To: References: <506CB823.7070203@mozilla.com> Message-ID: <506CE820.6020704@mozilla.com> On 10/03/2012 06:16 PM, Adam wrote: > I'm on Windows 8 64-bit RTM as well, however when I run rustc I get a > prompted that "libgcc_s_dw2-1.dll is missing from your computer". This sounds like a symptom of not running from the MinGW shell (an unfortunate limitation in our Windows build). There are some instructions for getting MinGW setup on the wiki. * https://github.com/mozilla/rust/issues/1603 * https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust From amitava.shee at gmail.com Wed Oct 3 19:13:16 2012 From: amitava.shee at gmail.com (Amitava Shee) Date: Wed, 3 Oct 2012 22:13:16 -0400 Subject: [rust-dev] rust-0.4 on osx - expected `&/str` but found `&&static/str` Message-ID: I just built rust from git source on my osx 10.6.8. amitava$ rustc --version rustc 0.4 (c3f9b72 2012-09-30 21:35:32 -0700) host: x86_64-apple-darwin I am trying to compile the following "hello.rs" fn main() { let x = ["hello","world"]; for x.each |y| { io::println(y); } } I get the following error amitava:l2 amitava$ make rustc -g hello.rs hello.rs:4:16: 4:17 error: mismatched types: expected `&/str` but found `&&static/str` (expected &/str but found &-ptr) hello.rs:4 io::println(y); ^ error: aborting due to previous error make: *** [hello] Error 101 What am I missing? Thanks & Regards, Amitava Shee -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Wed Oct 3 19:15:09 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 03 Oct 2012 19:15:09 -0700 Subject: [rust-dev] rust-0.4 on osx - expected `&/str` but found `&&static/str` In-Reply-To: References: Message-ID: <506CF12D.50703@mozilla.com> On 10/3/12 7:13 PM, Amitava Shee wrote: > I just built rust from git source on my osx 10.6.8. > > amitava$ rustc --version > rustc 0.4 (c3f9b72 2012-09-30 21:35:32 -0700) > host: x86_64-apple-darwin > > I am trying to compile the following "hello.rs " > > fn main() { > let x = ["hello","world"]; > for x.each |y| { > io::println(y); > } > } > > I get the following error > amitava:l2 amitava$ make > rustc -g hello.rs > hello.rs:4:16: 4:17 error: mismatched types: expected `&/str` but found > `&&static/str` (expected &/str but found &-ptr) > hello.rs:4 io::println(y); > ^ > error: aborting due to previous error > make: *** [hello] Error 101 > > What am I missing? each now returns a reference, so you want `io::println(*y)`. Patrick From amitava.shee at gmail.com Wed Oct 3 19:17:52 2012 From: amitava.shee at gmail.com (Amitava Shee) Date: Wed, 3 Oct 2012 22:17:52 -0400 Subject: [rust-dev] rust-0.4 on osx - expected `&/str` but found `&&static/str` In-Reply-To: <506CF12D.50703@mozilla.com> References: <506CF12D.50703@mozilla.com> Message-ID: That did it. Thanks, Amitava What am I missing? >> > > each now returns a reference, so you want `io::println(*y)`. > > Patrick > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hatahet at gmail.com Wed Oct 3 19:22:10 2012 From: hatahet at gmail.com (Ziad Hatahet) Date: Wed, 3 Oct 2012 19:22:10 -0700 Subject: [rust-dev] rust-0.4 on osx - expected `&/str` but found `&&static/str` In-Reply-To: <506CF12D.50703@mozilla.com> References: <506CF12D.50703@mozilla.com> Message-ID: So will we always have to dereference a ref variable using the asterisk symbol? In effect this is passing a pointer (like C), correct? What about if we want to call a method on a ref variable, will it be a.foo(), or (*a).foo()? Thanks -- Ziad On Wed, Oct 3, 2012 at 7:15 PM, Patrick Walton wrote: > On 10/3/12 7:13 PM, Amitava Shee wrote: > >> I just built rust from git source on my osx 10.6.8. >> >> amitava$ rustc --version >> rustc 0.4 (c3f9b72 2012-09-30 21:35:32 -0700) >> host: x86_64-apple-darwin >> >> I am trying to compile the following "hello.rs " >> >> >> fn main() { >> let x = ["hello","world"]; >> for x.each |y| { >> io::println(y); >> } >> } >> >> I get the following error >> amitava:l2 amitava$ make >> rustc -g hello.rs >> >> hello.rs:4:16: 4:17 error: mismatched types: expected `&/str` but found >> `&&static/str` (expected &/str but found &-ptr) >> hello.rs:4 io::println(y); >> >> ^ >> error: aborting due to previous error >> make: *** [hello] Error 101 >> >> What am I missing? >> > > each now returns a reference, so you want `io::println(*y)`. > > Patrick > > > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Wed Oct 3 19:26:15 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 03 Oct 2012 19:26:15 -0700 Subject: [rust-dev] rust-0.4 on osx - expected `&/str` but found `&&static/str` In-Reply-To: References: <506CF12D.50703@mozilla.com> Message-ID: <506CF3C7.1080306@mozilla.com> On 10/3/12 7:22 PM, Ziad Hatahet wrote: > So will we always have to dereference a ref variable using the asterisk > symbol? In effect this is passing a pointer (like C), correct? Yes. > What > about if we want to call a method on a ref variable, will it be a.foo(), > or (*a).foo()? Either one works. Patrick From ben.striegel at gmail.com Wed Oct 3 20:07:49 2012 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Wed, 3 Oct 2012 23:07:49 -0400 Subject: [rust-dev] rust-0.4 on osx - expected `&/str` but found `&&static/str` In-Reply-To: References: <506CF12D.50703@mozilla.com> Message-ID: > So will we always have to dereference a ref variable using the asterisk symbol? At least until irrefutable patterns are supported in argument lists: https://github.com/mozilla/rust/issues/3586 On Wed, Oct 3, 2012 at 10:22 PM, Ziad Hatahet wrote: > So will we always have to dereference a ref variable using the asterisk > symbol? In effect this is passing a pointer (like C), correct? What about > if we want to call a method on a ref variable, will it be a.foo(), or > (*a).foo()? > > Thanks > > -- > Ziad > > > > On Wed, Oct 3, 2012 at 7:15 PM, Patrick Walton wrote: > >> On 10/3/12 7:13 PM, Amitava Shee wrote: >> >>> I just built rust from git source on my osx 10.6.8. >>> >>> amitava$ rustc --version >>> rustc 0.4 (c3f9b72 2012-09-30 21:35:32 -0700) >>> host: x86_64-apple-darwin >>> >>> I am trying to compile the following "hello.rs " >>> >>> >>> fn main() { >>> let x = ["hello","world"]; >>> for x.each |y| { >>> io::println(y); >>> } >>> } >>> >>> I get the following error >>> amitava:l2 amitava$ make >>> rustc -g hello.rs >>> >>> hello.rs:4:16: 4:17 error: mismatched types: expected `&/str` but found >>> `&&static/str` (expected &/str but found &-ptr) >>> hello.rs:4 io::println(y); >>> >>> ^ >>> error: aborting due to previous error >>> make: *** [hello] Error 101 >>> >>> What am I missing? >>> >> >> each now returns a reference, so you want `io::println(*y)`. >> >> Patrick >> >> >> ______________________________**_________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/**listinfo/rust-dev >> > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From robinei at gmail.com Thu Oct 4 07:00:31 2012 From: robinei at gmail.com (Robin Eidissen) Date: Thu, 4 Oct 2012 16:00:31 +0200 Subject: [rust-dev] Rust tasks as coroutines Message-ID: As I understand it Rust tasks seem a lot like coroutines, but can't quite be used like one. What I'd like is to be able to create a task B from my task A, and then directly transfer control from A to B by calling for example "coro::resume" on it, until it "yields" a value (not task::yield, maybe coro::yield), which will return control (and the value) directly back to A. Calling task::yield from B would return control to the scheduler (which does not know about B), and when it later resumes A, control starts after the task::yield in B. Now it seems like you'd have to spawn a task to run in the scheduler, pass it a channel to which it writes the values, and which we can later read from. I'd like to do (maybe stupid) things like writing a parser as a coroutine, to which I pass a single character at a time, and it then yields either NeedMore or Value(x) for example. It is an extremely attractive way of writing certain kinds of code. Wouldn't this be fairly lightweight and fast when directly transferring control, and a bit slow when going through channels, and via the scheduler? Would it be possible for tasks to serve this dual-purpose, able to both be run in the scheduler, and also able to be directly invoked from other tasks? Is it already possible, or maybe it would be a bad way of implementing coroutines? I'm assuming the data structures required for a task are extremely lightweight, since coroutines should be. - Robin From graydon at mozilla.com Thu Oct 4 08:41:47 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 04 Oct 2012 08:41:47 -0700 Subject: [rust-dev] Rust tasks as coroutines In-Reply-To: References: Message-ID: <506DAE3B.7000802@mozilla.com> On 04/10/2012 7:00 AM, Robin Eidissen wrote: > Wouldn't this be fairly lightweight and fast when directly transferring control, > and a bit slow when going through channels, and via the scheduler? Our goal is to make that sort of pattern affordable with the abstractions we have. Two things to note about those: 1. Our "scheduler" is _really_ blunt. It picks the next runnable task at (pseudo) random. It may well be that it has a fast(er) path for picking a receiving task when switching-away from a sending task on a shared pipe -- if not this is probably an optimization worth making -- but in a scheduler with only two tasks anyway, you can expect a pretty direct switch. (and you're allowed to make your own sub-schedulers and confine your tasks to them, so they will just switch back and forth) 2. The "channel" abstraction got replaced / augmented this summer with a higher-speed and more flexible abstraction called pipes; these are 1:1, default-synchronous and support bi-directional communication; they'll support the scenario you describe much more efficiently than a pair of ports and channels. In general I expect a fair quantity of stuff we were doing with channels to switch over to lower-level pipe protocols at some point. But this is something that'll happen in stages; there's a lot still being-digested from the summer (interns!) > I'm assuming the data structures required for a task are extremely lightweight, > since coroutines should be. They're pretty lightweight. Not "nothing" -- there's a certain balance between minimum stack chunk size and early costs of stack growth, so wager a few kb of initial allocation -- but yes, cheap enough to spawn many thousands of them on a normal system. -Graydon From banderson at mozilla.com Thu Oct 4 14:38:24 2012 From: banderson at mozilla.com (Brian Anderson) Date: Thu, 04 Oct 2012 14:38:24 -0700 Subject: [rust-dev] Rust 0.4 call for testing In-Reply-To: References: <506CB823.7070203@mozilla.com> Message-ID: <506E01D0.5090907@mozilla.com> On 10/03/2012 05:49 PM, Sebastian Sylvan wrote: > Consider this a very preliminary bug report, I only gave it about two > minutes because I have to run, so I could probably track this down > further with some process monitor logging. In case this is useful as > is I'll just tell you here. > > On 64-bit Windows 8 RTM I get this in a message box when running the > executable produced by compiling the example on rust-lang.org. > > --------------------------- > helloworld.exe - Entry Point Not Found > --------------------------- > The procedure entry point > _ZN4rand14__extensions__10meth_1235514gen_uint_range17_be256aac3933fdb73_04E > could not be located in the dynamic link library > D:\Programming\rust\helloworld.exe. Thanks, Sebastian! Do you have your PATH environment variable set up to point to the appropriate library directory (something like bin/rustc/i686-pc-mingw/bin)? I filed an issue: https://github.com/mozilla/rust/issues/3660 From me at johnmurray.io Thu Oct 4 14:33:31 2012 From: me at johnmurray.io (John Murray) Date: Thu, 4 Oct 2012 17:33:31 -0400 Subject: [rust-dev] Update to Tutorial Message-ID: Hey, Just in case the Twitter isn't checked/used often (didn't look like it was), I wanted to mention that there is a Sublime Text add-on for Rust (syntax highlighting and building) and I was hoping this could be added to the tutorial (where you mention the config files for emacs and vim)? If so, that would be great! -- Thanks! John Murray -------------- next part -------------- An HTML attachment was scrubbed... URL: From lists.rust at dbp.mm.st Thu Oct 4 15:23:37 2012 From: lists.rust at dbp.mm.st (Daniel Patterson) Date: Thu, 4 Oct 2012 18:23:37 -0400 Subject: [rust-dev] Update to Tutorial In-Reply-To: References: Message-ID: Hi John, It's mentioned in the current version of the tutorial, which will be released along with Rust 0.4. (It didn't exist when 0.3 was released, hence not being in that version of the tutorial). -Daniel On Oct 4, 2012, at 5:33 PM, John Murray wrote: > Hey, > > Just in case the Twitter isn't checked/used often (didn't look like it was), I wanted to mention that there is a Sublime Text add-on for Rust (syntax highlighting and building) and I was hoping this could be added to the tutorial (where you mention the config files for emacs and vim)? If so, that would be great! > > -- > Thanks! > John Murray > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From banderson at mozilla.com Thu Oct 4 15:25:18 2012 From: banderson at mozilla.com (Brian Anderson) Date: Thu, 04 Oct 2012 15:25:18 -0700 Subject: [rust-dev] Update to Tutorial In-Reply-To: References: Message-ID: <506E0CCE.4040907@mozilla.com> On 10/04/2012 02:33 PM, John Murray wrote: > Hey, > > Just in case the Twitter isn't checked/used often (didn't look like it > was), I wanted to mention that there is a Sublime Text add-on for Rust > (syntax highlighting and building) and I was hoping this could be added > to the tutorial (where you mention the config files for emacs and vim)? > If so, that would be great! > The 0.4 tutorial mentions Sublime Text: http://dl.rust-lang.org/doc/tutorial.html#editing-rust-code I know there have been several Sublime Text plugins for Rust. Is that the one you are thinking of? As a side note, we should do more with the Twitter account so it doesn't appear that we are dead. Regards, Brian From hsivonen at iki.fi Fri Oct 5 00:49:00 2012 From: hsivonen at iki.fi (Henri Sivonen) Date: Fri, 5 Oct 2012 10:49:00 +0300 Subject: [rust-dev] Fall-through in alt, break&continue by label In-Reply-To: <4F8438AF.9090003@alum.mit.edu> References: <4F8438AF.9090003@alum.mit.edu> Message-ID: On Tue, Apr 10, 2012 at 4:42 PM, Niko Matsakis wrote: > On 4/10/12 5:53 AM, Henri Sivonen wrote: >> >> The use case I have is targeting Rust with the translator that >> currently targets C++ and generates the HTML parser in Gecko. (It uses >> goto hidden behind macros to emulate break and continue by label in >> C++.) > > > There is currently no way to do that kind of control flow beyond using flags > with `if` checks or restructuring the code in some other way (tail calls, if > they worked, seem like they would be useful). I believe our `break` can > only target loops in any case. > > How hard would it be do you think to prototype a version that avoids these > control-flow features? Also, how important is fall-through for alt vs break > to labeled blocks? Sorry about the ridiculously long delay. Unfortunate things got in my way. The HTML parser has the following important break/continue patterns: The basic pattern of the tokenizer is stateloop: for (;;) { switch (state) { ... case SOME_STATE: somestateloop: for (;;) { if (++pos == endPos) { break stateloop; } c = buf[pos]; switch (c) { case '\r': silentCarriageReturn(); break stateloop; case '\n': silentLineFeed(); // fall thru case ' ': case '\t': case '\u000C': continue; case '/': ... state = WHATEVER_STATE; continue stateloop; case '\u0000': c = '\uFFFD'; // fall thru case '<': case '=': errBadCharOrNull(c); // fall thru to treat like anything else default: ... state = OTHER_STATE; continue stateloop; } } case OTHER_STATE: ... } } Key characteristics: 1) There's a huge conditionless loop with a huge switch right inside with a case for each tokenizer state. 2) State cases contain an inner conditionless loop. 3) If the position advances to the end of the buffer or there is a carriage return, the inner loop breaks out of both loops. 4) State cases never need a break statement to end a state, because states are exited by assigning to the state variable and then immediately continuing back to the top of the state loop. 5) Inside the inner loop right after advancing the position and reading another character from the buffer, there is the switch on the newly-read character. 6) The switch on the character never needs a plain break statement for breaking out of a switch case, either. Instead, each case either falls through, continues the inner loop or continues the state loop. 7) The linefeed case always calls a method and then falls through to the case for space, tab on a form feed. 8) There are also fall through this around the handling of nul and errors. In this example, the nul case changes the character to the replacement character and then falls through to the same cases a couple of erroneous characters and then that case, after reporting error, falls through to the "anything else" state. It would be possible to remove the fall-throughs in the inner switch by automatically duplicating code from the subsequent cases. It would be possible to change continuing the stateloop from within the inner loop to breaking from the inner loop. It would be possible to change breaking the outer loop from within the inner loop by introducing a boolean exit condition for the outer loop and setting it in the inner loop and then breaking the inner loop. In practice, the tokenizer state loop isn't quite like presented above. In the example, there's a transition to OTHER_STATE which happens to be the next state in the outer switch. To avoid checking the state variable at the top of the loop in that case, I have used the following micro optimization instead: ... state = OTHER_STATE; break somestateloop; } } case OTHER_STATE: ... That is, the code breaks the inner loop and then ends up falling through between cases in the outer switch. This characteristic could be removed by automatically rewriting the code to the basic case presented first. The tree builder is more problematic. It looks like this: starttagloop: for (;;) { switch (mode) { case FIRST_MODE: // This inner loop never loops. It's only to be broken as a "goto" to the // next mode. firstmodeloop: for (;;) { switch (element) { case foo: ... break starttagloop; case bar: ... mode = OTHER_MODE; continue starttagloop; case baz: if (...) { ... // move onto next mode break firstmodeloop: } ... break starttagloop; case qux: ... continue starttagloop; default: // move onto next mode break firstmodeloop: } } case SECOND_MODE: ... } } So in the tree builder, there is an outer loop and a switch on the tree builder mode inside it. The cases in this switch are *huge* and they fall through to the next case as a chain. Eliminating fall-through by making the translator duplicate code automatically would result in a massive amounts of duplicated code. Making the translator generate a method for each mode would be error-prone and messy and would introduce needless recursion where the above example breaks or continues the outer loop and a method-per-mode version would call a method for another mode. It would probably be less messy to break the outer switch into one "if" statement per mode and making the conditions of the form (mode <= SECOND_MODE) to make fall-throughs also enter the next "if"s. It seems to me that with the current facilities provided by Rust, it would be fairly straightforward to make the translator change the structure of the tokenizer to get rid of the language features of Java that Rust does not have, but it would involve making the translator duplicate some code in the inner switch cases. Dealing with the tree builder by deconstructing the outer switch into a series of "if"s and introducing helper variables for breaking or continuing the outer loop from within the inner loop would be possible but more special-casey. That is, at present, it appears that automatically translating the HTML parser to Rust would be possible without language changes to Rust, but being able to apply "break" or "again" to an outer loop and having a statement for continuing from the end of an "alt" branch to the next branch in the same "alt" would make the translation nicer. > I think adding labeled blocks/loops and the ability to break/continue with a > label is plausible, but a fair bit of work. Fall-through in alt seems less > likely. Even break and continue by label would be useful without fall-through in alt. -- Henri Sivonen hsivonen at iki.fi http://hsivonen.iki.fi/ From banderson at mozilla.com Fri Oct 5 12:03:51 2012 From: banderson at mozilla.com (Brian Anderson) Date: Fri, 05 Oct 2012 12:03:51 -0700 Subject: [rust-dev] Fall-through in alt, break&continue by label In-Reply-To: References: <4F8438AF.9090003@alum.mit.edu> Message-ID: <506F2F17.1080703@mozilla.com> On 10/05/2012 12:49 AM, Henri Sivonen wrote: > On Tue, Apr 10, 2012 at 4:42 PM, Niko Matsakis wrote: >> On 4/10/12 5:53 AM, Henri Sivonen wrote: >>> >>> The use case I have is targeting Rust with the translator that >>> currently targets C++ and generates the HTML parser in Gecko. (It uses >>> goto hidden behind macros to emulate break and continue by label in >>> C++.) >> >> >> There is currently no way to do that kind of control flow beyond using flags >> with `if` checks or restructuring the code in some other way (tail calls, if >> they worked, seem like they would be useful). I believe our `break` can >> only target loops in any case. >> >> How hard would it be do you think to prototype a version that avoids these >> control-flow features? Also, how important is fall-through for alt vs break >> to labeled blocks? > > Sorry about the ridiculously long delay. Unfortunate things got in my way. > > The HTML parser has the following important break/continue patterns: > > The basic pattern of the tokenizer is > > stateloop: for (;;) { > switch (state) { > ... > case SOME_STATE: > somestateloop: for (;;) { > if (++pos == endPos) { > break stateloop; > } > c = buf[pos]; > switch (c) { > case '\r': > silentCarriageReturn(); > break stateloop; > case '\n': > silentLineFeed(); > // fall thru > case ' ': > case '\t': > case '\u000C': > continue; > case '/': > ... > state = WHATEVER_STATE; > continue stateloop; > case '\u0000': > c = '\uFFFD'; > // fall thru > case '<': > case '=': > errBadCharOrNull(c); > // fall thru to treat like anything else > default: > ... > state = OTHER_STATE; > continue stateloop; > } > } > case OTHER_STATE: > ... > } > } > > Key characteristics: > > 1) There's a huge conditionless loop with a huge switch right inside > with a case for each tokenizer state. > > 2) State cases contain an inner conditionless loop. > > 3) If the position advances to the end of the buffer or there is a > carriage return, the inner loop breaks out of both loops. > > 4) State cases never need a break statement to end a state, because > states are exited by assigning to the state variable and then > immediately continuing back to the top of the state loop. > > 5) Inside the inner loop right after advancing the position and > reading another character from the buffer, there is the switch on the > newly-read character. > > 6) The switch on the character never needs a plain break statement for > breaking out of a switch case, either. Instead, each case either falls > through, continues the inner loop or continues the state loop. > > 7) The linefeed case always calls a method and then falls through to > the case for space, tab on a form feed. > > 8) There are also fall through this around the handling of nul and > errors. In this example, the nul case changes the character to the > replacement character and then falls through to the same cases a > couple of erroneous characters and then that case, after reporting > error, falls through to the "anything else" state. > > It would be possible to remove the fall-throughs in the inner switch > by automatically duplicating code from the subsequent cases. It would > be possible to change continuing the stateloop from within the inner > loop to breaking from the inner loop. It would be possible to change > breaking the outer loop from within the inner loop by introducing a > boolean exit condition for the outer loop and setting it in the inner > loop and then breaking the inner loop. > > In practice, the tokenizer state loop isn't quite like presented > above. In the example, there's a transition to OTHER_STATE which > happens to be the next state in the outer switch. To avoid checking > the state variable at the top of the loop in that case, I have used > the following micro optimization instead: > > ... > state = OTHER_STATE; > break somestateloop; > } > } > case OTHER_STATE: > ... > > That is, the code breaks the inner loop and then ends up falling > through between cases in the outer switch. > > This characteristic could be removed by automatically rewriting the > code to the basic case presented first. > > The tree builder is more problematic. It looks like this: > > starttagloop: for (;;) { > switch (mode) { > case FIRST_MODE: > // This inner loop never loops. It's only to be broken as a "goto" to the > // next mode. > firstmodeloop: for (;;) { > switch (element) { > case foo: > ... > break starttagloop; > case bar: > ... > mode = OTHER_MODE; > continue starttagloop; > case baz: > if (...) { > ... > // move onto next mode > break firstmodeloop: > } > ... > break starttagloop; > case qux: > ... > continue starttagloop; > default: > // move onto next mode > break firstmodeloop: > } > } > case SECOND_MODE: > ... > } > } > > So in the tree builder, there is an outer loop and a switch on the > tree builder mode inside it. The cases in this switch are *huge* and > they fall through to the next case as a chain. Eliminating > fall-through by making the translator duplicate code automatically > would result in a massive amounts of duplicated code. Making the > translator generate a method for each mode would be error-prone and > messy and would introduce needless recursion where the above example > breaks or continues the outer loop and a method-per-mode version would > call a method for another mode. It would probably be less messy to > break the outer switch into one "if" statement per mode and making the > conditions of the form (mode <= SECOND_MODE) to make fall-throughs > also enter the next "if"s. > > It seems to me that with the current facilities provided by Rust, it > would be fairly straightforward to make the translator change the > structure of the tokenizer to get rid of the language features of Java > that Rust does not have, but it would involve making the translator > duplicate some code in the inner switch cases. Dealing with the tree > builder by deconstructing the outer switch into a series of "if"s and > introducing helper variables for breaking or continuing the outer loop > from within the inner loop would be possible but more special-casey. > > That is, at present, it appears that automatically translating the > HTML parser to Rust would be possible without language changes to > Rust, but being able to apply "break" or "again" to an outer loop and > having a statement for continuing from the end of an "alt" branch to > the next branch in the same "alt" would make the translation nicer. > >> I think adding labeled blocks/loops and the ability to break/continue with a >> label is plausible, but a fair bit of work. Fall-through in alt seems less >> likely. > > Even break and continue by label would be useful without fall-through in alt. > Thanks, Henri. I've posted this information to our bugtracker: https://github.com/mozilla/rust/issues/2216 From eddycizeron at gmail.com Sat Oct 6 11:14:11 2012 From: eddycizeron at gmail.com (Eddy Cizeron) Date: Sat, 6 Oct 2012 20:14:11 +0200 Subject: [rust-dev] Rust philosophy and OOP Message-ID: Hello, I'm new to Rust, and I have some questions concerning some aspects of the language. From what I understand until now, rust has no dynamic linkage for methods as it would be the case in any standard OOP language. This is surely an intentionaly different philosophy from the current trend among other recent programming languages. But why not after all. I like the idea. So I find myself skeptical when I read the chapters of the documentation about OOP-like concepts like classes or interfaces. The essence of the "class" concept lies in the possibility to gather a data structure (a type) and the related processes that can act on the corresponding instances (methods) in a single bundle. But, tell me if you disagree, the only interesting purpose of such an operation is the ability to use inheritance. If no concept of inheritance exists, I hardly see what is the need of making functions "pets" for data. All we obtain are classical design issues like "is my 'f(a,b)' function a 'a.f(b)' method or a 'b.f(a)' method ?" (and I don't think the rust "resource" concept requires classes, as destructors or destructor-like functions are not methods). I'm afraid that the answer is merely to offer a supposedly "attractive" syntax for OOP users. And I think this would be a weak argument The concept of interface/implementation in rust is surely different than the usual one, but again to me it looks like it has some limitations due to the same reason than above: it tries to look OOP. I could have imagined a very similar interface concept but that does not focus on a *single *type: iface shape_drawing { fn draw(Sf, Sh); fn bounding_box(Sh) -> bounding_box; } fn draw_twice>(surface: Sf, shape: Sh) { draw(surface, shape); draw(surface, shape); } Of course this example is a simple one. And any consistent system like this (if it does exist but I'm pretty sure it does) would have been more complex than the current one. But also more general and then more powerful. Let me clear about something: I don't expect anybody to change the current design. I'm nobody and I know it's always easier to criticize than to do things. I'm just expressing the feeling that while Rust tried to take a different direction from all the other new JVM-compliant-OOP-languages-with-functional-features (which I really really value very much) it seems it has not got rid of some conceptual patterns that are not, IMHO, necessary anymore. And I wish people could give their opinion about this. Thank you -- Eddy Cizeron -------------- next part -------------- An HTML attachment was scrubbed... URL: From catamorphism at gmail.com Sat Oct 6 11:16:54 2012 From: catamorphism at gmail.com (Tim Chevalier) Date: Sat, 6 Oct 2012 11:16:54 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: Hi, Eddy -- Traits and impls in Rust are based on type classes, which originated in Haskell. You may find it interesting to read about type classes: "Type classes: exploring the design space" by Simon Peyton Jones, Mark Jones, and Erik Meijer, is a good start: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.5674 ("Interfaces" have been renamed to "traits" in the soon-to-be-released Rust 0.4 release, by the way; it looks like you may be looking at the docs from Rust 0.3.) Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "Gains in likability have deep costs in personal integrity." -- Kirk Read From lists.rust at dbp.mm.st Sat Oct 6 12:18:03 2012 From: lists.rust at dbp.mm.st (Daniel Patterson) Date: Sat, 6 Oct 2012 15:18:03 -0400 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: I think saying that objects are only useful in so far as inheritance exists is strange. The point of objects, as I've understood them, is to provide some form of encapsulation - to be able to give limited access to certain data so that you can maintain invariants on the data that are not expressible with a type system (if such a system even exists). Objects can exist without inheritance (and are still useful). Inheritance seems to solve a different problem - how to write code that targets many different types of objects in a simple way. But inheritance isn't really needed there, just a way to deal with objects that behave like a certain thing, or have a certain "interface". Java's interfaces, and rust's traits, seem to solve this in a better way, because a single type can implement many interfaces (and multiple inheritance is?. just bad). The only thing that inheritance seems to provide that isn't covered by abstract types (i.e., a module exports a type and not its constructor, so you can use it, but only in the way defined by its interface) and interfaces (traits here, or typeclasses in haskell) seems to be code reuse - i.e., you write a foo, and then a specialized foo that reuses a bunch of code from foo. But you can approximate that pretty well with traits as well (or you can have your "superclass" as an attribute in your "subclass") - and I think you are left with a more flexible system in general. Of course, that's just my opinion (and, I am more of a functional programmer than an OO programmer). destructors are provided (currently as a drop attribute in a struct), and will (very shortly) be provided by implementing a Drop interface. i.e., you define a drop method, and when the type goes out of scope, or is garbage collected, the method is called. Again, I think this is more flexible, as it means that if you don't need to have a destructor, you don't have to, but any type can have one if it needs it. I think it is better to think of rust as a functional language than an object oriented language. Granted, these are all just words, and approximations at best (as most languages incorporate things from all over the place), but I think it explains some of the philosophy a little more. As for your example, you can probably define an implementation for pairs, i.e.: trait ShapeDrawing<(Sf,Sh)> { ? } Or even abstract it a little more into: trait Drawable { ? } and then: trait ShapeDrawing<~[Drawable]> { ... } Etc. I might be mixing up the syntax a little, but the basic idea should be correct. It is certainly a different approach, but I think you'll find that it isn't less powerful (and you may find it to be more flexible - but you may not!). On Oct 6, 2012, at 2:14 PM, Eddy Cizeron wrote: > > Hello, > > I'm new to Rust, and I have some questions concerning some aspects of the language. From what I understand until now, rust has no dynamic linkage for methods as it would be the case in any standard OOP language. This is surely an intentionaly different philosophy from the current trend among other recent programming languages. But why not after all. I like the idea. So I find myself skeptical when I read the chapters of the documentation about OOP-like concepts like classes or interfaces. > > The essence of the "class" concept lies in the possibility to gather a data structure (a type) and the related processes that can act on the corresponding instances (methods) in a single bundle. But, tell me if you disagree, the only interesting purpose of such an operation is the ability to use inheritance. If no concept of inheritance exists, I hardly see what is the need of making functions "pets" for data. All we obtain are classical design issues like "is my 'f(a,b)' function a 'a.f(b)' method or a 'b.f(a)' method ?" (and I don't think the rust "resource" concept requires classes, as destructors or destructor-like functions are not methods). I'm afraid that the answer is merely to offer a supposedly "attractive" syntax for OOP users. And I think this would be a weak argument > > The concept of interface/implementation in rust is surely different than the usual one, but again to me it looks like it has some limitations due to the same reason than above: it tries to look OOP. I could have imagined a very similar interface concept but that does not focus on a single type: > > iface shape_drawing { > fn draw(Sf, Sh); > fn bounding_box(Sh) -> bounding_box; > } > > fn draw_twice>(surface: Sf, shape: Sh) { > draw(surface, shape); > draw(surface, shape); > } > > Of course this example is a simple one. And any consistent system like this (if it does exist but I'm pretty sure it does) would have been more complex than the current one. But also more general and then more powerful. > > Let me clear about something: I don't expect anybody to change the current design. I'm nobody and I know it's always easier to criticize than to do things. I'm just expressing the feeling that while Rust tried to take a different direction from all the other new JVM-compliant-OOP-languages-with-functional-features (which I really really value very much) it seems it has not got rid of some conceptual patterns that are not, IMHO, necessary anymore. And I wish people could give their opinion about this. > > Thank you > > -- > Eddy Cizeron > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: From banderson at mozilla.com Sat Oct 6 14:00:17 2012 From: banderson at mozilla.com (Brian Anderson) Date: Sat, 06 Oct 2012 14:00:17 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: <50709BE1.3000409@mozilla.com> On 10/06/2012 11:14 AM, Eddy Cizeron wrote: > > Hello, > > I'm new to Rust, and I have some questions concerning some aspects of > the language. From what I understand until now, rust has no dynamic > linkage for methods as it would be the case in any standard OOP > language. This is surely an intentionaly different philosophy from the > current trend among other recent programming languages. But why not > after all. I like the idea. So I find myself skeptical when I read the > chapters of the documentation about OOP-like concepts like classes or > interfaces. Hi! I can understand how you would have this perception, as most Rust code favors using traits as Haskell-style type classes, with static dispatch (it is more efficient). OO-style dynamic dispatch is an important use case though, and Rust supports it, but the implementation is not as mature. On Rust's master branch you can do things like this: impl @Circle: Drawable { fn draw() { ... } } impl @Rectangle: Drawable { fn draw() { ... } } let c: @Circle = @new_circle(); let r: @Rectangle = @new_rectangle(); // Cast box things that implement Drawable to boxed Drawables draw_all(~[c as @Drawable, r as @Drawable]); This gives you dynamic dispatch on any Drawable through a managed (@) vtable (fwiw I don't know if this is the recommended syntax - this is still in development). I recommend giving the 0.4 tutorial's section on [generics] a read. It does a much better job than the 0.3 tutorial at explaining how it all works. I hope that it will relieve some of your concerns. [generics]: http://dl.rust-lang.org/doc/tutorial.html#generics Additionally your concern about resources and classes not needing to be interrelated is spot on, and that issue will be resolved. In 0.4 still structs are the only type that contain destructors, but the intent is to make destructors just an implementation of `trait Drop` (or `Finalize` maybe). -Brian From nejucomo at gmail.com Mon Oct 8 01:05:37 2012 From: nejucomo at gmail.com (Nathan) Date: Mon, 8 Oct 2012 01:05:37 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: On Sat, Oct 6, 2012 at 11:16 AM, Tim Chevalier wrote: > Hi, Eddy -- > > Traits and impls in Rust are based on type classes, which originated > in Haskell. You may find it interesting to read about type classes: > "Type classes: exploring the design space" by Simon Peyton Jones, Mark > Jones, and Erik Meijer, is a good start: > > http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.5674 > > ("Interfaces" have been renamed to "traits" in the soon-to-be-released > Rust 0.4 release, by the way; it looks like you may be looking at the > docs from Rust 0.3.) > > Cheers, > Tim > I'm about half-way through this paper, which is a great reference. Thanks! I'm curious if multi-parameter traits are anywhere on the rust roadmap. I'm not certain about which challenges or restrictions they may require but perhaps by the time I finish this reference I'll have a better understanding. I'd recommend reading the paper if only to see motivating examples of multi-parameter traits. Regards, Nathan > -- > Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt > "Gains in likability have deep costs in personal integrity." -- Kirk Read > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From eddycizeron at gmail.com Mon Oct 8 15:19:34 2012 From: eddycizeron at gmail.com (Eddy Cizeron) Date: Tue, 9 Oct 2012 00:19:34 +0200 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: Hi everyone 2012/10/6 Tim Chevalier > Traits and impls in Rust are based on type classes, which originated > in Haskell. You may find it interesting to read about type classes: > "Type classes: exploring the design space" by Simon Peyton Jones, Mark > Jones, and Erik Meijer, is a good start: > http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.5674 Thank you for the reference Tim. I'm not really fluent in Haskell but I think I understand the concepts and apparently multi-parameter type classes are very close to what I would expect from Rust interfaces/traits. 2012/10/6 Tim Chevalier > ("Interfaces" have been renamed to "traits" in the soon-to-be-released > Rust 0.4 release, by the way; it looks like you may be looking at the docs from Rust 0.3.) Right, I was looking at docs 0.3 but I could not find any newer documentation. 2012/10/6 Sebastian Sylvan > I strongly feel that the focus on inheritance in (recent) OOP is a > huge mistake. OOP was originally more about the metaphor of messages > and objects than inheritance. Inheritance leads to so many bugs and > [...] > Interfaces (even trees of them) are great, just not inheritance of > implementation. 2012/10/6 Daniel Patterson > Inheritance seems to solve a different problem - how to write code that > targets many different types of objects in a simple way. But inheritance > isn't really needed there, > [...] > Of course, that's just my opinion (and, I am more of a functional programmer than an OO programmer). Sorry I have not made myself clear enough. My point is absolulety not say that inheritance is a good/bad/required/unnecessary feature. My point is that if you're not using it (or at least if you're not using dynamic linkage), I cannot see where or why OOP concepts and syntax are relevant anymore. (But apparently there are some attempts to use dynamic linkage with interfaces and I didn't know that). Your remark about the metaphor is indeed interesting. Actually I cannot remember where I had read someone complaining about that. This guy said "I know what is sending messages, and it's certainly not that". His point was precisely that this metaphor fails because the notion of message implies asynchrony (I'm not paralyzed when I'm waiting for a response to a mail) and this is certainly not the intended meaning in OOP. I agree with this view. You both focus on the functional inspiration for Rust. This is good news. It's obvious to me the functional paradigm has deep roots in the math world. Which is also good news. But in mathematics nobody wonder if such-and-such a function is owned by one of its argument and which one. Or to say it a la OOP, if this function is a method of one of its argument. This bias, when taken to the extreme, has generaly lead some languages to syntactical "oddities" (some of my neurones would say "monstrosities") like: "x = (PI / 4).sin;" or "y = 2.'+'(7);" Can anyone explain me why it makes more sense to think about this addition as a message sent to 2 with parameter 7? What does this metaphor makes clearer ? One may justifiably argue that mathematical concepts are different from everyday life ones. But I don't think 'file.moveTo(directory)' or 'directory.move(file)' carries better meaning than 'moveTo(directory, file)'. If you want to express more efficiently the purpose of every argument of a function, named arguments are a far better idea. 2012/10/6 Daniel Patterson > I think saying that objects are only useful in so far as inheritance > exists is strange. The point of objects, as I've understood them, is to > provide some form of encapsulation - to be able to give limited access > to certain data so that you can maintain invariants on the data that are > not expressible with a type system (if such a system even exists). > Objects can exist without inheritance (and are still useful). This is a question of terminology. Unfortunately in computer science and programming, definitions are generally fuzzy or/and depend on the author. I keep the word "encapsulation" for the idea of grouping together data and functions and personally prefer the expression "data hidding" or "data accessibility" for the feature you're describing. And the fact is this too concepts are certainly not as strongly linked as you might think. You can perfectly imagine a system where data accessibility does not apply to the exterior of a class but to the exterior of other bundles (modules, packages, etc). This way you can craft more precisely the accessibility of multiple types in multiple functions. Classes are not needed for this. 2012/10/6 Daniel Patterson > As for your example, you can probably define an implementation for pairs, i.e.: > trait ShapeDrawing<(Sf,Sh)> { > ? > } > [...] > It is certainly a different approach, but I think you'll find that it isn't less > powerful (and you may find it to be more flexible - but you may not!). Well as long as I have not read some document about traits, any criticism or any conclusion from me about this would be pointless (I've just noticed Brian's link to new documentation). But after a first glance it does not seem to remove the limitations I found in the previous concept of interfaces. And I'm almost sure that interfaces, as they where explained in the documentation 0.3 are less powerfull. For the same reason the authors of the article proposed by Tim explain single-parameter type classes in Haskell are less powerfull than multi-parameter type classes. I'll come back as soon as my comprehension of Rust traits will be less superficial (and after a session of self-flagellation if my premonitions/arguments turn out to be wrong :-)) 2012/10/6 Brian Anderson > Additionally your concern about resources and classes not needing to be interrelated > is spot on, and that issue will be resolved. In 0.4 still structs are the only type > that contain destructors, but the intent is to make destructors just an implementation > of `trait Drop` (or `Finalize` maybe). Precisely, I'm not sure that the fact destructors are turned into methods is good news to me. Thank you for this stimulating discussion and references -- Eddy Cizeron -------------- next part -------------- An HTML attachment was scrubbed... URL: From lindsey at rockstargirl.org Mon Oct 8 15:42:35 2012 From: lindsey at rockstargirl.org (Lindsey Kuper) Date: Mon, 8 Oct 2012 18:42:35 -0400 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: On Mon, Oct 8, 2012 at 6:19 PM, Eddy Cizeron wrote: > 2012/10/6 Tim Chevalier >> ("Interfaces" have been renamed to "traits" in the soon-to-be-released >> Rust 0.4 release, by the way; it looks like you may be looking at the docs >> from Rust 0.3.) > > Right, I was looking at docs 0.3 but I could not find any newer > documentation. It looks like Brian already pointed you to the head-of-the-tree tutorial, but also, all the in-development docs are linked from https://github.com/mozilla/rust/wiki/Docs . (0.4 should land any day now, too.) > I'll come back as soon > as my comprehension of Rust traits will be less superficial (and after a > session of self-flagellation if my premonitions/arguments turn out to be > wrong :-)) And, in case nobody has pointed them out yet, here are a couple more resources: * An introduction to traits on Patrick's blog: http://pcwalton.github.com/blog/2012/08/08/a-gentle-introduction-to-traits-in-rust * A talk I did in August, with a side-by-side Haskell/Rust comparison: https://air.mozilla.org/rust-typeclasses Cheers, Lindsey From amitava.shee at gmail.com Mon Oct 8 17:14:34 2012 From: amitava.shee at gmail.com (Amitava Shee) Date: Mon, 8 Oct 2012 20:14:34 -0400 Subject: [rust-dev] Assertion failure while compiling Message-ID: I get an assertion failure while trying to compile the following use io::println; fn main() { trait Text { fn to_str(&self) -> ~str; } fn to_string(t: Text) { println(t.to_str()); } } amitava:l2 amitava$ rustc -g trait.rs Assertion failed: (Ty && "Invalid GetElementPtrInst indices for type!"), function checkGEPType, file /Users/amitava/opt/rust/src/rust/src/llvm/include/llvm/Instructions.h, line 705. Abort trap: 6 Clearly, this code is nonsensical since there is no implementation of the trait "Text". Should the compiler produce a different message? Thanks & Regards, Amitava Shee There are two ways of constructing a software design. One is to make it so simple that there are obviously no deficiencies; the other is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult. -- C. A. R. Hoare The Emperor's Old Clothes, CACM February 1981 -------------- next part -------------- An HTML attachment was scrubbed... URL: From catamorphism at gmail.com Mon Oct 8 17:15:53 2012 From: catamorphism at gmail.com (Tim Chevalier) Date: Mon, 8 Oct 2012 17:15:53 -0700 Subject: [rust-dev] Assertion failure while compiling In-Reply-To: References: Message-ID: On Mon, Oct 8, 2012 at 5:14 PM, Amitava Shee wrote: > I get an assertion failure while trying to compile the following > > use io::println; > > fn main() { > trait Text { > fn to_str(&self) -> ~str; > } > > fn to_string(t: Text) { > println(t.to_str()); > } > > } > > amitava:l2 amitava$ rustc -g trait.rs > Assertion failed: (Ty && "Invalid GetElementPtrInst indices for type!"), > function checkGEPType, file > /Users/amitava/opt/rust/src/rust/src/llvm/include/llvm/Instructions.h, line > 705. > Abort trap: 6 > > Clearly, this code is nonsensical since there is no implementation of the > trait "Text". Should the compiler produce a different message? > Yes, this is a compiler bug. Would you mind filling out an issue report at: https://github.com/mozilla/rust/issues/new ? (Don't worry about any of the labels or fields; we'll take care of that.) Thanks, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt 'Wouldn't you rather be anything other than the kid who runs around telling stuff what he thinks it is?" -- DavEnd From arcata at gmail.com Mon Oct 8 17:22:31 2012 From: arcata at gmail.com (Joe Groff) Date: Mon, 8 Oct 2012 17:22:31 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: On Mon, Oct 8, 2012 at 3:19 PM, Eddy Cizeron wrote: > Sorry I have not made myself clear enough. My point is absolulety not say > that inheritance is a good/bad/required/unnecessary feature. My point is > that if you're not using it (or at least if you're not using dynamic > linkage), I cannot see where or why OOP concepts and syntax are relevant > anymore. (But apparently there are some attempts to use dynamic linkage with > interfaces and I didn't know that). One minor non-semantic, non-scientific benefit of OOP syntax over Algol-style function application syntax is that it's syntactically more composable?compare `a.foo().bar().bas()`, which reads left-to-right and composes to the right, to `bas(bar(foo(a)))`, which reads inside-out and requires bracketing on both sides of an inner experssion to compose calls. (Of course this only works if your APIs are designed up front in a "fluent" way, and isn't quite as flexible as what you can do with combinators in ML or Haskell.) -Joe From amitava.shee at gmail.com Mon Oct 8 17:32:25 2012 From: amitava.shee at gmail.com (Amitava Shee) Date: Mon, 8 Oct 2012 20:32:25 -0400 Subject: [rust-dev] Assertion failure while compiling In-Reply-To: References: Message-ID: Here's the issue report - https://github.com/mozilla/rust/issues/3702 Amitava On Mon, Oct 8, 2012 at 8:15 PM, Tim Chevalier wrote: > On Mon, Oct 8, 2012 at 5:14 PM, Amitava Shee > wrote: > > I get an assertion failure while trying to compile the following > > > > use io::println; > > > > fn main() { > > trait Text { > > fn to_str(&self) -> ~str; > > } > > > > fn to_string(t: Text) { > > println(t.to_str()); > > } > > > > } > > > > amitava:l2 amitava$ rustc -g trait.rs > > Assertion failed: (Ty && "Invalid GetElementPtrInst indices for type!"), > > function checkGEPType, file > > /Users/amitava/opt/rust/src/rust/src/llvm/include/llvm/Instructions.h, > line > > 705. > > Abort trap: 6 > > > > Clearly, this code is nonsensical since there is no implementation of the > > trait "Text". Should the compiler produce a different message? > > > > Yes, this is a compiler bug. Would you mind filling out an issue report at: > > https://github.com/mozilla/rust/issues/new > > ? (Don't worry about any of the labels or fields; we'll take care of that.) > > Thanks, > > Tim > > -- > Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt > 'Wouldn't you rather be anything other than the kid who runs around > telling stuff what he thinks it is?" -- DavEnd > -- Amitava Shee Software Architect There are two ways of constructing a software design. One is to make it so simple that there are obviously no deficiencies; the other is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult. -- C. A. R. Hoare The Emperor's Old Clothes, CACM February 1981 -------------- next part -------------- An HTML attachment was scrubbed... URL: From nejucomo at gmail.com Mon Oct 8 17:55:27 2012 From: nejucomo at gmail.com (Nathan) Date: Mon, 8 Oct 2012 17:55:27 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: Hello, On Mon, Oct 8, 2012 at 3:19 PM, Eddy Cizeron wrote: > Hi everyone > > 2012/10/6 Tim Chevalier >> Traits and impls in Rust are based on type classes, which originated >> in Haskell. You may find it interesting to read about type classes: >> "Type classes: exploring the design space" by Simon Peyton Jones, Mark >> Jones, and Erik Meijer, is a good start: >> http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.5674 > > Thank you for the reference Tim. I'm not really fluent in Haskell but I > think I understand the concepts and apparently multi-parameter type classes > are very close to what I would expect from Rust interfaces/traits. > > 2012/10/6 Tim Chevalier >> ("Interfaces" have been renamed to "traits" in the soon-to-be-released >> Rust 0.4 release, by the way; it looks like you may be looking at the docs >> from Rust 0.3.) > > Right, I was looking at docs 0.3 but I could not find any newer > documentation. > > 2012/10/6 Sebastian Sylvan >> I strongly feel that the focus on inheritance in (recent) OOP is a >> huge mistake. OOP was originally more about the metaphor of messages >> and objects than inheritance. Inheritance leads to so many bugs and >> [...] >> Interfaces (even trees of them) are great, just not inheritance of >> implementation. > > 2012/10/6 Daniel Patterson >> Inheritance seems to solve a different problem - how to write code that >> targets many different types of objects in a simple way. But inheritance >> isn't really needed there, >> [...] >> Of course, that's just my opinion (and, I am more of a functional >> programmer than an OO programmer). > > Sorry I have not made myself clear enough. My point is absolulety not say > that inheritance is a good/bad/required/unnecessary feature. My point is > that if you're not using it (or at least if you're not using dynamic > linkage), I cannot see where or why OOP concepts and syntax are relevant > anymore. (But apparently there are some attempts to use dynamic linkage with > interfaces and I didn't know that). > > Your remark about the metaphor is indeed interesting. Actually I cannot > remember where I had read someone complaining about that. This guy said "I > know what is sending messages, and it's certainly not that". His point was > precisely that this metaphor fails because the notion of message implies > asynchrony (I'm not paralyzed when I'm waiting for a response to a mail) and > this is certainly not the intended meaning in OOP. I agree with this view. > > You both focus on the functional inspiration for Rust. This is good news. > It's obvious to me the functional paradigm has deep roots in the math world. > Which is also good news. But in mathematics nobody wonder if such-and-such a > function is owned by one of its argument and which one. Or to say it a la > OOP, if this function is a method of one of its argument. This bias, when > taken to the extreme, has generaly lead some languages to syntactical > "oddities" (some of my neurones would say "monstrosities") like: "x = (PI / > 4).sin;" or "y = 2.'+'(7);" Can anyone explain me why it makes more sense to > think about this addition as a message sent to 2 with parameter 7? It does not make sense. Think about a general add interface. It's type could be like the following (I am still fuzzy on rust's memory location/lifetime type modifiers, so here I assume T is somehow copy-by-value): add( a: T, b: T ) -> T There's nothing special about a compared to b, and also the return type is the same type. If we could generalize this to an interface called "Addable", then a single implementation would exist for a given type, and there'd be nothing special about which argument position(s) have that type. I seem to recall there was some constraint on rust traits which says the parameterized type must appear in a particular position. Is this still true? Is this a constraint that will be lifted in the future? I hope so, because then interfaces can be much more expressive, such as as "JSON-compatible interface": to_json( x: T ) -> ~str; from_json( text: ~str ) -> Option; This seems like a coherent and useful kind of interface. > What does > this metaphor makes clearer ? One may justifiably argue that mathematical > concepts are different from everyday life ones. But I don't think > 'file.moveTo(directory)' or 'directory.move(file)' carries better meaning > than 'moveTo(directory, file)'. If you want to express more efficiently the > purpose of every argument of a function, named arguments are a far better > idea. > > 2012/10/6 Daniel Patterson >> I think saying that objects are only useful in so far as inheritance >> exists is strange. The point of objects, as I've understood them, is to >> provide some form of encapsulation - to be able to give limited access >> to certain data so that you can maintain invariants on the data that are >> not expressible with a type system (if such a system even exists). >> Objects can exist without inheritance (and are still useful). > > This is a question of terminology. Unfortunately in computer science and > programming, definitions are generally fuzzy or/and depend on the author. I > keep the word "encapsulation" for the idea of grouping together data and > functions and personally prefer the expression "data hidding" or "data > accessibility" for the feature you're describing. And the fact is this too > concepts are certainly not as strongly linked as you might think. You can > perfectly imagine a system where data accessibility does not apply to the > exterior of a class but to the exterior of other bundles (modules, packages, > etc). This way you can craft more precisely the accessibility of multiple > types in multiple functions. Classes are not needed for this. The common OO idiom you allude to specifically ties interface, data accessibility, and namespace together. That's a particular choice. You are right that these can be decoupled. I'm personally a fan of "fewer ways to do it; less flexibility", so I like nailing down a namespace and data accessibility for example. Or for another example, I'm a fan of "the namespace must correlate directly to the file path in some manner" versus having those decoupled. But that's just me, and I see more flexibility in rust. I'm not certain but I think data accessibility may be tied to namespaces (which are decoupled from filenames somewhat), as well as types, so maybe it already has the flexibility you describe? > > 2012/10/6 Daniel Patterson >> As for your example, you can probably define an implementation for pairs, >> i.e.: >> trait ShapeDrawing<(Sf,Sh)> { >> ? >> } >> [...] >> It is certainly a different approach, but I think you'll find that it >> isn't less >> powerful (and you may find it to be more flexible - but you may not!). > This is intriguing, but not as general as multi-parameter type classes. Consider an interface for two types, A and B, like this: insert( elem: A, container: B ) -> void; peek( container: B ) -> Option; There's no (A,B) parameter or return type anywhere. That would fit into insert(), but it would not make sense for peek, where I have no B at hand. > Well as long as I have not read some document about traits, any criticism or > any conclusion from me about this would be pointless (I've just noticed > Brian's link to new documentation). But after a first glance it does not > seem to remove the limitations I found in the previous concept of > interfaces. And I'm almost sure that interfaces, as they where explained in > the documentation 0.3 are less powerfull. For the same reason the authors of > the article proposed by Tim explain single-parameter type classes in Haskell > are less powerfull than multi-parameter type classes. I'll come back as soon > as my comprehension of Rust traits will be less superficial (and after a > session of self-flagellation if my premonitions/arguments turn out to be > wrong :-)) > Just to recap, rust traits are constrained to be single-type-parameter. I also read somewhere (but can't find the reference off-hand) that they are also constrained in the position of the type parameter in all methods. Relaxing the latter constraint would allow more expressiveness, and relaxing the former would allow even more. I am not very clear on how feasible or difficult relaxing either would be. I don't see particular design problems with relaxing the positional constraint, but I may be missing other related aspects of rust. There may be some confusing cases or developer confusion around multi-parameter traits. > 2012/10/6 Brian Anderson >> Additionally your concern about resources and classes not needing to be >> interrelated >> is spot on, and that issue will be resolved. In 0.4 still structs are the >> only type >> that contain destructors, but the intent is to make destructors just an >> implementation >> of `trait Drop` (or `Finalize` maybe). > > Precisely, I'm not sure that the fact destructors are turned into methods is > good news to me. > > Thank you for this stimulating discussion and references > > -- > Eddy Cizeron > Regards, Nathan Wilcox > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > From bklooste at gmail.com Mon Oct 8 19:11:22 2012 From: bklooste at gmail.com (Bennie Kloosteman) Date: Tue, 9 Oct 2012 10:11:22 +0800 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: Multiple parameter are very useful eg a collection and a second type , but it gets messy... it works ok provided its in a single compilation unit but else you get compilation unit dependency loops ,with generics ( which are similar) you can auto generate new libs to handle this not sure about rust traits.. Ben Just to recap, rust traits are constrained to be > single-type-parameter. I also read somewhere (but can't find the > reference off-hand) that they are also constrained in the position of > the type parameter in all methods. > > Relaxing the latter constraint would allow more expressiveness, and > relaxing the former would allow even more. > > I am not very clear on how feasible or difficult relaxing either would > be. I don't see particular design problems with relaxing the > positional constraint, but I may be missing other related aspects of > rust. There may be some confusing cases or developer confusion around > multi-parameter traits. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Mon Oct 8 19:18:28 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 08 Oct 2012 19:18:28 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: <50738974.40405@alum.mit.edu> There is no requirement that the self type in a trait appear in the receiver position. Rust supports traits like the Json trait you propose: trait Json { fn to_json(&self) -> ~str; fn from_json(value: ~str) -> self; } Today, however, we would require the keyword `static` in front of the second fn. We are phasing this out in favor of "explicit self". In the explicit self system, methods declare the receiver type explicitly, somewhat like Python. This lets you declare what kind of pointer to `self` you like. So `fn foo(&self)` means a method with a borrowed receiver, `fn foo(@self)` means a method with a managed receiver, and so on. You can also do `fn foo(self)` to mean "by-value" self. Niko > Nathan > October 8, 2012 5:55 PM > Hello, > > > On Mon, Oct 8, 2012 at 3:19 PM, Eddy Cizeron wrote: >> Hi everyone >> >> 2012/10/6 Tim Chevalier >>> Traits and impls in Rust are based on type classes, which originated >>> in Haskell. You may find it interesting to read about type classes: >>> "Type classes: exploring the design space" by Simon Peyton Jones, Mark >>> Jones, and Erik Meijer, is a good start: >>> http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.5674 >> Thank you for the reference Tim. I'm not really fluent in Haskell but I >> think I understand the concepts and apparently multi-parameter type classes >> are very close to what I would expect from Rust interfaces/traits. >> >> 2012/10/6 Tim Chevalier >>> ("Interfaces" have been renamed to "traits" in the soon-to-be-released >>> Rust 0.4 release, by the way; it looks like you may be looking at the docs >>> from Rust 0.3.) >> Right, I was looking at docs 0.3 but I could not find any newer >> documentation. >> >> 2012/10/6 Sebastian Sylvan >>> I strongly feel that the focus on inheritance in (recent) OOP is a >>> huge mistake. OOP was originally more about the metaphor of messages >>> and objects than inheritance. Inheritance leads to so many bugs and >>> [...] >>> Interfaces (even trees of them) are great, just not inheritance of >>> implementation. >> 2012/10/6 Daniel Patterson >>> Inheritance seems to solve a different problem - how to write code that >>> targets many different types of objects in a simple way. But inheritance >>> isn't really needed there, >>> [...] >>> Of course, that's just my opinion (and, I am more of a functional >>> programmer than an OO programmer). >> Sorry I have not made myself clear enough. My point is absolulety not say >> that inheritance is a good/bad/required/unnecessary feature. My point is >> that if you're not using it (or at least if you're not using dynamic >> linkage), I cannot see where or why OOP concepts and syntax are relevant >> anymore. (But apparently there are some attempts to use dynamic linkage with >> interfaces and I didn't know that). >> >> Your remark about the metaphor is indeed interesting. Actually I cannot >> remember where I had read someone complaining about that. This guy said "I >> know what is sending messages, and it's certainly not that". His point was >> precisely that this metaphor fails because the notion of message implies >> asynchrony (I'm not paralyzed when I'm waiting for a response to a mail) and >> this is certainly not the intended meaning in OOP. I agree with this view. >> >> You both focus on the functional inspiration for Rust. This is good news. >> It's obvious to me the functional paradigm has deep roots in the math world. >> Which is also good news. But in mathematics nobody wonder if such-and-such a >> function is owned by one of its argument and which one. Or to say it a la >> OOP, if this function is a method of one of its argument. This bias, when >> taken to the extreme, has generaly lead some languages to syntactical >> "oddities" (some of my neurones would say "monstrosities") like: "x = (PI / >> 4).sin;" or "y = 2.'+'(7);" Can anyone explain me why it makes more sense to >> think about this addition as a message sent to 2 with parameter 7? > > It does not make sense. Think about a general add interface. It's > type could be like the following (I am still fuzzy on rust's memory > location/lifetime type modifiers, so here I assume T is somehow > copy-by-value): > > add( a: T, b: T ) -> T > > There's nothing special about a compared to b, and also the return > type is the same type. If we could generalize this to an interface > called "Addable", then a single implementation would exist for a given > type, and there'd be nothing special about which argument position(s) > have that type. > > I seem to recall there was some constraint on rust traits which says > the parameterized type must appear in a particular position. Is this > still true? Is this a constraint that will be lifted in the future? > > I hope so, because then interfaces can be much more expressive, such > as as "JSON-compatible interface": > > to_json( x: T ) -> ~str; > from_json( text: ~str ) -> Option; > > This seems like a coherent and useful kind of interface. > > >> What does >> this metaphor makes clearer ? One may justifiably argue that mathematical >> concepts are different from everyday life ones. But I don't think >> 'file.moveTo(directory)' or 'directory.move(file)' carries better meaning >> than 'moveTo(directory, file)'. If you want to express more efficiently the >> purpose of every argument of a function, named arguments are a far better >> idea. >> >> 2012/10/6 Daniel Patterson >>> I think saying that objects are only useful in so far as inheritance >>> exists is strange. The point of objects, as I've understood them, is to >>> provide some form of encapsulation - to be able to give limited access >>> to certain data so that you can maintain invariants on the data that are >>> not expressible with a type system (if such a system even exists). >>> Objects can exist without inheritance (and are still useful). >> This is a question of terminology. Unfortunately in computer science and >> programming, definitions are generally fuzzy or/and depend on the author. I >> keep the word "encapsulation" for the idea of grouping together data and >> functions and personally prefer the expression "data hidding" or "data >> accessibility" for the feature you're describing. And the fact is this too >> concepts are certainly not as strongly linked as you might think. You can >> perfectly imagine a system where data accessibility does not apply to the >> exterior of a class but to the exterior of other bundles (modules, packages, >> etc). This way you can craft more precisely the accessibility of multiple >> types in multiple functions. Classes are not needed for this. > > The common OO idiom you allude to specifically ties interface, data > accessibility, and namespace together. That's a particular choice. > You are right that these can be decoupled. > > I'm personally a fan of "fewer ways to do it; less flexibility", so I > like nailing down a namespace and data accessibility for example. Or > for another example, I'm a fan of "the namespace must correlate > directly to the file path in some manner" versus having those > decoupled. > > But that's just me, and I see more flexibility in rust. I'm not > certain but I think data accessibility may be tied to namespaces > (which are decoupled from filenames somewhat), as well as types, so > maybe it already has the flexibility you describe? > > >> 2012/10/6 Daniel Patterson >>> As for your example, you can probably define an implementation for pairs, >>> i.e.: >>> trait ShapeDrawing<(Sf,Sh)> { >>> ? >>> } >>> [...] >>> It is certainly a different approach, but I think you'll find that it >>> isn't less >>> powerful (and you may find it to be more flexible - but you may not!). > > This is intriguing, but not as general as multi-parameter type > classes. Consider an interface for two types, A and B, like this: > > insert( elem: A, container: B ) -> void; > peek( container: B ) -> Option; > > There's no (A,B) parameter or return type anywhere. That would fit > into insert(), but it would not make sense for peek, where I have no B > at hand. > > >> Well as long as I have not read some document about traits, any criticism or >> any conclusion from me about this would be pointless (I've just noticed >> Brian's link to new documentation). But after a first glance it does not >> seem to remove the limitations I found in the previous concept of >> interfaces. And I'm almost sure that interfaces, as they where explained in >> the documentation 0.3 are less powerfull. For the same reason the authors of >> the article proposed by Tim explain single-parameter type classes in Haskell >> are less powerfull than multi-parameter type classes. I'll come back as soon >> as my comprehension of Rust traits will be less superficial (and after a >> session of self-flagellation if my premonitions/arguments turn out to be >> wrong :-)) >> > > Just to recap, rust traits are constrained to be > single-type-parameter. I also read somewhere (but can't find the > reference off-hand) that they are also constrained in the position of > the type parameter in all methods. > > Relaxing the latter constraint would allow more expressiveness, and > relaxing the former would allow even more. > > I am not very clear on how feasible or difficult relaxing either would > be. I don't see particular design problems with relaxing the > positional constraint, but I may be missing other related aspects of > rust. There may be some confusing cases or developer confusion around > multi-parameter traits. > > > >> 2012/10/6 Brian Anderson >>> Additionally your concern about resources and classes not needing to be >>> interrelated >>> is spot on, and that issue will be resolved. In 0.4 still structs are the >>> only type >>> that contain destructors, but the intent is to make destructors just an >>> implementation >>> of `trait Drop` (or `Finalize` maybe). >> Precisely, I'm not sure that the fact destructors are turned into methods is >> good news to me. >> >> Thank you for this stimulating discussion and references >> >> -- >> Eddy Cizeron >> > > > Regards, > Nathan Wilcox > > >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev >> > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Eddy Cizeron > October 8, 2012 3:19 PM > Hi everyone > > 2012/10/6 Tim Chevalier > > > Traits and impls in Rust are based on type classes, which originated > > in Haskell. You may find it interesting to read about type classes: > > "Type classes: exploring the design space" by Simon Peyton Jones, Mark > > Jones, and Erik Meijer, is a good start: > > http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.5674 > > Thank you for the reference Tim. I'm not really fluent in Haskell but > I think I understand the concepts and apparently multi-parameter type > classes are very close to what I would expect from Rust interfaces/traits. > > 2012/10/6 Tim Chevalier > > > ("Interfaces" have been renamed to "traits" in the soon-to-be-released > > Rust 0.4 release, by the way; it looks like you may be looking at > the docs from Rust 0.3.) > > Right, I was looking at docs 0.3 but I could not find any newer > documentation. > > 2012/10/6 Sebastian Sylvan > > > I strongly feel that the focus on inheritance in (recent) OOP is a > > huge mistake. OOP was originally more about the metaphor of messages > > and objects than inheritance. Inheritance leads to so many bugs and > > [...] > > Interfaces (even trees of them) are great, just not inheritance of > > implementation. > > 2012/10/6 Daniel Patterson > > > Inheritance seems to solve a different problem - how to write code that > > targets many different types of objects in a simple way. But inheritance > > isn't really needed there, > > [...] > > Of course, that's just my opinion (and, I am more of a functional > programmer than an OO programmer). > > Sorry I have not made myself clear enough. My point is absolulety not > say that inheritance is a good/bad/required/unnecessary feature. My > point is that if you're not using it (or at least if you're not using > dynamic linkage), I cannot see where or why OOP concepts and syntax > are relevant anymore. (But apparently there are some attempts to use > dynamic linkage with interfaces and I didn't know that). > > Your remark about the metaphor is indeed interesting. Actually I > cannot remember where I had read someone complaining about that. This > guy said "I know what is sending messages, and it's certainly not > that". His point was precisely that this metaphor fails because the > notion of message implies asynchrony (I'm not paralyzed when I'm > waiting for a response to a mail) and this is certainly not the > intended meaning in OOP. I agree with this view. > > You both focus on the functional inspiration for Rust. This is good > news. It's obvious to me the functional paradigm has deep roots in the > math world. Which is also good news. But in mathematics nobody wonder > if such-and-such a function is owned by one of its argument and which > one. Or to say it a la OOP, if this function is a method of one of its > argument. This bias, when taken to the extreme, has generaly lead some > languages to syntactical "oddities" (some of my neurones would say > "monstrosities") like: "x = (PI / 4).sin;" or "y = 2.'+'(7);" Can > anyone explain me why it makes more sense to think about this addition > as a message sent to 2 with parameter 7? What does this metaphor makes > clearer ? One may justifiably argue that mathematical concepts are > different from everyday life ones. But I don't think > 'file.moveTo(directory)' or 'directory.move(file)' carries better > meaning than 'moveTo(directory, file)'. If you want to express more > efficiently the purpose of every argument of a function, named > arguments are a far better idea. > > 2012/10/6 Daniel Patterson > > > I think saying that objects are only useful in so far as inheritance > > exists is strange. The point of objects, as I've understood them, is to > > provide some form of encapsulation - to be able to give limited access > > to certain data so that you can maintain invariants on the data that are > > not expressible with a type system (if such a system even exists). > > Objects can exist without inheritance (and are still useful). > > This is a question of terminology. Unfortunately in computer science > and programming, definitions are generally fuzzy or/and depend on the > author. I keep the word "encapsulation" for the idea of grouping > together data and functions and personally prefer the expression "data > hidding" or "data accessibility" for the feature you're describing. > And the fact is this too concepts are certainly not as strongly linked > as you might think. You can perfectly imagine a system where data > accessibility does not apply to the exterior of a class but to the > exterior of other bundles (modules, packages, etc). This way you can > craft more precisely the accessibility of multiple types in multiple > functions. Classes are not needed for this. > > 2012/10/6 Daniel Patterson > > > As for your example, you can probably define an implementation for > pairs, i.e.: > > trait ShapeDrawing<(Sf,Sh)> { > > ? > > } > > [...] > > It is certainly a different approach, but I think you'll find that > it isn't less > > powerful (and you may find it to be more flexible - but you may not!). > > Well as long as I have not read some document about traits, any > criticism or any conclusion from me about this would be pointless > (I've just noticed Brian's link to new documentation). But after a > first glance it does not seem to remove the limitations I found in the > previous concept of interfaces. And I'm almost sure that interfaces, > as they where explained in the documentation 0.3 are less powerfull. > For the same reason the authors of the article proposed by Tim explain > single-parameter type classes in Haskell are less powerfull than > multi-parameter type classes. I'll come back as soon as my > comprehension of Rust traits will be less superficial (and after a > session of self-flagellation if my premonitions/arguments turn out to > be wrong :-)) > > 2012/10/6 Brian Anderson > > > Additionally your concern about resources and classes not needing to > be interrelated > > is spot on, and that issue will be resolved. In 0.4 still structs > are the only type > > that contain destructors, but the intent is to make destructors just > an implementation > > of `trait Drop` (or `Finalize` maybe). > > Precisely, I'm not sure that the fact destructors are turned into > methods is good news to me. > > Thank you for this stimulating discussion and references > > -- > Eddy Cizeron > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Nathan > October 8, 2012 1:05 AM > On Sat, Oct 6, 2012 at 11:16 AM, Tim Chevalier wrote: >> Hi, Eddy -- >> >> Traits and impls in Rust are based on type classes, which originated >> in Haskell. You may find it interesting to read about type classes: >> "Type classes: exploring the design space" by Simon Peyton Jones, Mark >> Jones, and Erik Meijer, is a good start: >> >> http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.5674 >> >> ("Interfaces" have been renamed to "traits" in the soon-to-be-released >> Rust 0.4 release, by the way; it looks like you may be looking at the >> docs from Rust 0.3.) >> >> Cheers, >> Tim >> > > I'm about half-way through this paper, which is a great reference. Thanks! > > I'm curious if multi-parameter traits are anywhere on the rust > roadmap. I'm not certain about which challenges or restrictions they > may require but perhaps by the time I finish this reference I'll have > a better understanding. > > I'd recommend reading the paper if only to see motivating examples of > multi-parameter traits. > > Regards, > Nathan > >> -- >> Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt >> "Gains in likability have deep costs in personal integrity." -- Kirk Read >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Tim Chevalier > October 6, 2012 11:16 AM > Hi, Eddy -- > > Traits and impls in Rust are based on type classes, which originated > in Haskell. You may find it interesting to read about type classes: > "Type classes: exploring the design space" by Simon Peyton Jones, Mark > Jones, and Erik Meijer, is a good start: > > http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.5674 > > ("Interfaces" have been renamed to "traits" in the soon-to-be-released > Rust 0.4 release, by the way; it looks like you may be looking at the > docs from Rust 0.3.) > > Cheers, > Tim > > Eddy Cizeron > October 6, 2012 11:14 AM > > Hello, > > I'm new to Rust, and I have some questions concerning some aspects of > the language. From what I understand until now, rust has no dynamic > linkage for methods as it would be the case in any standard OOP > language. This is surely an intentionaly different philosophy from the > current trend among other recent programming languages. But why not > after all. I like the idea. So I find myself skeptical when I read the > chapters of the documentation about OOP-like concepts like classes or > interfaces. > > The essence of the "class" concept lies in the possibility to gather a > data structure (a type) and the related processes that can act on the > corresponding instances (methods) in a single bundle. But, tell me if > you disagree, the only interesting purpose of such an operation is the > ability to use inheritance. If no concept of inheritance exists, I > hardly see what is the need of making functions "pets" for data. All > we obtain are classical design issues like "is my 'f(a,b)' function a > 'a.f(b)' method or a 'b.f(a)' method ?" (and I don't think the rust > "resource" concept requires classes, as destructors or destructor-like > functions are not methods). I'm afraid that the answer is merely to > offer a supposedly "attractive" syntax for OOP users. And I think this > would be a weak argument > > The concept of interface/implementation in rust is surely different > than the usual one, but again to me it looks like it has some > limitations due to the same reason than above: it tries to look OOP. I > could have imagined a very similar interface concept but that does not > focus on a *single *type: > > iface shape_drawing { > fn draw(Sf, Sh); > fn bounding_box(Sh) -> bounding_box; > } > > fn draw_twice>(surface: Sf, shape: Sh) { > draw(surface, shape); > draw(surface, shape); > } > > Of course this example is a simple one. And any consistent system like > this (if it does exist but I'm pretty sure it does) would have been > more complex than the current one. But also more general and then more > powerful. > > Let me clear about something: I don't expect anybody to change the > current design. I'm nobody and I know it's always easier to criticize > than to do things. I'm just expressing the feeling that while Rust > tried to take a different direction from all the other new > JVM-compliant-OOP-languages-with-functional-features (which I really > really value very much) it seems it has not got rid of some conceptual > patterns that are not, IMHO, necessary anymore. And I wish people > could give their opinion about this. > > Thank you > > -- > Eddy Cizeron > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: postbox-contact.jpg Type: image/jpeg Size: 1270 bytes Desc: not available URL: From sebastian.sylvan at gmail.com Mon Oct 8 21:34:54 2012 From: sebastian.sylvan at gmail.com (Sebastian Sylvan) Date: Mon, 8 Oct 2012 21:34:54 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: On Mon, Oct 8, 2012 at 5:22 PM, Joe Groff wrote: > On Mon, Oct 8, 2012 at 3:19 PM, Eddy Cizeron wrote: >> Sorry I have not made myself clear enough. My point is absolulety not say >> that inheritance is a good/bad/required/unnecessary feature. My point is >> that if you're not using it (or at least if you're not using dynamic >> linkage), I cannot see where or why OOP concepts and syntax are relevant >> anymore. (But apparently there are some attempts to use dynamic linkage with >> interfaces and I didn't know that). > > One minor non-semantic, non-scientific benefit of OOP syntax over > Algol-style function application syntax is that it's syntactically > more composable?compare `a.foo().bar().bas()`, which reads > left-to-right and composes to the right, to `bas(bar(foo(a)))`, which > reads inside-out and requires bracketing on both sides of an inner > experssion to compose calls. (Of course this only works if your APIs > are designed up front in a "fluent" way, and isn't quite as flexible > as what you can do with combinators in ML or Haskell.) I think there are two other benefits. The first is intellisense/code completion. Type "foo." and get a list of all methods in scope with a matching self type. This can be a massive productivity boost as it basically puts all your code and documentation in the IDE in a context sensitive way. Much harder to do this if you have to remember the name of the method before you see anything. Second, and much more subjectively, I think there's a difference between sort of value oriented programming, and the more low level mutable programming type where you're dealing with "objects" that have identity and complicated invariants. Subjective, but tying the methods to the data type in those cases "feels" okay to me because they kinda are inseparable in practice, so they might as well be syntactically tied together as well (with a more functional style you would group them by modules and visibility, but syntactically it doesn't look like an indivisible "object" that have a small set hard-wired built in methods on it as opposed to a value and a random grab bag of operations that happen to have matching types but could be written by any old schmuck and not necessarily "part of the object"). -- Sebastian Sylvan From hsivonen at iki.fi Wed Oct 10 04:16:19 2012 From: hsivonen at iki.fi (Henri Sivonen) Date: Wed, 10 Oct 2012 14:16:19 +0300 Subject: [rust-dev] Fall-through in alt, break&continue by label In-Reply-To: <506F2F17.1080703@mozilla.com> References: <4F8438AF.9090003@alum.mit.edu> <506F2F17.1080703@mozilla.com> Message-ID: On Fri, Oct 5, 2012 at 10:03 PM, Brian Anderson wrote: >> Even break and continue by label would be useful without fall-through in >> alt. > > Thanks, Henri. I've posted this information to our bugtracker: > https://github.com/mozilla/rust/issues/2216 Thanks. So does this mean I should work with the assumption that Rust will get break/continue by label and I should not develop a code transformation to work around the current lack thereof? As the first real code step towards translation to Rust, I wrote a Java to Java transformation for getting rid of fall-through in switch. The exercise was successful: The result still passes the test suite. (I did this Java to Java to be able to check the result with the test suite. I intend to use the Java to Java transformation as a preprocessing step for the translation to Rust.) -- Henri Sivonen hsivonen at iki.fi http://hsivonen.iki.fi/ From graydon at mozilla.com Wed Oct 10 07:49:22 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 10 Oct 2012 07:49:22 -0700 Subject: [rust-dev] Fall-through in alt, break&continue by label In-Reply-To: References: <4F8438AF.9090003@alum.mit.edu> <506F2F17.1080703@mozilla.com> Message-ID: <50758AF2.6080501@mozilla.com> On 10/10/2012 4:16 AM, Henri Sivonen wrote: > On Fri, Oct 5, 2012 at 10:03 PM, Brian Anderson wrote: >>> Even break and continue by label would be useful without fall-through in >>> alt. >> >> Thanks, Henri. I've posted this information to our bugtracker: >> https://github.com/mozilla/rust/issues/2216 > > Thanks. So does this mean I should work with the assumption that Rust > will get break/continue by label and I should not develop a code > transformation to work around the current lack thereof? That's a matter of timing more than anything else. If you need it done today, it's not working today. If you can wait .. a bit (+/- conversations with other servo-project members to indicate urgency) we do have the labeled break/loop stuff on the list for the near future, yes. I think it already parses, just doesn't translate. Shouldn't be a huge task. -Graydon From banderson at mozilla.com Wed Oct 10 11:48:09 2012 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 10 Oct 2012 11:48:09 -0700 Subject: [rust-dev] Fall-through in alt, break&continue by label In-Reply-To: References: <4F8438AF.9090003@alum.mit.edu> <506F2F17.1080703@mozilla.com> Message-ID: <5075C2E9.4060303@mozilla.com> On 10/10/2012 04:16 AM, Henri Sivonen wrote: > On Fri, Oct 5, 2012 at 10:03 PM, Brian Anderson wrote: >>> Even break and continue by label would be useful without fall-through in >>> alt. >> >> Thanks, Henri. I've posted this information to our bugtracker: >> https://github.com/mozilla/rust/issues/2216 > > Thanks. So does this mean I should work with the assumption that Rust > will get break/continue by label and I should not develop a code > transformation to work around the current lack thereof? Yes, if you still need it, then you can assume we will add it, though I don't know the timeframe. Sadly, there are a lot of things [prioritized] for the next release and labeled break and continue isn't on there. I will add it presently. [prioritized]: https://github.com/mozilla/rust/wiki/Note-0.5-priorities > > As the first real code step towards translation to Rust, I wrote a > Java to Java transformation for getting rid of fall-through in switch. > The exercise was successful: The result still passes the test suite. > (I did this Java to Java to be able to check the result with the test > suite. I intend to use the Java to Java transformation as a > preprocessing step for the translation to Rust.) > This is great news. Thank you so much for continuing to pursue this while we dally. From eddycizeron at gmail.com Wed Oct 10 15:49:24 2012 From: eddycizeron at gmail.com (Eddy Cizeron) Date: Thu, 11 Oct 2012 00:49:24 +0200 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: 2012/10/9 Lindsey Kuper > And, in case nobody has pointed them out yet, here are a couple more resources: > * An introduction to traits on Patrick's blog: http://pcwalton.github.com/blog/2012/08/08/a-gentle-introduction-to-traits-in-rust > * A talk I did in August, with a side-by-side Haskell/Rust > comparison: https://air.mozilla.org/rust-typeclasses > Cheers, Thank you for the references Lindsey. 2012/10/9 Joe Groff > One minor non-semantic, non-scientific benefit of OOP syntax over > Algol-style function application syntax is that it's syntactically > more composable?compare `a.foo().bar().bas()`, which reads > left-to-right and composes to the right, to `bas(bar(foo(a)))`, which > reads inside-out and requires bracketing on both sides of an inner > experssion to compose calls. (Of course this only works if your APIs > are designed up front in a "fluent" way, and isn't quite as flexible > as what you can do with combinators in ML or Haskell.) I'm a math guy so to me syntax `bas(bar(foo(a)))` is natural. Besides as you noticed yourself this only work in certain circumstances. For example when you have additional parameters, the syntax could sometime be something like `c.bar(a.foo(b)).bas()` which is less readable in my opinion than `bas(bar(c, foo(a, b)))`. But all this is very subjective, isn't it ? 2012/10/9 Sebastian Sylvan > I think there are two other benefits. The first is intellisense/code > completion. Type "foo." and get a list of all methods in scope with a > matching self type. This can be a massive productivity boost as it > basically puts all your code and documentation in the IDE in a context > sensitive way. Much harder to do this if you have to remember the name > of the method before you see anything. I agree that it's easier to start from a variable existing in the context rather than from a namespace or from a function name. But completion does not necessarily have to insert code after the considered identifier, even if it is indeed more usual. > Second, and much more subjectively, I think there's a difference > between sort of value oriented programming, and the more low level > mutable programming type where you're dealing with "objects" that have > identity and complicated invariants. Subjective, but tying the methods > to the data type in those cases "feels" okay to me because they kinda > are inseparable in practice, so they might as well be syntactically > tied together as well (with a more functional style you would group > them by modules and visibility, but syntactically it doesn't look like > an indivisible "object" that have a small set hard-wired built in > methods on it as opposed to a value and a random grab bag of > operations that happen to have matching types but could be written by > any old schmuck and not necessarily "part of the object"). This is precisely the subjective feeling I don't agree with. This feeling only exists because you think of processes/functions/methods as part of a single object rather than interactions between a group of objects. This is a very "Aristotelician" view. It sometimes work well (when object can be seen like "active" autonomous entities) but not in the general case IMHO. 2012/10/9 Nathan > It does not make sense. Think about a general add interface. It's > type could be like the following (I am still fuzzy on rust's memory > location/lifetime type modifiers, so here I assume T is somehow > copy-by-value): > > add( a: T, b: T ) -> T > > There's nothing special about a compared to b, and also the return > type is the same type. If we could generalize this to an interface > called "Addable", then a single implementation would exist for a given > type, and there'd be nothing special about which argument position(s) > have that type. Hem ... So this mean we agree right ? My point was precisely that this does not make sense. The syntax need not to give one of the arguments a specific role. > The common OO idiom you allude to specifically ties interface, data > accessibility, and namespace together. That's a particular choice. > You are right that these can be decoupled. > > I'm personally a fan of "fewer ways to do it; less flexibility", so I > like nailing down a namespace and data accessibility for example. Or > for another example, I'm a fan of "the namespace must correlate > directly to the file path in some manner" versus having those > decoupled. I may only partly agree. I too prefer Bertrand Meyer's "A programming language should provide one good way of performing any operation of interest; it should avoid providing two." to Larry Wall's "There's more than one way to do it". But this only apply to perfectly equivalent contructs. If there is several way to do related but distinct things, I found flexibility better. > But that's just me, and I see more flexibility in rust. I'm not > certain but I think data accessibility may be tied to namespaces > (which are decoupled from filenames somewhat), as well as types, so > maybe it already has the flexibility you describe? In all the docs I've read until now, the word "private" only appeared in the section for classes, so I guess no. > This is intriguing, but not as general as multi-parameter type > classes. Consider an interface for two types, A and B, like this: > > insert( elem: A, container: B ) -> void; > peek( container: B ) -> Option; > > There's no (A,B) parameter or return type anywhere. That would fit > into insert(), but it would not make sense for peek, where I have no B > at hand. This is definite the kind of interface/trait I would like to be express in Rust. But apparently it is not possible with the current design. 2012/10/9 Bennie Kloosteman > Multiple parameter are very useful eg a collection and a second type , > but it gets messy... it works ok provided its in a single compilation > unit but else you get compilation unit dependency loops ,with generics > ( which are similar) you can auto generate new libs to handle this > not sure about rust traits.. Hi Ben. I'm not sure to understand the link with compilation loop. Any previous discussion on this topic? So in conclusion, this means multiple parameter traits are not planned to be implemented in Rust ? right ? -- Eddy Cizeron -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Wed Oct 10 15:54:54 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 10 Oct 2012 15:54:54 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: <5075FCBE.6050107@mozilla.com> On 10/10/12 3:49 PM, Eddy Cizeron wrote: > > There's no (A,B) parameter or return type anywhere. That would fit > > into insert(), but it would not make sense for peek, where I have no B > > at hand. I do not see why this could not be written with a generic trait. Patrick From sebastian.sylvan at gmail.com Wed Oct 10 18:01:24 2012 From: sebastian.sylvan at gmail.com (Sebastian Sylvan) Date: Wed, 10 Oct 2012 18:01:24 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: On Wed, Oct 10, 2012 at 3:49 PM, Eddy Cizeron wrote: > 2012/10/9 Sebastian Sylvan >> I think there are two other benefits. The first is intellisense/code >> completion. Type "foo." and get a list of all methods in scope with a >> matching self type. This can be a massive productivity boost as it >> basically puts all your code and documentation in the IDE in a context >> sensitive way. Much harder to do this if you have to remember the name >> of the method before you see anything. > > I agree that it's easier to start from a variable existing in the context > rather than from a namespace or from a function name. But completion does > not necessarily have to insert code after the considered identifier, even if > it is indeed more usual. That would indeed be pretty unusual. Worse, it's how you write code normally. If function applications start with the name of the function and not the variable, then you have to decide before you even start that you want to invoke the "code completion feature" on this next expression, *skip* writing the function name (or put in some kind of placholder) and instad write the variable you want to act on combined with some magic incantation to make the IDE let you select and then pre-inject the function name in front of it. In an OOP style syntax you just write code like you're used to and the IDE just discretely flashes up little tool tips and lists of members to gently nudge you along your way (or allow you to short cut some typing) as you go about your normal coding. You don't need to do anything special, it's just constantly there if you need it, and can be ignored if you don't. I really can't stress enough what a force multipler it is to write code in an IDE with powerful code completion for someone who has internalized it into their workflow. I know real men use VIM etc., but I'm secure enough to admit that I am more productive in the actual coding phase using C# with Intellisense in VS than Haskell + Emacs or whatever, even though I recognize that on language merit alone it should be the other way around by far. Tooling matters so much these days. Arguably more than a lot of language semantics, and certainly more than worrying about slight syntactic redundancy, IMO. -- Sebastian Sylvan From catamorphism at gmail.com Wed Oct 10 18:05:00 2012 From: catamorphism at gmail.com (Tim Chevalier) Date: Wed, 10 Oct 2012 18:05:00 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: On Wed, Oct 10, 2012 at 6:01 PM, Sebastian Sylvan wrote: > > I really can't stress enough what a force multipler it is to write > code in an IDE with powerful code completion for someone who has > internalized it into their workflow. I know real men use VIM etc., but > I'm secure enough to admit that I am more productive in the actual > coding phase using C# with Intellisense in VS than Haskell + Emacs or > whatever, even though I recognize that on language merit alone it > should be the other way around by far. Tooling matters so much these > days. Arguably more than a lot of language semantics, and certainly > more than worrying about slight syntactic redundancy, IMO. Hey folks, two moderation-ish notes: 1. "Real men use VIM etc..." excludes women. We have Rust developers who aren't men, so please don't assume otherwise. I know it's just a joke, not intended to be sexist, etc., so there's no need to say that. Just don't do it again. 2. This discussion is getting a bit far from specifics of how to improve Rust. Please take it elsewhere. If there is interest, we may start a rust-cafe list in the vein of haskell-cafe for off-topic-ish discussions (or, in fact, anybody could, on Google Groups). But for now, please try to keep discussions on this list narrowly focused. Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt 'Wouldn't you rather be anything other than the kid who runs around telling stuff what he thinks it is?" -- DavEnd From bklooste at gmail.com Wed Oct 10 19:26:56 2012 From: bklooste at gmail.com (Bennie Kloosteman) Date: Thu, 11 Oct 2012 10:26:56 +0800 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: > > > 2. This discussion is getting a bit far from specifics of how to > improve Rust. Please take it elsewhere. If there is interest, we may > start a rust-cafe list in the vein of haskell-cafe for off-topic-ish > discussions (or, in fact, anybody could, on Google Groups). But for > now, please try to keep discussions on this list narrowly focused. > I think designing for Intellisense and auto completion is very important these days especially when you have huge number of libs or a large runtime . This means no short names taking up the namespace etc In addition the OO to functional story must be resolved and clear. Like it or not 90% of people are OO coders , which is rammed down your throats at every university in the world so you need a convincing case.. Personally most coders dont bother with inheritance anymore but full polymorphism through interfaces are important ( including having a typename in a file and then creating it at runtime) . If you cant provide this form of polymorphism then the alternatives , impact and reasons with examples need to be document. Haskell people understand typeclasses but they may struggle with Rust objects/traits while OO people will try to think of it in terms of generics.,.explaining and having a clear story for this middle ground is crucial. Ben -------------- next part -------------- An HTML attachment was scrubbed... URL: From lists.rust at dbp.mm.st Wed Oct 10 19:58:49 2012 From: lists.rust at dbp.mm.st (Daniel Patterson) Date: Wed, 10 Oct 2012 22:58:49 -0400 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: <1AB1E2E6-B2DC-4798-A5A0-1342E777D498@dbp.mm.st> On Oct 10, 2012, at 10:26 PM, Bennie Kloosteman wrote: > I think designing for Intellisense and auto completion is very important these days especially when you have huge number of libs or a large runtime . This means no short names taking up the namespace etc I think there is also some sense in which this is an issue of momentum/resources - certain languages have lots of it, and as a result, grow sophisticated tooling ecosystems. This is often distinct from what the semantics of the languages allow. For example, in languages with powerful type systems, there is potential for pretty amazing tooling. For instance, there is no reason why an editor / IDE for rust couldn't be doing type checking / inference while you are writing, and could highlight type system (or borrow checking) errors as they occur (this alone would be an amazing productivity booster). Similarly, you could write the name of a variable, and with some sort of completion, get any functions that take its type as the first parameter. Or I could imagine a system where you type the arguments to the function and hit a button and get completion of all functions that match the correct types (figuring out where the last statement ended, and thus the arguments started, is easy). We can also do the more familiar completion on trait implementations (i.e., methods). There are probably also ways in which the tooling could make use of the other special features that rust has (beyond just having a nice type system), but I haven't thought of them yet :) From niko at alum.mit.edu Wed Oct 10 21:14:24 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 10 Oct 2012 21:14:24 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: Message-ID: <507647A0.9000401@alum.mit.edu> For what it's worth, Sebastian, Simon Peyton Jones agrees with you: http://research.microsoft.com/en-us/um/people/simonpj/papers/haskell-retrospective/ (Skip ahead to page 56, he talks specifically about its use in intellisense, calling it "the power of the dot"). To me, there is another very important point regarding dot notation that I didn't see mentioned yet: it enables name resolution on a per-type basis. In Haskell, if I want to have to have something like "foo.context()" and "bar.context()" where the context of a foo has one type and bar has another, it's a big pain and I have to use import qualified or something crazy like that. In OOP this is no issue. And I find this very natural. Anyway, I think the design of the trait system is very much going towards a "best of both worlds" direction. You can define methods and you can define standalone functions. Based on our last meeting, there seems to be general agreement towards a system that allows methods to be imported as standalone functions that take the receiver as first argument as well [1]. Like most modern languages---including Haskell, Java, and C#---we support both parametric polymorphism (bounded generics) and ad-hoc polymorphism (trait types). Both have their place, after all. So basically there is no conflict here. You use the right tool for the job. Niko [1] As initially proposed here: https://mail.mozilla.org/pipermail/rust-dev/2012-August/002255.html > Sebastian Sylvan > October 10, 2012 6:01 PM > > That would indeed be pretty unusual. Worse, it's how you write code > normally. If function applications start with the name of the function > and not the variable, then you have to decide before you even start > that you want to invoke the "code completion feature" on this next > expression, *skip* writing the function name (or put in some kind of > placholder) and instad write the variable you want to act on combined > with some magic incantation to make the IDE let you select and then > pre-inject the function name in front of it. In an OOP style syntax > you just write code like you're used to and the IDE just discretely > flashes up little tool tips and lists of members to gently nudge you > along your way (or allow you to short cut some typing) as you go about > your normal coding. You don't need to do anything special, it's just > constantly there if you need it, and can be ignored if you don't. > > I really can't stress enough what a force multipler it is to write > code in an IDE with powerful code completion for someone who has > internalized it into their workflow. I know real men use VIM etc., but > I'm secure enough to admit that I am more productive in the actual > coding phase using C# with Intellisense in VS than Haskell + Emacs or > whatever, even though I recognize that on language merit alone it > should be the other way around by far. Tooling matters so much these > days. Arguably more than a lot of language semantics, and certainly > more than worrying about slight syntactic redundancy, IMO. > > Eddy Cizeron > October 10, 2012 3:49 PM > > 2012/10/9 Lindsey Kuper > > > And, in case nobody has pointed them out yet, here are a couple more > resources: > > * An introduction to traits on Patrick's blog: > http://pcwalton.github.com/blog/2012/08/08/a-gentle-introduction-to-traits-in-rust > > * A talk I did in August, with a side-by-side Haskell/Rust > > comparison: https://air.mozilla.org/rust-typeclasses > > Cheers, > > Thank you for the references Lindsey. > > 2012/10/9 Joe Groff > > > One minor non-semantic, non-scientific benefit of OOP syntax over > > Algol-style function application syntax is that it's syntactically > > more composable---compare `a.foo().bar().bas()`, which reads > > left-to-right and composes to the right, to `bas(bar(foo(a)))`, which > > reads inside-out and requires bracketing on both sides of an inner > > experssion to compose calls. (Of course this only works if your APIs > > are designed up front in a "fluent" way, and isn't quite as flexible > > as what you can do with combinators in ML or Haskell.) > > I'm a math guy so to me syntax `bas(bar(foo(a)))` is natural. Besides > as you noticed yourself this only work in certain circumstances. For > example when you have additional parameters, the syntax could sometime > be something like `c.bar(a.foo(b)).bas()` which is less readable in my > opinion than `bas(bar(c, foo(a, b)))`. But all this is very > subjective, isn't it ? > > 2012/10/9 Sebastian Sylvan > > > I think there are two other benefits. The first is intellisense/code > > completion. Type "foo." and get a list of all methods in scope with a > > matching self type. This can be a massive productivity boost as it > > basically puts all your code and documentation in the IDE in a context > > sensitive way. Much harder to do this if you have to remember the name > > of the method before you see anything. > > I agree that it's easier to start from a variable existing in the > context rather than from a namespace or from a function name. But > completion does not necessarily have to insert code after the > considered identifier, even if it is indeed more usual. > > > Second, and much more subjectively, I think there's a difference > > between sort of value oriented programming, and the more low level > > mutable programming type where you're dealing with "objects" that have > > identity and complicated invariants. Subjective, but tying the methods > > to the data type in those cases "feels" okay to me because they kinda > > are inseparable in practice, so they might as well be syntactically > > tied together as well (with a more functional style you would group > > them by modules and visibility, but syntactically it doesn't look like > > an indivisible "object" that have a small set hard-wired built in > > methods on it as opposed to a value and a random grab bag of > > operations that happen to have matching types but could be written by > > any old schmuck and not necessarily "part of the object"). > > This is precisely the subjective feeling I don't agree with. This > feeling only exists because you think of processes/functions/methods > as part of a single object rather than interactions between a group of > objects. This is a very "Aristotelician" view. It sometimes work well > (when object can be seen like "active" autonomous entities) but not in > the general case IMHO. > > 2012/10/9 Nathan > > > It does not make sense. Think about a general add interface. It's > > type could be like the following (I am still fuzzy on rust's memory > > location/lifetime type modifiers, so here I assume T is somehow > > copy-by-value): > > > > add( a: T, b: T ) -> T > > > > There's nothing special about a compared to b, and also the return > > type is the same type. If we could generalize this to an interface > > called "Addable", then a single implementation would exist for a given > > type, and there'd be nothing special about which argument position(s) > > have that type. > > Hem ... So this mean we agree right ? My point was precisely that this > does not make sense. The syntax need not to give one of the arguments > a specific role. > > > The common OO idiom you allude to specifically ties interface, data > > accessibility, and namespace together. That's a particular choice. > > You are right that these can be decoupled. > > > > I'm personally a fan of "fewer ways to do it; less flexibility", so I > > like nailing down a namespace and data accessibility for example. Or > > for another example, I'm a fan of "the namespace must correlate > > directly to the file path in some manner" versus having those > > decoupled. > > I may only partly agree. I too prefer Bertrand Meyer's "A programming > language should provide one good way of performing any operation of > interest; it should avoid providing two." to Larry Wall's "There's > more than one way to do it". But this only apply to perfectly > equivalent contructs. If there is several way to do related but > distinct things, I found flexibility better. > > > But that's just me, and I see more flexibility in rust. I'm not > > certain but I think data accessibility may be tied to namespaces > > (which are decoupled from filenames somewhat), as well as types, so > > maybe it already has the flexibility you describe? > > In all the docs I've read until now, the word "private" only appeared > in the section for classes, so I guess no. > > > This is intriguing, but not as general as multi-parameter type > > classes. Consider an interface for two types, A and B, like this: > > > > insert( elem: A, container: B ) -> void; > > peek( container: B ) -> Option; > > > > There's no (A,B) parameter or return type anywhere. That would fit > > into insert(), but it would not make sense for peek, where I have no B > > at hand. > > This is definite the kind of interface/trait I would like to be > express in Rust. But apparently it is not possible with the current > design. > > 2012/10/9 Bennie Kloosteman > > > Multiple parameter are very useful eg a collection and a second type , > > but it gets messy... it works ok provided its in a single compilation > > unit but else you get compilation unit dependency loops ,with generics > > ( which are similar) you can auto generate new libs to handle this > > not sure about rust traits.. > > Hi Ben. I'm not sure to understand the link with compilation loop. Any > previous discussion on this topic? > > So in conclusion, this means multiple parameter traits are not planned > to be implemented in Rust ? right ? > > -- > Eddy Cizeron > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Eddy Cizeron > October 6, 2012 11:14 AM > > Hello, > > I'm new to Rust, and I have some questions concerning some aspects of > the language. From what I understand until now, rust has no dynamic > linkage for methods as it would be the case in any standard OOP > language. This is surely an intentionaly different philosophy from the > current trend among other recent programming languages. But why not > after all. I like the idea. So I find myself skeptical when I read the > chapters of the documentation about OOP-like concepts like classes or > interfaces. > > The essence of the "class" concept lies in the possibility to gather a > data structure (a type) and the related processes that can act on the > corresponding instances (methods) in a single bundle. But, tell me if > you disagree, the only interesting purpose of such an operation is the > ability to use inheritance. If no concept of inheritance exists, I > hardly see what is the need of making functions "pets" for data. All > we obtain are classical design issues like "is my 'f(a,b)' function a > 'a.f(b)' method or a 'b.f(a)' method ?" (and I don't think the rust > "resource" concept requires classes, as destructors or destructor-like > functions are not methods). I'm afraid that the answer is merely to > offer a supposedly "attractive" syntax for OOP users. And I think this > would be a weak argument > > The concept of interface/implementation in rust is surely different > than the usual one, but again to me it looks like it has some > limitations due to the same reason than above: it tries to look OOP. I > could have imagined a very similar interface concept but that does not > focus on a *single *type: > > iface shape_drawing { > fn draw(Sf, Sh); > fn bounding_box(Sh) -> bounding_box; > } > > fn draw_twice>(surface: Sf, shape: Sh) { > draw(surface, shape); > draw(surface, shape); > } > > Of course this example is a simple one. And any consistent system like > this (if it does exist but I'm pretty sure it does) would have been > more complex than the current one. But also more general and then more > powerful. > > Let me clear about something: I don't expect anybody to change the > current design. I'm nobody and I know it's always easier to criticize > than to do things. I'm just expressing the feeling that while Rust > tried to take a different direction from all the other new > JVM-compliant-OOP-languages-with-functional-features (which I really > really value very much) it seems it has not got rid of some conceptual > patterns that are not, IMHO, necessary anymore. And I wish people > could give their opinion about this. > > Thank you > > -- > Eddy Cizeron > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: From niko at alum.mit.edu Wed Oct 10 21:44:11 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 10 Oct 2012 21:44:11 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: <507647A0.9000401@alum.mit.edu> References: <507647A0.9000401@alum.mit.edu> Message-ID: <50764E9B.9030705@alum.mit.edu> Niko Matsakis wrote: > Based on our last meeting, there seems to be general agreement towards > a system that allows methods to be imported as standalone functions > that take the receiver as first argument as well [1]. Actually, it occurs to me that we only discussed these kinds of imports in the context of static fns. But in any case I am a fan of permitting any function defined in an impl to be imported and used as a standalone function, and I think I am not alone in this. =) Niko From bklooste at gmail.com Wed Oct 10 22:22:01 2012 From: bklooste at gmail.com (Bennie Kloosteman) Date: Thu, 11 Oct 2012 13:22:01 +0800 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: <50764E9B.9030705@alum.mit.edu> References: <507647A0.9000401@alum.mit.edu> <50764E9B.9030705@alum.mit.edu> Message-ID: Niko , what about the performance of these polymorphic functions ? Even C++ virtual calls bite when you have calls to a different compilation unit compared to a good java run time ( mainly due to polymorphic inline caches). And how do you handle module traits there are some nasty issue here with Haskell. You still confident you can avoid the OO issues bitC hit when they tried to add OO calls to traits eg http://www.coyotos.org/pipermail/bitc-dev/2012-March/003300.html Ben On Thu, Oct 11, 2012 at 12:44 PM, Niko Matsakis wrote: > > > Niko Matsakis wrote: > >> Based on our last meeting, there seems to be general agreement towards a >> system that allows methods to be imported as standalone functions that take >> the receiver as first argument as well [1]. >> > > Actually, it occurs to me that we only discussed these kinds of imports in > the context of static fns. But in any case I am a fan of permitting any > function defined in an impl to be imported and used as a standalone > function, and I think I am not alone in this. =) > > > Niko > > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Thu Oct 11 06:20:03 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 11 Oct 2012 06:20:03 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: <507647A0.9000401@alum.mit.edu> <50764E9B.9030705@alum.mit.edu> Message-ID: <5076C783.4030801@alum.mit.edu> You are correct that using a virtual table does incur some runtime cost. That's one of the reasons we chose to offer the option of using bounded generics as an alternative, since (due to monomorphization) this implies no vtable. For example: trait SomeTrait { fn method(); } // Uses a vtable: dynamic dispatch fn foo(x: &SomeTrait) { x.method(); } // Does not use a vtable: static dispatch fn foo(x: &T) { x.method(); } So in your inner loop, you may want to stick to bounded generics. (Of course, it would be possible for a C++ or Rust compiler to emit code with PICs. However, that implies a rather larger runtime, and we are generally shooting for less runtime.) I am not sure which "OO issues" you are referring to from that e-mail precisely, but I do believe our design addresses many (if not all) of the points that Shapiro raised. Niko > Bennie Kloosteman > October 10, 2012 10:22 PM > Niko , what about the performance of these polymorphic functions ? > Even C++ virtual calls bite when you have calls to a different > compilation unit compared to a good java run time ( mainly due to > polymorphic inline caches). > And how do you handle module traits there are some nasty issue here > with Haskell. > > You still confident you can avoid the OO issues bitC hit when they > tried to add OO calls to traits eg > > http://www.coyotos.org/pipermail/bitc-dev/2012-March/003300.html > > Ben > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Niko Matsakis > October 10, 2012 9:14 PM > For what it's worth, Sebastian, Simon Peyton Jones agrees with you: > > http://research.microsoft.com/en-us/um/people/simonpj/papers/haskell-retrospective/ > > (Skip ahead to page 56, he talks specifically about its use in > intellisense, calling it "the power of the dot"). > > To me, there is another very important point regarding dot notation > that I didn't see mentioned yet: it enables name resolution on a > per-type basis. In Haskell, if I want to have to have something like > "foo.context()" and "bar.context()" where the context of a foo has one > type and bar has another, it's a big pain and I have to use import > qualified or something crazy like that. In OOP this is no issue. And > I find this very natural. > > Anyway, I think the design of the trait system is very much going > towards a "best of both worlds" direction. You can define methods and > you can define standalone functions. Based on our last meeting, there > seems to be general agreement towards a system that allows methods to > be imported as standalone functions that take the receiver as first > argument as well [1]. Like most modern languages---including > Haskell, Java, and C#---we support both parametric polymorphism > (bounded generics) and ad-hoc polymorphism (trait types). Both have > their place, after all. > > So basically there is no conflict here. You use the right tool for > the job. > > > Niko > > [1] As initially proposed here: > https://mail.mozilla.org/pipermail/rust-dev/2012-August/002255.html > > Sebastian Sylvan > October 10, 2012 6:01 PM > > That would indeed be pretty unusual. Worse, it's how you write code > normally. If function applications start with the name of the function > and not the variable, then you have to decide before you even start > that you want to invoke the "code completion feature" on this next > expression, *skip* writing the function name (or put in some kind of > placholder) and instad write the variable you want to act on combined > with some magic incantation to make the IDE let you select and then > pre-inject the function name in front of it. In an OOP style syntax > you just write code like you're used to and the IDE just discretely > flashes up little tool tips and lists of members to gently nudge you > along your way (or allow you to short cut some typing) as you go about > your normal coding. You don't need to do anything special, it's just > constantly there if you need it, and can be ignored if you don't. > > I really can't stress enough what a force multipler it is to write > code in an IDE with powerful code completion for someone who has > internalized it into their workflow. I know real men use VIM etc., but > I'm secure enough to admit that I am more productive in the actual > coding phase using C# with Intellisense in VS than Haskell + Emacs or > whatever, even though I recognize that on language merit alone it > should be the other way around by far. Tooling matters so much these > days. Arguably more than a lot of language semantics, and certainly > more than worrying about slight syntactic redundancy, IMO. > > Eddy Cizeron > October 10, 2012 3:49 PM > > 2012/10/9 Lindsey Kuper > > > And, in case nobody has pointed them out yet, here are a couple more > resources: > > * An introduction to traits on Patrick's blog: > http://pcwalton.github.com/blog/2012/08/08/a-gentle-introduction-to-traits-in-rust > > * A talk I did in August, with a side-by-side Haskell/Rust > > comparison: https://air.mozilla.org/rust-typeclasses > > Cheers, > > Thank you for the references Lindsey. > > 2012/10/9 Joe Groff > > > One minor non-semantic, non-scientific benefit of OOP syntax over > > Algol-style function application syntax is that it's syntactically > > more composable---compare `a.foo().bar().bas()`, which reads > > left-to-right and composes to the right, to `bas(bar(foo(a)))`, which > > reads inside-out and requires bracketing on both sides of an inner > > experssion to compose calls. (Of course this only works if your APIs > > are designed up front in a "fluent" way, and isn't quite as flexible > > as what you can do with combinators in ML or Haskell.) > > I'm a math guy so to me syntax `bas(bar(foo(a)))` is natural. Besides > as you noticed yourself this only work in certain circumstances. For > example when you have additional parameters, the syntax could sometime > be something like `c.bar(a.foo(b)).bas()` which is less readable in my > opinion than `bas(bar(c, foo(a, b)))`. But all this is very > subjective, isn't it ? > > 2012/10/9 Sebastian Sylvan > > > I think there are two other benefits. The first is intellisense/code > > completion. Type "foo." and get a list of all methods in scope with a > > matching self type. This can be a massive productivity boost as it > > basically puts all your code and documentation in the IDE in a context > > sensitive way. Much harder to do this if you have to remember the name > > of the method before you see anything. > > I agree that it's easier to start from a variable existing in the > context rather than from a namespace or from a function name. But > completion does not necessarily have to insert code after the > considered identifier, even if it is indeed more usual. > > > Second, and much more subjectively, I think there's a difference > > between sort of value oriented programming, and the more low level > > mutable programming type where you're dealing with "objects" that have > > identity and complicated invariants. Subjective, but tying the methods > > to the data type in those cases "feels" okay to me because they kinda > > are inseparable in practice, so they might as well be syntactically > > tied together as well (with a more functional style you would group > > them by modules and visibility, but syntactically it doesn't look like > > an indivisible "object" that have a small set hard-wired built in > > methods on it as opposed to a value and a random grab bag of > > operations that happen to have matching types but could be written by > > any old schmuck and not necessarily "part of the object"). > > This is precisely the subjective feeling I don't agree with. This > feeling only exists because you think of processes/functions/methods > as part of a single object rather than interactions between a group of > objects. This is a very "Aristotelician" view. It sometimes work well > (when object can be seen like "active" autonomous entities) but not in > the general case IMHO. > > 2012/10/9 Nathan > > > It does not make sense. Think about a general add interface. It's > > type could be like the following (I am still fuzzy on rust's memory > > location/lifetime type modifiers, so here I assume T is somehow > > copy-by-value): > > > > add( a: T, b: T ) -> T > > > > There's nothing special about a compared to b, and also the return > > type is the same type. If we could generalize this to an interface > > called "Addable", then a single implementation would exist for a given > > type, and there'd be nothing special about which argument position(s) > > have that type. > > Hem ... So this mean we agree right ? My point was precisely that this > does not make sense. The syntax need not to give one of the arguments > a specific role. > > > The common OO idiom you allude to specifically ties interface, data > > accessibility, and namespace together. That's a particular choice. > > You are right that these can be decoupled. > > > > I'm personally a fan of "fewer ways to do it; less flexibility", so I > > like nailing down a namespace and data accessibility for example. Or > > for another example, I'm a fan of "the namespace must correlate > > directly to the file path in some manner" versus having those > > decoupled. > > I may only partly agree. I too prefer Bertrand Meyer's "A programming > language should provide one good way of performing any operation of > interest; it should avoid providing two." to Larry Wall's "There's > more than one way to do it". But this only apply to perfectly > equivalent contructs. If there is several way to do related but > distinct things, I found flexibility better. > > > But that's just me, and I see more flexibility in rust. I'm not > > certain but I think data accessibility may be tied to namespaces > > (which are decoupled from filenames somewhat), as well as types, so > > maybe it already has the flexibility you describe? > > In all the docs I've read until now, the word "private" only appeared > in the section for classes, so I guess no. > > > This is intriguing, but not as general as multi-parameter type > > classes. Consider an interface for two types, A and B, like this: > > > > insert( elem: A, container: B ) -> void; > > peek( container: B ) -> Option; > > > > There's no (A,B) parameter or return type anywhere. That would fit > > into insert(), but it would not make sense for peek, where I have no B > > at hand. > > This is definite the kind of interface/trait I would like to be > express in Rust. But apparently it is not possible with the current > design. > > 2012/10/9 Bennie Kloosteman > > > Multiple parameter are very useful eg a collection and a second type , > > but it gets messy... it works ok provided its in a single compilation > > unit but else you get compilation unit dependency loops ,with generics > > ( which are similar) you can auto generate new libs to handle this > > not sure about rust traits.. > > Hi Ben. I'm not sure to understand the link with compilation loop. Any > previous discussion on this topic? > > So in conclusion, this means multiple parameter traits are not planned > to be implemented in Rust ? right ? > > -- > Eddy Cizeron > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Eddy Cizeron > October 6, 2012 11:14 AM > > Hello, > > I'm new to Rust, and I have some questions concerning some aspects of > the language. From what I understand until now, rust has no dynamic > linkage for methods as it would be the case in any standard OOP > language. This is surely an intentionaly different philosophy from the > current trend among other recent programming languages. But why not > after all. I like the idea. So I find myself skeptical when I read the > chapters of the documentation about OOP-like concepts like classes or > interfaces. > > The essence of the "class" concept lies in the possibility to gather a > data structure (a type) and the related processes that can act on the > corresponding instances (methods) in a single bundle. But, tell me if > you disagree, the only interesting purpose of such an operation is the > ability to use inheritance. If no concept of inheritance exists, I > hardly see what is the need of making functions "pets" for data. All > we obtain are classical design issues like "is my 'f(a,b)' function a > 'a.f(b)' method or a 'b.f(a)' method ?" (and I don't think the rust > "resource" concept requires classes, as destructors or destructor-like > functions are not methods). I'm afraid that the answer is merely to > offer a supposedly "attractive" syntax for OOP users. And I think this > would be a weak argument > > The concept of interface/implementation in rust is surely different > than the usual one, but again to me it looks like it has some > limitations due to the same reason than above: it tries to look OOP. I > could have imagined a very similar interface concept but that does not > focus on a *single *type: > > iface shape_drawing { > fn draw(Sf, Sh); > fn bounding_box(Sh) -> bounding_box; > } > > fn draw_twice>(surface: Sf, shape: Sh) { > draw(surface, shape); > draw(surface, shape); > } > > Of course this example is a simple one. And any consistent system like > this (if it does exist but I'm pretty sure it does) would have been > more complex than the current one. But also more general and then more > powerful. > > Let me clear about something: I don't expect anybody to change the > current design. I'm nobody and I know it's always easier to criticize > than to do things. I'm just expressing the feeling that while Rust > tried to take a different direction from all the other new > JVM-compliant-OOP-languages-with-functional-features (which I really > really value very much) it seems it has not got rid of some conceptual > patterns that are not, IMHO, necessary anymore. And I wish people > could give their opinion about this. > > Thank you > > -- > Eddy Cizeron > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: postbox-contact.jpg Type: image/jpeg Size: 1206 bytes Desc: not available URL: From bklooste at gmail.com Thu Oct 11 07:26:59 2012 From: bklooste at gmail.com (Bennie Kloosteman) Date: Thu, 11 Oct 2012 22:26:59 +0800 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: <5076C783.4030801@alum.mit.edu> References: <507647A0.9000401@alum.mit.edu> <50764E9B.9030705@alum.mit.edu> <5076C783.4030801@alum.mit.edu> Message-ID: On Thu, Oct 11, 2012 at 9:20 PM, Niko Matsakis wrote: > > You are correct that using a virtual table does incur some runtime cost. > > That's one of the reasons we chose to offer the option of using bounded generics as an alternative, since (due to monomorphization) this implies no vtable. For example: > > trait SomeTrait { fn method(); } > > // Uses a vtable: dynamic dispatch > fn foo(x: &SomeTrait) { x.method(); } > > // Does not use a vtable: static dispatch > fn foo(x: &T) { x.method(); } > > So in your inner loop, you may want to stick to bounded generics. (Of course, it would be possible for a C++ or Rust compiler to emit code with PICs. However, that implies a rather larger runtime, and we are generally shooting for less runtime.) And your VT will be an array which also has bound checking so performance will be worse than C++. This is not bad but clearly for Rust 90% of the time you want to use generics rather than OO . > > > I am not sure which "OO issues" you are referring to from that e-mail precisely, but I do believe our design addresses many (if not all) of the points that Shapiro raised. 1.Specifically the Instance Coherence problem The last (instance coherence) does not appear to admit any general solution, and it raises conceptual concerns about the use of type classes for method overload in my mind. 2.*The type class notion (more precisely: qualified types) is seductive, but absent a reasonable approach for instance coherence and lexical resolution it provides an unsatisfactory basis for operator overloading. There is a disturbingly close relationship between type class instances and object instances that needs further exploration by the PL community. The important distinction may be pragmatic rather than conceptual: type class instances are compile-time constants while object instances are run-time values. This has no major consequences for typing, but it leads to significant differences w.r.t. naming, binding, and [human] conceptualization.* * The human conceptualization is the difficult one. 3.And the VT Table ( which needs a this pointer) And introducing SelfType was an even bigger issue than introducing subtypes. It means moving out of System F<: entirely, and into the object type system of Cardelli *et al*. That wasn't just a matter of re-implementing the type checker to support a variant of the type system we already had. It meant re-formalizing the type system entirely, and learning how to think in a different model. 4.and the sections *Instance Coherence and Operator Overloading* *Conclusion about Type Classes and Overloading*: Ben Ben From pwalton at mozilla.com Thu Oct 11 08:56:50 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 11 Oct 2012 08:56:50 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: <507647A0.9000401@alum.mit.edu> <50764E9B.9030705@alum.mit.edu> <5076C783.4030801@alum.mit.edu> Message-ID: <5076EC42.3060609@mozilla.com> On 10/11/12 7:26 AM, Bennie Kloosteman wrote: > And your VT will be an array which also has bound checking so > performance will be worse than C++. No. Patrick From matthieu.monrocq at gmail.com Thu Oct 11 10:35:49 2012 From: matthieu.monrocq at gmail.com (Matthieu Monrocq) Date: Thu, 11 Oct 2012 19:35:49 +0200 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: <5076EC42.3060609@mozilla.com> References: <507647A0.9000401@alum.mit.edu> <50764E9B.9030705@alum.mit.edu> <5076C783.4030801@alum.mit.edu> <5076EC42.3060609@mozilla.com> Message-ID: On Thu, Oct 11, 2012 at 5:56 PM, Patrick Walton wrote: > On 10/11/12 7:26 AM, Bennie Kloosteman wrote: > >> And your VT will be an array which also has bound checking so >> performance will be worse than C++. >> > > No. > > Patrick > Expanding on the No: the VT dimensions and all the indexes are known at compile-time, there is no reason to have runtime checks on them. -- Matthieu -------------- next part -------------- An HTML attachment was scrubbed... URL: From graydon at mozilla.com Thu Oct 11 16:19:50 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 11 Oct 2012 16:19:50 -0700 Subject: [rust-dev] Rust philosophy and OOP In-Reply-To: References: <507647A0.9000401@alum.mit.edu> <50764E9B.9030705@alum.mit.edu> <5076C783.4030801@alum.mit.edu> Message-ID: <50775416.7080307@mozilla.com> On 12-10-11 07:26 AM, Bennie Kloosteman wrote: > 1.Specifically the Instance Coherence problem Yes, over the course of the spring and summer we moved Rust towards a set of instance-coherence rules specifically chosen to balance difficulties BitC encountered (and that Haskell and other languages have themselves confronted and chosen ad-hoc rules to solve). It's a balancing act but we think we have a good set of rules here. We had an _ok_ set of rules before, too, but the ones we moved to this summer seem to be working out even better. For some background, see Patrick's blog: http://pcwalton.github.com/blog/2012/05/28/coherence/ > 2.*The type class notion (more precisely: qualified types) is seductive, but > absent a reasonable approach for instance coherence and lexical resolution > it provides an unsatisfactory basis for operator overloading. There is a > disturbingly close relationship between type class instances and object > instances that needs further exploration by the PL community. The important > distinction may be pragmatic rather than conceptual: type class instances > are compile-time constants while object instances are run-time values. This > has no major consequences for typing, but it leads to significant > differences w.r.t. naming, binding, and [human] conceptualization.* As we've stated, Rust traits are both available as compile-time an runtime entities, from the same definition. This is a trick that Marijn stumbled onto last year. If you treat a trait name as a type and cast a pointer to a runtime value implementing that trait to a pointer to the trait type, you are given a vtable-pointer on which to perform dynamic dispatch to the implementation. Alternatively, if you use the trait name as a static type bound in a polymorphic function, the function is statically specialized to the implementation type at the call site, and there's no runtime cost. This all seems to work very well in practice. I'm not sure what all the rest of the ominous language in this paragraph refers to; in general I'd appreciate if you could try to ask specific questions or pose specific suggestions. Much of this thread is too vague to either answer or take any action on, thus nonproductive. > 3.And the VT Table ( which needs a this pointer) Only when you are doing dynamic dispatch. Most uses of traits appear to be as static type bounds, which wind up statically dispatching (and specializing, inlining). > And introducing SelfType was an even bigger issue than introducing > subtypes. It means moving out of System F<: entirely, and into the object > type system of Cardelli *et al*. Rust's use of 'self' is much, much more conservative than a Cardelli-Abadi object calculus. It does not support any such subtyping relationship on the 'self' type as those calculi are striving for. In Rust, 'self' is only ever treated as the opaque pointer+vtable pair to a specific trait (without subtyping) or as a syntactic placeholder which is replaced by an _exact_ implementation type (again without subtyping) when instantiating a trait. Neither of these contexts demand Cardelli-Abadi self-types. > *Instance Coherence and Operator Overloading* This is just a restatement of the instance-coherence problem, with a further vague implication that if you want very rich forms of overloading, it is slightly more pervasive a problem. Rust is quite conservative on operator overloading, and it doesn't seem to be any worse than any other context of instance coherence enforcement. (Please note that even in that section, he shows that haskell and C++ are both quite able to accommodate these issues by adopting certain compromises, they don't fundamentally fail as languages due to the tradeoffs they adopt. We have done the same. Shipping a language that works is more important to us than making one that can do everything.) > *Conclusion about Type Classes and Overloading*: This paragraph is the one you pasted in above under '2.* the type class notion'; I responded up there. -Graydon From dherman at mozilla.com Thu Oct 11 22:34:37 2012 From: dherman at mozilla.com (David Herman) Date: Thu, 11 Oct 2012 22:34:37 -0700 Subject: [rust-dev] Update to Tutorial In-Reply-To: <506E0CCE.4040907@mozilla.com> References: <506E0CCE.4040907@mozilla.com> Message-ID: On Oct 4, 2012, at 3:25 PM, Brian Anderson wrote: > As a side note, we should do more with the Twitter account so it doesn't appear that we are dead. If I can get the credentials to the account I'll be happy to share the responsibility for tweeting updates. Dave From pwalton at mozilla.com Fri Oct 12 10:41:47 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Fri, 12 Oct 2012 10:41:47 -0700 Subject: [rust-dev] RFC: All extern "C" functions are unsafe Message-ID: <5078565B.1030402@mozilla.com> This is bug #2628: https://github.com/mozilla/rust/issues/2628 After hacking on Servo I feel very strongly about this now. The vast majority of exploitable crashes are in code that Rust considers safe. In fact, I feel that if we *don't* do this, then we aren't any safer than C++ in a practical sense, despite all our efforts. A security auditor has to consider whether the target of every single call expression in safe or unsafe code could possibly alias an extern "C" function. Patrick From banderson at mozilla.com Fri Oct 12 11:38:34 2012 From: banderson at mozilla.com (Brian Anderson) Date: Fri, 12 Oct 2012 11:38:34 -0700 Subject: [rust-dev] RFC: All extern "C" functions are unsafe In-Reply-To: <5078565B.1030402@mozilla.com> References: <5078565B.1030402@mozilla.com> Message-ID: <507863AA.9040406@mozilla.com> On 10/12/2012 10:41 AM, Patrick Walton wrote: > This is bug #2628: https://github.com/mozilla/rust/issues/2628 > > After hacking on Servo I feel very strongly about this now. The vast > majority of exploitable crashes are in code that Rust considers safe. In > fact, I feel that if we *don't* do this, then we aren't any safer than > C++ in a practical sense, despite all our efforts. A security auditor > has to consider whether the target of every single call expression in > safe or unsafe code could possibly alias an extern "C" function. > +2 From dlacewell at gmail.com Fri Oct 12 12:05:01 2012 From: dlacewell at gmail.com (Dustin Lacewell) Date: Fri, 12 Oct 2012 14:05:01 -0500 Subject: [rust-dev] Composition in Rust ( and Go ) Message-ID: $ rust_question -vvvv I have some questions regarding the future of traits and their intended usage. Let me preface this post with the information that I am a decade old Python programmer and have little experience with static-typed languages and language academics in general so please bare with me if I exhibit any fundamental ignorance about the topics here. I began my discovery of Rust while looking at Go. I soon started to experiment with Go's structure embedding and interfaces and attempted to draft an experiment in object composition. In the following contrived example, we will attempt to build up a struct type that has a two-dimensional position and some "mix-ins" that provide functionality that work upon that position. In Go, one may embed structs within each other and the containing or parent struct "inherits" all fields and methods of embedded types. First, we define a basic struct called Position that implements an interface Positioned. You'll notice the interface essentially covers the Position type's getter/setter methods. This is the only way (that I know of) to enforce that a Positioned type has the right fields, in Go. package main import "fmt" type Positioned interface { X() int Y() int SetX(x int) SetY(y int) } type Position struct { x, y int } func (self *Position) X() int { return self.x } func (self *Position) Y() int { return self.y } func (self *Position) SetX(x int) { self.x = x } func (self *Position) SetY(y int) { self.y = y } Now we create two more empty struct types with corresponding interfaces called Renderer/Renderable and Mover/Movable. These represent components that depend and work upon a Positioned type. The important thing to note here, is that both Render() and Move() must take a reference to an externally provided Position reference. This will be explained below. type Renderable interface { Positioned Render(*Position) } type Renderer struct {} func (self *Renderer) Render (pos *Position) { fmt.Println("Rendered at,", pos.X(), pos.Y()) } type Movable interface { Positioned Move(pos *Position, dx, dy int) } type Mover struct {} func (self *Mover) Move (pos *Position, x, y int) { pos.SetX(pos.X() + x) pos.SetY(pos.Y() + y) fmt.Println("Moved to,", pos.X(), pos.Y()) } Lastly, we define our composite type Entity which embeds the Position, Renderer and Mover types. This grants Entity all the fields and methods of those types such as .pos and .Render() We show a basic main function that creates an Entity and its embedded structs and then calls the methods now available to the Entity type: type Entity struct { Position Renderer Mover } func main() { e := Entity { Position { x:0, y:0 }, Renderer{}, Mover{}, } e.Move(&e.Position, 20, 35) e.Render(&e.Position) } A runnable example of this is available here: http://play.golang.org/p/gCu91h9BqQ This is all fine and dandy. However some abrasive qualties of this example seem readily apparent to me. For one, even though the apparent intention of this code is to create a composite type that is Positioned, Renderable and Movable it ends up being quite cludgy. The biggest problem I see is that the "shared state" of the Position which Renderer and Mover depend on must be explicitly passed around when used with the composite type. One alternative is to wrap these methods in overrides in Entity to hide this apparently manual boilerplate. An updated example is here: http://play.golang.org/p/uD5gCihUKL Two wrapper methods are supplied for Entity: func (self *Entity) Move (x, y int) { self.Mover.Move(&self.Position, x, y) } func (self *Entity) Render () { self.Renderer.Render(&self.Position) } This allows the external interface for Entity to be much more natural and encapsulated: func main() { e := Entity { Position { x:0, y:0 }, Renderer{}, Mover{}, } e.Move(20, 35) e.Render() } What is the purpose of these two wrapper methods? They are, as far as I can tell, required invariant boilerplate. Invariant in that nothing changes about what I'm doing. Any sort of inter-dependency between constituent components in composed types will require this explicit passing of the shared state. The genesis of this problem is a detail with how methods are bound to types in Go. We can see that in the Render method of Renderer, we define the "method receiver" as (self *Renderer) func (self *Renderer) Render (pos *Position) { fmt.Println("Rendered at,", pos.X(), pos.Y()) } Okay. So Render() is a method that is available on Renderer pointers. But Go tricks us, in that we can embed a Renderer inside of another struct like Entity and Entity will gain the Render() method except that when you call Entity.Render, you are really called Entity.Renderer.Render. When the method is invoked the `self` receiver is still the Renderer. Once can imagine that if methods bound to structs that are embedded have their method reciever updated to be the parent struct instance then this no becomes a problem. The method should still be able to work upon the parent struct becuase it has recieved all of the fields and members of the original type. Here is what the program looks like in this imaginary version of Go: http://play.golang.org/p/8MbDFj-G8m It does not compile obviously, but the Render() and Move() methods are now much more natural in that they work upon the `self` name instead of an explicitly passed in Position reference. func (self *Renderer) Render () { fmt.Println("Rendered at,", self.X(), self.Y()) } func (self *Mover) Move (x, y int) { self.SetX(self.X() + x) self.SetY(self.Y() + y) fmt.Println("Moved to,", self.X(), self.Y()) } Alarms may now being going off, that the compiler will have no idea that the self receiver implements the X() and Y() methods, because self here is defined as Renderers and Movers. I understand this. One imagines that Go would need to add some sort of interface requirements or even allow the binding of methods to interfaces. func (self *Positioned) Render() {} would solve this problem entirely, I think. At this point, I put down Go and started looking elsewhere. I came across Rust. I found that trait look more like a proper object composition system, however Rust being so young somethings are either not implemented or not decided upon. The rest of what I'm going to say largely depends on Lindsey Kuper's work to unify typeclasses and traits: https://github.com/mozilla/rust/wiki/Proposal-for-unifying-traits-and-interfaces https://mail.mozilla.org/pipermail/rust-dev/2012-August/002276.html https://air.mozilla.org/rust-typeclasses/ I have begun to construct an example of the same contrived program. In current Rust, I believe this is as close as I can get. However, you'll notice that Renderable and Movable are now just plain-ol "interfaces" and the implmentation of Entity does all of the work implementing Render() and Move() itself: http://dpaste.com/hold/812966/ Assuming that I understand the little amount of information available on train "provided" and "required" methods and how those work, I can envision an update to the snippet. In this version, the traits are now supplying "provided" or "default" method implementations that work upon an explicitly passed `self` parameter. Not only do the Renderable and Movable traits provide methods they also declare field requirements for any type using the trait. In this example, if you're going to implement Movable for a type, it has to have mutable integer fields called "x" and "y": http://dpaste.com/812972/ The one thing here I'm making up, is the embedding of the Point struct into the Entity struct which with minimal effort allows the Entity to satisfy the field requirements of the traits by taking on the fields of the Point struct. Now each struct that would like to implement Renderable and Movable do not need to define their own individual fields but can just embed another struct that qualifies for the traits the composed type wants to use. If struct embedding is entirely out of the question, then the Renderable and Movable traits can simply require a pointer-to-a-position field which is only slightly less handy. So in the end, I suppose I'm looking for some advice as to whether I have interpreted the direction of traits, Lindsey's work, how idiomatic object composition and code reuse patters are intended to work in Rust. -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Fri Oct 12 12:29:49 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Fri, 12 Oct 2012 12:29:49 -0700 Subject: [rust-dev] RFC: All extern "C" functions are unsafe In-Reply-To: <507863AA.9040406@mozilla.com> References: <5078565B.1030402@mozilla.com> <507863AA.9040406@mozilla.com> Message-ID: <50786FAD.9020701@alum.mit.edu> +1 (one developer, one vote!) ;) > Brian Anderson > October 12, 2012 11:38 AM > > > +2 > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Patrick Walton > October 12, 2012 10:41 AM > This is bug #2628: https://github.com/mozilla/rust/issues/2628 > > After hacking on Servo I feel very strongly about this now. The vast > majority of exploitable crashes are in code that Rust considers safe. > In fact, I feel that if we *don't* do this, then we aren't any safer > than C++ in a practical sense, despite all our efforts. A security > auditor has to consider whether the target of every single call > expression in safe or unsafe code could possibly alias an extern "C" > function. > > Patrick > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: From graydon at mozilla.com Fri Oct 12 13:43:27 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 12 Oct 2012 13:43:27 -0700 Subject: [rust-dev] RFC: All extern "C" functions are unsafe In-Reply-To: <507863AA.9040406@mozilla.com> References: <5078565B.1030402@mozilla.com> <507863AA.9040406@mozilla.com> Message-ID: <507880EF.4010406@mozilla.com> On 12-10-12 11:38 AM, Brian Anderson wrote: > On 10/12/2012 10:41 AM, Patrick Walton wrote: >> This is bug #2628: https://github.com/mozilla/rust/issues/2628 >> >> After hacking on Servo I feel very strongly about this now. The vast >> majority of exploitable crashes are in code that Rust considers safe. In >> fact, I feel that if we *don't* do this, then we aren't any safer than >> C++ in a practical sense, despite all our efforts. A security auditor >> has to consider whether the target of every single call expression in >> safe or unsafe code could possibly alias an extern "C" function. >> > > +2 Yeah, I think I agree with this. It's a burden, but I think it's the correct one. C calls need to be handled as the sharp instruments they are. -Graydon From banderson at mozilla.com Sat Oct 13 14:57:47 2012 From: banderson at mozilla.com (Brian Anderson) Date: Sat, 13 Oct 2012 14:57:47 -0700 Subject: [rust-dev] Composition in Rust ( and Go ) In-Reply-To: References: Message-ID: <5079E3DB.7040701@mozilla.com> On 10/12/2012 12:05 PM, Dustin Lacewell wrote: > $ rust_question -vvvv > > I have some questions regarding the future of traits and their > intended usage. Let me preface this post with the information that I > am a decade old Python programmer and have little experience with > static-typed languages and language academics in general so please > bare with me if I exhibit any fundamental ignorance about the topics here. > > I began my discovery of Rust while looking at Go. I soon started to > experiment with Go's structure embedding and interfaces and attempted > to draft an experiment in object composition. In the following > contrived example, we will attempt to build up a struct type that has > a two-dimensional position and some "mix-ins" that provide > functionality that work upon that position. In Go, one may embed > structs within each other and the containing or parent struct > "inherits" all fields and methods of embedded types. > > First, we define a basic struct called Position that implements an > interface Positioned. You'll notice the interface essentially covers > the Position type's getter/setter methods. This is the only way (that > I know of) to enforce that a Positioned type has the right fields, in Go. > > package main > > import "fmt" > > type Positioned interface { > X() int > Y() int > SetX(x int) > SetY(y int) > } > > type Position struct { > x, y int > } > > func (self *Position) X() int { return self.x } > func (self *Position) Y() int { return self.y } > func (self *Position) SetX(x int) { self.x = x } > func (self *Position) SetY(y int) { self.y = y } > > Now we create two more empty struct types with corresponding > interfaces called Renderer/Renderable and Mover/Movable. These > represent components that depend and work upon a Positioned type. The > important thing to note here, is that both Render() and Move() must > take a reference to an externally provided Position reference. This > will be explained below. > > type Renderable interface { > Positioned > Render(*Position) > } > > type Renderer struct {} > > func (self *Renderer) Render (pos *Position) { > fmt.Println("Rendered at,", pos.X(), pos.Y()) > } > > type Movable interface { > Positioned > Move(pos *Position, dx, dy int) > } > > type Mover struct {} > > func (self *Mover) Move (pos *Position, x, y int) { > pos.SetX(pos.X() + x) > pos.SetY(pos.Y() + y) > fmt.Println("Moved to,", pos.X(), pos.Y()) > } > > Lastly, we define our composite type Entity which embeds the Position, > Renderer and Mover types. This grants Entity all the fields and > methods of those types such as .pos and .Render() We show a basic main > function that creates an Entity and its embedded structs and then > calls the methods now available to the Entity type: > > type Entity struct { > Position > Renderer > Mover > } > > func main() { > e := Entity { > Position { x:0, y:0 }, > Renderer{}, Mover{}, > } > e.Move(&e.Position, 20, 35) > e.Render(&e.Position) > } > > A runnable example of this is available here: > http://play.golang.org/p/gCu91h9BqQ > > This is all fine and dandy. However some abrasive qualties of this > example seem readily apparent to me. For one, even though the apparent > intention of this code is to create a composite type that is > Positioned, Renderable and Movable it ends up being quite cludgy. The > biggest problem I see is that the "shared state" of the Position which > Renderer and Mover depend on must be explicitly passed around when > used with the composite type. One alternative is to wrap these methods > in overrides in Entity to hide this apparently manual boilerplate. An > updated example is here: http://play.golang.org/p/uD5gCihUKL > > Two wrapper methods are supplied for Entity: > > func (self *Entity) Move (x, y int) { > self.Mover.Move(&self.Position, x, y) > } > > func (self *Entity) Render () { > self.Renderer.Render(&self.Position) > } > > > This allows the external interface for Entity to be much more natural > and encapsulated: > > > func main() { > e := Entity { > Position { x:0, y:0 }, > Renderer{}, Mover{}, > } > e.Move(20, 35) > e.Render() > } > > What is the purpose of these two wrapper methods? They are, as far as > I can tell, required invariant boilerplate. Invariant in that nothing > changes about what I'm doing. Any sort of inter-dependency between > constituent components in composed types will require this explicit > passing of the shared state. The genesis of this problem is a detail > with how methods are bound to types in Go. We can see that in the > Render method of Renderer, we define the "method receiver" as (self > *Renderer) > > func (self *Renderer) Render (pos *Position) { > fmt.Println("Rendered at,", pos.X(), pos.Y()) > } > > Okay. So Render() is a method that is available on Renderer pointers. > But Go tricks us, in that we can embed a Renderer inside of another > struct like Entity and Entity will gain the Render() method except > that when you call Entity.Render, you are really called > Entity.Renderer.Render. When the method is invoked the `self` receiver > is still the Renderer. Once can imagine that if methods bound to > structs that are embedded have their method reciever updated to be the > parent struct instance then this no becomes a problem. The method > should still be able to work upon the parent struct becuase it has > recieved all of the fields and members of the original type. Here is > what the program looks like in this imaginary version of Go: > http://play.golang.org/p/8MbDFj-G8m > > It does not compile obviously, but the Render() and Move() methods are > now much more natural in that they work upon the `self` name instead > of an explicitly passed in Position reference. > > func (self *Renderer) Render () { > fmt.Println("Rendered at,", self.X(), self.Y()) > } > > func (self *Mover) Move (x, y int) { > self.SetX(self.X() + x) > self.SetY(self.Y() + y) > fmt.Println("Moved to,", self.X(), self.Y()) > } > > > Alarms may now being going off, that the compiler will have no idea > that the self receiver implements the X() and Y() methods, because > self here is defined as Renderers and Movers. I understand this. One > imagines that Go would need to add some sort of interface requirements > or even allow the binding of methods to interfaces. func (self > *Positioned) Render() {} would solve this problem entirely, I think. > > At this point, I put down Go and started looking elsewhere. I came > across Rust. I found that trait look more like a proper object > composition system, however Rust being so young somethings are either > not implemented or not decided upon. The rest of what I'm going to say > largely depends on Lindsey Kuper's work to unify typeclasses and traits: > > https://github.com/mozilla/rust/wiki/Proposal-for-unifying-traits-and-interfaces > > https://mail.mozilla.org/pipermail/rust-dev/2012-August/002276.html > > https://air.mozilla.org/rust-typeclasses/ > > I have begun to construct an example of the same contrived program. In > current Rust, I believe this is as close as I can get. However, you'll > notice that Renderable and Movable are now just plain-ol "interfaces" > and the implmentation of Entity does all of the work implementing > Render() and Move() itself: http://dpaste.com/hold/812966/ > > Assuming that I understand the little amount of information available > on train "provided" and "required" methods and how those work, I can > envision an update to the snippet. In this version, the traits are now > supplying "provided" or "default" method implementations that work > upon an explicitly passed `self` parameter. Not only do the Renderable > and Movable traits provide methods they also declare field > requirements for any type using the trait. In this example, if you're > going to implement Movable for a type, it has to have mutable integer > fields called "x" and "y": http://dpaste.com/812972/ > > The one thing here I'm making up, is the embedding of the Point struct > into the Entity struct which with minimal effort allows the Entity to > satisfy the field requirements of the traits by taking on the fields > of the Point struct. Now each struct that would like to implement > Renderable and Movable do not need to define their own individual > fields but can just embed another struct that qualifies for the traits > the composed type wants to use. > > If struct embedding is entirely out of the question, then the > Renderable and Movable traits can simply require a > pointer-to-a-position field which is only slightly less handy. > > So in the end, I suppose I'm looking for some advice as to whether I > have interpreted the direction of traits, Lindsey's work, how > idiomatic object composition and code reuse patters are intended to > work in Rust. > We discussed this some on IRC. I made an [updated] example in Rust, based off your version. This one uses trait inheritance and default methods to give `Entity` the combined behavior of `Positioned`, `Moveable` and `Renderable`. This syntax may not be exactly right, and some of it is not implemented yet. I'm not entirely up to speed. [updated]: https://gist.github.com/3886118 To my eyes this looks pretty good, except for `impl Entity : Positioned`, which is pure boilerplate. I'm not sure if there is a planned solution for that, but it looks to me like an impl that the compiler could derive automatically. There are plans (but no firm design) for automatically deriving implementations for traits like Eq. WRT embedding Point in Entity I confess to not knowing much about that solution. It seems like the purpose of that would be to let you get rid of the Positioned trait and access .x and .y directly, and that would require `trait Moveable`, etc. to know about the data layout of self. From lucian.branescu at gmail.com Sat Oct 13 15:13:20 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Sat, 13 Oct 2012 23:13:20 +0100 Subject: [rust-dev] Composition in Rust ( and Go ) In-Reply-To: <5079E3DB.7040701@mozilla.com> References: <5079E3DB.7040701@mozilla.com> Message-ID: On 13 October 2012 22:57, Brian Anderson wrote: > On 10/12/2012 12:05 PM, Dustin Lacewell wrote: >> >> $ rust_question -vvvv >> >> I have some questions regarding the future of traits and their intended >> usage. Let me preface this post with the information that I am a decade old >> Python programmer and have little experience with static-typed languages and >> language academics in general so please bare with me if I exhibit any >> fundamental ignorance about the topics here. >> >> I began my discovery of Rust while looking at Go. I soon started to >> experiment with Go's structure embedding and interfaces and attempted to >> draft an experiment in object composition. In the following contrived >> example, we will attempt to build up a struct type that has a >> two-dimensional position and some "mix-ins" that provide functionality that >> work upon that position. In Go, one may embed structs within each other and >> the containing or parent struct "inherits" all fields and methods of >> embedded types. >> >> First, we define a basic struct called Position that implements an >> interface Positioned. You'll notice the interface essentially covers the >> Position type's getter/setter methods. This is the only way (that I know of) >> to enforce that a Positioned type has the right fields, in Go. >> >> package main >> >> import "fmt" >> >> type Positioned interface { >> X() int >> Y() int >> SetX(x int) >> SetY(y int) >> } >> >> type Position struct { >> x, y int >> } >> >> func (self *Position) X() int { return self.x } >> func (self *Position) Y() int { return self.y } >> func (self *Position) SetX(x int) { self.x = x } >> func (self *Position) SetY(y int) { self.y = y } >> >> Now we create two more empty struct types with corresponding interfaces >> called Renderer/Renderable and Mover/Movable. These represent components >> that depend and work upon a Positioned type. The important thing to note >> here, is that both Render() and Move() must take a reference to an >> externally provided Position reference. This will be explained below. >> >> type Renderable interface { >> Positioned >> Render(*Position) >> } >> >> type Renderer struct {} >> >> func (self *Renderer) Render (pos *Position) { >> fmt.Println("Rendered at,", pos.X(), pos.Y()) >> } >> >> type Movable interface { >> Positioned >> Move(pos *Position, dx, dy int) >> } >> >> type Mover struct {} >> >> func (self *Mover) Move (pos *Position, x, y int) { >> pos.SetX(pos.X() + x) >> pos.SetY(pos.Y() + y) >> fmt.Println("Moved to,", pos.X(), pos.Y()) >> } >> >> Lastly, we define our composite type Entity which embeds the Position, >> Renderer and Mover types. This grants Entity all the fields and methods of >> those types such as .pos and .Render() We show a basic main function that >> creates an Entity and its embedded structs and then calls the methods now >> available to the Entity type: >> >> type Entity struct { >> Position >> Renderer >> Mover >> } >> >> func main() { >> e := Entity { >> Position { x:0, y:0 }, >> Renderer{}, Mover{}, >> } >> e.Move(&e.Position, 20, 35) >> e.Render(&e.Position) >> } >> >> A runnable example of this is available here: >> http://play.golang.org/p/gCu91h9BqQ >> >> This is all fine and dandy. However some abrasive qualties of this example >> seem readily apparent to me. For one, even though the apparent intention of >> this code is to create a composite type that is Positioned, Renderable and >> Movable it ends up being quite cludgy. The biggest problem I see is that the >> "shared state" of the Position which Renderer and Mover depend on must be >> explicitly passed around when used with the composite type. One alternative >> is to wrap these methods in overrides in Entity to hide this apparently >> manual boilerplate. An updated example is here: >> http://play.golang.org/p/uD5gCihUKL >> >> Two wrapper methods are supplied for Entity: >> >> func (self *Entity) Move (x, y int) { >> self.Mover.Move(&self.Position, x, y) >> } >> >> func (self *Entity) Render () { >> self.Renderer.Render(&self.Position) >> } >> >> >> This allows the external interface for Entity to be much more natural and >> encapsulated: >> >> >> func main() { >> e := Entity { >> Position { x:0, y:0 }, >> Renderer{}, Mover{}, >> } >> e.Move(20, 35) >> e.Render() >> } >> >> What is the purpose of these two wrapper methods? They are, as far as I >> can tell, required invariant boilerplate. Invariant in that nothing changes >> about what I'm doing. Any sort of inter-dependency between constituent >> components in composed types will require this explicit passing of the >> shared state. The genesis of this problem is a detail with how methods are >> bound to types in Go. We can see that in the Render method of Renderer, we >> define the "method receiver" as (self *Renderer) >> >> func (self *Renderer) Render (pos *Position) { >> fmt.Println("Rendered at,", pos.X(), pos.Y()) >> } >> >> Okay. So Render() is a method that is available on Renderer pointers. But >> Go tricks us, in that we can embed a Renderer inside of another struct like >> Entity and Entity will gain the Render() method except that when you call >> Entity.Render, you are really called Entity.Renderer.Render. When the method >> is invoked the `self` receiver is still the Renderer. Once can imagine that >> if methods bound to structs that are embedded have their method reciever >> updated to be the parent struct instance then this no becomes a problem. The >> method should still be able to work upon the parent struct becuase it has >> recieved all of the fields and members of the original type. Here is what >> the program looks like in this imaginary version of Go: >> http://play.golang.org/p/8MbDFj-G8m >> >> It does not compile obviously, but the Render() and Move() methods are now >> much more natural in that they work upon the `self` name instead of an >> explicitly passed in Position reference. >> >> func (self *Renderer) Render () { >> fmt.Println("Rendered at,", self.X(), self.Y()) >> } >> >> func (self *Mover) Move (x, y int) { >> self.SetX(self.X() + x) >> self.SetY(self.Y() + y) >> fmt.Println("Moved to,", self.X(), self.Y()) >> } >> >> >> Alarms may now being going off, that the compiler will have no idea that >> the self receiver implements the X() and Y() methods, because self here is >> defined as Renderers and Movers. I understand this. One imagines that Go >> would need to add some sort of interface requirements or even allow the >> binding of methods to interfaces. func (self *Positioned) Render() {} would >> solve this problem entirely, I think. >> >> At this point, I put down Go and started looking elsewhere. I came across >> Rust. I found that trait look more like a proper object composition system, >> however Rust being so young somethings are either not implemented or not >> decided upon. The rest of what I'm going to say largely depends on Lindsey >> Kuper's work to unify typeclasses and traits: >> >> >> https://github.com/mozilla/rust/wiki/Proposal-for-unifying-traits-and-interfaces >> >> https://mail.mozilla.org/pipermail/rust-dev/2012-August/002276.html >> >> https://air.mozilla.org/rust-typeclasses/ >> >> I have begun to construct an example of the same contrived program. In >> current Rust, I believe this is as close as I can get. However, you'll >> notice that Renderable and Movable are now just plain-ol "interfaces" and >> the implmentation of Entity does all of the work implementing Render() and >> Move() itself: http://dpaste.com/hold/812966/ >> >> Assuming that I understand the little amount of information available on >> train "provided" and "required" methods and how those work, I can envision >> an update to the snippet. In this version, the traits are now supplying >> "provided" or "default" method implementations that work upon an explicitly >> passed `self` parameter. Not only do the Renderable and Movable traits >> provide methods they also declare field requirements for any type using the >> trait. In this example, if you're going to implement Movable for a type, it >> has to have mutable integer fields called "x" and "y": >> http://dpaste.com/812972/ >> >> The one thing here I'm making up, is the embedding of the Point struct >> into the Entity struct which with minimal effort allows the Entity to >> satisfy the field requirements of the traits by taking on the fields of the >> Point struct. Now each struct that would like to implement Renderable and >> Movable do not need to define their own individual fields but can just embed >> another struct that qualifies for the traits the composed type wants to use. >> >> If struct embedding is entirely out of the question, then the Renderable >> and Movable traits can simply require a pointer-to-a-position field which is >> only slightly less handy. >> >> So in the end, I suppose I'm looking for some advice as to whether I have >> interpreted the direction of traits, Lindsey's work, how idiomatic object >> composition and code reuse patters are intended to work in Rust. >> > > We discussed this some on IRC. I made an [updated] example in Rust, based > off your version. This one uses trait inheritance and default methods to > give `Entity` the combined behavior of `Positioned`, `Moveable` and > `Renderable`. This syntax may not be exactly right, and some of it is not > implemented yet. I'm not entirely up to speed. > > [updated]: https://gist.github.com/3886118 > > To my eyes this looks pretty good, except for `impl Entity : Positioned`, > which is pure boilerplate. I'm not sure if there is a planned solution for > that, but it looks to me like an impl that the compiler could derive > automatically. There are plans (but no firm design) for automatically > deriving implementations for traits like Eq. > > WRT embedding Point in Entity I confess to not knowing much about that > solution. It seems like the purpose of that would be to let you get rid of > the Positioned trait and access .x and .y directly, and that would require > `trait Moveable`, etc. to know about the data layout of self. > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev What I was thinking is that if Rust had properties and they could be part of traits, x and y properties could be defined as part of the Positioned trait. Alternatively, fields could be part of traits and there could be a mechanism for implementations of Positioned to declare where their x and y fields are. I'm not sure any of this makes sense as part of the ongoing plans. From stefan.plantikow at gmail.com Sat Oct 13 02:55:30 2012 From: stefan.plantikow at gmail.com (Stefan Plantikow) Date: Sat, 13 Oct 2012 11:55:30 +0200 Subject: [rust-dev] RFC: All extern "C" functions are unsafe In-Reply-To: <50786FAD.9020701@alum.mit.edu> References: <5078565B.1030402@mozilla.com> <507863AA.9040406@mozilla.com> <50786FAD.9020701@alum.mit.edu> Message-ID: <407BE4F8-35DE-430E-8D19-A655EF161DDC@googlemail.com> Am 12.10.2012 um 21:29 schrieb Niko Matsakis : > +1 (one developer, one vote!) ;) > will there be a way to explicitly mark them as safe? Asking because if we go down this route, all calls in libmath will become unsafe without wrapping them in functions with unsafe blocks and that seems wrong. boggle. From jon.mb at proinbox.com Sun Oct 14 10:20:06 2012 From: jon.mb at proinbox.com (John Mija) Date: Sun, 14 Oct 2012 18:20:06 +0100 Subject: [rust-dev] Why does Rust compile slowly? Message-ID: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> This email is related to one sent to the Go mailing list[1] about the great difference in compiling time between Rust which took 50 minutes, and Go with a time of 2 minutes in build compiler, all libraries, all commands and testing. It looks that it is possible because it has been written in C, instead of use C++. It is also interesting to know that the Go compiler has been based in the Plan9 C compilers[2]. [1]: https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/bKDfVp0dzKw [2]: http://doc.cat-v.org/bell_labs/new_c_compilers/ http://doc.cat-v.org/plan_9/4th_edition/papers/compiler Note: do not take this email like negative, I only hope that Rust can go to better in time. From arcata at gmail.com Sun Oct 14 10:39:18 2012 From: arcata at gmail.com (Joe Groff) Date: Sun, 14 Oct 2012 10:39:18 -0700 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> Message-ID: On Sun, Oct 14, 2012 at 10:20 AM, John Mija wrote: > This email is related to one sent to the Go mailing list[1] about the > great difference in compiling time between Rust which took 50 minutes, > and Go with a time of 2 minutes in build compiler, all libraries, all > commands and testing. > > It looks that it is possible because it has been written in C, instead > of use C++. It is also interesting to know that the Go compiler has been > based in the Plan9 C compilers[2]. > > > [1]: > https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/bKDfVp0dzKw > [2]: http://doc.cat-v.org/bell_labs/new_c_compilers/ > http://doc.cat-v.org/plan_9/4th_edition/papers/compiler > > Note: do not take this email like negative, I only hope that Rust can go > to better in time. One factor is that Rust includes its own branch of LLVM as a submodule, and LLVM takes quite a long time to compile on its own. -Joe From elliottslaughter at gmail.com Sun Oct 14 10:44:48 2012 From: elliottslaughter at gmail.com (Elliott Slaughter) Date: Sun, 14 Oct 2012 10:44:48 -0700 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> Message-ID: On Sun, Oct 14, 2012 at 10:39 AM, Joe Groff wrote: > On Sun, Oct 14, 2012 at 10:20 AM, John Mija wrote: > > This email is related to one sent to the Go mailing list[1] about the > > great difference in compiling time between Rust which took 50 minutes, > > and Go with a time of 2 minutes in build compiler, all libraries, all > > commands and testing. > > > > It looks that it is possible because it has been written in C, instead > > of use C++. It is also interesting to know that the Go compiler has been > > based in the Plan9 C compilers[2]. > > > > > > [1]: > > > https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/bKDfVp0dzKw > > [2]: http://doc.cat-v.org/bell_labs/new_c_compilers/ > > http://doc.cat-v.org/plan_9/4th_edition/papers/compiler > > > > Note: do not take this email like negative, I only hope that Rust can go > > to better in time. > > One factor is that Rust includes its own branch of LLVM as a > submodule, and LLVM takes quite a long time to compile on its own. > The build includes not only all of LLVM, but Clang as well. Also note that the Rust compiler compiles itself 3 times, to ensure that the self-bootstrap process is stable. So your 50 minutes includes 1 build of a commercial grade C/C++ compiler, and 3 builds of the Rust compiler itself. -- Elliott Slaughter "Don't worry about what anybody else is going to do. The best way to predict the future is to invent it." - Alan Kay -------------- next part -------------- An HTML attachment was scrubbed... URL: From gtsiour at softlab.ntua.gr Sun Oct 14 10:48:25 2012 From: gtsiour at softlab.ntua.gr (Yiannis Tsiouris) Date: Sun, 14 Oct 2012 20:48:25 +0300 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> Message-ID: <507AFAE9.8060906@softlab.ntua.gr> Hi, > The build includes not only all of LLVM, but Clang as well. Sorry if this is something obvious, but why is clang *needed* for Rust? -Y. -- Yiannis Tsiouris Ph.D. student, Software Engineering Laboratory, National Technical University of Athens WWW: http://www.softlab.ntua.gr/~gtsiour From masklinn at masklinn.net Sun Oct 14 12:11:07 2012 From: masklinn at masklinn.net (Masklinn) Date: Sun, 14 Oct 2012 21:11:07 +0200 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: <507AFAE9.8060906@softlab.ntua.gr> References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> <507AFAE9.8060906@softlab.ntua.gr> Message-ID: On 2012-10-14, at 19:48 , Yiannis Tsiouris wrote: > Hi, > >> The build includes not only all of LLVM, but Clang as well. > > Sorry if this is something obvious, but why is clang *needed* for Rust? Without looking into the makefiles (so this really is nothing more than a guess): rust calls llvm's makefiles, which default to building clang as well, and nobody's been bothered enough to check which options should be passed to llvm's makefile to make it not build clang? From echristo at gmail.com Sun Oct 14 12:13:47 2012 From: echristo at gmail.com (Eric Christopher) Date: Sun, 14 Oct 2012 12:13:47 -0700 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> <507AFAE9.8060906@softlab.ntua.gr> Message-ID: On Sun, Oct 14, 2012 at 12:11 PM, Masklinn wrote: > On 2012-10-14, at 19:48 , Yiannis Tsiouris wrote: >> Hi, >> >>> The build includes not only all of LLVM, but Clang as well. >> >> Sorry if this is something obvious, but why is clang *needed* for Rust? > > Without looking into the makefiles (so this really is nothing more than > a guess): rust calls llvm's makefiles, which default to building clang > as well, and nobody's been bothered enough to check which options should > be passed to llvm's makefile to make it not build clang? If that's the case then just don't have the clang sources there. It'll avoid building them if they aren't present. -eric From pwalton at mozilla.com Sun Oct 14 12:16:41 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 14 Oct 2012 12:16:41 -0700 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> Message-ID: <507B0F99.4000204@mozilla.com> On 10/14/12 10:20 AM, John Mija wrote: > This email is related to one sent to the Go mailing list[1] about the > great difference in compiling time between Rust which took 50 minutes, > and Go with a time of 2 minutes in build compiler, all libraries, all > commands and testing. > > It looks that it is possible because it has been written in C, instead > of use C++. It is also interesting to know that the Go compiler has been > based in the Plan9 C compilers[2]. There are several reasons. Here they are, along with justification and what might be done to improve this where appropriate: * Rust requires LLVM. LLVM is a large, mature project with many optimization features. The advantage of using LLVM is that the code is deeply optimized and performance-competitive with GCC/MSVC for tight numeric kernels. This advantage matters a lot for applications like games and Web browsers; you can feel the difference between an unoptimized and optimized Servo when resizing the window. - However, it might be feasible to write a simpler backend in C or Rust that emits straightforward machine code directly from LLVM IR, much like LLVM FastISel does. This would be the mirror of the Go approach. This would be a lot of work and I'm somewhat skeptical that it would provide much benefit to the end user over FastISel, but it would definitely make the build go faster. * Rust requires Clang. This is due to the desire to use the Clang linker infrastructure (as Clang is really good at figuring out how to run the system linker), as well as the desire to allow Rust to #include pure C headers someday. None of this is implemented at the moment. I think that this could be significantly improved by hacking the build process; just off the top of my head, Sema, CodeGen, and StaticAnalysis are unnecessary for Rust, as is the C++ and Obj-C support. * Rust builds itself three times for bootstrapping. This is unavoidable as long as Rust is bootstrapped. * Rust builds itself with optimization on by default. This makes the LLVM passes 2x-3x slower. Note that turning optimization off doesn't actually help the build time of Rust much, because Rust builds itself three times -- thus the gains you achieve from turning optimization off are often negated by the slower compiler you have to use in the later stages of self-hosting! (This curious catch-22 doesn't apply to user code, just to the Rust compiler.) * Rust never uses the LLVM fast instruction selector (FastISel). This is because the Rust compiler emits instructions that aren't implemented in FastISel, so LLVM has to fall back to the slow instruction selector (which generates better code). This is fixable with some combination of hacking the FastISel to support the stuff that Rust generates and hacking Rust to avoid generating so many of these instructions. I think this is one of the biggest potential wins. * Rust reads in all the metadata for every external crate. This tends to dominate compilation time for tiny Rust programs. This is fixable by switching to lazy loading of modules, but needs some language changes to make tractable (in particular, "use mod" to load modules). * Some or all of these likely have an impact: use of DWARF exceptions, reference counting, visitor glue. Patrick From masklinn at masklinn.net Sun Oct 14 12:32:35 2012 From: masklinn at masklinn.net (Masklinn) Date: Sun, 14 Oct 2012 21:32:35 +0200 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: <507B0F99.4000204@mozilla.com> References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> <507B0F99.4000204@mozilla.com> Message-ID: On 2012-10-14, at 21:16 , Patrick Walton wrote: > > * Rust builds itself three times for bootstrapping. This is unavoidable as long as Rust is bootstrapped. Aren't the second and third builds for sanity-checking purpose? Surely if (when) Rust is "mature" and distributed as a tarball for source-based systems, only stage1 compile will actually be needed? From me at kevincantu.org Sun Oct 14 12:48:53 2012 From: me at kevincantu.org (Kevin Cantu) Date: Sun, 14 Oct 2012 12:48:53 -0700 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> <507B0F99.4000204@mozilla.com> Message-ID: For those folks we might as well distribute only the binaries. Zero build time. :D Kevin On Sun, Oct 14, 2012 at 12:32 PM, Masklinn wrote: > On 2012-10-14, at 21:16 , Patrick Walton wrote: >> >> * Rust builds itself three times for bootstrapping. This is unavoidable as long as Rust is bootstrapped. > > Aren't the second and third builds for sanity-checking purpose? Surely > if (when) Rust is "mature" and distributed as a tarball for source-based > systems, only stage1 compile will actually be needed? > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From marijnh at gmail.com Sun Oct 14 12:52:11 2012 From: marijnh at gmail.com (Marijn Haverbeke) Date: Sun, 14 Oct 2012 21:52:11 +0200 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> <507B0F99.4000204@mozilla.com> Message-ID: Regardless of all that, yes, the Rust compiler *is* slower than the Go compiler. Not a factor 25, when you make a fair comparison, but still quite a lot slower. This has two reasons. Firstly, the Go language has partially been designed with compiler speed in mind. It is a simple language, compared to Rust, and thus the compiler simply has to do less work. Secondly, Rob Pike has probably implemented more compilers than all of the Rust team combined, so there's the issue of the Rust compiler simply not being written as cleverly as the Go compiler. This second factor can, and will, be mitigated in the future as the language stabilizes and the compiler gets streamlined further. The first issue means that Rust will probably never compile quite as quickly as Go, because it trades developer ergonomics for compilation time. Best, Marijn From niko at alum.mit.edu Sun Oct 14 13:44:37 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sun, 14 Oct 2012 13:44:37 -0700 Subject: [rust-dev] Composition in Rust ( and Go ) In-Reply-To: <5079E3DB.7040701@mozilla.com> References: <5079E3DB.7040701@mozilla.com> Message-ID: <507B2435.3050800@alum.mit.edu> What Brian wrote looks about right to me. I don't think any of the deriving ideas we had discussed could accommodate that particular example, though clearly it's not hard to imagine how one might do so. Or perhaps use a macro. Niko > Brian Anderson > October 13, 2012 2:57 PM > > > We discussed this some on IRC. I made an [updated] example in Rust, > based off your version. This one uses trait inheritance and default > methods to give `Entity` the combined behavior of `Positioned`, > `Moveable` and `Renderable`. This syntax may not be exactly right, and > some of it is not implemented yet. I'm not entirely up to speed. > > [updated]: https://gist.github.com/3886118 > > To my eyes this looks pretty good, except for `impl Entity : > Positioned`, which is pure boilerplate. I'm not sure if there is a > planned solution for that, but it looks to me like an impl that the > compiler could derive automatically. There are plans (but no firm > design) for automatically deriving implementations for traits like Eq. > > WRT embedding Point in Entity I confess to not knowing much about that > solution. It seems like the purpose of that would be to let you get > rid of the Positioned trait and access .x and .y directly, and that > would require `trait Moveable`, etc. to know about the data layout of > self. > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Dustin Lacewell > October 12, 2012 12:05 PM > $ rust_question -vvvv > > I have some questions regarding the future of traits and their > intended usage. Let me preface this post with the information that I > am a decade old Python programmer and have little experience with > static-typed languages and language academics in general so please > bare with me if I exhibit any fundamental ignorance about the topics here. > > I began my discovery of Rust while looking at Go. I soon started to > experiment with Go's structure embedding and interfaces and attempted > to draft an experiment in object composition. In the following > contrived example, we will attempt to build up a struct type that has > a two-dimensional position and some "mix-ins" that provide > functionality that work upon that position. In Go, one may embed > structs within each other and the containing or parent struct > "inherits" all fields and methods of embedded types. > > First, we define a basic struct called Position that implements an > interface Positioned. You'll notice the interface essentially covers > the Position type's getter/setter methods. This is the only way (that > I know of) to enforce that a Positioned type has the right fields, in Go. > > package main > > import "fmt" > > type Positioned interface { > X() int > Y() int > SetX(x int) > SetY(y int) > } > > type Position struct { > x, y int > } > > func (self *Position) X() int { return self.x } > func (self *Position) Y() int { return self.y } > func (self *Position) SetX(x int) { self.x = x } > func (self *Position) SetY(y int) { self.y = y } > > Now we create two more empty struct types with corresponding > interfaces called Renderer/Renderable and Mover/Movable. These > represent components that depend and work upon a Positioned type. The > important thing to note here, is that both Render() and Move() must > take a reference to an externally provided Position reference. This > will be explained below. > > type Renderable interface { > Positioned > Render(*Position) > } > > type Renderer struct {} > > func (self *Renderer) Render (pos *Position) { > fmt.Println("Rendered at,", pos.X(), pos.Y()) > } > > type Movable interface { > Positioned > Move(pos *Position, dx, dy int) > } > > type Mover struct {} > > func (self *Mover) Move (pos *Position, x, y int) { > pos.SetX(pos.X() + x) > pos.SetY(pos.Y() + y) > fmt.Println("Moved to,", pos.X(), pos.Y()) > } > > Lastly, we define our composite type Entity which embeds the Position, > Renderer and Mover types. This grants Entity all the fields and > methods of those types such as .pos and .Render() We show a basic main > function that creates an Entity and its embedded structs and then > calls the methods now available to the Entity type: > > type Entity struct { > Position > Renderer > Mover > } > > func main() { > e := Entity { > Position { x:0, y:0 }, > Renderer{}, Mover{}, > } > e.Move(&e.Position, 20, 35) > e.Render(&e.Position) > } > > A runnable example of this is available here: > http://play.golang.org/p/gCu91h9BqQ > > This is all fine and dandy. However some abrasive qualties of this > example seem readily apparent to me. For one, even though the apparent > intention of this code is to create a composite type that is > Positioned, Renderable and Movable it ends up being quite cludgy. The > biggest problem I see is that the "shared state" of the Position which > Renderer and Mover depend on must be explicitly passed around when > used with the composite type. One alternative is to wrap these methods > in overrides in Entity to hide this apparently manual boilerplate. An > updated example is here: http://play.golang.org/p/uD5gCihUKL > > Two wrapper methods are supplied for Entity: > > func (self *Entity) Move (x, y int) { > self.Mover.Move(&self.Position, x, y) > } > > func (self *Entity) Render () { > self.Renderer.Render(&self.Position) > } > > > This allows the external interface for Entity to be much more natural > and encapsulated: > > > func main() { > e := Entity { > Position { x:0, y:0 }, > Renderer{}, Mover{}, > } > e.Move(20, 35) > e.Render() > } > > What is the purpose of these two wrapper methods? They are, as far as > I can tell, required invariant boilerplate. Invariant in that nothing > changes about what I'm doing. Any sort of inter-dependency between > constituent components in composed types will require this explicit > passing of the shared state. The genesis of this problem is a detail > with how methods are bound to types in Go. We can see that in the > Render method of Renderer, we define the "method receiver" as (self > *Renderer) > > func (self *Renderer) Render (pos *Position) { > fmt.Println("Rendered at,", pos.X(), pos.Y()) > } > > Okay. So Render() is a method that is available on Renderer pointers. > But Go tricks us, in that we can embed a Renderer inside of another > struct like Entity and Entity will gain the Render() method except > that when you call Entity.Render, you are really called > Entity.Renderer.Render. When the method is invoked the `self` receiver > is still the Renderer. Once can imagine that if methods bound to > structs that are embedded have their method reciever updated to be the > parent struct instance then this no becomes a problem. The method > should still be able to work upon the parent struct becuase it has > recieved all of the fields and members of the original type. Here is > what the program looks like in this imaginary version of Go: > http://play.golang.org/p/8MbDFj-G8m > > It does not compile obviously, but the Render() and Move() methods are > now much more natural in that they work upon the `self` name instead > of an explicitly passed in Position reference. > > func (self *Renderer) Render () { > fmt.Println("Rendered at,", self.X(), self.Y()) > } > > func (self *Mover) Move (x, y int) { > self.SetX(self.X() + x) > self.SetY(self.Y() + y) > fmt.Println("Moved to,", self.X(), self.Y()) > } > > > Alarms may now being going off, that the compiler will have no idea > that the self receiver implements the X() and Y() methods, because > self here is defined as Renderers and Movers. I understand this. One > imagines that Go would need to add some sort of interface requirements > or even allow the binding of methods to interfaces. func (self > *Positioned) Render() {} would solve this problem entirely, I think. > > At this point, I put down Go and started looking elsewhere. I came > across Rust. I found that trait look more like a proper object > composition system, however Rust being so young somethings are either > not implemented or not decided upon. The rest of what I'm going to say > largely depends on Lindsey Kuper's work to unify typeclasses and traits: > > https://github.com/mozilla/rust/wiki/Proposal-for-unifying-traits-and-interfaces > > https://mail.mozilla.org/pipermail/rust-dev/2012-August/002276.html > > https://air.mozilla.org/rust-typeclasses/ > > I have begun to construct an example of the same contrived program. In > current Rust, I believe this is as close as I can get. However, you'll > notice that Renderable and Movable are now just plain-ol "interfaces" > and the implmentation of Entity does all of the work implementing > Render() and Move() itself: http://dpaste.com/hold/812966/ > > Assuming that I understand the little amount of information available > on train "provided" and "required" methods and how those work, I can > envision an update to the snippet. In this version, the traits are now > supplying "provided" or "default" method implementations that work > upon an explicitly passed `self` parameter. Not only do the Renderable > and Movable traits provide methods they also declare field > requirements for any type using the trait. In this example, if you're > going to implement Movable for a type, it has to have mutable integer > fields called "x" and "y": http://dpaste.com/812972/ > > The one thing here I'm making up, is the embedding of the Point struct > into the Entity struct which with minimal effort allows the Entity to > satisfy the field requirements of the traits by taking on the fields > of the Point struct. Now each struct that would like to implement > Renderable and Movable do not need to define their own individual > fields but can just embed another struct that qualifies for the traits > the composed type wants to use. > > If struct embedding is entirely out of the question, then the > Renderable and Movable traits can simply require a > pointer-to-a-position field which is only slightly less handy. > > So in the end, I suppose I'm looking for some advice as to whether I > have interpreted the direction of traits, Lindsey's work, how > idiomatic object composition and code reuse patters are intended to > work in Rust. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: postbox-contact.jpg Type: image/jpeg Size: 1151 bytes Desc: not available URL: From banderson at mozilla.com Sun Oct 14 18:07:24 2012 From: banderson at mozilla.com (Brian Anderson) Date: Sun, 14 Oct 2012 18:07:24 -0700 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> Message-ID: <507B61CC.5090202@mozilla.com> On 10/14/2012 10:20 AM, John Mija wrote: > This email is related to one sent to the Go mailing list[1] about the > great difference in compiling time between Rust which took 50 minutes, > and Go with a time of 2 minutes in build compiler, all libraries, all > commands and testing. > That the entire test suite runs in under two minutes is an amazing feat. Go's efficient toolchain is one of its great strengths. We are probably never Going to catch Go here, but there is a whole lot that Rust can do to improve. Patrick discussed most of the major problems. There are general Rust performance issues, specific compiler issues, and build system issues. This email is about the build system. There are _a lot_ of duplicate and redundant builds in a full build/test run. I was curious about how long the build would take if we removed all the redundancy. In other words, how long does it take an optimized rustc to build and test all the Rust components, without optimizations, minus LLVM and clang (which we presumably won't fork forever), just once? (TL;DR 8m45s) Here's the goal: * Build these native components: libuv (C), rt (C++), rustllvm (C++) * Build and test these crates: core, std, syntax, rustc, cargo, rustdoc, compiletest * Run the compiler test suite (everything in src/test) (including the pretty-printer tests which run most of the test suite through entire parser processes multiple times) * Build and test the documentation First I ran `make` to build the stage2 compiler, with optimizations on. Then I ran `time make check CFG_DISABLE_OPTIMIZE=1 CFG_DISABLE_VALGRIND=1`. Due to the way crate testing is currently done this will (re)do most of the work to build a full rust toolchain (yes, testing the Rust compiler more or less involves a full rebuild). It will build and test core, std, rustc, cargo, and rustdoc (not syntax which has not a single unit test). It will also run the compiler test suite and the documentation tests. Also builds 'compiletest', the compiler test driver. On my modest 4-core system that took 7m53s (and 15m53 cpu time, so some parallelism). Syntax, measured separately, took 18s. So around 8m10s to build and test all the rust code. That leaves building libuv, rt, and rustllvm, and the docs. I measure these as libuv/rt: 19s, rustllvm: 4s, docs: 12s. Total of 35s for native code and docs. That's 8m45s to compile and test all of Rust. To compare, simply running `time make check`, using the default (optimized, valgrinding) configuration, with a prebuilt llvm and clang, takes 36m. This machine builds and tests go in under 2 minutes. Getting the Rust build to actually go that fast in the default configuration will take some work. From nadavvin at gmail.com Mon Oct 15 01:42:55 2012 From: nadavvin at gmail.com (Nadav Vinik) Date: Mon, 15 Oct 2012 10:42:55 +0200 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: <507B61CC.5090202@mozilla.com> References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> <507B61CC.5090202@mozilla.com> Message-ID: Why rust work with a special custom llvm instead of the standard? Will it change in the future? On 15 October 2012 03:07, Brian Anderson wrote: > On 10/14/2012 10:20 AM, John Mija wrote: > >> This email is related to one sent to the Go mailing list[1] about the >> great difference in compiling time between Rust which took 50 minutes, >> and Go with a time of 2 minutes in build compiler, all libraries, all >> commands and testing. >> >> > That the entire test suite runs in under two minutes is an amazing feat. > Go's efficient toolchain is one of its great strengths. > > We are probably never Going to catch Go here, but there is a whole lot > that Rust can do to improve. > > Patrick discussed most of the major problems. There are general Rust > performance issues, specific compiler issues, and build system issues. This > email is about the build system. > > There are _a lot_ of duplicate and redundant builds in a full build/test > run. I was curious about how long the build would take if we removed all > the redundancy. In other words, how long does it take an optimized rustc to > build and test all the Rust components, without optimizations, minus LLVM > and clang (which we presumably won't fork forever), just once? (TL;DR 8m45s) > > Here's the goal: > > * Build these native components: libuv (C), rt (C++), rustllvm (C++) > * Build and test these crates: core, std, syntax, rustc, cargo, rustdoc, > compiletest > * Run the compiler test suite (everything in src/test) (including the > pretty-printer tests which run most of the test suite through entire parser > processes multiple times) > * Build and test the documentation > > First I ran `make` to build the stage2 compiler, with optimizations on. > > Then I ran `time make check CFG_DISABLE_OPTIMIZE=1 > CFG_DISABLE_VALGRIND=1`. Due to the way crate testing is currently done > this will (re)do most of the work to build a full rust toolchain (yes, > testing the Rust compiler more or less involves a full rebuild). It will > build and test core, std, rustc, cargo, and rustdoc (not syntax which has > not a single unit test). It will also run the compiler test suite and the > documentation tests. Also builds 'compiletest', the compiler test driver. > > On my modest 4-core system that took 7m53s (and 15m53 cpu time, so some > parallelism). > > Syntax, measured separately, took 18s. So around 8m10s to build and test > all the rust code. That leaves building libuv, rt, and rustllvm, and the > docs. I measure these as libuv/rt: 19s, rustllvm: 4s, docs: 12s. Total of > 35s for native code and docs. > > That's 8m45s to compile and test all of Rust. To compare, simply running > `time make check`, using the default (optimized, valgrinding) > configuration, with a prebuilt llvm and clang, takes 36m. This machine > builds and tests go in under 2 minutes. > > Getting the Rust build to actually go that fast in the default > configuration will take some work. > > > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > -- ????? ???: http://nadavvin.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From erick.tryzelaar at gmail.com Mon Oct 15 06:21:04 2012 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Mon, 15 Oct 2012 06:21:04 -0700 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> <507B61CC.5090202@mozilla.com> Message-ID: We have some patches to the llvm garbage collection system that we haven't sent upstream yet. It's my impression we plan to do that once we get gc stabilized. On Monday, October 15, 2012, Nadav Vinik wrote: > Why rust work with a special custom llvm instead of the standard? > > Will it change in the future? > > On 15 October 2012 03:07, Brian Anderson > > wrote: > >> On 10/14/2012 10:20 AM, John Mija wrote: >> >>> This email is related to one sent to the Go mailing list[1] about the >>> great difference in compiling time between Rust which took 50 minutes, >>> and Go with a time of 2 minutes in build compiler, all libraries, all >>> commands and testing. >>> >>> >> That the entire test suite runs in under two minutes is an amazing feat. >> Go's efficient toolchain is one of its great strengths. >> >> We are probably never Going to catch Go here, but there is a whole lot >> that Rust can do to improve. >> >> Patrick discussed most of the major problems. There are general Rust >> performance issues, specific compiler issues, and build system issues. This >> email is about the build system. >> >> There are _a lot_ of duplicate and redundant builds in a full build/test >> run. I was curious about how long the build would take if we removed all >> the redundancy. In other words, how long does it take an optimized rustc to >> build and test all the Rust components, without optimizations, minus LLVM >> and clang (which we presumably won't fork forever), just once? (TL;DR 8m45s) >> >> Here's the goal: >> >> * Build these native components: libuv (C), rt (C++), rustllvm (C++) >> * Build and test these crates: core, std, syntax, rustc, cargo, rustdoc, >> compiletest >> * Run the compiler test suite (everything in src/test) (including the >> pretty-printer tests which run most of the test suite through entire parser >> processes multiple times) >> * Build and test the documentation >> >> First I ran `make` to build the stage2 compiler, with optimizations on. >> >> Then I ran `time make check CFG_DISABLE_OPTIMIZE=1 >> CFG_DISABLE_VALGRIND=1`. Due to the way crate testing is currently done >> this will (re)do most of the work to build a full rust toolchain (yes, >> testing the Rust compiler more or less involves a full rebuild). It will >> build and test core, std, rustc, cargo, and rustdoc (not syntax which has >> not a single unit test). It will also run the compiler test suite and the >> documentation tests. Also builds 'compiletest', the compiler test driver. >> >> On my modest 4-core system that took 7m53s (and 15m53 cpu time, so some >> parallelism). >> >> Syntax, measured separately, took 18s. So around 8m10s to build and test >> all the rust code. That leaves building libuv, rt, and rustllvm, and the >> docs. I measure these as libuv/rt: 19s, rustllvm: 4s, docs: 12s. Total of >> 35s for native code and docs. >> >> That's 8m45s to compile and test all of Rust. To compare, simply running >> `time make check`, using the default (optimized, valgrinding) >> configuration, with a prebuilt llvm and clang, takes 36m. This machine >> builds and tests go in under 2 minutes. >> >> Getting the Rust build to actually go that fast in the default >> configuration will take some work. >> >> >> ______________________________**_________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/**listinfo/rust-dev >> > > > > -- > ????? ???: > http://nadavvin.com > -------------- next part -------------- An HTML attachment was scrubbed... URL: From peterhull90 at gmail.com Mon Oct 15 07:11:28 2012 From: peterhull90 at gmail.com (Peter Hull) Date: Mon, 15 Oct 2012 15:11:28 +0100 Subject: [rust-dev] Possible rustdoc error? Message-ID: I noticed that some of the code documentation is truncated - for example vec::each_mut (http://dl.rust-lang.org/doc/core/vec.html#function-each_mut) says: Like each(), but for the case where you have and the actual code is (https://github.com/mozilla/rust/blob/master/src/libcore/vec.rs) /// Like `each()`, but for the case where you have /// a vector with mutable contents and you would like /// to mutate the contents as you iterate. #[inline(always)] pub fn each_mut(v: &[mut T], f: fn(elem: &mut T) -> bool) { I couldn't see an issue report on this, if it is indeed a bug (maybe multiple single-line doc comments are not meant to be concatenated?) Should I file a report? Pete ps. on a side note I am trying to get up to speed with rust now it's settling down a bit with 0.4. I noticed some functions aren't documented at all in the source (e.g. vec::append), so would it be helpful if I added documentation as I go along and submit a pull request, or is that already in hand? From niko at alum.mit.edu Mon Oct 15 08:14:52 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 15 Oct 2012 08:14:52 -0700 Subject: [rust-dev] RFC: All extern "C" functions are unsafe In-Reply-To: <559C4AFB-0026-4C11-A705-022770BC1BE1@googlemail.com> References: <5078565B.1030402@mozilla.com> <507863AA.9040406@mozilla.com> <50786FAD.9020701@alum.mit.edu> <407BE4F8-35DE-430E-8D19-A655EF161DDC@googlemail.com> <507B2241.7090300@alum.mit.edu> <559C4AFB-0026-4C11-A705-022770BC1BE1@googlemail.com> Message-ID: <507C286C.3060905@alum.mit.edu> (Note: we somehow lost the rust-dev cc, see Stefan's e-mail below) Under the plan as I envisioned it in my head, ignoring the question about unsafety, it would be necessary to write a wrapper for a C function if you wanted it to have the same type as a Rust fn (as opposed to an `extern "C" fn()` type). However, I could imagine permitting extern fn items to be coerced to Rust type, and having the compiler auto-generate a wrapper. We plan to do something similar with top-level Rust fns: they will be coercable to a C function type, so that any Rust fn item can used as a callback, and not just an "extern fn". However, this of course immediately raises the question of unsafety: we could presumably want a way to declare that those C functions are safe as well. Another option is just to use a macro, of course. Or that would be an option if we supported item-level macros, which we hopefully will soon. The question I guess is how often this situation comes up. Is it just libmath? Or is this sort of thing extremely common when doing bindings? Niko > Stefan Plantikow > October 15, 2012 12:35 AM > > So will it be necessary to write wrappers manually in the future? > Right now f32 just re-exports native functions explicitly marked as > pure in cmath:c_float. > How would that change? Don't really care that much as long as it > doesn't become a boilerplaty hassle ;) > > > Cheers, > > > Stefan. > > > Niko Matsakis > October 14, 2012 1:36 PM > Most likely such wrappers will be needed anyway eventually, because C > functions are going to have type `extern "C" fn(...)` as part of > . (Right now rustc > generates those wrappers automatically) > > > Niko > > Stefan Plantikow wrote: > Stefan Plantikow > October 13, 2012 2:55 AM > > > will there be a way to explicitly mark them as safe? Asking because if > we go down this route, all calls in libmath will become unsafe without > wrapping them in functions with unsafe blocks and that seems wrong. > > > > boggle. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Niko Matsakis > October 12, 2012 12:29 PM > +1 (one developer, one vote!) ;) > > Brian Anderson > October 12, 2012 11:38 AM > > > +2 > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: postbox-contact.jpg Type: image/jpeg Size: 1206 bytes Desc: not available URL: From marijnh at gmail.com Mon Oct 15 08:27:58 2012 From: marijnh at gmail.com (Marijn Haverbeke) Date: Mon, 15 Oct 2012 17:27:58 +0200 Subject: [rust-dev] RFC: All extern "C" functions are unsafe In-Reply-To: <507C286C.3060905@alum.mit.edu> References: <5078565B.1030402@mozilla.com> <507863AA.9040406@mozilla.com> <50786FAD.9020701@alum.mit.edu> <407BE4F8-35DE-430E-8D19-A655EF161DDC@googlemail.com> <507B2241.7090300@alum.mit.edu> <559C4AFB-0026-4C11-A705-022770BC1BE1@googlemail.com> <507C286C.3060905@alum.mit.edu> Message-ID: > > The question I guess is how often this situation comes up. Is it just > libmath? Or is this sort of thing extremely common when doing bindings? > Extremely common. I'm somewhat appalled that the blanket 'all C functions are unsafe' idea is even being considered (and enthusiastically supported). Yes, C code can segfault and do other nasty things if you call it incorrectly. But wrapping every call to a C function in an unsafe block will dilute the 'red flag' role of unsafe blocks to the point of making them just painful noise, and wrapping the C functions themselves in a wrapper function to make them safe is, in most cases, a wax nose -- the wrapper will not be able to guarantee that the call won't go wrong, so no safety is added. Best, Marijn -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Mon Oct 15 08:44:04 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 15 Oct 2012 08:44:04 -0700 Subject: [rust-dev] RFC: All extern "C" functions are unsafe In-Reply-To: References: <5078565B.1030402@mozilla.com> <507863AA.9040406@mozilla.com> <50786FAD.9020701@alum.mit.edu> <407BE4F8-35DE-430E-8D19-A655EF161DDC@googlemail.com> <507B2241.7090300@alum.mit.edu> <559C4AFB-0026-4C11-A705-022770BC1BE1@googlemail.com> <507C286C.3060905@alum.mit.edu> Message-ID: <507C2F44.2010609@mozilla.com> On 10/15/12 8:27 AM, Marijn Haverbeke wrote: > Extremely common. I'm somewhat appalled that the blanket 'all C > functions are unsafe' idea is even being considered (and > enthusiastically supported). Yes, C code can segfault and do other nasty > things if you call it incorrectly. But wrapping every call to a C > function in an unsafe block will dilute the 'red flag' role of unsafe > blocks to the point of making them just painful noise, and wrapping the > C functions themselves in a wrapper function to make them safe is, in > most cases, a wax nose -- the wrapper will not be able to guarantee that > the call won't go wrong, so no safety is added. Usually, one needs such a wrapper anyway to sanitize the arguments. Essentially any C function that takes a pointer (which is most of them) needs a wrapper to be invoked safely. This wrapper needs to ensure that the data pointed at is of the right size and type, is not null in some cases, etc. Additionally, an awful lot of C libraries create their own reference counting systems (examples: Cairo, Azure, any "Core" library on Mac OS, all Objective-C libraries, GTK+, all GObject-based libraries, all COM-based libraries on Windows). All of the objects passed to these functions must be wrapped, to ensure that the reference counting is right. Failure to get the reference counting right leads to exploitable security vulnerabilities (use-after-free + indirect function call + heap-spray). Rust can enforce that the reference counting is used properly, but only if the raw functions are off-limits. Certainly, some C functions don't need wrappers. I'd be OK with a #[safe] annotation for stuff like libmath. For those functions, writing a wrapper is pure boilerplate, and reducing the boilerplate to 7 characters seems fine. Patrick From mad.one at gmail.com Mon Oct 15 09:09:26 2012 From: mad.one at gmail.com (Austin Seipp) Date: Mon, 15 Oct 2012 11:09:26 -0500 Subject: [rust-dev] RFC: All extern "C" functions are unsafe In-Reply-To: References: <5078565B.1030402@mozilla.com> <507863AA.9040406@mozilla.com> <50786FAD.9020701@alum.mit.edu> <407BE4F8-35DE-430E-8D19-A655EF161DDC@googlemail.com> <507B2241.7090300@alum.mit.edu> <559C4AFB-0026-4C11-A705-022770BC1BE1@googlemail.com> <507C286C.3060905@alum.mit.edu> Message-ID: I am +1 for this. In my experience writing many foreign library bindings in Haskell (I've done it a lot,) the vast majority of people who will ever do this are going to do it in a library and offer it up there. As an author, I find it often pays off the most in the long (for users) to wrap things anyway - to expose abstractions the users will expect of the host language. This is often achievable, and I try to write as little supporting C code as possible when writing things like bindings. Rust (or Haskell) is so much more expressive than C, I'd rather import raw functions, unsafe or not (in Haskell this is IO vs. no IO type, a bit different from Rust, but I mostly mark them all as 'possibly firing missiles') and abstract over the low-level nastiness as much as possible in the 'host' language, and give good interfaces. This pays off in my experience in maintenance and ease of use for everyone. I generally let raw FFI code sit in a separate sub module where people who Know What They Are Doing can touch stuff and live dangerously, and otherwise emphasize high level interfaces instead. They don't even need to be a lot more high level - just clear memory safety and say, unicode/thread awareness. You will often have to write lots of code in the host language for this support anyway, because some useful C libraries will have complications, or be oblivious to these concerns. They can otherwise be pretty direct mappings with some high level types, and you can abstract over the 'imperativeness' even more if you want, or add more static safety, etc. in other interfaces. I think this is a very good approach for users, although it comes with burden to the author it may seem. I realize that there is still room for a lot of design in the core libraries and the sort of Rust best practices (if there is such a thing yet,) but overall I've found no matter what you will have to do at least basic sanity checking and offer up some kind of respectable interface to your users. Nobody wants to write lots of raw pointer-y crash-y C-y style code in Rust, just like nobody using Haskell really wants to do the same thing. In practice I think there won't be much noise, any more than what is necessary in most cases anyway. And when I write Rust, I would expect the language to be informative of the fact I can violate memory safety, so I can take the necessary precautions and prepare myself for a long night. On Mon, Oct 15, 2012 at 10:27 AM, Marijn Haverbeke wrote: >> The question I guess is how often this situation comes up. Is it just >> libmath? Or is this sort of thing extremely common when doing bindings? > > > Extremely common. I'm somewhat appalled that the blanket 'all C functions > are unsafe' idea is even being considered (and enthusiastically supported). > Yes, C code can segfault and do other nasty things if you call it > incorrectly. But wrapping every call to a C function in an unsafe block will > dilute the 'red flag' role of unsafe blocks to the point of making them just > painful noise, and wrapping the C functions themselves in a wrapper function > to make them safe is, in most cases, a wax nose -- the wrapper will not be > able to guarantee that the call won't go wrong, so no safety is added. > > Best, > Marijn > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -- Regards, Austin From stefan.plantikow at gmail.com Mon Oct 15 08:53:27 2012 From: stefan.plantikow at gmail.com (Stefan Plantikow) Date: Mon, 15 Oct 2012 17:53:27 +0200 Subject: [rust-dev] RFC: All extern "C" functions are unsafe In-Reply-To: References: <5078565B.1030402@mozilla.com> <507863AA.9040406@mozilla.com> <50786FAD.9020701@alum.mit.edu> <407BE4F8-35DE-430E-8D19-A655EF161DDC@googlemail.com> <507B2241.7090300@alum.mit.edu> <559C4AFB-0026-4C11-A705-022770BC1BE1@googlemail.com> <507C286C.3060905@alum.mit.edu> Message-ID: Am 15.10.2012 um 17:27 schrieb Marijn Haverbeke : > The question I guess is how often this situation comes up. Is it just libmath? Or is this sort of thing extremely common when doing bindings? > > Extremely common. I'm somewhat appalled that the blanket 'all C functions are unsafe' idea is even being considered (and enthusiastically supported). Yes, C code can segfault and do other nasty things if you call it incorrectly. But wrapping every call to a C function in an unsafe block will dilute the 'red flag' role of unsafe blocks to the point of making them just painful noise, and wrapping the C functions themselves in a wrapper function to make them safe is, in most cases, a wax nose -- the wrapper will not be able to guarantee that the call won't go wrong, so no safety is added. > An 'extern safe' vs. 'extern' as 'extern unsafe' by default would be my favorite: At least it gives the author of a binding a chance to say 'I thought about this and don't expect it to do anything nasty'. This already should help prioritize when hunting bugs and auditing code. I'd love if such declarations would optionally come with a person's name for increased social interaction ;) On the crate level it may be worthwhile to be able to use other crates and say to what degree they are trusted, i.e. wether calls to that crate should be considered unsafe or not. Exploring this may make it desirable to have a third trust level for 'claimed safe by the author'. Cheers, Stefan. -------------- next part -------------- An HTML attachment was scrubbed... URL: From stefan.plantikow at gmail.com Mon Oct 15 00:57:05 2012 From: stefan.plantikow at gmail.com (Stefan Plantikow) Date: Mon, 15 Oct 2012 09:57:05 +0200 Subject: [rust-dev] Composition in Rust ( and Go ) In-Reply-To: <507B2435.3050800@alum.mit.edu> References: <5079E3DB.7040701@mozilla.com> <507B2435.3050800@alum.mit.edu> Message-ID: Am 14.10.2012 um 22:44 schrieb Niko Matsakis : > What Brian wrote looks about right to me. I don't think any of the deriving ideas we had discussed could accommodate that particular example, though clearly it's not hard to imagine how one might do so. Or perhaps use a macro. > Yes, I am glad this has been brought up again. I was thinking about this awhile back and put some drafty ideas into the 'Delegation' section of https://github.com/mozilla/rust/wiki/Proposal-for-interfaces The main idea was to allow for a syntax that basically says "implement that interface for self by delegation to member or a pure call" The page is outdated. However,I still think having support for automatic delegation could prove to be useful. I remember that there was a talk on IRC with the conclusion to implement this via macros later. Since it this feature has come up again I wonder wether that still is the correct answer. Cheers, Stefan. From graydon at mozilla.com Mon Oct 15 11:03:14 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Mon, 15 Oct 2012 11:03:14 -0700 Subject: [rust-dev] RFC: All extern "C" functions are unsafe In-Reply-To: References: <5078565B.1030402@mozilla.com> <507863AA.9040406@mozilla.com> <50786FAD.9020701@alum.mit.edu> <407BE4F8-35DE-430E-8D19-A655EF161DDC@googlemail.com> <507B2241.7090300@alum.mit.edu> <559C4AFB-0026-4C11-A705-022770BC1BE1@googlemail.com> <507C286C.3060905@alum.mit.edu> Message-ID: <507C4FE2.1070504@mozilla.com> On 12-10-15 08:27 AM, Marijn Haverbeke wrote: > The question I guess is how often this situation comes up. Is it > just libmath? Or is this sort of thing extremely common when doing > bindings? > > > Extremely common. I'm somewhat appalled that the blanket 'all C > functions are unsafe' idea is even being considered (and > enthusiastically supported). Yes, C code can segfault and do other nasty > things if you call it incorrectly. But wrapping every call to a C > function in an unsafe block will dilute the 'red flag' role of unsafe > blocks to the point of making them just painful noise, and wrapping the > C functions themselves in a wrapper function to make them safe is, in > most cases, a wax nose -- the wrapper will not be able to guarantee that > the call won't go wrong, so no safety is added. A potential middle-ground: unsafe if it takes or returns a raw pointer, safe otherwise? Not perfect (eg. racing on static data, and Spooky System Calls, still foul it up) but perhaps a closer approximation of fact? In any case I agree with the notion that this has to be an (overridable) default, not a requirement for masses of nuisance boilerplate. In general we should notice cases where boilerplate is arising and nip them in the bud. -Graydon From me at kevincantu.org Mon Oct 15 11:08:48 2012 From: me at kevincantu.org (Kevin Cantu) Date: Mon, 15 Oct 2012 11:08:48 -0700 Subject: [rust-dev] Possible rustdoc error? In-Reply-To: References: Message-ID: Pull requests are more than welcome, Peter! Kevin On Mon, Oct 15, 2012 at 7:11 AM, Peter Hull wrote: > I noticed that some of the code documentation is truncated - for > example vec::each_mut > (http://dl.rust-lang.org/doc/core/vec.html#function-each_mut) says: > Like each(), but for the case where you have > and the actual code is > (https://github.com/mozilla/rust/blob/master/src/libcore/vec.rs) > /// Like `each()`, but for the case where you have > /// a vector with mutable contents and you would like > /// to mutate the contents as you iterate. > #[inline(always)] > pub fn each_mut(v: &[mut T], f: fn(elem: &mut T) -> bool) { > > I couldn't see an issue report on this, if it is indeed a bug (maybe > multiple single-line doc comments are not meant to be concatenated?) > Should I file a report? > > Pete > > ps. on a side note I am trying to get up to speed with rust now it's > settling down a bit with 0.4. I noticed some functions aren't > documented at all in the source (e.g. vec::append), so would it be > helpful if I added documentation as I go along and submit a pull > request, or is that already in hand? > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From mahmutbulut0 at gmail.com Mon Oct 15 11:29:17 2012 From: mahmutbulut0 at gmail.com (Mahmut Bulut) Date: Mon, 15 Oct 2012 21:29:17 +0300 Subject: [rust-dev] Specific help needed section for Rust Message-ID: Hi I'm Mahmut. I want to ask any specific help on something in Rust. Lexer, memory management etc. ? Please guide me through... Thanks in advance -------------- next part -------------- An HTML attachment was scrubbed... URL: From lists.rust at dbp.mm.st Mon Oct 15 11:56:39 2012 From: lists.rust at dbp.mm.st (Daniel Patterson) Date: Mon, 15 Oct 2012 14:56:39 -0400 Subject: [rust-dev] Specific help needed section for Rust In-Reply-To: References: Message-ID: Check the issue tracker - there are plenty of things to do! https://github.com/mozilla/rust/issues On Oct 15, 2012, at 2:29 PM, Mahmut Bulut wrote: > Hi I'm Mahmut. I want to ask any specific help on something in Rust. Lexer, memory management etc. ? Please guide me through... > Thanks in advance > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Mon Oct 15 11:59:53 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 15 Oct 2012 11:59:53 -0700 Subject: [rust-dev] Possible rustdoc error? In-Reply-To: References: Message-ID: <507C5D29.7030905@alum.mit.edu> Peter Hull wrote: > I couldn't see an issue report on this, if it is indeed a bug (maybe > multiple single-line doc comments are not meant to be concatenated?) > Should I file a report? Yes, the correct thing is to use /** ... */ there. This could well be my fault, I didn't realize this for a while, and hence was using ///. Niko From jld at panix.com Mon Oct 15 12:35:19 2012 From: jld at panix.com (Jed Davis) Date: Mon, 15 Oct 2012 12:35:19 -0700 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: <507B0F99.4000204@mozilla.com> References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> <507B0F99.4000204@mozilla.com> Message-ID: <20121015193518.GA19874@panix.com> On Sun, Oct 14, 2012 at 12:16:41PM -0700, Patrick Walton wrote: > * Rust builds itself three times for bootstrapping. This is > unavoidable as long as Rust is bootstrapped. GCC also builds itself three times for bootstrapping; like rustc, it's written in the language that it compiles. GCC can be built without bootstrapping for development (or to use as a cross-compiler), but a successful bootstrap is required as part of testing. So I don't know that it's entirely fair to criticize Rust for this aspect of the compilation time. (It would be nice to have --disable-bootstrap, though.) --Jed From mahmutbulut0 at gmail.com Mon Oct 15 12:40:30 2012 From: mahmutbulut0 at gmail.com (Mahmut Bulut) Date: Mon, 15 Oct 2012 22:40:30 +0300 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: <20121015193518.GA19874@panix.com> References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> <507B0F99.4000204@mozilla.com> <20121015193518.GA19874@panix.com> Message-ID: in my opinion i saw lots of valgrind checks and this causes slow compilation... 15 Eki 2012 22:35 tarihinde "Jed Davis" yazd?: > On Sun, Oct 14, 2012 at 12:16:41PM -0700, Patrick Walton wrote: > > * Rust builds itself three times for bootstrapping. This is > > unavoidable as long as Rust is bootstrapped. > > GCC also builds itself three times for bootstrapping; like rustc, it's > written in the language that it compiles. GCC can be built without > bootstrapping for development (or to use as a cross-compiler), but a > successful bootstrap is required as part of testing. > > So I don't know that it's entirely fair to criticize Rust for this aspect > of the compilation time. (It would be nice to have --disable-bootstrap, > though.) > > --Jed > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From banderson at mozilla.com Mon Oct 15 12:41:59 2012 From: banderson at mozilla.com (Brian Anderson) Date: Mon, 15 Oct 2012 12:41:59 -0700 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> <507B61CC.5090202@mozilla.com> Message-ID: <507C6707.1040707@mozilla.com> On 10/15/2012 01:42 AM, Nadav Vinik wrote: > Why rust work with a special custom llvm instead of the standard? Right now we are carrying a number of GC patches and a few misc bugfixes that haven't been upstreamed. From banderson at mozilla.com Mon Oct 15 12:51:09 2012 From: banderson at mozilla.com (Brian Anderson) Date: Mon, 15 Oct 2012 12:51:09 -0700 Subject: [rust-dev] Possible rustdoc error? In-Reply-To: References: Message-ID: <507C692D.4000900@mozilla.com> On 10/15/2012 07:11 AM, Peter Hull wrote: > I noticed that some of the code documentation is truncated - for > example vec::each_mut > (http://dl.rust-lang.org/doc/core/vec.html#function-each_mut) says: > Like each(), but for the case where you have > and the actual code is > (https://github.com/mozilla/rust/blob/master/src/libcore/vec.rs) > /// Like `each()`, but for the case where you have > /// a vector with mutable contents and you would like > /// to mutate the contents as you iterate. > #[inline(always)] > pub fn each_mut(v: &[mut T], f: fn(elem: &mut T) -> bool) { > > I couldn't see an issue report on this, if it is indeed a bug (maybe > multiple single-line doc comments are not meant to be concatenated?) > Should I file a report? > Yes, please. Each /// line is parsed as a single attribute and rustdoc is only using the first and ignoring the rest. From banderson at mozilla.com Mon Oct 15 12:55:30 2012 From: banderson at mozilla.com (Brian Anderson) Date: Mon, 15 Oct 2012 12:55:30 -0700 Subject: [rust-dev] RFC: All extern "C" functions are unsafe In-Reply-To: <507C286C.3060905@alum.mit.edu> References: <5078565B.1030402@mozilla.com> <507863AA.9040406@mozilla.com> <50786FAD.9020701@alum.mit.edu> <407BE4F8-35DE-430E-8D19-A655EF161DDC@googlemail.com> <507B2241.7090300@alum.mit.edu> <559C4AFB-0026-4C11-A705-022770BC1BE1@googlemail.com> <507C286C.3060905@alum.mit.edu> Message-ID: <507C6A32.1090000@mozilla.com> On 10/15/2012 08:14 AM, Niko Matsakis wrote: > (Note: we somehow lost the rust-dev cc, see Stefan's e-mail below) > > Under the plan as I envisioned it in my head, ignoring the question > about unsafety, it would be necessary to write a wrapper for a C > function if you wanted it to have the same type as a Rust fn (as opposed > to an `extern "C" fn()` type). However, I could imagine permitting > extern fn items to be coerced to Rust type, and having the compiler > auto-generate a wrapper. We plan to do something similar with top-level > Rust fns: they will be coercable to a C function type, so that any Rust > fn item can used as a callback, and not just an "extern fn". However, > this of course immediately raises the question of unsafety: we could > presumably want a way to declare that those C functions are safe as well. > > Another option is just to use a macro, of course. Or that would be an > option if we supported item-level macros, which we hopefully will soon. > > The question I guess is how often this situation comes up. Is it just > libmath? Or is this sort of thing extremely common when doing bindings? Personally, I think making c_math do wrappers is not a big deal. Somewhat OT: Regarding our new approach of generating the wrappers on demand, I think that this is fine, but also that someday we probably will want to be able to call cdecl Rust functions directly from native code, without a stack switch. JS wants to call in to Rust as fast as technically possible and that may eventually mean getting rid of the extra function pointer. From niko at alum.mit.edu Mon Oct 15 13:09:43 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 15 Oct 2012 13:09:43 -0700 Subject: [rust-dev] Specific help needed section for Rust In-Reply-To: References: Message-ID: <507C6D87.1060401@alum.mit.edu> I would suggest browsing the bugs tagged as E-Easy: https://github.com/mozilla/rust/issues?labels=E-easy&page=1&state=open or for something a bit more ambitious, those tagged as A-an-interesting-project: https://github.com/mozilla/rust/issues?labels=E-easy%2CA-an-interesting-project&page=1&state=open Niko > Mahmut Bulut > October 15, 2012 11:29 AM > > Hi I'm Mahmut. I want to ask any specific help on something in Rust. > Lexer, memory management etc. ? Please guide me through... > Thanks in advance > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: postbox-contact.jpg Type: image/jpeg Size: 1323 bytes Desc: not available URL: From banderson at mozilla.com Mon Oct 15 13:16:41 2012 From: banderson at mozilla.com (Brian Anderson) Date: Mon, 15 Oct 2012 13:16:41 -0700 Subject: [rust-dev] Specific help needed section for Rust In-Reply-To: References: Message-ID: <507C6F29.9010701@mozilla.com> On 10/15/2012 11:56 AM, Daniel Patterson wrote: > Check the issue tracker - there are plenty of things to do! > > https://github.com/mozilla/rust/issues > This wiki page has a section called 'picking something interesting to do' that offers some suggestions for finding the good stuff: https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust From graydon at mozilla.com Mon Oct 15 13:31:06 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Mon, 15 Oct 2012 13:31:06 -0700 Subject: [rust-dev] Rust 0.4 released Message-ID: <507C728A.3090309@mozilla.com> Mozilla and the Rust community are pleased to announce version 0.4 of the Rust compiler and associated tools. This release focuses on stabilizing as much of the language syntax as possible, fully integrating borrowed pointers, and removing argument modes. The brief release notes are included in this announcement, and there is further explanation in the detailed release [notes] on the wiki. Documentation and all the links in this email are available on the [website]. As usual, version 0.4 should be considered an alpha release, suitable for early adopters and language enthusiasts. Please file [bugs]. [notes]: https://github.com/mozilla/rust/wiki/Doc-detailed-release-notes [website]: http://www.rust-lang.org [bugs]: http://github.com/mozilla/rust/issues This release is available as both a tarball and a Windows installer: * http://dl.rust-lang.org/dist/rust-0.4.tar.gz http://dl.rust-lang.org/dist/rust-0.4.tar.gz.asc SHA256 (of .tar.gz): 150685f07e4d605cadf9fba25b05e9cc1b009364dd744131cf4230d64981d093 * http://dl.rust-lang.org/dist/rust-0.4-install.exe http://dl.rust-lang.org/dist/rust-0.4-install.exe.asc SHA256 (of .exe): 957bb98c0ff0af209a646c0e961abc98117363695e244e31a89c76d32d4ca827 Regrettably, installing 0.4 over 0.3 will not work as expected. Please uninstall first. Note that the Windows installer still requires a somewhat specific version of MinGW and Msys to operate; recent builds of MinGW provide versions of GCC that are incompatible. Rust presently builds and tests with release 20110802, containing GCC 4.5. [Details] can be found on the wiki. [details]: https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust Thanks to everybody who has contributed[1]. Regards, The Rust Team Version 0.4 (October 2012) -------------------------- * ~2200 changes, numerous bugfixes * Syntax * All keywords are now strict and may not be used as identifiers anywhere * Keyword removal: 'again', 'import', 'export', 'check', 'new', 'owned', 'send', 'of', 'with', 'to', 'class'. * Classes are replaced with simpler structs * Explicit method self types * `ret` became `return` and `alt` became `match` * `import` is now `use`; `use is now `extern mod` * `extern mod { ... }` is now `extern { ... }` * `use mod` is the recommended way to import modules * `pub` and `priv` replace deprecated export lists * The syntax of `match` pattern arms now uses fat arrow (=>) * `main` no longer accepts an args vector; use `os::args` instead * Semantics * Trait implementations are now coherent, ala Haskell typeclasses * Trait methods may be static * Argument modes are deprecated * Borrowed pointers are much more mature and recommended for use * Static strings and vectors are stored in constant memory * Typestate was removed * Resolution rewritten to be more reliable * Support for 'dual-mode' data structures (freezing and thawing) * Libraries * Most binary operators can now be overloaded via the traits in `core::ops' * `std::net::url` for representing URLs * Sendable hash maps in `core::send_map` * `core::task' gained a (currently unsafe) task-local storage API * Concurrency * An efficient new intertask communication primitive called the pipe, along with a number of higher-level channel types, in `core::pipes` * `std::arc`, an atomically reference counted, immutable, shared memory type * `std::sync`, various synchronization tools based on arcs and pipes * Futures are now based on pipes and sendable * More robust linked task failure * Improved task builder API * Other * Improved error reporting * Preliminary JIT support * Preliminary work on precise GC * Extensive architectural improvements to rustc * Begun a transition away from buggy C++-based reflection (shape) code to Rust-based (visitor) code * All hash functions and tables converted to secure, randomized SipHash [1]: Contributors to Rust 0.4: Andrew Paseltiner Ben Blum Ben Striegel Benjamin Peterson Brian Anderson Brian J. Burg Chris Peterson Damian Gryski Daniel Patterson Drew Willcoxon Elliott Slaughter Eric Holk Erick Tryzelaar Francisco Souza Gareth Daniel Smith Glenn Willen Gon?alo Cabrita Graydon Hoare Jacob Harris Cryer Kragh Jed Davis Jeff Olson Jesse Ruderman Jim Blandy Joshua Wise Jyun-Yan You Kevin Cantu Lindsey Kuper Luca Bruno Max Penet Michael Sullivan Niko Matsakis Orph?e Lafond-Lummis Patrick Walton Patrik K?rlin Paul Stansifer Philipp Br?schweiler Ryan Scheel Ted Horst Tim Chevalier Vincent Belliard Yasuhiro Fujii Zack Corr alexrp auREAX tav From bklooste at gmail.com Mon Oct 15 23:54:15 2012 From: bklooste at gmail.com (Bennie Kloosteman) Date: Tue, 16 Oct 2012 14:54:15 +0800 Subject: [rust-dev] RFC: All extern "C" functions are unsafe In-Reply-To: <507C6A32.1090000@mozilla.com> References: <5078565B.1030402@mozilla.com> <507863AA.9040406@mozilla.com> <50786FAD.9020701@alum.mit.edu> <407BE4F8-35DE-430E-8D19-A655EF161DDC@googlemail.com> <507B2241.7090300@alum.mit.edu> <559C4AFB-0026-4C11-A705-022770BC1BE1@googlemail.com> <507C286C.3060905@alum.mit.edu> <507C6A32.1090000@mozilla.com> Message-ID: I think its quite important especially when you get 100K to 1M line projects knowing what is safe .. Nothing more annoying that c Heisenbugs some which took a decade to track down . If the c lib is mature people will write wrappers and with a bit of luck eventually the wrappers may mature into safe rust libs. In C# they use assemblies and you must explicitly allow unsafe assemblies except for system libs ( i dont know the mechanism but mscorlib has a ton of unsafe). The idea being that they put that unsafe through an incredible amount of automated and manual checks which is not likely to be repeated in typical projects. Ist there are a compile switch to allow unsafe then you can link in c at will . Ben -------------- next part -------------- An HTML attachment was scrubbed... URL: From peterhull90 at gmail.com Tue Oct 16 02:15:01 2012 From: peterhull90 at gmail.com (Peter Hull) Date: Tue, 16 Oct 2012 10:15:01 +0100 Subject: [rust-dev] Possible rustdoc error? In-Reply-To: <507C692D.4000900@mozilla.com> References: <507C692D.4000900@mozilla.com> Message-ID: On Mon, Oct 15, 2012 at 8:51 PM, Brian Anderson wrote: > Yes, please. Each /// line is parsed as a single attribute and rustdoc is > only using the first and ignoring the rest. OK, it's issue #3780 Pete From garethdanielsmith at gmail.com Tue Oct 16 12:02:34 2012 From: garethdanielsmith at gmail.com (Gareth Smith) Date: Tue, 16 Oct 2012 20:02:34 +0100 Subject: [rust-dev] Rust 0.4 released In-Reply-To: <507C728A.3090309@mozilla.com> References: <507C728A.3090309@mozilla.com> Message-ID: <507DAF4A.9080901@gmail.com> On 15/10/12 21:31, Graydon Hoare wrote: > Mozilla and the Rust community are pleased to announce version 0.4 of > the Rust compiler and associated tools. Thanks Graydon and the rest of Mozilla and the others. Rust is shaping up. :) Gareth From jonathan.bragg at alum.rpi.edu Tue Oct 16 17:47:20 2012 From: jonathan.bragg at alum.rpi.edu (Nate Bragg) Date: Tue, 16 Oct 2012 20:47:20 -0400 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> Message-ID: Just wanted to say, to those of you who are concerned about the build time, that at least for you it builds in under an hour. I just built 0.4, and it took almost exactly 25 hours. One more sign that I should upgrade my computer. ;^) On Sun, Oct 14, 2012 at 1:20 PM, John Mija wrote: > This email is related to one sent to the Go mailing list[1] about the > great difference in compiling time between Rust which took 50 minutes, > and Go with a time of 2 minutes in build compiler, all libraries, all > commands and testing. > > It looks that it is possible because it has been written in C, instead > of use C++. It is also interesting to know that the Go compiler has been > based in the Plan9 C compilers[2]. > > > [1]: > https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/bKDfVp0dzKw > [2]: http://doc.cat-v.org/bell_labs/new_c_compilers/ > http://doc.cat-v.org/plan_9/4th_edition/papers/compiler > > Note: do not take this email like negative, I only hope that Rust can go > to better in time. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From catamorphism at gmail.com Tue Oct 16 19:03:23 2012 From: catamorphism at gmail.com (Tim Chevalier) Date: Tue, 16 Oct 2012 19:03:23 -0700 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> Message-ID: On Tue, Oct 16, 2012 at 5:47 PM, Nate Bragg wrote: > Just wanted to say, to those of you who are concerned about the build time, > that at least for you it builds in under an hour. > > I just built 0.4, and it took almost exactly 25 hours. > > One more sign that I should upgrade my computer. ;^) I'm guessing this is a sign that you don't have enough physical memory to build Rust > > On Sun, Oct 14, 2012 at 1:20 PM, John Mija wrote: >> >> This email is related to one sent to the Go mailing list[1] about the >> great difference in compiling time between Rust which took 50 minutes, >> and Go with a time of 2 minutes in build compiler, all libraries, all >> commands and testing. >> >> It looks that it is possible because it has been written in C, instead >> of use C++. It is also interesting to know that the Go compiler has been >> based in the Plan9 C compilers[2]. >> >> >> [1]: >> >> https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/bKDfVp0dzKw >> [2]: http://doc.cat-v.org/bell_labs/new_c_compilers/ >> http://doc.cat-v.org/plan_9/4th_edition/papers/compiler >> >> Note: do not take this email like negative, I only hope that Rust can go >> to better in time. >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev > > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt 'Wouldn't you rather be anything other than the kid who runs around telling stuff what he thinks it is?" -- DavEnd From ben.striegel at gmail.com Wed Oct 17 12:09:06 2012 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Wed, 17 Oct 2012 15:09:06 -0400 Subject: [rust-dev] GPU programming In-Reply-To: <1350500647.4304.140661142045461.75C74857@webmail.messagingengine.com> References: <1350500647.4304.140661142045461.75C74857@webmail.messagingengine.com> Message-ID: (Hi folks, the mailing list has been having some trouble, so I'm forwarding this on John's behalf.) ---------- Forwarded message ---------- From: John Mija Date: Wed, Oct 17, 2012 at 3:04 PM Subject: GPU programming To: ben.striegel at gmail.com Since Rust compiles down to LLVM and OpenCL is also built on LLVM compiler technology, could be used the GPU from Rust? Which would be perfect to build games and graphical applications in general that require a lot of processing. -------------- next part -------------- An HTML attachment was scrubbed... URL: From tony at rfw.name Thu Oct 18 04:00:14 2012 From: tony at rfw.name (Tony Young) Date: Fri, 19 Oct 2012 00:00:14 +1300 Subject: [rust-dev] Should rustdoc include documentation from public imports? Message-ID: I'm not sure where this should be posted so I hope I won't get yelled at for putting it here. Looking at the documentation for f64 (http://dl.rust-lang.org/doc/0.4/core/f64.html), there isn't any mention of the imports from cmath (https://github.com/mozilla/rust/blob/master/src/libcore/f64.rs#L5), which is confusing when I tried to find where the sin and cos functions were. I'm not sure if this is a fault of incomplete documentation, unintuitive behavior on the part of rustdoc or a "feature". Cheers, Tony From dbp at riseup.net Thu Oct 18 18:05:24 2012 From: dbp at riseup.net (Daniel Patterson) Date: Thu, 18 Oct 2012 21:05:24 -0400 Subject: [rust-dev] Announce: rustle, an api search tool Message-ID: <2FE3D83A-4AC8-486F-96B5-4F164F245033@riseup.net> I'm announcing an initial version of an API search tool for Rust called Rustle. It is inspired by the api search tool for Haskell called Hoogle (http://www.haskell.org/hoogle). It is quite new, but can already do some useful things. You can install it for yourself (http://github.com/dbp/rustle) and run it at the commandline, or use the (experimental) web version at http://lab.dbpmail.net/rustle/. Some example queries it can can respond to (command line responses shown, but the web-app is similar): rustle> Either -> A core::either::unwrap_left - fn unwrap_left(eith: Either) -> T - Retrieves the value in the left branch. Fails if the either is Right. rustle> ([A], fn(A)->B) -> [B] core::vec::map - fn map(v: & [T], f: fn&(t: & T) -> U) -> ~[U] - Apply a function to each element of a vector and return the results core::vec::map_consume - fn map_consume(v: ~[T], f: fn&(v: T) -> U) -> ~[U] - ... rustle> Either -> uint core::either::unwrap_left - fn unwrap_left(eith: Either) -> T - Retrieves the value in the left branch. Fails if the either is Right. core::either::unwrap_right - fn unwrap_right(eith: Either) -> U - Retrieves the value in the right branch. Fails if the either is Left. rustle> Option,Option -> Option core::option::or - fn or(opta: Option, optb: Option) -> Option - Returns the leftmost some() value, or none if both are none. rustle> each core::str::each - fn each(s: & str, it: fn&(u8) -> bool) - Iterate over the bytes in a string core::vec::each - fn each(v: &r/[T], f: fn&(&r/T) -> bool) - Iterates over a vector, with option to break ... core::vec::each_mut - fn each_mut(v: & [mut T], f: fn&(elem: & mut T) -> bool) - Like core::vec::each_permutation - fn each_permutation(v: & [T], put: fn&(ts: & [T]) -> bool) - Iterate over all permutations of vector ... It will search for functions by types (with tolerance to renamed type variables - i.e., Option matches Option). It will also try to look for more general functions (i.e., Option -> uint matches Option -> T), and rearrange the order of arguments. There is limited support for methods - we include ones declared on types, but not ones that come through traits. There are also massive simplifications - all pointer types are ignored (with the intent being that for searching, you want to see all variants), all single letter uppercase types are treated as polymorphic (so trait constraints are ignored), and the only heuristic for results is the order I chose to import the modules. You can search for functions by names, but only prefixes (this limit will go away eventually). On the other hand, it already does some neat things! To try it out, contribute, improve, file bugs, etc, go to http://github.com/dbp/rustle . The readme should explain how to get started with it. You can also try it out at http://lab.dbpmail.net/rustle/. The web frontend is currently very basic, but it does link to the official documentation. It is all written in rust, except the html scraper (which is not needed to run it). Feedback welcome! Daniel From jon.mb at proinbox.com Thu Oct 18 23:43:09 2012 From: jon.mb at proinbox.com (John Mija) Date: Fri, 19 Oct 2012 07:43:09 +0100 Subject: [rust-dev] Attributes Message-ID: <1350628989.7971.140661142711417.5919C434@webmail.messagingengine.com> Rust has attributes[1] at function-level but (1) the compilation could be faster if they were at file-level, and (2) the project would be more homogeneous and clean. + Instead of to have the attribute "#[test]" for a function, those tests functions could be into a file with the name finished in "_test" (foo_test.rs) indicating that there are unit tests. On this case, we would not need an attribute. + Instead of to have conditionally-compiled modules at function level, that code could be into a file finished in the system name (foo_linux.rs), and/or use attributes at file level. See how Go solved this problem, in Build constraints[2]. + Instead of to have an attribute for the documentation, the parser could get the comment on top of the function to get its documentation. Now: // A documentation attribute #[doc = "Add two numbers together."] fn add(x: int, y: int) { x + y } Proposal: // add adds two numbers together." fn add(x: int, y: int) { x + y } [1]: http://dl.rust-lang.org/doc/0.4/rust.html#attributes [2]: http://golang.org/pkg/go/build/ From pwalton at mozilla.com Thu Oct 18 23:49:17 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 18 Oct 2012 23:49:17 -0700 Subject: [rust-dev] Attributes In-Reply-To: <1350628989.7971.140661142711417.5919C434@webmail.messagingengine.com> References: <1350628989.7971.140661142711417.5919C434@webmail.messagingengine.com> Message-ID: <5080F7ED.4000903@mozilla.com> On 10/18/12 11:43 PM, John Mija wrote: > Rust has attributes[1] at function-level but (1) the compilation could > be faster if they were at file-level I don't think it'd be significantly faster. cfg'd off items are eliminated very early in compilation (right after parsing). > (2) the project would be more homogeneous and clean. At the cost of annoyance when you just have a few functions that differ per-platform. For example, there's just one Apple-specific function in our Apple gl2.rs bindings right now. Having to create a gl2_mac.rs file would be inconvenient. > + Instead of to have the attribute "#[test]" for a function, those tests > functions could be into a file with the name finished in "_test" > (foo_test.rs) indicating that there are unit tests. On this case, we > would not need an attribute. If there are few unit tests, this could get annoying. > + Instead of to have an attribute for the documentation, the parser > could get the comment on top of the function to get its documentation. This already works, if you use /** */ or /// to begin the comments. (I think /// has a bug though in that it only takes the first such comment; that's a bug and should be fixed.) Patrick From jon.mb at proinbox.com Fri Oct 19 00:23:04 2012 From: jon.mb at proinbox.com (John Mija) Date: Fri, 19 Oct 2012 08:23:04 +0100 Subject: [rust-dev] Attributes In-Reply-To: <5080F7ED.4000903@mozilla.com> References: <1350628989.7971.140661142711417.5919C434@webmail.messagingengine.com> <5080F7ED.4000903@mozilla.com> Message-ID: <5080FFD8.2070507@proinbox.com> On 19/10/12 07:49, Patrick Walton wrote: > On 10/18/12 11:43 PM, John Mija wrote: >> Rust has attributes[1] at function-level but (1) the compilation could >> be faster if they were at file-level > > I don't think it'd be significantly faster. cfg'd off items are > eliminated very early in compilation (right after parsing). > >> (2) the project would be more homogeneous and clean. > > At the cost of annoyance when you just have a few functions that differ > per-platform. For example, there's just one Apple-specific function in > our Apple gl2.rs bindings right now. Having to create a gl2_mac.rs file > would be inconvenient. > >> + Instead of to have the attribute "#[test]" for a function, those tests >> functions could be into a file with the name finished in "_test" >> (foo_test.rs) indicating that there are unit tests. On this case, we >> would not need an attribute. > > If there are few unit tests, this could get annoying. > It would make sense to have an attribute at file-level in cases where you have a lot of tests or code for a specific system/architecture, or just because you want to have all more organized. From xtzgzorex at gmail.com Fri Oct 19 00:37:30 2012 From: xtzgzorex at gmail.com (=?ISO-8859-1?Q?Alex_R=F8nne_Petersen?=) Date: Fri, 19 Oct 2012 09:37:30 +0200 Subject: [rust-dev] Should rustdoc include documentation from public imports? In-Reply-To: References: Message-ID: On Thu, Oct 18, 2012 at 1:00 PM, Tony Young wrote: > I'm not sure where this should be posted so I hope I won't get yelled > at for putting it here. > > Looking at the documentation for f64 > (http://dl.rust-lang.org/doc/0.4/core/f64.html), there isn't any > mention of the imports from cmath > (https://github.com/mozilla/rust/blob/master/src/libcore/f64.rs#L5), > which is confusing when I tried to find where the sin and cos > functions were. > > I'm not sure if this is a fault of incomplete documentation, > unintuitive behavior on the part of rustdoc or a "feature". The problem seems to be that core::f64 is importing cmath::c_double::* and then exporting acos which is defined in the latter module. I think rustdoc should make this clear in the generated documentation. Regards, Alex From jon.mb at proinbox.com Fri Oct 19 01:03:39 2012 From: jon.mb at proinbox.com (John Mija) Date: Fri, 19 Oct 2012 09:03:39 +0100 Subject: [rust-dev] GPU programming In-Reply-To: References: <1350500647.4304.140661142045461.75C74857@webmail.messagingengine.com> Message-ID: <5081095B.3060304@proinbox.com> On 17/10/12 20:09, John Mija wrote: > Since Rust compiles down to LLVM and OpenCL is also built on LLVM > compiler technology, could be used the GPU from Rust? Which would be > perfect to build games and graphical applications in general that > require a lot of processing. Does anybody could say if it could be possible any day? Due to that both compilers use LLVM. From lucian.branescu at gmail.com Fri Oct 19 01:05:20 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Fri, 19 Oct 2012 09:05:20 +0100 Subject: [rust-dev] GPU programming In-Reply-To: References: <1350500647.4304.140661142045461.75C74857@webmail.messagingengine.com> Message-ID: I think it might be even more interesting to be able to compile a subset of Rust to GLSL, similar to https://github.com/ztellman/penumbra/wiki/Shaders-and-GPGPU On 17 October 2012 20:09, Benjamin Striegel wrote: > (Hi folks, the mailing list has been having some trouble, so I'm forwarding > this on John's behalf.) > > ---------- Forwarded message ---------- > From: John Mija > Date: Wed, Oct 17, 2012 at 3:04 PM > Subject: GPU programming > To: ben.striegel at gmail.com > > > Since Rust compiles down to LLVM and OpenCL is also built on LLVM > compiler technology, could be used the GPU from Rust? Which would be > perfect to build games and graphical applications in general that > require a lot of processing. > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > From jon.mb at proinbox.com Fri Oct 19 01:12:19 2012 From: jon.mb at proinbox.com (John Mija) Date: Fri, 19 Oct 2012 09:12:19 +0100 Subject: [rust-dev] GPU programming In-Reply-To: References: <1350500647.4304.140661142045461.75C74857@webmail.messagingengine.com> Message-ID: <50810B63.5090104@proinbox.com> El 19/10/12 09:05, Lucian Branescu escribi?: > I think it might be even more interesting to be able to compile a > subset of Rust to GLSL, similar to > https://github.com/ztellman/penumbra/wiki/Shaders-and-GPGPU Penumbra is an wrapper for OpenGL in Clojure; and whatever wrapper to C/C++ code could be created in Rust too. From lucian.branescu at gmail.com Fri Oct 19 01:14:01 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Fri, 19 Oct 2012 09:14:01 +0100 Subject: [rust-dev] GPU programming In-Reply-To: <50810B63.5090104@proinbox.com> References: <1350500647.4304.140661142045461.75C74857@webmail.messagingengine.com> <50810B63.5090104@proinbox.com> Message-ID: Sure, but that's not the interesting bit. Penumbra compiles a subset of Clojure to GLSL, so you don't have to see that silly language so much. This is done with macros in Clojure, but I'm not sure if Rust's macros are as expressive. At the very least it should be doable as a compiler plugin. On 19 October 2012 09:12, John Mija wrote: > > El 19/10/12 09:05, Lucian Branescu escribi?: > >> I think it might be even more interesting to be able to compile a >> subset of Rust to GLSL, similar to >> https://github.com/ztellman/penumbra/wiki/Shaders-and-GPGPU > > Penumbra is an wrapper for OpenGL in Clojure; and whatever wrapper to C/C++ > code could be created in Rust too. > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From lucian.branescu at gmail.com Fri Oct 19 02:18:49 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Fri, 19 Oct 2012 10:18:49 +0100 Subject: [rust-dev] Attributes In-Reply-To: <1350628989.7971.140661142711417.5919C434@webmail.messagingengine.com> References: <1350628989.7971.140661142711417.5919C434@webmail.messagingengine.com> Message-ID: I've found first-class documentation to be very useful in Python, and much more reliable than javadoc-like things. I'd much rather have an attribute that is clearly linked to the function rather than a comment floating about. On 19 October 2012 07:43, John Mija wrote: > Rust has attributes[1] at function-level but (1) the compilation could > be faster if they were at file-level, and (2) the project would be more > homogeneous and clean. > > + Instead of to have the attribute "#[test]" for a function, those tests > functions could be into a file with the name finished in "_test" > (foo_test.rs) indicating that there are unit tests. On this case, we > would not need an attribute. > > + Instead of to have conditionally-compiled modules at function level, > that code could be into a file finished in the system name > (foo_linux.rs), and/or use attributes at file level. See how Go solved > this problem, in Build constraints[2]. > > + Instead of to have an attribute for the documentation, the parser > could get the comment on top of the function to get its documentation. > > Now: > > // A documentation attribute > #[doc = "Add two numbers together."] > fn add(x: int, y: int) { x + y } > > Proposal: > > // add adds two numbers together." > fn add(x: int, y: int) { x + y } > > > [1]: http://dl.rust-lang.org/doc/0.4/rust.html#attributes > [2]: http://golang.org/pkg/go/build/ > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From graydon at mozilla.com Fri Oct 19 07:47:57 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 19 Oct 2012 07:47:57 -0700 Subject: [rust-dev] Attributes In-Reply-To: <5080FFD8.2070507@proinbox.com> References: <1350628989.7971.140661142711417.5919C434@webmail.messagingengine.com> <5080F7ED.4000903@mozilla.com> <5080FFD8.2070507@proinbox.com> Message-ID: <5081681D.8030700@mozilla.com> On 19/10/2012 12:23 AM, John Mija wrote: > It would make sense to have an attribute at file-level in cases where > you have a lot of tests or code for a specific system/architecture, or > just because you want to have all more organized. This is already possible. Attribute the 'mod' item that links the file into the crate namespace itself. "Files" don't really exist much in the rust compiler's brain; it's dimly aware of them during initial parse, after that it just works on a single module tree, and the residue of a "file" is a module-boundary in the module tree. Any module can have attributes on it. -Graydon From graydon at mozilla.com Fri Oct 19 07:50:05 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 19 Oct 2012 07:50:05 -0700 Subject: [rust-dev] Attributes In-Reply-To: References: <1350628989.7971.140661142711417.5919C434@webmail.messagingengine.com> Message-ID: <5081689D.5050508@mozilla.com> On 19/10/2012 2:18 AM, Lucian Branescu wrote: > I've found first-class documentation to be very useful in Python, and > much more reliable than javadoc-like things. > > I'd much rather have an attribute that is clearly linked to the > function rather than a comment floating about. This was my preference too but enough people wanted the comment-based syntax that we support it as well. They're synonymous: /** ... */ is treated merely as a different syntax for #[doc="..."]. -Graydon From graydon at mozilla.com Fri Oct 19 08:13:37 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 19 Oct 2012 08:13:37 -0700 Subject: [rust-dev] GPU programming In-Reply-To: <5081095B.3060304@proinbox.com> References: <1350500647.4304.140661142045461.75C74857@webmail.messagingengine.com> <5081095B.3060304@proinbox.com> Message-ID: <50816E21.4060607@mozilla.com> On 19/10/2012 1:03 AM, John Mija wrote: > > On 17/10/12 20:09, John Mija wrote: >> Since Rust compiles down to LLVM and OpenCL is also built on LLVM >> compiler technology, could be used the GPU from Rust? Which would be >> perfect to build games and graphical applications in general that >> require a lot of processing. > Does anybody could say if it could be possible any day? Due to that both > compilers use LLVM. There's no support for this in rustc presently, nor do Mozilla engineers have it on our near-term roadmap for language work _we're_ planning to do in the next couple releases. There's nothing about it that's intrinsically impossible -- certainly we've talked a bit about it and a number of people have expressed interest -- but we haven't committed any of our own resources to exploring it yet. Exploratory patches in this area, if they aren't too disruptive to the rest of the compiler, might be something we'd merge into our branch. For example, hooking up to LLVM's JIT wasn't a _high_ priority for 0.4, but Zack Corr decided to tackle it and it turned out to work without too much disruption, so we merged it into our branch too. If someone's really keen to start playing around with a concrete version of an OpenCL binding or embedding, please let us know. (Personally I suspect the best way to approach this is in separate steps: first make a binding to the OpenCL runtime using the C API for transferring data and loading/activating kernels explicitly from Rust, then start tinkering with possible language subsets for defining kernels in rust and/or automating portions of the data-transfer. But there's a lot of experimentation to do here, I might be completely wrong. I've actually never programmed in OpenCL, so take my advice with suspicion.) -Graydon From banderson at mozilla.com Fri Oct 19 13:06:53 2012 From: banderson at mozilla.com (Brian Anderson) Date: Fri, 19 Oct 2012 13:06:53 -0700 (PDT) Subject: [rust-dev] Announce: rustle, an api search tool In-Reply-To: <2FE3D83A-4AC8-486F-96B5-4F164F245033@riseup.net> Message-ID: <559585922.3512633.1350677213602.JavaMail.root@mozilla.com> This is awesome. From banderson at mozilla.com Fri Oct 19 13:18:04 2012 From: banderson at mozilla.com (Brian Anderson) Date: Fri, 19 Oct 2012 13:18:04 -0700 (PDT) Subject: [rust-dev] Should rustdoc include documentation from public imports? In-Reply-To: Message-ID: <714218952.3513551.1350677884108.JavaMail.root@mozilla.com> ----- Original Message ----- > From: "Alex R?nne Petersen" > To: "Tony Young" > Cc: rust-dev at mozilla.org > Sent: Friday, October 19, 2012 12:37:30 AM > Subject: Re: [rust-dev] Should rustdoc include documentation from public imports? > > On Thu, Oct 18, 2012 at 1:00 PM, Tony Young wrote: > > I'm not sure where this should be posted so I hope I won't get > > yelled > > at for putting it here. > > > > I'm not sure if this is a fault of incomplete documentation, > > unintuitive behavior on the part of rustdoc or a "feature". > > The problem seems to be that core::f64 is importing > cmath::c_double::* > and then exporting acos which is defined in the latter module. > > I think rustdoc should make this clear in the generated > documentation. > Documenting reexports (pub use) is a [problem] for rustdoc because figuring out what those items actually represent requires running the full compiler resolution pass, which requires fully compiling all dependencies, and that is not the place of a documentation tool. [problem]: https://github.com/mozilla/rust/issues/3537 One thing we could do is add new rustdoc attributes for manually annotating reexports, either at the reexport site itself or the original definition site. We could also come up with language changes to remove this problem. Certainly toolability is a major goal of Rust and reexports are not tool-friendly. From graydon at mozilla.com Fri Oct 19 13:27:15 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 19 Oct 2012 13:27:15 -0700 Subject: [rust-dev] Announce: rustle, an api search tool In-Reply-To: <2FE3D83A-4AC8-486F-96B5-4F164F245033@riseup.net> References: <2FE3D83A-4AC8-486F-96B5-4F164F245033@riseup.net> Message-ID: <5081B7A3.3060504@mozilla.com> On 12-10-18 06:05 PM, Daniel Patterson wrote: > To try it out, contribute, improve, file bugs, etc, go to http://github.com/dbp/rustle . The readme > should explain how to get started with it. You can also try it out at http://lab.dbpmail.net/rustle/. The > web frontend is currently very basic, but it does link to the official documentation. It is all written in rust, > except the html scraper (which is not needed to run it). > > Feedback welcome! It's great! Can we integrate it into the 'standard' toolset we ship at some point? I'd very much like command-line API-search to be normal / built-in, or even considered part of rustdoc. "rust doc -s " or such. (Not to detract too much from all the clever rust-derived names flying past; I mostly just want tools to be _discoverable_) -Graydon From graydon at mozilla.com Fri Oct 19 16:48:37 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 19 Oct 2012 16:48:37 -0700 Subject: [rust-dev] condition handling Message-ID: <5081E6D5.50700@mozilla.com> Hi, If you're going to respond to this email, please read it in full, don't just skim. I've been sketching a module in core::condition this week that implements a condition-handling system on top of the TLS feature (task::local_data) that Ben Blum added over the summer. This email is a very specific description of what I'm adding (many people have asked) along with a very specific poll about how best to structure the outermost part of the API. I'd appreciate replies here be kept focused on those points -- clarifying questions + indication of preference on API -- as there are a lot of new people on the list since we last discussed this, but we are _not_ changing plan here. This is the same plan we've had for 6-ish years, off-and-on, sketched numerous times, whenever it seems implementable with the pieces lying around. I'm not interested in having a big discussion of all the possible ways condition-systems can be built, or (re-)exploring the design-space. Some references to the lurking plan here: https://mail.mozilla.org/pipermail/rust-dev/2012-May/001879.html https://mail.mozilla.org/pipermail/rust-dev/2011-November/000999.html https://github.com/mozilla/rust/issues/1945#issuecomment-4425610 Anyway, here is the system (again) in a nutshell: - Tasks have a task-local storage system (TLS). TLS maps keys to values that stick to the task until released. The keys are addresses, conventionally static addresses of items (this is a hack for producing 'unique' keys, but it works). - Handlers are stack-closures that get pushed and popped from TLS. They obey stack discipline and can capture their lexical environment since they'll be popped before the pushing frame exits. - Handlers are put in TLS keyed to a condition. A condition is a static, symbolic value used mostly for its TLS-keying and method-dispatching capabilities. Conditions don't store values, they just name situations that might occur and give-type-to any values passed-to and returned-from potential handlers of such situations. - Code can raise a condition whenever it likes. No static checking of which conditions might occur where; no relationship to function types. Raising of a condition in a module is indicated by the condition being present in the module, by convention, or by documentation. - Raising a condition can pass a value giving further details on the condition, beyond just its type/name. If the raise is handled, a value may return. The types of values raised-to and returned-from handlers is specified by a condition. That is, a condition is declared like "const OutOfKittens : Condition = ..." where T is the type of values passed to an OutOfKittens handler, and U is the type of values returned from an OutOfKittens handler when it is returning a solution to the condition. U might well be a symbolic type such as an enum of reasonable recovery strategies. - There is no change to the fail/unwind system. Failure is still unrecoverable, results in unwinding, and is the only possible cause of unwinding. If a condition is handled, it doesn't unwind. If it's unhandled, or if the handler fails, the task fails and unwinds. This is not an unwind-rewind system or an unwind-catch system. - Condition.raise is a normal function and does something very simple: - look in TLS to see if there's a handler - if so, call it and return the result to the raiser - if not, fail - This means condition-handling happens _at site_ of raising. If the handler returns a useful value, processing continues as if nothing went wrong. It's _just_ a rendezvous mechanism for an outer frame to dynamically provide a handler closure to an inner frame where a condition occurs. Given that description, astute readers may note that there's not much to this "system", mostly just convention and existing pieces. This is intentional. It's supposed to be very minimal and only took about a day to get working, beyond the miserable slog Ben already fought through implementing TLS over the summer. Nonetheless I want to get it _right_ since this is probably going to be a convention that sticks and gets used extensively across our libraries. Getting it nailed down is a priority for the 0.5 cycle, as we're trying to knock out the top few remaining toe-stubs when writing libraries, and this is one of them. We've grown an unfortunate dependence on using the core::Result type for managing recoverable-problems in library code and I would like to move away from that in as many cases as practical, since at-site handling tends to be much cleaner for users. Since 'Result' is so clunky we wind up using unrecoverable 'fail' in a lot of cases too, sometimes cases where having the option to recover makes sense. So: API survey. Modulo a few residual bugs on consts and function regions (currently hacked around in the implementation), I have 3 different APIs that all seem to work -- which I've given different names for discussion sake -- and I'm trying to decide between them. They mostly differ in the number of pieces and the location and shape of the boilerplate a user of the condition system has to write. My current preference is #3 but I'd like a show of hands on others' preferences. Here they are: 1. "Protect/handle", a.k.a. "make it look like try/catch": this version pursues the arrangement with protected-code coming first and handlers coming second. To do this, the protected-code has to be suspended in a closure, which is then passed to a temporary struct, which is responsible for both capturing the remaining handler-part and firing the push/run/pop cycle together at the end. Uses of it look like this: let b = do OutOfKittens.protect { do_some_stuff(); that_might_raise(); out_of_kittens(); }; do b.handle |t| { UseAardvarksInstead } It's not really an ideal use of our 'do' syntax, nor are many other variants of this API I've tried. It might read slightly better (or worse) as such: (do OutOfKittens.protect { do_some_stuff(); that_might_raise(); out_of_kittens(); }).handle(|t| UseAardvarksInstead ); 2. "Guard", a.k.a. "make it look like RAII": this version has only a single "floating in space" handler-block that is assigned to a temporary guard object in the current scope, and all subsequent code in that scope is protected. Reads like this: { let _g = OutOfKittens.guard(|t| UseAardvarksInstead); do_some_stuff(); that_might_raise(); out_of_kittens(); } Downsides of this mechanism are that a user might try to move _g out of the current frame or otherwise tamper with it -- we might need to do some tricks with the region system to prevent that -- and it gives rise to this somewhat artificial _g variable and otherwise unclear extra block to contain it. 3. "Trap/in", a.k.a. "the system I like the look of best": this is the version Patrick suggested yesterday. It sets up the handlers in the head of a do-block and then invokes the protected code. It's order-inverted from protect/handle -- the handlers come before the protected code -- but it still reads ok to my eyes, and seems to play nicely with our existing syntax: do OutOfKittens.trap(|t| UseAardvarksInstead).in { do_some_stuff(); that_might_raise(); out_of_kittens(); } Opinions? Clarifying questions? Thanks, -Graydon From erick.tryzelaar at gmail.com Fri Oct 19 17:16:42 2012 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Fri, 19 Oct 2012 17:16:42 -0700 Subject: [rust-dev] condition handling In-Reply-To: <5081E6D5.50700@mozilla.com> References: <5081E6D5.50700@mozilla.com> Message-ID: On Fri, Oct 19, 2012 at 4:48 PM, Graydon Hoare wrote: > > 3. "Trap/in", a.k.a. "the system I like the look of best": this is the > version Patrick suggested yesterday. It sets up the handlers in the head > of a do-block and then invokes the protected code. It's order-inverted > from protect/handle -- the handlers come before the protected code -- > but it still reads ok to my eyes, and seems to play nicely with our > existing syntax: > > do OutOfKittens.trap(|t| UseAardvarksInstead).in { > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > } > > Opinions? Clarifying questions? I like 3 the best, and 2 not at all unless we can somehow gensym and hide the guard value. Otherwise I expect I'd forget to store it in a variables and not actually have my trap enabled. From jboy at jboy.me Sat Oct 20 02:16:34 2012 From: jboy at jboy.me (James Boyden) Date: Sat, 20 Oct 2012 20:16:34 +1100 Subject: [rust-dev] condition handling In-Reply-To: <5081E6D5.50700@mozilla.com> References: <5081E6D5.50700@mozilla.com> Message-ID: On Sat, Oct 20, 2012 at 10:48 AM, Graydon Hoare wrote: > Some references to the lurking plan here: > https://mail.mozilla.org/pipermail/rust-dev/2011-November/000999.html Firstly, I'd like to express my appreciation for the clear reasoning in this linked post. I found the arguments clear and compelling, matching my own experience -- especially the enumeration of the small set of realistic uses of exception handling (ignore, retry, hard-fail, log, or try one of a small number of alternatives to achieve the desired result). > - Condition.raise is a normal function and does something very simple: > - look in TLS to see if there's a handler > - if so, call it and return the result to the raiser > - if not, fail > > - This means condition-handling happens _at site_ of raising. If > the handler returns a useful value, processing continues as if > nothing went wrong. It's _just_ a rendezvous mechanism for an > outer frame to dynamically provide a handler closure to an inner > frame where a condition occurs. This all seems reasonable after reading that post. > So: API survey. Modulo a few residual bugs on consts and function > regions (currently hacked around in the implementation), I have 3 > different APIs that all seem to work -- which I've given different names > for discussion sake -- and I'm trying to decide between them. They > mostly differ in the number of pieces and the location and shape of the > boilerplate a user of the condition system has to write. My current > preference is #3 but I'd like a show of hands on others' preferences. > Opinions? Clarifying questions? I prefer option #3. I like that it states the condition and handler up-front (in contrast to most exception-handling syntaxes, that leave you guessing what might go wrong until you reach the catch statements at the end of the try/catch block). I like that the error-handling code is implicitly not an afterthought. (I find that when I'm writing the code on the main path, there's a strong temptation to just "keep on coding", and come back to insert the error-handling code "later".) I like that it has the minimum of boilerplate code (in contrast to option #1 especially). In addition to the boilerplate, I don't really like option #1 because of the separation of the protected block from the handler code. My concern with option #2 is that, despite my general fondness for RAII, the '_g' variable isn't explicitly used anywhere, so creating a named variable seems redundant. Plus, having an object that can reach out of its variable and affect all the code that follows in its block scope is too "magical" for my liking. jb From matthieu.monrocq at gmail.com Sat Oct 20 04:19:26 2012 From: matthieu.monrocq at gmail.com (Matthieu Monrocq) Date: Sat, 20 Oct 2012 13:19:26 +0200 Subject: [rust-dev] condition handling In-Reply-To: References: <5081E6D5.50700@mozilla.com> Message-ID: On Sat, Oct 20, 2012 at 11:16 AM, James Boyden wrote: > On Sat, Oct 20, 2012 at 10:48 AM, Graydon Hoare > wrote: > > > Some references to the lurking plan here: > > https://mail.mozilla.org/pipermail/rust-dev/2011-November/000999.html > > Firstly, I'd like to express my appreciation for the clear reasoning > in this linked post. > > I found the arguments clear and compelling, matching my own experience > -- especially the enumeration of the small set of realistic uses of > exception handling (ignore, retry, hard-fail, log, or try one of a > small number of alternatives to achieve the desired result). > > > - Condition.raise is a normal function and does something very simple: > > - look in TLS to see if there's a handler > > - if so, call it and return the result to the raiser > > - if not, fail > > > > - This means condition-handling happens _at site_ of raising. If > > the handler returns a useful value, processing continues as if > > nothing went wrong. It's _just_ a rendezvous mechanism for an > > outer frame to dynamically provide a handler closure to an inner > > frame where a condition occurs. > > This all seems reasonable after reading that post. > > > So: API survey. Modulo a few residual bugs on consts and function > > regions (currently hacked around in the implementation), I have 3 > > different APIs that all seem to work -- which I've given different names > > for discussion sake -- and I'm trying to decide between them. They > > mostly differ in the number of pieces and the location and shape of the > > boilerplate a user of the condition system has to write. My current > > preference is #3 but I'd like a show of hands on others' preferences. > > > Opinions? Clarifying questions? > > I prefer option #3. > > I like that it states the condition and handler up-front (in contrast > to most exception-handling syntaxes, that leave you guessing what > might go wrong until you reach the catch statements at the end of the > try/catch block). > > I like that the error-handling code is implicitly not an afterthought. > (I find that when I'm writing the code on the main path, there's a > strong temptation to just "keep on coding", and come back to insert > the error-handling code "later".) > > I like that it has the minimum of boilerplate code (in contrast to > option #1 especially). > > In addition to the boilerplate, I don't really like option #1 because > of the separation of the protected block from the handler code. > > My concern with option #2 is that, despite my general fondness for > RAII, the '_g' variable isn't explicitly used anywhere, so creating a > named variable seems redundant. > > Plus, having an object that can reach out of its variable and affect > all the code that follows in its block scope is too "magical" for my > liking. > > jb > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > This seems heavily influenced by Lisp's Conditions & Restarts[1] (not that I have used Lisp before though, but I *am* interesting in error handling strategies), however it seems relatively unclear to me how the syntax work. If I understood correctly there are 3 steps: - declare the condition - setup the handler for that condition (with the poll going on) - raise a signal for that condition At the moment you only show the first 2, and it's unclear to me exactly how the handler is *used* at the call site (looks to me like a regular function call passing an instance of T as argument and getting a U in exchange). I suppose it would something like: let u = core::condition::signal(OutOfKitten, t) One of the point I find "difficult" about this (and which is as difficult with exceptions, short of going the path of the damned with exceptions specification) is that it might become difficult to know exactly which handlers to setup; as such this: - Condition.raise is a normal function and does something very simple: - look in TLS to see if there's a handler - if so, call it and return the result to the raiser - if not, fail might be a little forceful. As such, I would have a tiny request: => Would it make sense to just make it a "point of customization" but have a way to specify a default result in case there is no handler, or even specify a default handler ? This means 2 or 3 different flavors of "raising a condition", which adds to the complexity of the language though. On the other hand, using the syntax I used above, it's just: let u = core::condition::signal(OutOfKitten, t) // default behavior, ie fail if no handler let u = core::condition::signal(OutOfKitten, t, |t| { fail }) // default behavior made explicit let u = core::condition::signal(OutOfKitten, t, |t| { if t == 0 then fail else 3 }) // custom handler, if none setup let u = core::condition::signal(OutOfKitten, t, 4) // simple way to pass a default return value without actually having to write up a lambda, ala |t| { 4 } (just to avoid boilerplate really) As for the poll, like the others I prefer #3 too. #2 is *definitely* one weird cookie. And it seems weird to give names to things that are not invoked through this name later on... (typical issue with RAII) -- Matthieu [1]: http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From garethdanielsmith at gmail.com Sat Oct 20 04:37:02 2012 From: garethdanielsmith at gmail.com (Gareth Smith) Date: Sat, 20 Oct 2012 12:37:02 +0100 Subject: [rust-dev] condition handling In-Reply-To: <5081E6D5.50700@mozilla.com> References: <5081E6D5.50700@mozilla.com> Message-ID: <50828CDE.7060703@gmail.com> Option 3 looks prettiest to me, but I like that in Option 1 the error-raising code comes before the error-handling code (based on experience with other languages). This might not be an issue in practice. I am not sure how I like Option 3 with a more complex trap block: OutOfKittens.trap(|t| { OrderFailure.trap(|t| notify_support()).in { order_more_kittens(); } UseAardvarksInstead }).in { do_some_stuff(); that_might_raise(); out_of_kittens(); } Compare this to some "ideal" syntax: protect { do_some_stuff(); that_might_raise(); out_of_kittens(); } handle OutOfKittens(t) { protect { order_more_kittens(); } handle OrderFailure(t) { notify_support(); } UseAardvarksInstead ) Gareth From matthieu.monrocq at gmail.com Sat Oct 20 05:31:08 2012 From: matthieu.monrocq at gmail.com (Matthieu Monrocq) Date: Sat, 20 Oct 2012 14:31:08 +0200 Subject: [rust-dev] condition handling In-Reply-To: <50828CDE.7060703@gmail.com> References: <5081E6D5.50700@mozilla.com> <50828CDE.7060703@gmail.com> Message-ID: On Sat, Oct 20, 2012 at 1:37 PM, Gareth Smith wrote: > Option 3 looks prettiest to me, but I like that in Option 1 the > error-raising code comes before the error-handling code (based on > experience with other languages). This might not be an issue in practice. > > I am not sure how I like Option 3 with a more complex trap block: > > OutOfKittens.trap(|t| { > OrderFailure.trap(|t| notify_support()).in { > order_more_kittens(); > } > UseAardvarksInstead > }).in { > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > } > > Compare this to some "ideal" syntax: > > protect { > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > } handle OutOfKittens(t) { > protect { > order_more_kittens(); > } handle OrderFailure(t) { > notify_support(); > } > UseAardvarksInstead > ) > > Gareth > > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > I just realized I had missed a point, which is somewhat similar to what Gareth raised: composability. Let us start with an example in a C++ like language: UserPreferences loadUserPreferences(std::string const& username) { try { return loadUserPreferencesFromJson(username); } catch(FileNotFound const&) { if (username == "toto") { throw; } return loadUserPreferencesFromXml(username); // not so long ago we used xml } } The one thing here is "throw;", which rethrows the current exception and pass it up the handler chain. Is there any plan to have this available in this Condition/Signal scheme ? Ie, being able in a condition to defer the decision to the previous handler that was setup for the very same condition ? It could be as simple as a core::condition::signal(OutOfKittens, t) from within the current handler block. Which basically means that during its invocation the current handler is temporarily "popped" from the stack of handlers (for that condition) and after its executes (if it does not fail) is pushed back. I even wonder if this could not become "automatic", that is unless a handler "fails" hard or returns a proper value, its "predecessor" is automatically called. However I failed to see how this could be nicely integrated in the syntax and wonder what the ratio of "pass-up-the-chain" vs "ignore-predecessors" would be in practice. -- Matthieu -------------- next part -------------- An HTML attachment was scrubbed... URL: From graydon at mozilla.com Sat Oct 20 10:04:40 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Sat, 20 Oct 2012 10:04:40 -0700 Subject: [rust-dev] condition handling In-Reply-To: References: <5081E6D5.50700@mozilla.com> Message-ID: <5082D9A8.1010607@mozilla.com> On 20/10/2012 4:19 AM, Matthieu Monrocq wrote: > This seems heavily influenced by Lisp's Conditions & Restarts[1] (not > that I have used Lisp before though, but I *am* interesting in error > handling strategies), Similar. A bit less involved. But yes. Resumable at-site condition systems have a relatively long parallel history to exception (throw/unwind/catch) systems. Conditions in Dylan and CL, Signals in Mesa, Conditions in PL/I, etc. > At the moment you only show the first 2, and it's unclear to me exactly > how the handler is *used* at the call site (looks to me like a regular > function call passing an instance of T as argument and getting a U in > exchange). I suppose it would something like: > > let u = core::condition::signal(OutOfKitten, t) More like "let u = OutOfKittens.raise(t)"; OutOfKittens is a const struct of type Condition, with methods like 'raise' impl'ed for that struct. > As such, I would have a tiny request: > > => Would it make sense to just make it a "point of customization" but > have a way to specify a default result in case there is no handler, or > even specify a default handler ? Yeah, I haven't added an API point for this yet but was assuming we'd have such a raise-variant. The raise-point can also just explicitly probe the condition to see if it has a handler, or manually fetch the handler itself. Does "do OutOfKittens.raise_or_else(t) { ... }" work? Or "OutOfKittens.raise_with_default(t, d)"? -Graydon From graydon at mozilla.com Sat Oct 20 10:18:23 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Sat, 20 Oct 2012 10:18:23 -0700 Subject: [rust-dev] condition handling In-Reply-To: References: <5081E6D5.50700@mozilla.com> <50828CDE.7060703@gmail.com> Message-ID: <5082DCDF.40303@mozilla.com> On 20/10/2012 5:31 AM, Matthieu Monrocq wrote: > I just realized I had missed a point, which is somewhat similar to what > Gareth raised: composability. Yeah. None of them have _great_ composability but it's actually the main thing pressing me towards #3. There are composition hazards in #1 and #2, #1 especially; #3 is the most robust, compositionally, even as it requires a bit more indenting. IME multi-condition handling and handling-within-handler cases are *comparatively* rare, not the end of the world if they read a bit worse than simple 1-handler cases (you can always factor body or handler parts out into helper functions); I'm more concerned that the composition is _safe_, and doesn't have confusing or surprising semantics. > Is there any plan to have this available in this Condition/Signal scheme > ? Ie, being able in a condition to defer the decision to the previous > handler that was setup for the very same condition ? Yes. The first version I sketched had this, then I took it out (out of curiosity to see if chaining via the guards also worked) but I'm intending to put it back in once the API-variant is chosen. > I even wonder if this could not become "automatic", that is unless a > handler "fails" hard or returns a proper value, its "predecessor" is > automatically called. However I failed to see how this could be nicely > integrated in the syntax and wonder what the ratio of > "pass-up-the-chain" vs "ignore-predecessors" would be in practice. A handler is just a function. Functions always either return (a "proper value", even if it's ()) or diverge (exit, fail, iloop). There's no 3rd case like "not returning a value" in which to put this as automatic behavior. But we can readily provide API points to handle re-raising (or just make the meaning of .raise called from a handler act this way). -Graydon From graydon at mozilla.com Sat Oct 20 11:33:53 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Sat, 20 Oct 2012 11:33:53 -0700 Subject: [rust-dev] Announce: rustle, an api search tool In-Reply-To: References: <2FE3D83A-4AC8-486F-96B5-4F164F245033@riseup.net> <5081B7A3.3060504@mozilla.com> Message-ID: <5082EE91.4000406@mozilla.com> On 20/10/2012 10:48 AM, Peter Hull wrote: > Graydon, is all the required information already provided by libsyntax > or will Daniel indeed have to wait for a librustdoc before he can stop > scraping the HTML? Rustdoc should become a library in the near-ish future; but its source is in-tree and available to extend, and as I suggested, this strikes me as a reasonable "search mode" for rustdoc itself, not necessarily a separate tool. In any case you can get the _signatures_ of functions, and their per-item doc attributes by parsing (via libsyntax). Rustdoc is more concerned with cleaning up, sorting, organizing, paginating and constructing a particular formatted organization of the doc-fragments pulled from those attributes. > All in all, I like the idea a lot; I've never seen an api search work > like this before, and it will be useful given that (as I understand > it) recent discussion has suggested that Java/C++ -style > 'intellisense' won't work as well with Rust. I'm not sure where this comes from; I have no reason to think Rust would resist intellisense-like tooling. It might require running portions of the resolver or typechecker, but so does any such thing in Java or C++. -Graydon From peterhull90 at gmail.com Sat Oct 20 13:59:47 2012 From: peterhull90 at gmail.com (Peter Hull) Date: Sat, 20 Oct 2012 21:59:47 +0100 Subject: [rust-dev] Fwd: Announce: rustle, an api search tool In-Reply-To: References: <2FE3D83A-4AC8-486F-96B5-4F164F245033@riseup.net> <5081B7A3.3060504@mozilla.com> Message-ID: Sorry, sent to Graydon directly instead of to the list. Pete ---------- Forwarded message ---------- From: Peter Hull Date: Sat, Oct 20, 2012 at 6:48 PM Subject: Re: [rust-dev] Announce: rustle, an api search tool To: Graydon Hoare > On 12-10-18 06:05 PM, Daniel Patterson wrote: > >> To try it out, contribute, improve, file bugs, etc, go to http://github.com/dbp/rustle . The readme >> should explain how to get started with it. You can also try it out at http://lab.dbpmail.net/rustle/. The >> web frontend is currently very basic, but it does link to the official documentation. It is all written in rust, >> except the html scraper (which is not needed to run it). >> >> Feedback welcome! I may have misunderstood how to use it, but I typed '([A])->bool' into the web interface and expected to see vec::is_empty (amongst others) but it just drew a blank. Graydon, is all the required information already provided by libsyntax or will Daniel indeed have to wait for a librustdoc before he can stop scraping the HTML? All in all, I like the idea a lot; I've never seen an api search work like this before, and it will be useful given that (as I understand it) recent discussion has suggested that Java/C++ -style 'intellisense' won't work as well with Rust. Pete From peterhull90 at gmail.com Sat Oct 20 13:59:57 2012 From: peterhull90 at gmail.com (Peter Hull) Date: Sat, 20 Oct 2012 21:59:57 +0100 Subject: [rust-dev] Announce: rustle, an api search tool In-Reply-To: <5082EE91.4000406@mozilla.com> References: <2FE3D83A-4AC8-486F-96B5-4F164F245033@riseup.net> <5081B7A3.3060504@mozilla.com> <5082EE91.4000406@mozilla.com> Message-ID: On Sat, Oct 20, 2012 at 7:33 PM, Graydon Hoare wrote: > On 20/10/2012 10:48 AM, Peter Hull wrote: > I'm not sure where this comes from; I have no reason to think Rust would > resist intellisense-like tooling. It might require running portions of > the resolver or typechecker, but so does any such thing in Java or C++. It was from the discussion titled 'Rust philosophy and OOP' earlier this month. I'm glad you think it will be OK. Pete From masklinn at masklinn.net Sat Oct 20 14:08:30 2012 From: masklinn at masklinn.net (Masklinn) Date: Sat, 20 Oct 2012 23:08:30 +0200 Subject: [rust-dev] Announce: rustle, an api search tool In-Reply-To: <2FE3D83A-4AC8-486F-96B5-4F164F245033@riseup.net> References: <2FE3D83A-4AC8-486F-96B5-4F164F245033@riseup.net> Message-ID: On 2012-10-19, at 03:05 , Daniel Patterson wrote: > I'm announcing an initial version of an API search tool for Rust called Rustle. It is inspired by the api search tool for Haskell > called Hoogle (http://www.haskell.org/hoogle). Haskell's community also has Hayoo[0], which is less focused on type-searches (though they still work well), and has quite a few interesting feature (e.g. the "type cloud" which displays type-searches similar to the one entered). It's also based on an indexing library which could be imitated to provide generic API searching capabilities to Rust. [0] http://holumbus.fh-wedel.de From james at mansionfamily.plus.com Sat Oct 20 15:26:42 2012 From: james at mansionfamily.plus.com (james) Date: Sat, 20 Oct 2012 23:26:42 +0100 Subject: [rust-dev] GPU programming In-Reply-To: <50816E21.4060607@mozilla.com> References: <1350500647.4304.140661142045461.75C74857@webmail.messagingengine.com> <5081095B.3060304@proinbox.com> <50816E21.4060607@mozilla.com> Message-ID: <50832522.1070800@mansionfamily.plus.com> I've started playing with C++ AMP and its really very straightforward, if currently trting that I can't get full double support on Win7. If you can support attributes that do the equivalent of restrict (and the key here is that the attribute is involved in overload resolution) then it could be very handy; I'm not sure that OpenCL C compilers being imlemented in LLVM is relevant though. AMP is essentially managing a translation to HLSL, so the equivalent is to translate to OpenCL C and let the vendor compiler kick in at runtime. James (Oh please; when can I have a nice MSI that doesn't need a stupid not-current mingw and is properly independant of that stuff? ;-( I'll do more than lurk and actually try rust, but not until then. Life is to short.) From banderson at mozilla.com Sat Oct 20 16:47:47 2012 From: banderson at mozilla.com (Brian Anderson) Date: Sat, 20 Oct 2012 16:47:47 -0700 Subject: [rust-dev] condition handling In-Reply-To: <5081E6D5.50700@mozilla.com> References: <5081E6D5.50700@mozilla.com> Message-ID: <50833823.6040105@mozilla.com> > > 1. "Protect/handle", a.k.a. "make it look like try/catch": this version > pursues the arrangement with protected-code coming first and handlers > coming second. To do this, the protected-code has to be suspended in a > closure, which is then passed to a temporary struct, which is > responsible for both capturing the remaining handler-part and firing the > push/run/pop cycle together at the end. Uses of it look like this: > > let b = do OutOfKittens.protect { > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > }; > > do b.handle |t| { > UseAardvarksInstead > } > > It's not really an ideal use of our 'do' syntax, nor are many other > variants of this API I've tried. It might read slightly better (or > worse) as such: > > (do OutOfKittens.protect { > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > }).handle(|t| > UseAardvarksInstead > ); This is my preferred arrangement, though without the parens. The primary reason is because I always prefer the exceptional flow to come last. I could also imagine something like: do protect { ... }.handle::(|ex| ).handle::(|ex| ); > > > 2. "Guard", a.k.a. "make it look like RAII": this version has only a > single "floating in space" handler-block that is assigned to a temporary > guard object in the current scope, and all subsequent code in that scope > is protected. Reads like this: > > { > let _g = OutOfKittens.guard(|t| UseAardvarksInstead); > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > } > > Downsides of this mechanism are that a user might try to move _g out of > the current frame or otherwise tamper with it -- we might need to do > some tricks with the region system to prevent that -- and it gives rise > to this somewhat artificial _g variable and otherwise unclear extra > block to contain it. > > 3. "Trap/in", a.k.a. "the system I like the look of best": this is the > version Patrick suggested yesterday. It sets up the handlers in the head > of a do-block and then invokes the protected code. It's order-inverted > from protect/handle -- the handlers come before the protected code -- > but it still reads ok to my eyes, and seems to play nicely with our > existing syntax: > > do OutOfKittens.trap(|t| UseAardvarksInstead).in { > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > } > From dbp at riseup.net Sat Oct 20 18:51:20 2012 From: dbp at riseup.net (Daniel Patterson) Date: Sat, 20 Oct 2012 21:51:20 -0400 Subject: [rust-dev] Fwd: Announce: rustle, an api search tool In-Reply-To: References: <2FE3D83A-4AC8-486F-96B5-4F164F245033@riseup.net> <5081B7A3.3060504@mozilla.com> Message-ID: <13C9615E-CEA5-402E-856E-9A4F3506673E@riseup.net> > I may have misunderstood how to use it, but I typed '([A])->bool' into > the web interface and expected to see vec::is_empty (amongst others) > but it just drew a blank. Nope, just a bug (which should be fixed now) - I just rewrote the parsing code (such as it is) from an extremely simplistic initial version to a slightly-less simplistic second version, and in doing so introduced bugs (and hadn't updated all the tests? errp). I've been playing a little fast and loose with the parsing code, because I'm assuming it will be replaced very soon with the existing parser (i.e. libsyntax, whether used by way of a librustdoc or on its own). > Graydon, is all the required information already provided by libsyntax > or will Daniel indeed have to wait for a librustdoc before he can stop > scraping the HTML? My hope was to piggyback on parts of rustdoc, as my requirements are really similar (i.e., stripping a lot of information out of the AST that libsyntax produces), and I'm actually working on the librustdoc refactor (should be done very soon, just some makefile stuff), but barring that I can just use libsyntax. Or I can just incorporate it into rustdoc and share that way. > All in all, I like the idea a lot; I've never seen an api search work > like this before, and it will be useful given that (as I understand > it) recent discussion has suggested that Java/C++ -style > 'intellisense' won't work as well with Rust. Thanks for the positive feedback! It's still got a ways to go, but I've found this kind of tool very useful in haskell (for which the 'original' seach-by-type documentation tool, hoogle, was written). From emmanuel.surleau at gmail.com Sun Oct 21 06:51:47 2012 From: emmanuel.surleau at gmail.com (Emmanuel Surleau) Date: Sun, 21 Oct 2012 15:51:47 +0200 Subject: [rust-dev] Attributes In-Reply-To: <1350628989.7971.140661142711417.5919C434@webmail.messagingengine.com> References: <1350628989.7971.140661142711417.5919C434@webmail.messagingengine.com> Message-ID: On Fri, Oct 19, 2012 at 8:43 AM, John Mija wrote: > Rust has attributes[1] at function-level but (1) the compilation could > be faster if they were at file-level, and (2) the project would be more > homogeneous and clean. > > + Instead of to have the attribute "#[test]" for a function, those tests > functions could be into a file with the name finished in "_test" > (foo_test.rs) indicating that there are unit tests. On this case, we > would not need an attribute. > > + Instead of to have conditionally-compiled modules at function level, > that code could be into a file finished in the system name > (foo_linux.rs), and/or use attributes at file level. See how Go solved > this problem, in Build constraints[2]. > > + Instead of to have an attribute for the documentation, the parser > could get the comment on top of the function to get its documentation. > > Now: > > // A documentation attribute > #[doc = "Add two numbers together."] > fn add(x: int, y: int) { x + y } > > Proposal: > > // add adds two numbers together." > fn add(x: int, y: int) { x + y } There are very good reasons for having attributes at a lower level than file (test autodiscovery, when you want something more reliable than an easily mistyped convention, automated dependency injection, marking transactional methods...). Of course, a lot of this would need rust's attributes to be usable outside of the compiler (as opposed to a handful of hardcoded elements), but I hope we'll have this in the near future (hint hint). Cheers, Emm From ben.striegel at gmail.com Sun Oct 21 21:50:24 2012 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Mon, 22 Oct 2012 00:50:24 -0400 Subject: [rust-dev] condition handling In-Reply-To: <5081E6D5.50700@mozilla.com> References: <5081E6D5.50700@mozilla.com> Message-ID: If it's not too much trouble, a complete example (using any one of the proposed syntaxes) would be enlightening. I'm still having a hard time imagining how OutOfKittens is defined, and how do_some_stuff et al signal it in the first place, and how the input/output of OutOfKittens can be utilized within the signalling function. On Fri, Oct 19, 2012 at 7:48 PM, Graydon Hoare wrote: > Hi, > > If you're going to respond to this email, please read it in full, don't > just skim. > > I've been sketching a module in core::condition this week that > implements a condition-handling system on top of the TLS feature > (task::local_data) that Ben Blum added over the summer. > > This email is a very specific description of what I'm adding (many > people have asked) along with a very specific poll about how best to > structure the outermost part of the API. > > I'd appreciate replies here be kept focused on those points -- > clarifying questions + indication of preference on API -- as there are a > lot of new people on the list since we last discussed this, but we are > _not_ changing plan here. This is the same plan we've had for 6-ish > years, off-and-on, sketched numerous times, whenever it seems > implementable with the pieces lying around. I'm not interested in having > a big discussion of all the possible ways condition-systems can be > built, or (re-)exploring the design-space. > > Some references to the lurking plan here: > > https://mail.mozilla.org/pipermail/rust-dev/2012-May/001879.html > https://mail.mozilla.org/pipermail/rust-dev/2011-November/000999.html > https://github.com/mozilla/rust/issues/1945#issuecomment-4425610 > > Anyway, here is the system (again) in a nutshell: > > - Tasks have a task-local storage system (TLS). TLS maps keys to > values that stick to the task until released. The keys are > addresses, conventionally static addresses of items (this is a > hack for producing 'unique' keys, but it works). > > - Handlers are stack-closures that get pushed and popped from TLS. > They obey stack discipline and can capture their lexical environment > since they'll be popped before the pushing frame exits. > > - Handlers are put in TLS keyed to a condition. A condition is a > static, symbolic value used mostly for its TLS-keying and > method-dispatching capabilities. Conditions don't store values, > they just name situations that might occur and give-type-to any > values passed-to and returned-from potential handlers of such > situations. > > - Code can raise a condition whenever it likes. No static checking > of which conditions might occur where; no relationship to function > types. Raising of a condition in a module is indicated by the > condition being present in the module, by convention, or by > documentation. > > - Raising a condition can pass a value giving further details on > the condition, beyond just its type/name. If the raise is handled, > a value may return. The types of values raised-to and returned-from > handlers is specified by a condition. That is, a condition is > declared like "const OutOfKittens : Condition = ..." where > T is the type of values passed to an OutOfKittens handler, and > U is the type of values returned from an OutOfKittens handler when > it is returning a solution to the condition. U might well be a > symbolic type such as an enum of reasonable recovery strategies. > > - There is no change to the fail/unwind system. Failure is still > unrecoverable, results in unwinding, and is the only possible > cause of unwinding. If a condition is handled, it doesn't unwind. > If it's unhandled, or if the handler fails, the task fails and > unwinds. This is not an unwind-rewind system or an unwind-catch > system. > > - Condition.raise is a normal function and does something very simple: > - look in TLS to see if there's a handler > - if so, call it and return the result to the raiser > - if not, fail > > - This means condition-handling happens _at site_ of raising. If > the handler returns a useful value, processing continues as if > nothing went wrong. It's _just_ a rendezvous mechanism for an > outer frame to dynamically provide a handler closure to an inner > frame where a condition occurs. > > Given that description, astute readers may note that there's not much to > this "system", mostly just convention and existing pieces. This is > intentional. It's supposed to be very minimal and only took about a day > to get working, beyond the miserable slog Ben already fought through > implementing TLS over the summer. > > Nonetheless I want to get it _right_ since this is probably going to be > a convention that sticks and gets used extensively across our libraries. > Getting it nailed down is a priority for the 0.5 cycle, as we're trying > to knock out the top few remaining toe-stubs when writing libraries, and > this is one of them. We've grown an unfortunate dependence on using the > core::Result type for managing recoverable-problems in library code and > I would like to move away from that in as many cases as practical, since > at-site handling tends to be much cleaner for users. Since 'Result' is > so clunky we wind up using unrecoverable 'fail' in a lot of cases too, > sometimes cases where having the option to recover makes sense. > > So: API survey. Modulo a few residual bugs on consts and function > regions (currently hacked around in the implementation), I have 3 > different APIs that all seem to work -- which I've given different names > for discussion sake -- and I'm trying to decide between them. They > mostly differ in the number of pieces and the location and shape of the > boilerplate a user of the condition system has to write. My current > preference is #3 but I'd like a show of hands on others' preferences. > > Here they are: > > 1. "Protect/handle", a.k.a. "make it look like try/catch": this version > pursues the arrangement with protected-code coming first and handlers > coming second. To do this, the protected-code has to be suspended in a > closure, which is then passed to a temporary struct, which is > responsible for both capturing the remaining handler-part and firing the > push/run/pop cycle together at the end. Uses of it look like this: > > let b = do OutOfKittens.protect { > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > }; > > do b.handle |t| { > UseAardvarksInstead > } > > It's not really an ideal use of our 'do' syntax, nor are many other > variants of this API I've tried. It might read slightly better (or > worse) as such: > > (do OutOfKittens.protect { > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > }).handle(|t| > UseAardvarksInstead > ); > > > 2. "Guard", a.k.a. "make it look like RAII": this version has only a > single "floating in space" handler-block that is assigned to a temporary > guard object in the current scope, and all subsequent code in that scope > is protected. Reads like this: > > { > let _g = OutOfKittens.guard(|t| UseAardvarksInstead); > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > } > > Downsides of this mechanism are that a user might try to move _g out of > the current frame or otherwise tamper with it -- we might need to do > some tricks with the region system to prevent that -- and it gives rise > to this somewhat artificial _g variable and otherwise unclear extra > block to contain it. > > 3. "Trap/in", a.k.a. "the system I like the look of best": this is the > version Patrick suggested yesterday. It sets up the handlers in the head > of a do-block and then invokes the protected code. It's order-inverted > from protect/handle -- the handlers come before the protected code -- > but it still reads ok to my eyes, and seems to play nicely with our > existing syntax: > > do OutOfKittens.trap(|t| UseAardvarksInstead).in { > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > } > > Opinions? Clarifying questions? > > Thanks, > > -Graydon > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ben.striegel at gmail.com Mon Oct 22 02:12:51 2012 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Mon, 22 Oct 2012 05:12:51 -0400 Subject: [rust-dev] condition handling In-Reply-To: <5081E6D5.50700@mozilla.com> References: <5081E6D5.50700@mozilla.com> Message-ID: Could the RAII-styled second option be rewritten as follows? do |cond, handler| { cond.add(handler); do_some_stuff(); that_might_raise(); out_of_kittens(); }(OutOfKittens) |t| { UseAardvarksInstead } This has the advantage of requiring neither block to be surrounded by parentheses, nor requiring any nebulous unused temporary variable. It also puts the error-handling code after the guarded code, if you're a fan of try/catch. (If this is just mind-bendingly bizarre or outright wrong, please excuse me as I've been up all night.) On Fri, Oct 19, 2012 at 7:48 PM, Graydon Hoare wrote: > Hi, > > If you're going to respond to this email, please read it in full, don't > just skim. > > I've been sketching a module in core::condition this week that > implements a condition-handling system on top of the TLS feature > (task::local_data) that Ben Blum added over the summer. > > This email is a very specific description of what I'm adding (many > people have asked) along with a very specific poll about how best to > structure the outermost part of the API. > > I'd appreciate replies here be kept focused on those points -- > clarifying questions + indication of preference on API -- as there are a > lot of new people on the list since we last discussed this, but we are > _not_ changing plan here. This is the same plan we've had for 6-ish > years, off-and-on, sketched numerous times, whenever it seems > implementable with the pieces lying around. I'm not interested in having > a big discussion of all the possible ways condition-systems can be > built, or (re-)exploring the design-space. > > Some references to the lurking plan here: > > https://mail.mozilla.org/pipermail/rust-dev/2012-May/001879.html > https://mail.mozilla.org/pipermail/rust-dev/2011-November/000999.html > https://github.com/mozilla/rust/issues/1945#issuecomment-4425610 > > Anyway, here is the system (again) in a nutshell: > > - Tasks have a task-local storage system (TLS). TLS maps keys to > values that stick to the task until released. The keys are > addresses, conventionally static addresses of items (this is a > hack for producing 'unique' keys, but it works). > > - Handlers are stack-closures that get pushed and popped from TLS. > They obey stack discipline and can capture their lexical environment > since they'll be popped before the pushing frame exits. > > - Handlers are put in TLS keyed to a condition. A condition is a > static, symbolic value used mostly for its TLS-keying and > method-dispatching capabilities. Conditions don't store values, > they just name situations that might occur and give-type-to any > values passed-to and returned-from potential handlers of such > situations. > > - Code can raise a condition whenever it likes. No static checking > of which conditions might occur where; no relationship to function > types. Raising of a condition in a module is indicated by the > condition being present in the module, by convention, or by > documentation. > > - Raising a condition can pass a value giving further details on > the condition, beyond just its type/name. If the raise is handled, > a value may return. The types of values raised-to and returned-from > handlers is specified by a condition. That is, a condition is > declared like "const OutOfKittens : Condition = ..." where > T is the type of values passed to an OutOfKittens handler, and > U is the type of values returned from an OutOfKittens handler when > it is returning a solution to the condition. U might well be a > symbolic type such as an enum of reasonable recovery strategies. > > - There is no change to the fail/unwind system. Failure is still > unrecoverable, results in unwinding, and is the only possible > cause of unwinding. If a condition is handled, it doesn't unwind. > If it's unhandled, or if the handler fails, the task fails and > unwinds. This is not an unwind-rewind system or an unwind-catch > system. > > - Condition.raise is a normal function and does something very simple: > - look in TLS to see if there's a handler > - if so, call it and return the result to the raiser > - if not, fail > > - This means condition-handling happens _at site_ of raising. If > the handler returns a useful value, processing continues as if > nothing went wrong. It's _just_ a rendezvous mechanism for an > outer frame to dynamically provide a handler closure to an inner > frame where a condition occurs. > > Given that description, astute readers may note that there's not much to > this "system", mostly just convention and existing pieces. This is > intentional. It's supposed to be very minimal and only took about a day > to get working, beyond the miserable slog Ben already fought through > implementing TLS over the summer. > > Nonetheless I want to get it _right_ since this is probably going to be > a convention that sticks and gets used extensively across our libraries. > Getting it nailed down is a priority for the 0.5 cycle, as we're trying > to knock out the top few remaining toe-stubs when writing libraries, and > this is one of them. We've grown an unfortunate dependence on using the > core::Result type for managing recoverable-problems in library code and > I would like to move away from that in as many cases as practical, since > at-site handling tends to be much cleaner for users. Since 'Result' is > so clunky we wind up using unrecoverable 'fail' in a lot of cases too, > sometimes cases where having the option to recover makes sense. > > So: API survey. Modulo a few residual bugs on consts and function > regions (currently hacked around in the implementation), I have 3 > different APIs that all seem to work -- which I've given different names > for discussion sake -- and I'm trying to decide between them. They > mostly differ in the number of pieces and the location and shape of the > boilerplate a user of the condition system has to write. My current > preference is #3 but I'd like a show of hands on others' preferences. > > Here they are: > > 1. "Protect/handle", a.k.a. "make it look like try/catch": this version > pursues the arrangement with protected-code coming first and handlers > coming second. To do this, the protected-code has to be suspended in a > closure, which is then passed to a temporary struct, which is > responsible for both capturing the remaining handler-part and firing the > push/run/pop cycle together at the end. Uses of it look like this: > > let b = do OutOfKittens.protect { > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > }; > > do b.handle |t| { > UseAardvarksInstead > } > > It's not really an ideal use of our 'do' syntax, nor are many other > variants of this API I've tried. It might read slightly better (or > worse) as such: > > (do OutOfKittens.protect { > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > }).handle(|t| > UseAardvarksInstead > ); > > > 2. "Guard", a.k.a. "make it look like RAII": this version has only a > single "floating in space" handler-block that is assigned to a temporary > guard object in the current scope, and all subsequent code in that scope > is protected. Reads like this: > > { > let _g = OutOfKittens.guard(|t| UseAardvarksInstead); > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > } > > Downsides of this mechanism are that a user might try to move _g out of > the current frame or otherwise tamper with it -- we might need to do > some tricks with the region system to prevent that -- and it gives rise > to this somewhat artificial _g variable and otherwise unclear extra > block to contain it. > > 3. "Trap/in", a.k.a. "the system I like the look of best": this is the > version Patrick suggested yesterday. It sets up the handlers in the head > of a do-block and then invokes the protected code. It's order-inverted > from protect/handle -- the handlers come before the protected code -- > but it still reads ok to my eyes, and seems to play nicely with our > existing syntax: > > do OutOfKittens.trap(|t| UseAardvarksInstead).in { > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > } > > Opinions? Clarifying questions? > > Thanks, > > -Graydon > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hsivonen at iki.fi Mon Oct 22 06:52:38 2012 From: hsivonen at iki.fi (Henri Sivonen) Date: Mon, 22 Oct 2012 16:52:38 +0300 Subject: [rust-dev] Using char literals with non-char match Message-ID: While working on the translation of the HTML parser from Java to Rust, I noticed this does not compile in Rust 0.4: fn main() { let c: u8 = 0x20; match c { ' ' => { io::println("Space"); } } return; } I can make the translator generate integer literals as the patterns for the arms of the match. However, I think the generated Rust code would be nicer for humans to read with char literals in the patterns. I suggest allowing char literals when matching on an integer (or when otherwise comparing to an integer or when assigning to an integer variable) as long as the Unicode code point of the character represented by the character literal is not greater than the largest integer representable by the integer type. (Aside: I liked the old syntax without => and with mandatory braces around each arm better.) -- Henri Sivonen hsivonen at iki.fi http://hsivonen.iki.fi/ From graydon at mozilla.com Mon Oct 22 09:08:48 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Mon, 22 Oct 2012 09:08:48 -0700 Subject: [rust-dev] Using char literals with non-char match In-Reply-To: References: Message-ID: <50856F90.8010007@mozilla.com> On 22/10/2012 6:52 AM, Henri Sivonen wrote: > I can make the translator generate integer literals as the patterns > for the arms of the match. However, I think the generated Rust code > would be nicer for humans to read with char literals in the patterns. Write it like: "match c as char { ... }" then. I imagine the resulting generated code is identical. > I suggest allowing char literals when matching on an integer (or when > otherwise comparing to an integer or when assigning to an integer > variable) as long as the Unicode code point of the character > represented by the character literal is not greater than the largest > integer representable by the integer type. Interesting possibility. As in: add char literals to the set of types to which integer-type inference applies? > (Aside: I liked the old syntax without => and with mandatory braces > around each arm better.) Me too, but I think we're done changing that part :) -Graydon From pwalton at mozilla.com Mon Oct 22 10:05:02 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 22 Oct 2012 10:05:02 -0700 Subject: [rust-dev] Using char literals with non-char match In-Reply-To: <50856F90.8010007@mozilla.com> References: <50856F90.8010007@mozilla.com> Message-ID: <50857CBE.60901@mozilla.com> On 10/22/12 9:08 AM, Graydon Hoare wrote: >> I suggest allowing char literals when matching on an integer (or when >> otherwise comparing to an integer or when assigning to an integer >> variable) as long as the Unicode code point of the character >> represented by the character literal is not greater than the largest >> integer representable by the integer type. > > Interesting possibility. As in: add char literals to the set of types to > which integer-type inference applies? Seems to me that might be confusing. "match c as char" seems clearer. Just IMHO, of course. Patrick From vadimcn at gmail.com Sun Oct 21 13:31:06 2012 From: vadimcn at gmail.com (Vadim) Date: Sun, 21 Oct 2012 13:31:06 -0700 Subject: [rust-dev] Borrowed pointers Message-ID: After reading the Borrowed Pointer Tutorial, I started wondering: why should the programmer have to specify whether to pass function parameters by-copy of by-reference? Couldn't Rust just drop the '&' sigil and let the compiler decide on parameter passing mode? If functions parameters are immutable by default, there is no semantic difference in usage of the parameter no matter which mode was chosen. And if the intention is to modify caller's variable, that is already conveyed by the 'mut' keyword, so, again, the compiler can choose appropriately. There's already plenty of precedent for letting compiler decide on such things: even in c++, what looks like a by-reference parameter may end up being by-value if the function gets inlined (and vice-versa). Not to mention the whole inlining decision itself... Same for c++ return value optimization (which is even observable by the program!). Vadim -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Mon Oct 22 10:57:50 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 22 Oct 2012 10:57:50 -0700 Subject: [rust-dev] Borrowed pointers In-Reply-To: References: Message-ID: <5085891E.8070004@mozilla.com> On 10/21/12 1:31 PM, Vadim wrote: > After reading the Borrowed Pointer Tutorial, I started wondering: why > should the programmer have to specify whether to pass function > parameters by-copy of by-reference? Couldn't Rust just drop the '&' > sigil and let the compiler decide on parameter passing mode? We tried this and it was pretty painful (the whole "mode" debacle). The problems tend to surface with generics, when the compiler isn't actually aware of the type (it's just an opaque T), and then it has to arbitrarily choose whether to pass by reference or by value (which have different semantics in borrow checking and so forth, so it can't just be a codegen decision). Patrick From chad.retz at gmail.com Mon Oct 22 12:28:28 2012 From: chad.retz at gmail.com (Chad Retz) Date: Mon, 22 Oct 2012 14:28:28 -0500 Subject: [rust-dev] Transpiling to Rust Message-ID: I am very new to Rust, but I have a little project where I'd like to compile something else into Rust code. I have seen the macro syntax which doesn't operate on pure strings (from what I see) and I have seen projects like rust-repl that parse and inject at runtime. Which approach should I take if I want to be able to transpile both to a string to save into a file and to use it at runtime depending on what the user wants? (I have done this in D, yet the mixins there work with strings natively so there is no real decision to make). Thanks, Chad -------------- next part -------------- An HTML attachment was scrubbed... URL: From pazaconyoman at gmail.com Mon Oct 22 12:49:43 2012 From: pazaconyoman at gmail.com (Viktor Dahl) Date: Mon, 22 Oct 2012 21:49:43 +0200 Subject: [rust-dev] Warn on useless comparisons Message-ID: I believe that the addition of warnings for useless comparisons, similar to gcc's -Wtype-limits would be a nice feature to have for a safety-minded language such as Rust. Consider this program: fn main() { let x = ~[1, 2, 3, 4, 5]; let mut i = x.len() - 1; while i >= 0 { if x[i] <= 3 { io::println("At most three"); } i -= 1; } } The behaviour one might expect here is for the program to print "at most three" three times and then exiting. The actual program output is: At most three At most three At most three rust: task failed at 'index out of bounds: the len is 5 but the index is -1', uint.rs:6 rust: domain main @0xdd9c10 root task failed The problem is that i is unsigned, so the comparison i >= 0 will always be true. With the addition of "-Wtype-limits" this (and similar errors) could easily be avoided. From catamorphism at gmail.com Mon Oct 22 12:50:59 2012 From: catamorphism at gmail.com (Tim Chevalier) Date: Mon, 22 Oct 2012 12:50:59 -0700 Subject: [rust-dev] Warn on useless comparisons In-Reply-To: References: Message-ID: This would be nice as a lint pass. Feel free to file it as an enhancement request: https://github.com/mozilla/rust/issues/new Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt 'Wouldn't you rather be anything other than the kid who runs around telling stuff what he thinks it is?" -- DavEnd From vadimcn at gmail.com Mon Oct 22 13:09:14 2012 From: vadimcn at gmail.com (Vadim) Date: Mon, 22 Oct 2012 13:09:14 -0700 Subject: [rust-dev] Borrowed pointers Message-ID: I've got to admit, I am not very familiar with Rust's history, but from a brief skimming of what I could find on parameter modes, I got the impression that this feature was removed because it pushed too many low-level decisions onto the developer. Would you mind pointing me towards the thread that discussed the problems with generics that you are referring to? thanks, Vadim -------------- next part -------------- An HTML attachment was scrubbed... URL: From nejucomo at gmail.com Mon Oct 22 13:20:17 2012 From: nejucomo at gmail.com (Nathan) Date: Mon, 22 Oct 2012 13:20:17 -0700 Subject: [rust-dev] Using char literals with non-char match In-Reply-To: <50857CBE.60901@mozilla.com> References: <50856F90.8010007@mozilla.com> <50857CBE.60901@mozilla.com> Message-ID: On Mon, Oct 22, 2012 at 10:05 AM, Patrick Walton wrote: > On 10/22/12 9:08 AM, Graydon Hoare wrote: >>> >>> I suggest allowing char literals when matching on an integer (or when >>> otherwise comparing to an integer or when assigning to an integer >>> variable) as long as the Unicode code point of the character >>> represented by the character literal is not greater than the largest >>> integer representable by the integer type. >> >> >> Interesting possibility. As in: add char literals to the set of types to >> which integer-type inference applies? > > > Seems to me that might be confusing. "match c as char" seems clearer. Just > IMHO, of course. > +1 on explicit "as char". -1 on char literals inferred as numeric types. Explicit seems less surprising, especially where the inference result is hard to determine from examining source. It's a minimal amount of boilerplate and more readable. I'm not hating on inference here, which is an excellent language feature, I just assume it is possible to write large confusing expressions that may be surprising in cases like this, where a reader may not realize some inference rules. Relatedly, where can I find the casting rules between characters and integer types? I imagine two steps: Translate a character to an arbitrary precision integer, then translate that "ideal" value into a specific type by wrap-around, or truncation, or compilation error. If that's accurate, how is the first step accomplished? Is the unicode codepoint used, or is it ascii, or something else? If wrap around is used, does this mean casting different unicode characters (whose codepoints differ by 256) to u8 will yield the same u8 value? Can I cast the same character literal to u8 and i8 to get different semantic values (with the same bit-wise representation, assuming 2's complement)? I didn't notice where this is specified in the 0.4 manual. The only bit about casting I found says integer types can be cast between each other and pointers can be cast in various ways. Are characters considered integer types? Is there more specific documentation? If not, and if someone points me at the relevant source, I could take a crack at a documentation patch. I'm on the "purist / idealist" side of the fence in considering characters to be non-numbers, but I recognize that especially for a systems-compatible language, some C-like looseness in character types might be very practical. OTOH, I'd argue there's also a rich and ancient history of bugs, security problems, and usability problems around confusing characters and integers. Perhaps that is mostly around confusing "character" with C's i8 equivalent "char", though. > Patrick > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev Nathan From nejucomo at gmail.com Mon Oct 22 13:59:27 2012 From: nejucomo at gmail.com (Nathan) Date: Mon, 22 Oct 2012 13:59:27 -0700 Subject: [rust-dev] Warn on useless comparisons In-Reply-To: References: Message-ID: This confused me, a rust neophyte, so I wanted to ask for clarification, inline below: I apologize this is a little off topic; is there a better venue for language-as-it-is learning versus design / implementation discussions? Has rust passed the threshold where those two topic groups split off or are they still intertwingled? On Mon, Oct 22, 2012 at 12:49 PM, Viktor Dahl wrote: > I believe that the addition of warnings for useless comparisons, > similar to gcc's > -Wtype-limits would be a nice feature to have for a safety-minded language > such as Rust. > > Consider this program: > > fn main() { > let x = ~[1, 2, 3, 4, 5]; > let mut i = x.len() - 1; > while i >= 0 { > if x[i] <= 3 { > io::println("At most three"); > } > i -= 1; > } > } > > The behaviour one might expect here is for the program to print "at most three" > three times and then exiting. The actual program output is: > > At most three > At most three > At most three > rust: task failed at 'index out of bounds: the len is 5 but the index > is -1', uint.rs:6 This is where I'm confused. i should be inferred to be uint, so it can never represent a negative value. Does this mean the indexing operation takes a signed type and the expression i - 1 is implicitly coerced? Is the indexing operation a primitive language implementation, or does it translate into a trait method or some other user-definable behavior? In the latter case, what is it's interface? (Nothing in the vec docs for 0.4 obviously implement v[i].) > rust: domain main @0xdd9c10 root task failed > > The problem is that i is unsigned, so the comparison i >= 0 will always be > true. With the addition of "-Wtype-limits" this (and similar errors) could > easily be avoided. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev Nathan From pwalton at mozilla.com Mon Oct 22 14:14:02 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 22 Oct 2012 14:14:02 -0700 Subject: [rust-dev] Warn on useless comparisons In-Reply-To: References: Message-ID: <5085B71A.6050109@mozilla.com> On 10/22/12 1:59 PM, Nathan wrote: > Is the indexing operation a primitive language implementation, or does > it translate into a trait method or some other user-definable > behavior? In the latter case, what is it's interface? (Nothing in > the vec docs for 0.4 obviously implement v[i].) It desugars to an invocation of a method on the Index trait in core::ops, which is parameterized over the right-hand side. However, indexing into a primitive vector type is currently a primitive operation defined over both ints and uints. If it doesn't prove would be terribly inconvenient, I would be in favor of changing this to desugar to a trait implementation in the core vec module defined over uints only. Patrick From graydon at mozilla.com Mon Oct 22 15:29:46 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Mon, 22 Oct 2012 15:29:46 -0700 Subject: [rust-dev] condition handling In-Reply-To: References: <5081E6D5.50700@mozilla.com> Message-ID: <5085C8DA.7080403@mozilla.com> On 12-10-22 02:12 AM, Benjamin Striegel wrote: > Could the RAII-styled second option be rewritten as follows? > > do |cond, handler| { > cond.add(handler); > do_some_stuff(); > that_might_raise(); > out_of_kittens(); > }(OutOfKittens) |t| { > UseAardvarksInstead > } Not with that syntax, no. I gather the overall aim in most of these responses is to reduce the use of () rather than {} wherever possible, and to support multiple handlers stacked in a row, rather than requiring a separate block per handler; but the fact is we have no support for multiple blocks in do-notation right now, so at best this turns into some kind of accumulate-into-a-heap-vec hack that is costly and fragile and .. still doesn't get you into braces. We could conceivably add a multi-brace form to 'do', but that would be a different matter (also one I'm not sure about the correct translation of). For example, supposing we supported: do foo |a, b, c| { ... } bar |d, e, f| { ... } baz |g, h, i| { ... } It is unclear to me whether this is best parsed as: foo(|a, b, c| ..., bar(|d, e, f| ..., baz(|g, h, i| ...))) or baz(|g, h, i| ..., bar(|d, e, f| ..., foo(|a, b, c| ...))) or foo(|a, b, c| ...).bar(|d, e, f| ...).baz(|g, h, i| ...) or baz(|g, h, i| ...).bar(|d, e, f| ...).foo(|a, b, c ...) In any case, the handler-before-protected vs. protected-before-handler question is orthogonal, and while I'm sympathetic to "going with tradition" (handlers after) the implementation involves delaying the code until destruction of a temporary, which is just a bit too unintuitive for me to feel good about, and also removes the possibility of returning a value (the value has to be written via environment capture to an option in the environment, say). I think I'll go with #3 at this point and fix the remaining implementation-blocking bugs. Worst case we can revisit -- possibly build a multi-block syntax like above, as I can see other cases it'd be nice -- but I think #3 will work well enough for now and there's other stuff to do. Thanks, -Graydon From nejucomo at gmail.com Mon Oct 22 15:53:29 2012 From: nejucomo at gmail.com (Nathan) Date: Mon, 22 Oct 2012 15:53:29 -0700 Subject: [rust-dev] condition handling In-Reply-To: References: <5081E6D5.50700@mozilla.com> <50828CDE.7060703@gmail.com> Message-ID: On Sat, Oct 20, 2012 at 5:31 AM, Matthieu Monrocq wrote: > > > On Sat, Oct 20, 2012 at 1:37 PM, Gareth Smith > wrote: >> >> Option 3 looks prettiest to me, but I like that in Option 1 the >> error-raising code comes before the error-handling code (based on experience >> with other languages). This might not be an issue in practice. >> >> I am not sure how I like Option 3 with a more complex trap block: >> >> OutOfKittens.trap(|t| { >> OrderFailure.trap(|t| notify_support()).in { >> order_more_kittens(); >> } >> UseAardvarksInstead >> }).in { >> do_some_stuff(); >> that_might_raise(); >> out_of_kittens(); >> } >> >> Compare this to some "ideal" syntax: >> >> protect { >> do_some_stuff(); >> that_might_raise(); >> out_of_kittens(); >> } handle OutOfKittens(t) { >> protect { >> order_more_kittens(); >> } handle OrderFailure(t) { >> notify_support(); >> } >> UseAardvarksInstead >> ) >> >> Gareth >> >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev > > > I just realized I had missed a point, which is somewhat similar to what > Gareth raised: composability. > > Let us start with an example in a C++ like language: > > UserPreferences loadUserPreferences(std::string const& username) { > try { > return loadUserPreferencesFromJson(username); > } catch(FileNotFound const&) { > if (username == "toto") { throw; } > return loadUserPreferencesFromXml(username); // not so long ago > we used xml > } > } > > The one thing here is "throw;", which rethrows the current exception and > pass it up the handler chain. > > Is there any plan to have this available in this Condition/Signal scheme ? > Ie, being able in a condition to defer the decision to the previous handler > that was setup for the very same condition ? > I might not understand TPS well, but it sounds like a user could implement this "stack" using closures, even if the condition library did not provide it: // Excuse my poor imitation rust: fn loadUserPreferences( username : ~str ) : UserPreferences { let outerHandler = TPS::read( &FileNotFoundCondition ); // Note: I assume a TPS::read function, but I'm not sure if it fits with TPS design. // Now pretend the #3 "trap" style API: do FileNotFoundCondition.trap( |t| if (username == "toto") then outerHandler(t) else loadUserPreferencesFromXml( username )) ).in { return loadUserPreferencesFromJson( username ); } }; } Is this feasible? If not, what have I missed? > It could be as simple as a core::condition::signal(OutOfKittens, t) > from within the current handler block. Which basically means that during its > invocation the current handler is temporarily "popped" from the stack of > handlers (for that condition) and after its executes (if it does not fail) > is pushed back. > > I even wonder if this could not become "automatic", that is unless a handler > "fails" hard or returns a proper value, its "predecessor" is automatically > called. However I failed to see how this could be nicely integrated in the > syntax and wonder what the ratio of "pass-up-the-chain" vs > "ignore-predecessors" would be in practice. > > -- Matthieu > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Nathan From graydon at mozilla.com Mon Oct 22 18:44:12 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Mon, 22 Oct 2012 18:44:12 -0700 Subject: [rust-dev] condition handling In-Reply-To: References: <5081E6D5.50700@mozilla.com> Message-ID: <5085F66C.4000401@mozilla.com> On 12-10-21 09:50 PM, Benjamin Striegel wrote: > If it's not too much trouble, a complete example (using any one of the > proposed syntaxes) would be enlightening. I'm still having a hard time > imagining how OutOfKittens is defined, and how do_some_stuff et al > signal it in the first place, and how the input/output of OutOfKittens > can be utilized within the signalling function. Sure. Let's use a real case such as "trying to open a file that might be missing in the middle of a call to read_whole_file_str". This involves a few assumed changes to the way io is structured, but nothing deep: // Boilerplate for declaring TLS key fn missing_file_key(_x: @Handler) { } const missing_file : Condition = Condition { key: missing_file_key }; mod io { // Revised to not use Result anymore pub fn file_reader(path: &Path) -> Reader { let f = do os::as_c_charp(path.to_str()) |p| { do os::as_c_charp("r") |m| { libc::fopen(p, m) } }; if f as uint == 0u { // No such file; ask for help via .raise missing_file.raise(path) } else { FILE_reader(f, true)) } } } fn main() { do missing_file.trap(|_p| BytesReader { bytes: ~[], pos: 0u } as Reader ).in { // This will trap in io::file_reader and // substitute the empty bytes_reader above let s = io::read_whole_file_str(Path("/nonexistent")); } } Clear enough? -Graydon From amitsinghai.jain at gmail.com Tue Oct 23 01:44:19 2012 From: amitsinghai.jain at gmail.com (Amit Jain) Date: Tue, 23 Oct 2012 17:44:19 +0900 Subject: [rust-dev] How to get code of snapshot compiler Message-ID: Just curious if its open for public than how to get code of snapshot compiler and libraries so instead of fetching binaries I can build locally and use them. TIA Amit -------------- next part -------------- An HTML attachment was scrubbed... URL: From hsivonen at iki.fi Tue Oct 23 04:17:20 2012 From: hsivonen at iki.fi (Henri Sivonen) Date: Tue, 23 Oct 2012 14:17:20 +0300 Subject: [rust-dev] Using char literals with non-char match In-Reply-To: <50856F90.8010007@mozilla.com> References: <50856F90.8010007@mozilla.com> Message-ID: On Mon, Oct 22, 2012 at 7:08 PM, Graydon Hoare wrote: > On 22/10/2012 6:52 AM, Henri Sivonen wrote: > >> I can make the translator generate integer literals as the patterns >> for the arms of the match. However, I think the generated Rust code >> would be nicer for humans to read with char literals in the patterns. > > Write it like: "match c as char { ... }" then. I imagine the resulting > generated code is identical. That would work for match but doesn?t work for using char literals for initializing u8 arrays and the like. Absent the ability to use char literals the same way unsuffixed integer literals work, I guess the easiest path forward is for me to generate hex integer literals instead of char literals. :-( >> I suggest allowing char literals when matching on an integer (or when >> otherwise comparing to an integer or when assigning to an integer >> variable) as long as the Unicode code point of the character >> represented by the character literal is not greater than the largest >> integer representable by the integer type. > > Interesting possibility. As in: add char literals to the set of types to > which integer-type inference applies? Yes. For any code that holds ASCII-compatible data as u8 (including UTF-8) or that holds UTF-16 data as u16, being able to use char literals as alternative spellings of integer literals makes code more readable. -- Henri Sivonen hsivonen at iki.fi http://hsivonen.iki.fi/ From hsivonen at iki.fi Tue Oct 23 05:17:20 2012 From: hsivonen at iki.fi (Henri Sivonen) Date: Tue, 23 Oct 2012 15:17:20 +0300 Subject: [rust-dev] Object orientation without polymorphism Message-ID: Now that classes are gone, what?s the right way to group a bunch of fields and methods when polymorphism is not needed? That is, if I have a struct with some fields, some constants that make sense in the context of that struct and some methods that operate on the struct, how should I group them when there is no need for inheritance? Basically, is there a guide for migrating away from classes? -- Henri Sivonen hsivonen at iki.fi http://hsivonen.iki.fi/ From lucian.branescu at gmail.com Tue Oct 23 05:20:35 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Tue, 23 Oct 2012 13:20:35 +0100 Subject: [rust-dev] Object orientation without polymorphism In-Reply-To: References: Message-ID: I think it's possible to implement methods on a struct directly, without a trait in between. On 23 October 2012 13:17, Henri Sivonen wrote: > Now that classes are gone, what?s the right way to group a bunch of > fields and methods when polymorphism is not needed? > > That is, if I have a struct with some fields, some constants that make > sense in the context of that struct and some methods that operate on > the struct, how should I group them when there is no need for > inheritance? > > Basically, is there a guide for migrating away from classes? > > -- > Henri Sivonen > hsivonen at iki.fi > http://hsivonen.iki.fi/ > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From hsivonen at iki.fi Tue Oct 23 05:23:52 2012 From: hsivonen at iki.fi (Henri Sivonen) Date: Tue, 23 Oct 2012 15:23:52 +0300 Subject: [rust-dev] Object orientation without polymorphism In-Reply-To: References: Message-ID: On Tue, Oct 23, 2012 at 3:20 PM, Lucian Branescu wrote: > I think it's possible to implement methods on a struct directly, > without a trait in between. This does not compile: struct Foo { x: i32, y: i32, fn bar() { }, } -- Henri Sivonen hsivonen at iki.fi http://hsivonen.iki.fi/ From ttaubert at mozilla.com Tue Oct 23 05:24:10 2012 From: ttaubert at mozilla.com (Tim Taubert) Date: Tue, 23 Oct 2012 14:24:10 +0200 Subject: [rust-dev] Object orientation without polymorphism In-Reply-To: References: Message-ID: <50868C6A.9040505@mozilla.com> On 10/23/2012 02:20 PM, Lucian Branescu wrote: > I think it's possible to implement methods on a struct directly, > without a trait in between. Indeed, like this: struct Storage { ... } impl Storage { fn listen() { ... } } - Tim > On 23 October 2012 13:17, Henri Sivonen wrote: >> Now that classes are gone, what?s the right way to group a bunch of >> fields and methods when polymorphism is not needed? >> >> That is, if I have a struct with some fields, some constants that make >> sense in the context of that struct and some methods that operate on >> the struct, how should I group them when there is no need for >> inheritance? >> >> Basically, is there a guide for migrating away from classes? >> >> -- >> Henri Sivonen >> hsivonen at iki.fi >> http://hsivonen.iki.fi/ >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -- Tim Taubert Firefox Engineer ttaubert at mozilla.com From lucian.branescu at gmail.com Tue Oct 23 05:24:40 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Tue, 23 Oct 2012 13:24:40 +0100 Subject: [rust-dev] Object orientation without polymorphism In-Reply-To: References: Message-ID: Something like this http://pcwalton.github.com/blog/2012/08/08/a-gentle-introduction-to-traits-in-rust/ On 23 October 2012 13:23, Henri Sivonen wrote: > On Tue, Oct 23, 2012 at 3:20 PM, Lucian Branescu > wrote: >> I think it's possible to implement methods on a struct directly, >> without a trait in between. > > This does not compile: > > struct Foo { > x: i32, > y: i32, > fn bar() { > > }, > } > > -- > Henri Sivonen > hsivonen at iki.fi > http://hsivonen.iki.fi/ > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From hsivonen at iki.fi Tue Oct 23 05:30:44 2012 From: hsivonen at iki.fi (Henri Sivonen) Date: Tue, 23 Oct 2012 15:30:44 +0300 Subject: [rust-dev] Object orientation without polymorphism In-Reply-To: <50868C6A.9040505@mozilla.com> References: <50868C6A.9040505@mozilla.com> Message-ID: On Tue, Oct 23, 2012 at 3:24 PM, Tim Taubert wrote: > struct Storage { > ... > } > > impl Storage { > fn listen() { > ... > } > } Thanks. Is there a way to scope constants under the namespace of a struct? -- Henri Sivonen hsivonen at iki.fi http://hsivonen.iki.fi/ From whity at tgcm.eu Tue Oct 23 05:46:07 2012 From: whity at tgcm.eu (Julien Blanc) Date: Tue, 23 Oct 2012 14:46:07 +0200 Subject: [rust-dev] Object orientation without polymorphism In-Reply-To: References: Message-ID: Lucian Branescu a ?crit : > Something like this > http://pcwalton.github.com/blog/2012/08/08/a-gentle-introduction-to-traits-in-rust/ Very nice introduction. The only question that arises for me (coming from c++ ground and comparing this to c++ templates) is why trait implementation is made explicit ? Is it a design decision or a current compiler limitation ? I guess the compiler could not too difficultly be made smart enough to determine from its actual interface if a type conforms to a trait. Code generation may be more a problem, though? Julien > On 23 October 2012 13:23, Henri Sivonen wrote: >> On Tue, Oct 23, 2012 at 3:20 PM, Lucian Branescu >> wrote: >>> I think it's possible to implement methods on a struct directly, >>> without a trait in between. >> >> This does not compile: >> >> struct Foo { >> x: i32, >> y: i32, >> fn bar() { >> >> }, >> } >> >> -- >> Henri Sivonen >> hsivonen at iki.fi >> http://hsivonen.iki.fi/ >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > From paul.stansifer at gmail.com Tue Oct 23 05:57:37 2012 From: paul.stansifer at gmail.com (Paul Stansifer) Date: Tue, 23 Oct 2012 08:57:37 -0400 Subject: [rust-dev] How to get code of snapshot compiler In-Reply-To: References: Message-ID: The code in the Rust repo *is* the code for the snapshot compiler. Since the Rust compiler is written in Rust, everyone has to download a binary version of the compiler in order to compile their own copy. In the distant past, there existed an Ocaml compiler for Rust, which was how the process was originally bootstraped. However, the language has changed drastically since then, so it's no longer useful. Paul From ben.striegel at gmail.com Tue Oct 23 06:36:31 2012 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Tue, 23 Oct 2012 09:36:31 -0400 Subject: [rust-dev] condition handling In-Reply-To: <5085F66C.4000401@mozilla.com> References: <5081E6D5.50700@mozilla.com> <5085F66C.4000401@mozilla.com> Message-ID: Thanks, this is very informative. I also have a few questions, so I apologize in advance if I betray my ignorance. The TLS key boilerplate would be rather unfortunate if it was forced to be in both the API provider and the API consumer, would it be possible to stick it in the io mod and then do const missing_file : Condition = Condition { key: io::missing_file_key }; (Not sure if there's some limitation on consts that prevents this.) I'm also unsure as to why missing_file_key needs to be a function at all, nor why Condition needs to be a single-element struct. For example, would it be possible for the io module to define an IoCondition enum, with variants for all of its potential keys? const missing_file : IoCondition = MissingFile; (I presume that there's some subtle point I'm missing here.) Lastly, is it expected that rustdoc will learn to detect every time that .raise() is called on a Condition? How will users of an API be expected to discover all the possible signals that are available to be trapped from any given function? On Mon, Oct 22, 2012 at 9:44 PM, Graydon Hoare wrote: > On 12-10-21 09:50 PM, Benjamin Striegel wrote: > > If it's not too much trouble, a complete example (using any one of the > > proposed syntaxes) would be enlightening. I'm still having a hard time > > imagining how OutOfKittens is defined, and how do_some_stuff et al > > signal it in the first place, and how the input/output of OutOfKittens > > can be utilized within the signalling function. > > Sure. Let's use a real case such as "trying to open a file that might be > missing in the middle of a call to read_whole_file_str". This involves a > few assumed changes to the way io is structured, but nothing deep: > > // Boilerplate for declaring TLS key > fn missing_file_key(_x: @Handler) { } > > const missing_file : Condition = > Condition { key: missing_file_key }; > > mod io { > // Revised to not use Result anymore > pub fn file_reader(path: &Path) -> Reader { > let f = do os::as_c_charp(path.to_str()) |p| { > do os::as_c_charp("r") |m| { > libc::fopen(p, m) > } > }; > if f as uint == 0u { > // No such file; ask for help via .raise > missing_file.raise(path) > } else { > FILE_reader(f, true)) > } > } > } > > fn main() { > do missing_file.trap(|_p| > BytesReader { bytes: ~[], pos: 0u } as Reader > ).in { > // This will trap in io::file_reader and > // substitute the empty bytes_reader above > let s = io::read_whole_file_str(Path("/nonexistent")); > } > } > > Clear enough? > > -Graydon > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hsivonen at iki.fi Tue Oct 23 06:52:13 2012 From: hsivonen at iki.fi (Henri Sivonen) Date: Tue, 23 Oct 2012 16:52:13 +0300 Subject: [rust-dev] Looping again but incrementing the loop counter first Message-ID: In C, Java, JS, etc., using |continue| in a |for| loop evaluates the update expression before going back to the condition. That is, in a C |for|, |continue| is a goto to the bottom of the loop and |continue| in |while| is a goto to right before the condition. What?s the correct way to write the equivalent of C/Java/JS for loop in Rust without having to repeat the update expression before each |loop;| statement (as one would have to when reformulating the loops as a Rust |while| loop)? -- Henri Sivonen hsivonen at iki.fi http://hsivonen.iki.fi/ From ben.striegel at gmail.com Tue Oct 23 07:35:16 2012 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Tue, 23 Oct 2012 10:35:16 -0400 Subject: [rust-dev] Looping again but incrementing the loop counter first In-Reply-To: References: Message-ID: Because of the special treatment of `for` loops in Rust, I'd need a more specific example of what you're trying to do. On Tue, Oct 23, 2012 at 9:52 AM, Henri Sivonen wrote: > In C, Java, JS, etc., using |continue| in a |for| loop evaluates the > update expression before going back to the condition. That is, in a C > |for|, |continue| is a goto to the bottom of the loop and |continue| > in |while| is a goto to right before the condition. > > What?s the correct way to write the equivalent of C/Java/JS for loop > in Rust without having to repeat the update expression before each > |loop;| statement (as one would have to when reformulating the loops > as a Rust |while| loop)? > > -- > Henri Sivonen > hsivonen at iki.fi > http://hsivonen.iki.fi/ > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From olson.jeffery at gmail.com Tue Oct 23 07:58:47 2012 From: olson.jeffery at gmail.com (Jeffery Olson) Date: Tue, 23 Oct 2012 07:58:47 -0700 Subject: [rust-dev] condition handling In-Reply-To: References: <5081E6D5.50700@mozilla.com> <5085F66C.4000401@mozilla.com> Message-ID: > How will users of an API be expected to > discover all the possible signals that are available to be trapped from any > given function? This is an existent problem on any platform with unchecked exceptions (C#/.NET, python, ruby, etc). There's no good answer, besides auditing of callee code or trial-and-error. From dteller at mozilla.com Tue Oct 23 08:00:11 2012 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Tue, 23 Oct 2012 17:00:11 +0200 Subject: [rust-dev] condition handling In-Reply-To: References: <5081E6D5.50700@mozilla.com> <5085F66C.4000401@mozilla.com> Message-ID: <5086B0FB.9040202@mozilla.com> I suspect that we can add optional static analysis (? la OCamlExc or Haskell Catch), executed as part of a strengthened build system. Cheers, David On 10/23/12 4:58 PM, Jeffery Olson wrote: >> How will users of an API be expected to >> discover all the possible signals that are available to be trapped from any >> given function? > > This is an existent problem on any platform with unchecked exceptions > (C#/.NET, python, ruby, etc). There's no good answer, besides auditing > of callee code or trial-and-error. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -- David Rajchenbach-Teller, PhD Performance Team, Mozilla -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: OpenPGP digital signature URL: From pwalton at mozilla.com Tue Oct 23 08:07:12 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Tue, 23 Oct 2012 08:07:12 -0700 Subject: [rust-dev] Object orientation without polymorphism In-Reply-To: References: <50868C6A.9040505@mozilla.com> Message-ID: <5086B2A0.5020908@mozilla.com> On 10/23/12 5:30 AM, Henri Sivonen wrote: > Is there a way to scope constants under the namespace of a struct? > Not at the moment. You can work around it by making the constants pure inline functions. I don't think it would be hard to add this now that we merged the type and module namespaces (this is only on git master though, not on 0.4). Patrick From pwalton at mozilla.com Tue Oct 23 08:10:14 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Tue, 23 Oct 2012 08:10:14 -0700 Subject: [rust-dev] Using char literals with non-char match In-Reply-To: References: <50856F90.8010007@mozilla.com> Message-ID: <5086B356.9030201@mozilla.com> On 10/23/12 4:17 AM, Henri Sivonen wrote: > That would work for match but doesn?t work for using char literals for > initializing u8 arrays and the like. Absent the ability to use char > literals the same way unsuffixed integer literals work, I guess the > easiest path forward is for me to generate hex integer literals > instead of char literals. :-( Note that casts are considered const exprs, so "'x' as u8" does work in a constant position. But yes, I've wanted a shorter syntax for char-literals-as-bytes as well. Something like 'x'u8 perhaps? Or I guess we could just infer it, but that adds a fair amount of complexity to the typechecker. Patrick From dteller at mozilla.com Tue Oct 23 08:30:11 2012 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Tue, 23 Oct 2012 17:30:11 +0200 Subject: [rust-dev] condition handling In-Reply-To: <5081E6D5.50700@mozilla.com> References: <5081E6D5.50700@mozilla.com> Message-ID: <5086B803.5010109@mozilla.com> As most people around here, I would prefer avoiding #2 and its magic variable, unless we can wrap it in a nice syntax extension/macro. Between #1 and #3, I prefer #1 for the exact reason James Boyden dislikes it: it lets me concentrate on the most common path, without having to deal with low-level issues upfront. I believe that this makes both writing and reading algorithms easier. I would also like to see a more complete example. Finally, I would like to be sure that I understand one thing: as far as I understand, this mechanism is not designed to handle any kind of concurrent condition, i.e. a condition raised in one task and best handled in another. The mechanism intended to handle such conditions is task failure. Am I correct? But, once again, I like the shape of things. Thanks, David -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: OpenPGP digital signature URL: From dteller at mozilla.com Tue Oct 23 09:00:28 2012 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Tue, 23 Oct 2012 18:00:28 +0200 Subject: [rust-dev] condition handling In-Reply-To: <5085F66C.4000401@mozilla.com> References: <5081E6D5.50700@mozilla.com> <5085F66C.4000401@mozilla.com> Message-ID: <5086BF1C.2010208@mozilla.com> On 10/23/12 3:44 AM, Graydon Hoare wrote: > On 12-10-21 09:50 PM, Benjamin Striegel wrote: >> If it's not too much trouble, a complete example (using any one of the >> proposed syntaxes) would be enlightening. I'm still having a hard time >> imagining how OutOfKittens is defined, and how do_some_stuff et al >> signal it in the first place, and how the input/output of OutOfKittens >> can be utilized within the signalling function. > > Sure. Let's use a real case such as "trying to open a file that might be > missing in the middle of a call to read_whole_file_str". This involves a > few assumed changes to the way io is structured, but nothing deep: > > // Boilerplate for declaring TLS key > fn missing_file_key(_x: @Handler) { } I do not understand this line. > const missing_file : Condition = > Condition { key: missing_file_key }; I have a little trouble parsing this line in which Condition appears both as a type name and as a constructor. Nothing fatal, but it might be a little difficult on end users. > > mod io { [...] > } > > Clear enough? Looks good to me, and I appreciate the demonstration that we can effectively write the definition of handlers after the protected code, at least as a coding convention. Cheers, David -- David Rajchenbach-Teller, PhD Performance Team, Mozilla -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: OpenPGP digital signature URL: From dbp at riseup.net Tue Oct 23 09:12:55 2012 From: dbp at riseup.net (Daniel Patterson) Date: Tue, 23 Oct 2012 12:12:55 -0400 Subject: [rust-dev] condition handling In-Reply-To: <5086BF1C.2010208@mozilla.com> References: <5081E6D5.50700@mozilla.com> <5085F66C.4000401@mozilla.com> <5086BF1C.2010208@mozilla.com> Message-ID: On Oct 23, 2012, at 12:00 PM, David Rajchenbach-Teller wrote: >> // Boilerplate for declaring TLS key >> fn missing_file_key(_x: @Handler) { } > I do not understand this line. TLS storage needs a unique key to identify it. Right now, the way that is done, as I understand it, is with the memory location for a global function. So this is truly boilerplate, just a way to get a unique identifier for the storage. From dteller at mozilla.com Tue Oct 23 09:14:27 2012 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Tue, 23 Oct 2012 18:14:27 +0200 Subject: [rust-dev] condition handling In-Reply-To: References: <5081E6D5.50700@mozilla.com> <5085F66C.4000401@mozilla.com> <5086BF1C.2010208@mozilla.com> Message-ID: <5086C263.5020006@mozilla.com> On 10/23/12 6:12 PM, Daniel Patterson wrote: > On Oct 23, 2012, at 12:00 PM, David Rajchenbach-Teller wrote: >>> // Boilerplate for declaring TLS key >>> fn missing_file_key(_x: @Handler) { } >> I do not understand this line. > > TLS storage needs a unique key to identify it. Right now, the way that is done, as I understand it, is with the memory location for a global function. So this is truly boilerplate, just a way to get a unique identifier for the storage. > Couldn't |missing_file| itself be the TLS key? Cheers, David -- David Rajchenbach-Teller, PhD Performance Team, Mozilla -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: OpenPGP digital signature URL: From matthieu.monrocq at gmail.com Tue Oct 23 10:37:51 2012 From: matthieu.monrocq at gmail.com (Matthieu Monrocq) Date: Tue, 23 Oct 2012 19:37:51 +0200 Subject: [rust-dev] Object orientation without polymorphism In-Reply-To: References: Message-ID: On Tue, Oct 23, 2012 at 2:46 PM, Julien Blanc wrote: > Lucian Branescu a ?crit : > > Something like this > > > http://pcwalton.github.com/blog/2012/08/08/a-gentle-introduction-to-traits-in-rust/ > > Very nice introduction. The only question that arises for me (coming from > c++ ground and comparing this to c++ templates) is why trait > implementation is made explicit ? > > Is it a design decision or a current compiler limitation ? I guess the > compiler could not too difficultly be made smart enough to determine from > its actual interface if a type conforms to a trait. Code generation may be > more a problem, though? > It is actually a design decision, quite similar to how typeclass in Haskell require explicit instantiation whereas Go's interfaces, like C++ templates, do not. Automatic detection is also called duck typing: it if quacks like a duck, then it's a duck. There are two main disadvantages: - functionally, it means that you can use an object for something it has never really been meant for => just because the signatures of some functions match does not mean that their semantics match too - in terms of codegen, this might imply bloat (C++) or runtime overhead (Go) On the other hand, Haskell's approach is quite practical.... as long as one solves the coherence issue. -- Matthieu -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Tue Oct 23 10:43:35 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Tue, 23 Oct 2012 10:43:35 -0700 Subject: [rust-dev] Object orientation without polymorphism In-Reply-To: References: Message-ID: <5086D747.6060901@mozilla.com> On 10/23/12 5:46 AM, Julien Blanc wrote: > Lucian Branescu a ?crit : >> Something like this >> http://pcwalton.github.com/blog/2012/08/08/a-gentle-introduction-to-traits-in-rust/ > > Very nice introduction. The only question that arises for me (coming from > c++ ground and comparing this to c++ templates) is why trait > implementation is made explicit ? > > Is it a design decision or a current compiler limitation ? I guess the > compiler could not too difficultly be made smart enough to determine from > its actual interface if a type conforms to a trait. Code generation may be > more a problem, though? The problem is that you wouldn't know which trait a method belongs to. There can be multiple traits that both define a method with the same name and signature, say, `foo`. In general it's hard to prevent this in the presence of separate compilation. Suppose we have library A that defines a trait with a method `foo` and, separately, there's a library B that defines a different trait with a method named `foo`. Now you want to link A and B together... Patrick From banderson at mozilla.com Tue Oct 23 11:21:30 2012 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 23 Oct 2012 11:21:30 -0700 Subject: [rust-dev] Looping again but incrementing the loop counter first In-Reply-To: References: Message-ID: <5086E02A.9030109@mozilla.com> On 10/23/2012 06:52 AM, Henri Sivonen wrote: > In C, Java, JS, etc., using |continue| in a |for| loop evaluates the > update expression before going back to the condition. That is, in a C > |for|, |continue| is a goto to the bottom of the loop and |continue| > in |while| is a goto to right before the condition. > > What?s the correct way to write the equivalent of C/Java/JS for loop > in Rust without having to repeat the update expression before each > |loop;| statement (as one would have to when reformulating the loops > as a Rust |while| loop)? > Those kind of counters are typically encapsulated in iterator functions that can be used with `for` so I guess this doesn't come up often. I'm assuming you need to do this with `loop` specifically for the HTML parser (since that is the only looping construct rust is currently implementing labeled break/continue for). I don't know a great solution. Maybe it could be put immediately after the entrance to the loop, but not increment the first time through. let i = LoopCounter(0, |val| val + 1); loop { i.update(); // Doesn't do anything the first time it's called if i.get() == 10 { loop; } } struct LoopCounter { val: T, update_fn: &fn(&T) -> T, first: bool } impl LoopCounter { fn update() { if self.first { self.first = false } else { self.val = self.update_fn(&self.val) } } } impl LoopCounter { fn get() -> T { copy self.val } } It's not pretty, but maybe good enough for transpiling? From graydon at mozilla.com Tue Oct 23 13:01:34 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 23 Oct 2012 13:01:34 -0700 Subject: [rust-dev] condition handling In-Reply-To: <5086B803.5010109@mozilla.com> References: <5081E6D5.50700@mozilla.com> <5086B803.5010109@mozilla.com> Message-ID: <5086F79E.9070509@mozilla.com> On 12-10-23 08:30 AM, David Rajchenbach-Teller wrote: > Finally, I would like to be sure that I understand one thing: as far as > I understand, this mechanism is not designed to handle any kind of > concurrent condition, i.e. a condition raised in one task and best > handled in another. The mechanism intended to handle such conditions is > task failure. Am I correct? Well, raise() is just a normal, synchronous call to a handler. The handler is free to do things like, say, send a message and wait for a response from a supervisor task, before continuing. It's really a just a piece in any particular error-management puzzle; can be composed a variety of ways. -Graydon From dteller at mozilla.com Tue Oct 23 13:03:17 2012 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Tue, 23 Oct 2012 22:03:17 +0200 Subject: [rust-dev] condition handling In-Reply-To: <5086F79E.9070509@mozilla.com> References: <5081E6D5.50700@mozilla.com> <5086B803.5010109@mozilla.com> <5086F79E.9070509@mozilla.com> Message-ID: <5086F805.9020306@mozilla.com> On 10/23/12 10:01 PM, Graydon Hoare wrote: > On 12-10-23 08:30 AM, David Rajchenbach-Teller wrote: > >> Finally, I would like to be sure that I understand one thing: as far as >> I understand, this mechanism is not designed to handle any kind of >> concurrent condition, i.e. a condition raised in one task and best >> handled in another. The mechanism intended to handle such conditions is >> task failure. Am I correct? > > Well, raise() is just a normal, synchronous call to a handler. The > handler is free to do things like, say, send a message and wait for a > response from a supervisor task, before continuing. Good point. I imagine that we will see nice applications to this. Cheers, David -- David Rajchenbach-Teller, PhD Performance Team, Mozilla -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: OpenPGP digital signature URL: From graydon at mozilla.com Tue Oct 23 13:13:48 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 23 Oct 2012 13:13:48 -0700 Subject: [rust-dev] condition handling In-Reply-To: References: <5081E6D5.50700@mozilla.com> <5085F66C.4000401@mozilla.com> Message-ID: <5086FA7C.3010008@mozilla.com> On 12-10-23 06:36 AM, Benjamin Striegel wrote: > Thanks, this is very informative. I also have a few questions, so I > apologize in advance if I betray my ignorance. > > The TLS key boilerplate would be rather unfortunate if it was forced to > be in both the API provider and the API consumer, would it be possible > to stick it in the io mod and then do The boilerplate will eventually get absorbed into an item macro. And in any case, yes, it should be declared in the IO module itself. Both the TLS key and the Condition. That was a .. presentation mistake in my example. > I'm also unsure as to why missing_file_key needs to be a function at > all, nor why Condition needs to be a single-element struct. In order for the .trap method to _exist_. It's an impl on a type. We could also write: do Condition::trap(missing_file_key, || handler).in { } it's pretty much synonymous, I just like the way it reads a bit better as an impl. Could be implemented on an enum too, but there's no real benefit either way. > Lastly, is it expected that rustdoc will learn to detect every time that > .raise() is called on a Condition? How will users of an API be expected > to discover all the possible signals that are available to be trapped > from any given function? We might be able to do some decoration with attributes to help rustdoc out here, but in general it's a transitive thing (not just conditions in this function, but conditions in any called-functions) so not going to be easy to bound without hoisting it up into the type system, which we're not intending to do. Part of the ... let's say "philosophy" of error handling in Rust is that one ought to accept the possibility that any task can fail in ways you can't foresee, though: OS signals, termination from other tasks, out of memory, array overrun, etc. etc. The task boundary exists for this reason: to protect you from having to know or be-able-to-recover from all forms of failure. So while I agree it'll be nice if we can present conditions via docs to some extent, and possibly some extreme forms of extended static checks, I don't expect "exhaustive handling" to really ever be the norm on this sort of thing. -Graydon From graydon at mozilla.com Tue Oct 23 13:19:03 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 23 Oct 2012 13:19:03 -0700 Subject: [rust-dev] condition handling In-Reply-To: <5086C263.5020006@mozilla.com> References: <5081E6D5.50700@mozilla.com> <5085F66C.4000401@mozilla.com> <5086BF1C.2010208@mozilla.com> <5086C263.5020006@mozilla.com> Message-ID: <5086FBB7.6050103@mozilla.com> On 12-10-23 09:14 AM, David Rajchenbach-Teller wrote: > Couldn't |missing_file| itself be the TLS key? Probably. I believe it wasn't done that way for two reasons: - Data addresses can be recycled by accident, due to stack/heap reuse. Code segment addresses are Really Unique at load time. - TLS needs function pointers anyways to have cleanups associated with TLS entries when tasks die. It might be possible to merge these a bit more (there are unfortunate linkage complications with PLTs anyways) but in general I expect to hide whatever boilerplate there is behind an item macro like: condition! missing_file(&Path) -> Reader; -Graydon From niko at alum.mit.edu Tue Oct 23 16:31:51 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 23 Oct 2012 16:31:51 -0700 Subject: [rust-dev] condition handling In-Reply-To: <5086FBB7.6050103@mozilla.com> References: <5081E6D5.50700@mozilla.com> <5085F66C.4000401@mozilla.com> <5086BF1C.2010208@mozilla.com> <5086C263.5020006@mozilla.com> <5086FBB7.6050103@mozilla.com> Message-ID: <508728E7.4030905@alum.mit.edu> On the topic of TLS boilerplate: At some point it was proposed that we use the type descriptor itself as the key. With some minimal effort, we could make them unique, at least for nominal types---TLS could just fail if a non-nominal type were used as the value, or perhaps we can enforce this statically through a kind. That would eliminate the boilerplate of using TLS, basically. You'd just have to declare the struct/enum type that will serve as the value. I like this idea. Niko > Graydon Hoare > October 23, 2012 1:19 PM > > Probably. I believe it wasn't done that way for two reasons: > > - Data addresses can be recycled by accident, due to stack/heap > reuse. Code segment addresses are Really Unique at load time. > > - TLS needs function pointers anyways to have cleanups associated > with TLS entries when tasks die. > > It might be possible to merge these a bit more (there are unfortunate > linkage complications with PLTs anyways) but in general I expect to hide > whatever boilerplate there is behind an item macro like: > > condition! missing_file(&Path) -> Reader; > > -Graydon > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > David Rajchenbach-Teller > October 23, 2012 8:14 AM > > Couldn't |missing_file| itself be the TLS key? > > Cheers, > David > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Daniel Patterson > October 23, 2012 8:12 AM > > TLS storage needs a unique key to identify it. Right now, the way that > is done, as I understand it, is with the memory location for a global > function. So this is truly boilerplate, just a way to get a unique > identifier for the storage. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > David Rajchenbach-Teller > October 23, 2012 8:00 AM > On 10/23/12 3:44 AM, Graydon Hoare wrote: >> On 12-10-21 09:50 PM, Benjamin Striegel wrote: >>> If it's not too much trouble, a complete example (using any one of the >>> proposed syntaxes) would be enlightening. I'm still having a hard time >>> imagining how OutOfKittens is defined, and how do_some_stuff et al >>> signal it in the first place, and how the input/output of OutOfKittens >>> can be utilized within the signalling function. >> Sure. Let's use a real case such as "trying to open a file that might be >> missing in the middle of a call to read_whole_file_str". This involves a >> few assumed changes to the way io is structured, but nothing deep: >> >> // Boilerplate for declaring TLS key >> fn missing_file_key(_x: @Handler) { } > I do not understand this line. > >> const missing_file : Condition = >> Condition { key: missing_file_key }; > I have a little trouble parsing this line in which Condition appears > both as a type name and as a constructor. Nothing fatal, but it might be > a little difficult on end users. > >> mod io { > [...] >> } >> >> Clear enough? > > Looks good to me, and I appreciate the demonstration that we can > effectively write the definition of handlers after the protected code, > at least as a coding convention. > > Cheers, > David > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Graydon Hoare > October 22, 2012 5:44 PM > > Sure. Let's use a real case such as "trying to open a file that might be > missing in the middle of a call to read_whole_file_str". This involves a > few assumed changes to the way io is structured, but nothing deep: > > // Boilerplate for declaring TLS key > fn missing_file_key(_x: @Handler) { } > > const missing_file : Condition = > Condition { key: missing_file_key }; > > mod io { > // Revised to not use Result anymore > pub fn file_reader(path: &Path) -> Reader { > let f = do os::as_c_charp(path.to_str()) |p| { > do os::as_c_charp("r") |m| { > libc::fopen(p, m) > } > }; > if f as uint == 0u { > // No such file; ask for help via .raise > missing_file.raise(path) > } else { > FILE_reader(f, true)) > } > } > } > > fn main() { > do missing_file.trap(|_p| > BytesReader { bytes: ~[], pos: 0u } as Reader > ).in { > // This will trap in io::file_reader and > // substitute the empty bytes_reader above > let s = io::read_whole_file_str(Path("/nonexistent")); > } > } > > Clear enough? > > -Graydon > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: postbox-contact.jpg Type: image/jpeg Size: 1154 bytes Desc: not available URL: From jruderman at gmail.com Tue Oct 23 20:49:31 2012 From: jruderman at gmail.com (Jesse Ruderman) Date: Tue, 23 Oct 2012 20:49:31 -0700 Subject: [rust-dev] Purity by default Message-ID: Should functions default to pure? * With http://smallcultfollowing.com/babysteps/blog/2012/10/12/extending-the-definition-of-purity-in-rust/ I think most functions will be able to be pure. * Would avoid the problem of forgetting to mark a function as pure, causing pain for a caller. (Or worse, causing the compiler to generate slower code?) * Would encourage writing pure code, by making pure less typing than impure. * With http://smallcultfollowing.com/babysteps/blog/2012/10/23/function-and-object-types/ the "impure" and "unsafe" modifiers would move in the same direction. (Currently, "pure" and "unsafe" move in opposite directions from the default, which is impure.) From me at kevincantu.org Tue Oct 23 23:17:33 2012 From: me at kevincantu.org (Kevin Cantu) Date: Tue, 23 Oct 2012 23:17:33 -0700 Subject: [rust-dev] Using char literals with non-char match In-Reply-To: <5086B356.9030201@mozilla.com> References: <50856F90.8010007@mozilla.com> <5086B356.9030201@mozilla.com> Message-ID: There's always "x"[0], right? Kevin On Tue, Oct 23, 2012 at 8:10 AM, Patrick Walton wrote: > On 10/23/12 4:17 AM, Henri Sivonen wrote: >> >> That would work for match but doesn?t work for using char literals for >> initializing u8 arrays and the like. Absent the ability to use char >> literals the same way unsuffixed integer literals work, I guess the >> easiest path forward is for me to generate hex integer literals >> instead of char literals. :-( > > > Note that casts are considered const exprs, so "'x' as u8" does work in a > constant position. > > But yes, I've wanted a shorter syntax for char-literals-as-bytes as well. > Something like 'x'u8 perhaps? Or I guess we could just infer it, but that > adds a fair amount of complexity to the typechecker. > > Patrick > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From hsivonen at iki.fi Tue Oct 23 23:41:47 2012 From: hsivonen at iki.fi (Henri Sivonen) Date: Wed, 24 Oct 2012 09:41:47 +0300 Subject: [rust-dev] Using char literals with non-char match In-Reply-To: <5086B356.9030201@mozilla.com> References: <50856F90.8010007@mozilla.com> <5086B356.9030201@mozilla.com> Message-ID: On Tue, Oct 23, 2012 at 6:10 PM, Patrick Walton wrote: > Something like 'x'u8 perhaps? That would suit my use case. -- Henri Sivonen hsivonen at iki.fi http://hsivonen.iki.fi/ From hsivonen at iki.fi Wed Oct 24 00:19:42 2012 From: hsivonen at iki.fi (Henri Sivonen) Date: Wed, 24 Oct 2012 10:19:42 +0300 Subject: [rust-dev] Looping again but incrementing the loop counter first In-Reply-To: References: Message-ID: On Tue, Oct 23, 2012 at 5:35 PM, Benjamin Striegel wrote: > Because of the special treatment of `for` loops in Rust, I'd need a more > specific example of what you're trying to do. Looping over a part of an array by index and moving on immediately when a ?not interested? condition matches. Stuff like for (int i = start; i < end; i++) { char c = buf[i]; ... if (c == uninteresting) { continue; } ... } On Tue, Oct 23, 2012 at 9:21 PM, Brian Anderson wrote: > I'm assuming > you need to do this with `loop` specifically for the HTML parser (since that > is the only looping construct rust is currently implementing labeled > break/continue for). The HTML parser breaks/continues by label only with ?infinite? loop. The loops with an index variable are not continued/broken by label. > It's not pretty, but maybe good enough for transpiling? Yeah, not pretty. I think the simplest solution is to transform the Java ?for? loops that have an update expression into Rust ?while? loops and copy the update expression to the end of the loop and to before each loop; statement. (And then maybe changing the Java source over time to make this pattern occur less.) (Aside: Now that Rust has both loop { } and loop;, talking about the ?loop statement? would be ambiguous.) -- Henri Sivonen hsivonen at iki.fi http://hsivonen.iki.fi/ From stefan.plantikow at gmail.com Wed Oct 24 00:28:04 2012 From: stefan.plantikow at gmail.com (Stefan Plantikow) Date: Wed, 24 Oct 2012 09:28:04 +0200 Subject: [rust-dev] Purity by default In-Reply-To: References: Message-ID: <2CA65573-7D1D-41B5-89A6-BE1ADF494199@googlemail.com> Am 24.10.2012 um 05:49 schrieb Jesse Ruderman : > Should functions default to pure? > > * With http://smallcultfollowing.com/babysteps/blog/2012/10/12/extending-the-definition-of-purity-in-rust/ > I think most functions will be able to be pure. > > * Would avoid the problem of forgetting to mark a function as pure, > causing pain for a caller. (Or worse, causing the compiler to > generate slower code?) > > * Would encourage writing pure code, by making pure less typing than impure. > > * With http://smallcultfollowing.com/babysteps/blog/2012/10/23/function-and-object-types/ > the "impure" and "unsafe" modifiers would move in the same direction. > (Currently, "pure" and "unsafe" move in opposite directions from the > default, which is impure.) I like that idea very much except that there are probably situations in which one wants the reverse, i.e. modules marked as impure which then requires purity annotations for functions. boggle. From arkaitzj at gmail.com Wed Oct 24 00:41:00 2012 From: arkaitzj at gmail.com (arkaitzj at gmail.com) Date: Wed, 24 Oct 2012 09:41:00 +0200 Subject: [rust-dev] Rust simplest server Message-ID: Hi, I'm starting with rust, although I've been looking inside for a while its the first time I try writing real rust code. So, I pulled from master yesterday and wrote this simple server http://pastebin.com/MMiNpXYG No tasks, no concurrency, a single-threaded, single-tasked server, that to my eyes should be able to handle one client after another, however, I seem to be unable to see any other client than the first one in the server, netcat does not complain but listen.rs does not see the new client. Am I doing anything wrong? AFAIK, rust is not going to support traditional socket handling, everything is going to go over libuv, is this statement correct? Thanks -- Arkaitz -------------- next part -------------- An HTML attachment was scrubbed... URL: From lucian.branescu at gmail.com Wed Oct 24 02:50:55 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Wed, 24 Oct 2012 10:50:55 +0100 Subject: [rust-dev] Rust simplest server In-Reply-To: References: Message-ID: On 24 October 2012 08:41, arkaitzj at gmail.com wrote: > AFAIK, rust is not going to support traditional socket handling, everything > is going to go over libuv, is this statement correct? Rust will (and already does) support blocking IO, it just won't try to automatically make it look non-blocking (like Go does). So you can use sockets if you wish, but you have all the usual problems of blocking IO. From arkaitzj at gmail.com Wed Oct 24 02:52:58 2012 From: arkaitzj at gmail.com (arkaitzj at gmail.com) Date: Wed, 24 Oct 2012 11:52:58 +0200 Subject: [rust-dev] Rust simplest server In-Reply-To: References: Message-ID: Hi, On Wed, Oct 24, 2012 at 11:50 AM, Lucian Branescu wrote: > On 24 October 2012 08:41, arkaitzj at gmail.com wrote: > > AFAIK, rust is not going to support traditional socket handling, > everything > > is going to go over libuv, is this statement correct? > > Rust will (and already does) support blocking IO, it just won't try to > automatically make it look non-blocking (like Go does). > So you can use sockets if you wish, but you have all the usual > problems of blocking IO. > I thought everything in std::net::tcp was on top of uv, is this not true? Where can I find functions for sockets,select/poll, etc.. ? Thanks Arkaitz -------------- next part -------------- An HTML attachment was scrubbed... URL: From lucian.branescu at gmail.com Wed Oct 24 02:55:05 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Wed, 24 Oct 2012 10:55:05 +0100 Subject: [rust-dev] Rust simplest server In-Reply-To: References: Message-ID: On 24 October 2012 10:52, arkaitzj at gmail.com wrote: >> On 24 October 2012 08:41, arkaitzj at gmail.com wrote: >> > AFAIK, rust is not going to support traditional socket handling, >> > everything >> > is going to go over libuv, is this statement correct? >> >> Rust will (and already does) support blocking IO, it just won't try to >> automatically make it look non-blocking (like Go does). >> So you can use sockets if you wish, but you have all the usual >> problems of blocking IO. > > I thought everything in std::net::tcp was on top of uv, is this not true? > Where can I find functions for sockets,select/poll, etc.. ? I don't know, it's possible that they aren't wrapped. It's pretty easy to call C libs, so you could try that maybe? From lucian.branescu at gmail.com Wed Oct 24 05:04:21 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Wed, 24 Oct 2012 13:04:21 +0100 Subject: [rust-dev] Transpiling to Rust In-Reply-To: References: Message-ID: On 22 October 2012 20:28, Chad Retz wrote: > I am very new to Rust, but I have a little project where I'd like to compile > something else into Rust code. I have seen the macro syntax which doesn't > operate on pure strings (from what I see) and I have seen projects like > rust-repl that parse and inject at runtime. Which approach should I take if > I want to be able to transpile both to a string to save into a file and to > use it at runtime depending on what the user wants? (I have done this in D, > yet the mixins there work with strings natively so there is no real decision > to make). Rust's macro system won't let you implement a DSL that is very different from rust itself. You could express the language as function calls, which you could do at runtime or from a macro. From arkaitzj at gmail.com Wed Oct 24 05:16:33 2012 From: arkaitzj at gmail.com (arkaitzj at gmail.com) Date: Wed, 24 Oct 2012 14:16:33 +0200 Subject: [rust-dev] Rust simplest server In-Reply-To: References: Message-ID: Hi, On Wed, Oct 24, 2012 at 9:41 AM, arkaitzj at gmail.com wrote: > Hi, > I'm starting with rust, although I've been looking inside for a while its > the first time I try writing real rust code. > So, I pulled from master yesterday and wrote this simple server > http://pastebin.com/MMiNpXYG > > No tasks, no concurrency, a single-threaded, single-tasked server, that to > my eyes should be able to handle one client after another, however, I seem > to be unable to see any other client than the first one in the server, > netcat does not complain but listen.rs does not see the new client. > Am I doing anything wrong? > I've tried using libuv in C to see if it was that, but looking at what I got working in http://pastebin.com/tPc4A9Sj I'd say something is not right. The C version looks pretty much the same as the rust version but the C version does work as expected, receiving new clients after the first one. Thanks Arkaitz -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.double at double.co.nz Wed Oct 24 05:58:51 2012 From: chris.double at double.co.nz (Chris Double) Date: Thu, 25 Oct 2012 01:58:51 +1300 Subject: [rust-dev] Looping again but incrementing the loop counter first In-Reply-To: References: Message-ID: On Wed, Oct 24, 2012 at 8:19 PM, Henri Sivonen wrote: > Looping over a part of an array by index and moving on immediately > when a ?not interested? condition matches. > > Stuff like > for (int i = start; i < end; i++) { > char c = buf[i]; > ... > if (c == uninteresting) { > continue; > } > ... > } You might be able to bend macros into something you want. For example: macro_rules! my_loop( ($cond:expr, $inc:expr, $body:expr) => { while $cond { while $cond { $body; $inc; } $inc; } }; ) fn main () { io::println("hello"); let mut i = 0; my_loop!(i < 10, i += 1, { if i < 5 { break; } io::println("foo"); }) } Here 'break' inside the macro is your 'continue' and in the example "i < 5" is the uninteresting check. I don't know how, in rust, to change all uses of some_string into "($inc; loop)" but if you can you can do better than this example. Chris. -- http://www.bluishcoder.co.nz From halperin.dr at gmail.com Wed Oct 24 08:23:44 2012 From: halperin.dr at gmail.com (Dave Halperin) Date: Wed, 24 Oct 2012 11:23:44 -0400 Subject: [rust-dev] Looping again but incrementing the loop counter first In-Reply-To: References: Message-ID: Python doesn't have c style for loops and the way you'd do this is use xrange to create an iterator over a range of numbers, then use a high level for loop. This seems like the cleanest solution for rust to me. Psuedo-code: for range(start, end) |i| { char c = buf[i]; ... if (c == uninteresting) { continue; } ... } Seems like range and some related functions should be considered for the standard library to support this style. On Wed, Oct 24, 2012 at 8:58 AM, Chris Double wrote: > On Wed, Oct 24, 2012 at 8:19 PM, Henri Sivonen wrote: > > Looping over a part of an array by index and moving on immediately > > when a ?not interested? condition matches. > > > > Stuff like > > for (int i = start; i < end; i++) { > > char c = buf[i]; > > ... > > if (c == uninteresting) { > > continue; > > } > > ... > > } > > You might be able to bend macros into something you want. For example: > > macro_rules! my_loop( > ($cond:expr, $inc:expr, $body:expr) => { > while $cond { > while $cond { > $body; > $inc; > } > $inc; > } > }; > ) > > fn main () { > io::println("hello"); > let mut i = 0; > my_loop!(i < 10, i += 1, { > if i < 5 { break; } > io::println("foo"); > }) > } > > Here 'break' inside the macro is your 'continue' and in the example "i > < 5" is the uninteresting check. I don't know how, in rust, to change > all uses of some_string into "($inc; loop)" but if you can you can do > better than this example. > > Chris. > -- > http://www.bluishcoder.co.nz > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From gwillen at nerdnet.org Wed Oct 24 08:58:05 2012 From: gwillen at nerdnet.org (Glenn Willen) Date: Wed, 24 Oct 2012 08:58:05 -0700 Subject: [rust-dev] Rust simplest server In-Reply-To: References: Message-ID: Well, it's worse than that I think? You will have far more than the usual problems of blocking I/O, because the Rust scheduler will be unaware of your blocking, and will not be able to switch tasks when you block. So if you have multiple tasks, blocking I/O will break everything. Glenn > Rust will (and already does) support blocking IO, it just won't try to > automatically make it look non-blocking (like Go does). > So you can use sockets if you wish, but you have all the usual > problems of blocking IO. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > > !DSPAM:5087b8fa307329028381310! > -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 243 bytes Desc: This is a digitally signed message part URL: From lucian.branescu at gmail.com Wed Oct 24 09:13:42 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Wed, 24 Oct 2012 17:13:42 +0100 Subject: [rust-dev] Rust simplest server In-Reply-To: References: Message-ID: I think you'd get back the same situation as in C with a scheduler that ran each task in its own thread, or at least that's what I was told. On 24 October 2012 16:58, Glenn Willen wrote: > Well, it's worse than that I think? You will have far more than the usual problems of blocking I/O, because the Rust scheduler will be unaware of your blocking, and will not be able to switch tasks when you block. So if you have multiple tasks, blocking I/O will break everything. > > Glenn > >> Rust will (and already does) support blocking IO, it just won't try to >> automatically make it look non-blocking (like Go does). >> So you can use sockets if you wish, but you have all the usual >> problems of blocking IO. >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev >> >> >> !DSPAM:5087b8fa307329028381310! >> > From gwillen at nerdnet.org Wed Oct 24 09:20:34 2012 From: gwillen at nerdnet.org (Glenn Willen) Date: Wed, 24 Oct 2012 09:20:34 -0700 Subject: [rust-dev] Rust simplest server In-Reply-To: References: Message-ID: That sounds about right, yes. (That's just not the scheduler that exists now. And this is the first I've heard of the idea that Rust might get such a scheduler, although it seems like a useful thing to have.) Glenn On Oct 24, 2012, at 9:13 AM, Lucian Branescu wrote: > I think you'd get back the same situation as in C with a scheduler > that ran each task in its own thread, or at least that's what I was > told. > > On 24 October 2012 16:58, Glenn Willen wrote: >> Well, it's worse than that I think? You will have far more than the usual problems of blocking I/O, because the Rust scheduler will be unaware of your blocking, and will not be able to switch tasks when you block. So if you have multiple tasks, blocking I/O will break everything. >> >> Glenn >> >>> Rust will (and already does) support blocking IO, it just won't try to >>> automatically make it look non-blocking (like Go does). >>> So you can use sockets if you wish, but you have all the usual >>> problems of blocking IO. >>> _______________________________________________ >>> Rust-dev mailing list >>> Rust-dev at mozilla.org >>> https://mail.mozilla.org/listinfo/rust-dev >>> >>> >>> >>> >> > > > !DSPAM:508813b1235362133512636! > -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 243 bytes Desc: This is a digitally signed message part URL: From dbp at riseup.net Wed Oct 24 09:20:57 2012 From: dbp at riseup.net (Daniel Patterson) Date: Wed, 24 Oct 2012 12:20:57 -0400 Subject: [rust-dev] Looping again but incrementing the loop counter first In-Reply-To: References: Message-ID: <5F17B588-DC1D-4DE0-ABBC-A89E34E91E53@riseup.net> See times, timesi (implemented for uint and int), and int::range (i.e., these all already exist) On Oct 24, 2012, at 11:23 AM, Dave Halperin wrote: > Python doesn't have c style for loops and the way you'd do this is use xrange to create an iterator over a range of numbers, then use a high level for loop. This seems like the cleanest solution for rust to me. Psuedo-code: > > for range(start, end) |i| { > char c = buf[i]; > ... > if (c == uninteresting) { > continue; > } > ... > } > > Seems like range and some related functions should be considered for the standard library to support this style. > > On Wed, Oct 24, 2012 at 8:58 AM, Chris Double wrote: > On Wed, Oct 24, 2012 at 8:19 PM, Henri Sivonen wrote: > > Looping over a part of an array by index and moving on immediately > > when a ?not interested? condition matches. > > > > Stuff like > > for (int i = start; i < end; i++) { > > char c = buf[i]; > > ... > > if (c == uninteresting) { > > continue; > > } > > ... > > } > > You might be able to bend macros into something you want. For example: > > macro_rules! my_loop( > ($cond:expr, $inc:expr, $body:expr) => { > while $cond { > while $cond { > $body; > $inc; > } > $inc; > } > }; > ) > > fn main () { > io::println("hello"); > let mut i = 0; > my_loop!(i < 10, i += 1, { > if i < 5 { break; } > io::println("foo"); > }) > } > > Here 'break' inside the macro is your 'continue' and in the example "i > < 5" is the uninteresting check. I don't know how, in rust, to change > all uses of some_string into "($inc; loop)" but if you can you can do > better than this example. > > Chris. > -- > http://www.bluishcoder.co.nz > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Wed Oct 24 09:49:03 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 24 Oct 2012 09:49:03 -0700 Subject: [rust-dev] Purity by default In-Reply-To: <2CA65573-7D1D-41B5-89A6-BE1ADF494199@googlemail.com> References: <2CA65573-7D1D-41B5-89A6-BE1ADF494199@googlemail.com> Message-ID: <50881BFF.5010001@alum.mit.edu> It's an interesting question. I am not sure whether "most" functions can be pure under the definition I gave in that blog post, but likely a great many. There is also some question of whether we should have purity at all. pcwalton and I have been thinking about an alternative which would allow us to remove the pure qualifier altogether, though unfortunately it's less expressive. The basic idea is that instead of requiring purity, the borrow checker would only permit calls to functions that cannot access mutable state. This can be guaranteed through a combination of a Const bound and by checking the types of values provided as a parameter. This has the advantage that all fn items fit this definition, presuming that their parameters are of appropriate type. I hope to get around to writing this up as a blog post trying to explore the areas where the newer approach would fall short of purity. Niko > Stefan Plantikow > October 24, 2012 12:28 AM > > I like that idea very much except that there are probably situations > in which one wants the reverse, i.e. > modules marked as impure which then requires purity annotations for > functions. > > boggle. > > > > > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Jesse Ruderman > October 23, 2012 7:49 PM > Should functions default to pure? > > * With > http://smallcultfollowing.com/babysteps/blog/2012/10/12/extending-the-definition-of-purity-in-rust/ > I think most functions will be able to be pure. > > * Would avoid the problem of forgetting to mark a function as pure, > causing pain for a caller. (Or worse, causing the compiler to > generate slower code?) > > * Would encourage writing pure code, by making pure less typing than > impure. > > * With > http://smallcultfollowing.com/babysteps/blog/2012/10/23/function-and-object-types/ > the "impure" and "unsafe" modifiers would move in the same direction. > (Currently, "pure" and "unsafe" move in opposite directions from the > default, which is impure.) > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: From halperin.dr at gmail.com Wed Oct 24 10:28:54 2012 From: halperin.dr at gmail.com (Dave Halperin) Date: Wed, 24 Oct 2012 13:28:54 -0400 Subject: [rust-dev] Looping again but incrementing the loop counter first In-Reply-To: <5F17B588-DC1D-4DE0-ABBC-A89E34E91E53@riseup.net> References: <5F17B588-DC1D-4DE0-ABBC-A89E34E91E53@riseup.net> Message-ID: Not exactly, those don't have the right signature to be used with a for loop, they just take a function. You wouldn't be able to use break or continue with them. On Wed, Oct 24, 2012 at 12:20 PM, Daniel Patterson wrote: > See times, timesi (implemented for uint and int), and int::range (i.e., > these all already exist) > > On Oct 24, 2012, at 11:23 AM, Dave Halperin wrote: > > Python doesn't have c style for loops and the way you'd do this is use > xrange to create an iterator over a range of numbers, then use a high level > for loop. This seems like the cleanest solution for rust to me. > Psuedo-code: > > for range(start, end) |i| { > char c = buf[i]; > ... > if (c == uninteresting) { > continue; > } > ... > } > > Seems like range and some related functions should be considered for the > standard library to support this style. > > On Wed, Oct 24, 2012 at 8:58 AM, Chris Double wrote: > >> On Wed, Oct 24, 2012 at 8:19 PM, Henri Sivonen wrote: >> > Looping over a part of an array by index and moving on immediately >> > when a ?not interested? condition matches. >> > >> > Stuff like >> > for (int i = start; i < end; i++) { >> > char c = buf[i]; >> > ... >> > if (c == uninteresting) { >> > continue; >> > } >> > ... >> > } >> >> You might be able to bend macros into something you want. For example: >> >> macro_rules! my_loop( >> ($cond:expr, $inc:expr, $body:expr) => { >> while $cond { >> while $cond { >> $body; >> $inc; >> } >> $inc; >> } >> }; >> ) >> >> fn main () { >> io::println("hello"); >> let mut i = 0; >> my_loop!(i < 10, i += 1, { >> if i < 5 { break; } >> io::println("foo"); >> }) >> } >> >> Here 'break' inside the macro is your 'continue' and in the example "i >> < 5" is the uninteresting check. I don't know how, in rust, to change >> all uses of some_string into "($inc; loop)" but if you can you can do >> better than this example. >> >> Chris. >> -- >> http://www.bluishcoder.co.nz >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev >> > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dbp at riseup.net Wed Oct 24 10:33:20 2012 From: dbp at riseup.net (Daniel Patterson) Date: Wed, 24 Oct 2012 13:33:20 -0400 Subject: [rust-dev] Looping again but incrementing the loop counter first In-Reply-To: References: <5F17B588-DC1D-4DE0-ABBC-A89E34E91E53@riseup.net> Message-ID: <58C57123-6CBA-428A-908D-8C582A29A133@riseup.net> See the section of the tutorial on for and do - they are desugared to use functions of that sort (i.e., the body is a closure which is the last parameter of the function used). The following code compiles: fn main() { for 5.timesi |i| { if i % 2 == 0 { loop; } io::println(i.to_str()); } for int::range(0,10) |i| { io::println(i.to_str()); if i > 5 { break; } } } And produces: 1 3 0 1 2 3 4 5 6 On Oct 24, 2012, at 1:28 PM, Dave Halperin wrote: > Not exactly, those don't have the right signature to be used with a for loop, they just take a function. You wouldn't be able to use break or continue with them. > > On Wed, Oct 24, 2012 at 12:20 PM, Daniel Patterson wrote: > See times, timesi (implemented for uint and int), and int::range (i.e., these all already exist) > > On Oct 24, 2012, at 11:23 AM, Dave Halperin wrote: > >> Python doesn't have c style for loops and the way you'd do this is use xrange to create an iterator over a range of numbers, then use a high level for loop. This seems like the cleanest solution for rust to me. Psuedo-code: >> >> for range(start, end) |i| { >> char c = buf[i]; >> ... >> if (c == uninteresting) { >> continue; >> } >> ... >> } >> >> Seems like range and some related functions should be considered for the standard library to support this style. >> >> On Wed, Oct 24, 2012 at 8:58 AM, Chris Double wrote: >> On Wed, Oct 24, 2012 at 8:19 PM, Henri Sivonen wrote: >> > Looping over a part of an array by index and moving on immediately >> > when a ?not interested? condition matches. >> > >> > Stuff like >> > for (int i = start; i < end; i++) { >> > char c = buf[i]; >> > ... >> > if (c == uninteresting) { >> > continue; >> > } >> > ... >> > } >> >> You might be able to bend macros into something you want. For example: >> >> macro_rules! my_loop( >> ($cond:expr, $inc:expr, $body:expr) => { >> while $cond { >> while $cond { >> $body; >> $inc; >> } >> $inc; >> } >> }; >> ) >> >> fn main () { >> io::println("hello"); >> let mut i = 0; >> my_loop!(i < 10, i += 1, { >> if i < 5 { break; } >> io::println("foo"); >> }) >> } >> >> Here 'break' inside the macro is your 'continue' and in the example "i >> < 5" is the uninteresting check. I don't know how, in rust, to change >> all uses of some_string into "($inc; loop)" but if you can you can do >> better than this example. >> >> Chris. >> -- >> http://www.bluishcoder.co.nz >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev >> >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nejucomo at gmail.com Wed Oct 24 11:51:33 2012 From: nejucomo at gmail.com (Nathan) Date: Wed, 24 Oct 2012 11:51:33 -0700 Subject: [rust-dev] Purity by default In-Reply-To: <50881BFF.5010001@alum.mit.edu> References: <2CA65573-7D1D-41B5-89A6-BE1ADF494199@googlemail.com> <50881BFF.5010001@alum.mit.edu> Message-ID: On Wed, Oct 24, 2012 at 9:49 AM, Niko Matsakis wrote: > It's an interesting question. I am not sure whether "most" functions can > be pure under the definition I gave in that blog post, but likely a great > many. > > There is also some question of whether we should have purity at all. > pcwalton and I have been thinking about an alternative which would allow us > to remove the pure qualifier altogether, though unfortunately it's less > expressive. The basic idea is that instead of requiring purity, the borrow > checker would only permit calls to functions that cannot access mutable > state. This can be guaranteed through a combination of a Const bound and > by checking the types of values provided as a parameter. This has the > advantage that all fn items fit this definition, presuming that their > parameters are of appropriate type. > > The value of the "pure" keyword is not only in the static checking, but also in the programmer documenting the intention of their API. When both of these benefits are tied together, the documentation benefit has much more value. In fact, there's a close parallel between purity inference and type inference, since we can think of purity as an aspect of the type. So even though we have type inference, it is very useful to see type annotations when looking at APIs. Therefore I'd propose that the purity keyword must be present and match the purity inference in every context where a type signature must be present to match the type inference. I hope to get around to writing this up as a blog post trying to explore > the areas where the newer approach would fall short of purity. > > > > Niko > > Regards, Nathan Wilcox > Stefan Plantikow > October 24, 2012 12:28 AM > > I like that idea very much except that there are probably situations in > which one wants the reverse, i.e. > modules marked as impure which then requires purity annotations for > functions. > > boggle. > > > > > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Jesse Ruderman > October 23, 2012 7:49 PM > Should functions default to pure? > > * With > http://smallcultfollowing.com/babysteps/blog/2012/10/12/extending-the-definition-of-purity-in-rust/ > I think most functions will be able to be pure. > > * Would avoid the problem of forgetting to mark a function as pure, > causing pain for a caller. (Or worse, causing the compiler to > generate slower code?) > > * Would encourage writing pure code, by making pure less typing than > impure. > > * With > http://smallcultfollowing.com/babysteps/blog/2012/10/23/function-and-object-types/ > the "impure" and "unsafe" modifiers would move in the same direction. > (Currently, "pure" and "unsafe" move in opposite directions from the > default, which is impure.) > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: From pwalton at mozilla.com Wed Oct 24 11:58:46 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 24 Oct 2012 11:58:46 -0700 Subject: [rust-dev] Purity by default In-Reply-To: References: <2CA65573-7D1D-41B5-89A6-BE1ADF494199@googlemail.com> <50881BFF.5010001@alum.mit.edu> Message-ID: <50883A66.7040209@mozilla.com> On 10/24/12 11:51 AM, Nathan wrote: > Therefore I'd propose that the purity keyword must be present and match > the purity inference in every context where a type signature must be > present to match the type inference. -1 on this. I think that it's often quite useful to reserve the right to make a presently-pure function impure later without breaking callers. When commenting out code, for example. Patrick From banderson at mozilla.com Wed Oct 24 12:11:26 2012 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 24 Oct 2012 12:11:26 -0700 Subject: [rust-dev] Rust simplest server In-Reply-To: References: Message-ID: <50883D5E.2060408@mozilla.com> On 10/24/2012 12:41 AM, arkaitzj at gmail.com wrote: > Hi, > I'm starting with rust, although I've been looking inside for a while > its the first time I try writing real rust code. > So, I pulled from master yesterday and wrote this simple server > http://pastebin.com/MMiNpXYG > > No tasks, no concurrency, a single-threaded, single-tasked server, that > to my eyes should be able to handle one client after another, however, I > seem to be unable to see any other client than the first one in the > server, netcat does not complain but listen.rs does > not see the new client. > Am I doing anything wrong? > > AFAIK, rust is not going to support traditional socket handling, > everything is going to go over libuv, is this statement correct? > Yes, this is correct. Ok, take this with a grain of salt as I haven't tried to write a server with std::net yet, but I think you need to spawn a new task in the connect callback. For reference, here is the server test case in net::tcp: https://github.com/mozilla/rust/blob/incoming/src/libstd/net_tcp.rs#L1560 In the connect callback it looks like it spawns a new task and waits for it to accept the connection. After the connection is accepted the child task handles the connection and the original task continues to listen for additional connections. As far as BSD sockets, there are bindings here: https://github.com/jdm/rust-socket/ As indicated elsewhere in this thread, when using sockets you have to be aware of the blocking. Specifically, you should start a new scheduler to make the blocking calls on, like `do task().sched_mode(SingleThreaded).spawn {`. One thing to be aware of when dealing with schedulers is that `spawn` always creates tasks on the *current* scheduler, so if you create a scheduler with the intent of blocking, then spawn additional tasks from that scheduler, they will end up blocking as well. This is a major hazard, should be fixed eventually. From hatahet at gmail.com Wed Oct 24 12:16:56 2012 From: hatahet at gmail.com (Ziad Hatahet) Date: Wed, 24 Oct 2012 12:16:56 -0700 Subject: [rust-dev] Purity by default In-Reply-To: <50883A66.7040209@mozilla.com> References: <2CA65573-7D1D-41B5-89A6-BE1ADF494199@googlemail.com> <50881BFF.5010001@alum.mit.edu> <50883A66.7040209@mozilla.com> Message-ID: On Wed, Oct 24, 2012 at 11:58 AM, Patrick Walton wrote: > On 10/24/12 11:51 AM, Nathan wrote: > >> Therefore I'd propose that the purity keyword must be present and match >> the purity inference in every context where a type signature must be >> present to match the type inference. >> > > -1 on this. I think that it's often quite useful to reserve the right to > make a presently-pure function impure later without breaking callers. When > commenting out code, for example. > > Patrick > > > Wouldn't that (semantically) break code that relied on the functions being called being pure? -- Ziad -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Wed Oct 24 12:20:30 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 24 Oct 2012 12:20:30 -0700 Subject: [rust-dev] Purity by default In-Reply-To: References: <2CA65573-7D1D-41B5-89A6-BE1ADF494199@googlemail.com> <50881BFF.5010001@alum.mit.edu> <50883A66.7040209@mozilla.com> Message-ID: <50883F7E.8070007@mozilla.com> On 10/24/12 12:16 PM, Ziad Hatahet wrote: > Wouldn't that (semantically) break code that relied on the functions > being called being pure? Not sure what you mean exactly, but in general you should not semantically rely on a function to be pure if it's not marked pure. Patrick From hatahet at gmail.com Wed Oct 24 12:25:36 2012 From: hatahet at gmail.com (Ziad Hatahet) Date: Wed, 24 Oct 2012 12:25:36 -0700 Subject: [rust-dev] Purity by default In-Reply-To: <50883F7E.8070007@mozilla.com> References: <2CA65573-7D1D-41B5-89A6-BE1ADF494199@googlemail.com> <50881BFF.5010001@alum.mit.edu> <50883A66.7040209@mozilla.com> <50883F7E.8070007@mozilla.com> Message-ID: On Wed, Oct 24, 2012 at 12:20 PM, Patrick Walton wrote: > Not sure what you mean exactly, but in general you should not semantically > rely on a function to be pure if it's not marked pure. > True, but the callers in this case rely on the fact that a function is being explicitly marked as pure right? -- Ziad -------------- next part -------------- An HTML attachment was scrubbed... URL: From arkaitzj at gmail.com Wed Oct 24 12:48:04 2012 From: arkaitzj at gmail.com (arkaitzj at gmail.com) Date: Wed, 24 Oct 2012 21:48:04 +0200 Subject: [rust-dev] Rust simplest server In-Reply-To: <50883D5E.2060408@mozilla.com> References: <50883D5E.2060408@mozilla.com> Message-ID: Hi On Wed, Oct 24, 2012 at 9:11 PM, Brian Anderson wrote: > For reference, here is the server test case in net::tcp: > > https://github.com/mozilla/**rust/blob/incoming/src/libstd/** > net_tcp.rs#L1560 > > In the connect callback it looks like it spawns a new task and waits for > it to accept the connection. After the connection is accepted the child > task handles the connection and the original task continues to listen for > additional connections. Well, but shouldn't this case just work without spawning tasks? tcp::listen should be blocking on fd IO, right, but the moment something becomes available it actually unblocks, runs the callback on the same task/thread and then blocks again till the listen fd becomes available again. However, it seems like it is only doing it for the first connection that comes in, after that it just does nothing. Are my assumptions incorrect? Thanks Arkaitz -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Wed Oct 24 12:50:30 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 24 Oct 2012 12:50:30 -0700 Subject: [rust-dev] Purity by default In-Reply-To: <50883A66.7040209@mozilla.com> References: <2CA65573-7D1D-41B5-89A6-BE1ADF494199@googlemail.com> <50881BFF.5010001@alum.mit.edu> <50883A66.7040209@mozilla.com> Message-ID: <50884686.40505@alum.mit.edu> Patrick--- I think what you're saying -1 on here is some kind of purity inference? That doesn't seem to be what was proposed, though. In fact, I *believe* Nathan's point was merely that it's useful sometimes to document "purity" in order to express the intention of the API, and that in those cases it's nice to write it explicitly, just as it's nice to have the types of parameters and return types written explicitly. This does not seem to be in disagreement with what you said about reserving the right to become impure. Niko > Patrick Walton > October 24, 2012 11:58 AM > > > -1 on this. I think that it's often quite useful to reserve the right > to make a presently-pure function impure later without breaking > callers. When commenting out code, for example. > > Patrick > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Nathan > October 24, 2012 10:51 AM > On Wed, Oct 24, 2012 at 9:49 AM, Niko Matsakis > wrote: > > It's an interesting question. I am not sure whether "most" > functions can be pure under the definition I gave in that blog > post, but likely a great many. > > There is also some question of whether we should have purity at > all. pcwalton and I have been thinking about an alternative which > would allow us to remove the pure qualifier altogether, though > unfortunately it's less expressive. The basic idea is that > instead of requiring purity, the borrow checker would only permit > calls to functions that cannot access mutable state. This can be > guaranteed through a combination of a Const bound and by checking > the types of values provided as a parameter. This has the > advantage that all fn items fit this definition, presuming that > their parameters are of appropriate type. > > > The value of the "pure" keyword is not only in the static checking, > but also in the programmer documenting the intention of their API. > When both of these benefits are tied together, the documentation > benefit has much more value. > > In fact, there's a close parallel between purity inference and type > inference, since we can think of purity as an aspect of the type. So > even though we have type inference, it is very useful to see type > annotations when looking at APIs. > > Therefore I'd propose that the purity keyword must be present and > match the purity inference in every context where a type signature > must be present to match the type inference. > > > I hope to get around to writing this up as a blog post trying to > explore the areas where the newer approach would fall short of purity. > > > > Niko > > > Regards, > Nathan Wilcox > >> Stefan Plantikow >> October 24, 2012 12:28 AM >> >> I like that idea very much except that there are probably >> situations in which one wants the reverse, i.e. >> modules marked as impure which then requires purity annotations >> for functions. >> >> boggle. >> >> >> >> >> >> >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev >> Jesse Ruderman >> October 23, 2012 7:49 PM >> Should functions default to pure? >> >> * With >> http://smallcultfollowing.com/babysteps/blog/2012/10/12/extending-the-definition-of-purity-in-rust/ >> I think most functions will be able to be pure. >> >> * Would avoid the problem of forgetting to mark a function as pure, >> causing pain for a caller. (Or worse, causing the compiler to >> generate slower code?) >> >> * Would encourage writing pure code, by making pure less typing >> than impure. >> >> * With >> http://smallcultfollowing.com/babysteps/blog/2012/10/23/function-and-object-types/ >> the "impure" and "unsafe" modifiers would move in the same direction. >> (Currently, "pure" and "unsafe" move in opposite directions from the >> default, which is impure.) >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > > Stefan Plantikow > October 23, 2012 11:28 PM > > I like that idea very much except that there are probably situations > in which one wants the reverse, i.e. > modules marked as impure which then requires purity annotations for > functions. > > boggle. > > > > > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Jesse Ruderman > October 23, 2012 7:49 PM > Should functions default to pure? > > * With > http://smallcultfollowing.com/babysteps/blog/2012/10/12/extending-the-definition-of-purity-in-rust/ > I think most functions will be able to be pure. > > * Would avoid the problem of forgetting to mark a function as pure, > causing pain for a caller. (Or worse, causing the compiler to > generate slower code?) > > * Would encourage writing pure code, by making pure less typing than > impure. > > * With > http://smallcultfollowing.com/babysteps/blog/2012/10/23/function-and-object-types/ > the "impure" and "unsafe" modifiers would move in the same direction. > (Currently, "pure" and "unsafe" move in opposite directions from the > default, which is impure.) > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.jpg Type: image/jpeg Size: 886 bytes Desc: not available URL: From niko at alum.mit.edu Wed Oct 24 14:01:17 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 24 Oct 2012 14:01:17 -0700 Subject: [rust-dev] Borrowed pointers In-Reply-To: References: Message-ID: <5088571D.3080302@alum.mit.edu> The problem with modes was not that they were trying to push low-level decisions onto the developer. In contrast, they were trying to hide low-level decisions, but they did an imperfect job. As a result, it was particularly confusing when mismatches between things like ++, +, and && modes would arise. I hope that by making pointers more explicit and clear, it should be less confusing when the compiler says "I expected a pointer here but I didn't get one" (or vice versa). Another problem was that modes were not especially expressive. You could not, for example, have a function that returned a pointer into the interior of a data structure. As a result, we tended to write functions that took a closure to do all operations. There are numerous related problems that arose: You could not move references values into a tuple or other structure, which hinders attempts to match over two types at once or to write generic wrappers for functions. You could not bundle up repetitive sets of parameters into structures. And so forth. Rust does not have the goal of *hiding* low-level implementation details from the user; rather the opposite in fact. But at the same time we *do* want to enable the construction of higher-level abstractions---and particularly ones that can be compiled to very efficient code. Sometimes these goals conflict. Sometimes they do not. Modes ultimately worked against both of these goals. Of course, Rust is a project with many authors, some of whom may have a different point of view. But that is how I see things. Niko > Vadim > October 22, 2012 1:09 PM > I've got to admit, I am not very familiar with Rust's history, but > from a brief skimming of what I could find on parameter modes, I got > the impression that this feature was removed because it pushed too > many low-level decisions onto the developer. > > Would you mind pointing me towards the thread that discussed the > problems with generics that you are referring to? > > thanks, > Vadim > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: From pwalton at mozilla.com Wed Oct 24 14:05:35 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 24 Oct 2012 14:05:35 -0700 Subject: [rust-dev] Purity by default In-Reply-To: <50884686.40505@alum.mit.edu> References: <2CA65573-7D1D-41B5-89A6-BE1ADF494199@googlemail.com> <50881BFF.5010001@alum.mit.edu> <50883A66.7040209@mozilla.com> <50884686.40505@alum.mit.edu> Message-ID: <5088581F.50406@mozilla.com> On 10/24/12 12:50 PM, Niko Matsakis wrote: > Patrick? > > I think what you're saying -1 on here is some kind of purity inference? > That doesn't seem to be what was proposed, though. > > In fact, I *believe* Nathan's point was merely that it's useful > sometimes to document "purity" in order to express the intention of the > API, and that in those cases it's nice to write it explicitly, just as > it's nice to have the types of parameters and return types written > explicitly. This does not seem to be in disagreement with what you said > about reserving the right to become impure. Oh, in that case I totally agree. I thought Nathan was asking for the purity specified in the function signature to always match the inferred purity of the function--in particular, for the compiler to enforce that a pure function is never marked impure. That was what I was objecting to. If I misinterpreted I apologize. Patrick From niko at alum.mit.edu Wed Oct 24 14:07:44 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 24 Oct 2012 14:07:44 -0700 Subject: [rust-dev] Purity by default In-Reply-To: <5088581F.50406@mozilla.com> References: <2CA65573-7D1D-41B5-89A6-BE1ADF494199@googlemail.com> <50881BFF.5010001@alum.mit.edu> <50883A66.7040209@mozilla.com> <50884686.40505@alum.mit.edu> <5088581F.50406@mozilla.com> Message-ID: <508858A0.2020308@alum.mit.edu> Patrick Walton wrote: > Oh, in that case I totally agree. I thought Nathan was asking for the > purity specified in the function signature to always match the > inferred purity of the function--in particular, for the compiler to > enforce that a pure function is never marked impure. That was what I > was objecting to. If I misinterpreted I apologize. Hmm, re-reading his post you may have been right. Maybe it's me who was mistaken. :) Niko From hatahet at gmail.com Wed Oct 24 14:27:47 2012 From: hatahet at gmail.com (Ziad Hatahet) Date: Wed, 24 Oct 2012 14:27:47 -0700 Subject: [rust-dev] Purity by default In-Reply-To: <5088581F.50406@mozilla.com> References: <2CA65573-7D1D-41B5-89A6-BE1ADF494199@googlemail.com> <50881BFF.5010001@alum.mit.edu> <50883A66.7040209@mozilla.com> <50884686.40505@alum.mit.edu> <5088581F.50406@mozilla.com> Message-ID: On Wed, Oct 24, 2012 at 2:05 PM, Patrick Walton wrote: > > Oh, in that case I totally agree. I thought Nathan was asking for the > purity specified in the function signature to always match the inferred > purity of the function--in particular, for the compiler to enforce that a > pure function is never marked impure. That was what I was objecting to. If > I misinterpreted I apologize. > > > It seems I may have misunderstood too :P -- Ziad -------------- next part -------------- An HTML attachment was scrubbed... URL: From chad.retz at gmail.com Wed Oct 24 15:37:09 2012 From: chad.retz at gmail.com (Chad Retz) Date: Wed, 24 Oct 2012 17:37:09 -0500 Subject: [rust-dev] Transpiling to Rust In-Reply-To: References: Message-ID: Thanks. I wasn't so much looking to make a DSL as I was making a code generator that spits out Rust code. It could be called and executed at runtime, or spit out code to stdout or to a file for later compilation. I just don't know how practical it is to build a big string and then "inject" it into the current runtime like rust-repl does it. On Wed, Oct 24, 2012 at 7:04 AM, Lucian Branescu wrote: > On 22 October 2012 20:28, Chad Retz wrote: > > I am very new to Rust, but I have a little project where I'd like to > compile > > something else into Rust code. I have seen the macro syntax which doesn't > > operate on pure strings (from what I see) and I have seen projects like > > rust-repl that parse and inject at runtime. Which approach should I take > if > > I want to be able to transpile both to a string to save into a file and > to > > use it at runtime depending on what the user wants? (I have done this in > D, > > yet the mixins there work with strings natively so there is no real > decision > > to make). > > Rust's macro system won't let you implement a DSL that is very > different from rust itself. > You could express the language as function calls, which you could do > at runtime or from a macro. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ben.striegel at gmail.com Thu Oct 25 07:03:47 2012 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Thu, 25 Oct 2012 10:03:47 -0400 Subject: [rust-dev] condition handling In-Reply-To: <508728E7.4030905@alum.mit.edu> References: <5081E6D5.50700@mozilla.com> <5085F66C.4000401@mozilla.com> <5086BF1C.2010208@mozilla.com> <5086C263.5020006@mozilla.com> <5086FBB7.6050103@mozilla.com> <508728E7.4030905@alum.mit.edu> Message-ID: I'd really be a fan of any alternative approach to the current boilerplate; even hidden behind a macro I still feel gross even knowing that it's there. On Tue, Oct 23, 2012 at 7:31 PM, Niko Matsakis wrote: > On the topic of TLS boilerplate: > > At some point it was proposed that we use the type descriptor itself as > the key. With some minimal effort, we could make them unique, at least for > nominal types---TLS could just fail if a non-nominal type were used as the > value, or perhaps we can enforce this statically through a kind. That > would eliminate the boilerplate of using TLS, basically. You'd just have > to declare the struct/enum type that will serve as the value. I like this > idea. > > > Niko > > Graydon Hoare > October 23, 2012 1:19 PM > > Probably. I believe it wasn't done that way for two reasons: > > - Data addresses can be recycled by accident, due to stack/heap > reuse. Code segment addresses are Really Unique at load time. > > - TLS needs function pointers anyways to have cleanups associated > with TLS entries when tasks die. > > It might be possible to merge these a bit more (there are unfortunate > linkage complications with PLTs anyways) but in general I expect to hide > whatever boilerplate there is behind an item macro like: > > condition! missing_file(&Path) -> Reader; > > -Graydon > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > David Rajchenbach-Teller > October 23, 2012 8:14 AM > > Couldn't |missing_file| itself be the TLS key? > > Cheers, > David > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Daniel Patterson > October 23, 2012 8:12 AM > > TLS storage needs a unique key to identify it. Right now, the way that is > done, as I understand it, is with the memory location for a global > function. So this is truly boilerplate, just a way to get a unique > identifier for the storage. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > David Rajchenbach-Teller > October 23, 2012 8:00 AM > > On 10/23/12 3:44 AM, Graydon Hoare wrote: > > On 12-10-21 09:50 PM, Benjamin Striegel wrote: > > If it's not too much trouble, a complete example (using any one of the > proposed syntaxes) would be enlightening. I'm still having a hard time > imagining how OutOfKittens is defined, and how do_some_stuff et al > signal it in the first place, and how the input/output of OutOfKittens > can be utilized within the signalling function. > > Sure. Let's use a real case such as "trying to open a file that might be > missing in the middle of a call to read_whole_file_str". This involves a > few assumed changes to the way io is structured, but nothing deep: > > // Boilerplate for declaring TLS key > fn missing_file_key(_x: @Handler) { } > > I do not understand this line. > > > const missing_file : Condition = > Condition { key: missing_file_key }; > > I have a little trouble parsing this line in which Condition appears > both as a type name and as a constructor. Nothing fatal, but it might be > a little difficult on end users. > > > mod io { > > [...] > > } > > Clear enough? > > Looks good to me, and I appreciate the demonstration that we can > effectively write the definition of handlers after the protected code, > at least as a coding convention. > > Cheers, > David > > > _______________________________________________ > Rust-dev mailing listRust-dev at mozilla.orghttps://mail.mozilla.org/listinfo/rust-dev > > Graydon Hoare > October 22, 2012 5:44 PM > > Sure. Let's use a real case such as "trying to open a file that might be > missing in the middle of a call to read_whole_file_str". This involves a > few assumed changes to the way io is structured, but nothing deep: > > // Boilerplate for declaring TLS key > fn missing_file_key(_x: @Handler) { } > > const missing_file : Condition = > Condition { key: missing_file_key }; > > mod io { > // Revised to not use Result anymore > pub fn file_reader(path: &Path) -> Reader { > let f = do os::as_c_charp(path.to_str()) |p| { > do os::as_c_charp("r") |m| { > libc::fopen(p, m) > } > }; > if f as uint == 0u { > // No such file; ask for help via .raise > missing_file.raise(path) > } else { > FILE_reader(f, true)) > } > } > } > > fn main() { > do missing_file.trap(|_p| > BytesReader { bytes: ~[], pos: 0u } as Reader > ).in { > // This will trap in io::file_reader and > // substitute the empty bytes_reader above > let s = io::read_whole_file_str(Path("/nonexistent")); > } > } > > Clear enough? > > -Graydon > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: postbox-contact.jpg Type: image/jpeg Size: 1154 bytes Desc: not available URL: From ben.striegel at gmail.com Thu Oct 25 07:24:52 2012 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Thu, 25 Oct 2012 10:24:52 -0400 Subject: [rust-dev] Rust simplest server In-Reply-To: References: Message-ID: I'd like to emphasize that Rust's standard libraries are all somewhat haphazard to various degrees, so I wouldn't presume that anything that is currently possible or impossible via the libraries implies any sort of overarching design philosophy. Though considering how many people seem eager to build servers in Rust, networking is probably an area that could use some refinement sooner rather than later. On Wed, Oct 24, 2012 at 3:41 AM, arkaitzj at gmail.com wrote: > Hi, > I'm starting with rust, although I've been looking inside for a while its > the first time I try writing real rust code. > So, I pulled from master yesterday and wrote this simple server > http://pastebin.com/MMiNpXYG > > No tasks, no concurrency, a single-threaded, single-tasked server, that to > my eyes should be able to handle one client after another, however, I seem > to be unable to see any other client than the first one in the server, > netcat does not complain but listen.rs does not see the new client. > Am I doing anything wrong? > > AFAIK, rust is not going to support traditional socket handling, > everything is going to go over libuv, is this statement correct? > > Thanks > > -- > Arkaitz > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From arkaitzj at gmail.com Thu Oct 25 08:05:56 2012 From: arkaitzj at gmail.com (arkaitzj at gmail.com) Date: Thu, 25 Oct 2012 17:05:56 +0200 Subject: [rust-dev] Rust simplest server In-Reply-To: References: Message-ID: I have tried more and more, hacking first on libuv c code, but noticed the problem is somewhere above. Check here: http://pastebin.com/ia0G5nwu Everything happens on rust code, the net_tcp::listen calls on_connect and on_connect executes, but NEVER returns, it just hangs there. The last thing that gets printed is "Finishing on_connect". So, I assume it cannot be uv or net_tcp related, it looks like when on_connect finishes executing somehow the task hangs in there... maybe some scheduling or return object copying or something. Could anybody help me on where could I trace this with GDB? At this point I am really curious about what the issue is. -- Arkaitz On Wed, Oct 24, 2012 at 9:41 AM, arkaitzj at gmail.com wrote: > Hi, > I'm starting with rust, although I've been looking inside for a while its > the first time I try writing real rust code. > So, I pulled from master yesterday and wrote this simple server > http://pastebin.com/MMiNpXYG > > No tasks, no concurrency, a single-threaded, single-tasked server, that to > my eyes should be able to handle one client after another, however, I seem > to be unable to see any other client than the first one in the server, > netcat does not complain but listen.rs does not see the new client. > Am I doing anything wrong? > > AFAIK, rust is not going to support traditional socket handling, > everything is going to go over libuv, is this statement correct? > > Thanks > > -- > Arkaitz > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nejucomo at gmail.com Thu Oct 25 12:10:20 2012 From: nejucomo at gmail.com (Nathan) Date: Thu, 25 Oct 2012 12:10:20 -0700 Subject: [rust-dev] Purity by default In-Reply-To: <5088581F.50406@mozilla.com> References: <2CA65573-7D1D-41B5-89A6-BE1ADF494199@googlemail.com> <50881BFF.5010001@alum.mit.edu> <50883A66.7040209@mozilla.com> <50884686.40505@alum.mit.edu> <5088581F.50406@mozilla.com> Message-ID: On Wed, Oct 24, 2012 at 2:05 PM, Patrick Walton wrote: > On 10/24/12 12:50 PM, Niko Matsakis wrote: >> >> Patrick? >> >> I think what you're saying -1 on here is some kind of purity inference? >> That doesn't seem to be what was proposed, though. >> >> In fact, I *believe* Nathan's point was merely that it's useful >> sometimes to document "purity" in order to express the intention of the >> API, and that in those cases it's nice to write it explicitly, just as >> it's nice to have the types of parameters and return types written >> explicitly. This does not seem to be in disagreement with what you said >> about reserving the right to become impure. > > > Oh, in that case I totally agree. I thought Nathan was asking for the purity > specified in the function signature to always match the inferred purity of > the function--in particular, for the compiler to enforce that a pure > function is never marked impure. That was what I was objecting to. If I > misinterpreted I apologize. > Patrick interpreted my suggestion correctly, but on second thought I withdraw it. Requiring inferred-pure functions to be explicitly marked pure is inconvenient, just as if a type may be inferred as ~[u8] but the API designer may want to declare it ~[mut u8] for future flexibility. > > Patrick > Nathan > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From gwillen at nerdnet.org Thu Oct 25 13:07:00 2012 From: gwillen at nerdnet.org (Glenn Willen) Date: Thu, 25 Oct 2012 16:07:00 -0400 Subject: [rust-dev] Rust simplest server In-Reply-To: References: Message-ID: <778F3C7D-F890-47F8-8039-126DC6F7DF19@nerdnet.org> There's something weird going on in the original Rust example. The flow of control seems to never be leaving the 'if result.is_ok()' block. I suspect 'socket' has a blocking destructor that's hanging the task until the socket is closed. That would explain why it would work if a new task is spawned. Can someone familiar with the socket internals confirm that this is what's happening? It is interesting that this kind of blocking behavior is possible. Is it considered desirable? It's certainly non-intuitive. The same thing is certainly possible in C++ (though not in Java where finalizers are asynchronous.) I think it would be bad form there for a destructor to block, though. Glenn On Oct 25, 2012, at 11:05 AM, arkaitzj at gmail.com wrote: > I have tried more and more, hacking first on libuv c code, but noticed the problem is somewhere above. > Check here: > http://pastebin.com/ia0G5nwu > > Everything happens on rust code, the net_tcp::listen calls on_connect and on_connect executes, but NEVER returns, it just hangs there. > The last thing that gets printed is "Finishing on_connect". > So, I assume it cannot be uv or net_tcp related, it looks like when on_connect finishes executing somehow the task hangs in there... maybe some scheduling or return object copying or something. > Could anybody help me on where could I trace this with GDB? At this point I am really curious about what the issue is. > > -- > Arkaitz > > > On Wed, Oct 24, 2012 at 9:41 AM, arkaitzj at gmail.com wrote: > Hi, > I'm starting with rust, although I've been looking inside for a while its the first time I try writing real rust code. > So, I pulled from master yesterday and wrote this simple server http://pastebin.com/MMiNpXYG > > No tasks, no concurrency, a single-threaded, single-tasked server, that to my eyes should be able to handle one client after another, however, I seem to be unable to see any other client than the first one in the server, netcat does not complain but listen.rs does not see the new client. > Am I doing anything wrong? > > AFAIK, rust is not going to support traditional socket handling, everything is going to go over libuv, is this statement correct? > > Thanks > > -- > Arkaitz > > !DSPAM:50895448316022347716413! _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > > !DSPAM:50895448316022347716413! -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 243 bytes Desc: This is a digitally signed message part URL: From arkaitzj at gmail.com Thu Oct 25 13:19:10 2012 From: arkaitzj at gmail.com (arkaitzj at gmail.com) Date: Thu, 25 Oct 2012 22:19:10 +0200 Subject: [rust-dev] Rust simplest server In-Reply-To: <778F3C7D-F890-47F8-8039-126DC6F7DF19@nerdnet.org> References: <778F3C7D-F890-47F8-8039-126DC6F7DF19@nerdnet.org> Message-ID: Hi, After some hours of hacking around finally pinpointed it in the destructor as you guessed it, I was mislead by an example where the accept wasn't being called and actually libuv was blocking the rest because its kind of low level interface here where it gives you a non accepted event on the listen port, so you are expected to accept always or obviously the client will remain the backlog of the listen port. But this is another story. What happens here, thanks to Niko Matsakis for helping me in the IRC, is that you cannot destroy a socket from the same thread where you run listen, basically the IO thread. There is a message exchange between the destructor and the listens task which obviously never finishes when they are in the same thread. So, the solution seems to be to spawn the listen in a different scheduler but then pass the sockets to their handlers spawning tasks in the main scheduler. This situation doesn't look ideal to me and I don't think its intuitive but seems to be the way to go for the moment in rust. Apparently a better/easier listen could be written on std::net::tcp that returns accepted sockets, but I am not too sure how would that play with the messaging destructor. To my eyes it should be possible to write a server without spawning any task since no concurrency is really needed, but things are like that atm. -- Arkaitz On Thu, Oct 25, 2012 at 10:07 PM, Glenn Willen wrote: > There's something weird going on in the original Rust example. > > The flow of control seems to never be leaving the 'if result.is_ok()' > block. I suspect 'socket' has a blocking destructor that's hanging the task > until the socket is closed. That would explain why it would work if a new > task is spawned. > > Can someone familiar with the socket internals confirm that this is what's > happening? > > It is interesting that this kind of blocking behavior is possible. Is it > considered desirable? It's certainly non-intuitive. The same thing is > certainly possible in C++ (though not in Java where finalizers are > asynchronous.) I think it would be bad form there for a destructor to > block, though. > > Glenn > > On Oct 25, 2012, at 11:05 AM, arkaitzj at gmail.com wrote: > > > I have tried more and more, hacking first on libuv c code, but noticed > the problem is somewhere above. > > Check here: > > http://pastebin.com/ia0G5nwu > > > > Everything happens on rust code, the net_tcp::listen calls on_connect > and on_connect executes, but NEVER returns, it just hangs there. > > The last thing that gets printed is "Finishing on_connect". > > So, I assume it cannot be uv or net_tcp related, it looks like when > on_connect finishes executing somehow the task hangs in there... maybe some > scheduling or return object copying or something. > > Could anybody help me on where could I trace this with GDB? At this > point I am really curious about what the issue is. > > > > -- > > Arkaitz > > > > > > On Wed, Oct 24, 2012 at 9:41 AM, arkaitzj at gmail.com > wrote: > > Hi, > > I'm starting with rust, although I've been looking inside for a while > its the first time I try writing real rust code. > > So, I pulled from master yesterday and wrote this simple server > http://pastebin.com/MMiNpXYG > > > > No tasks, no concurrency, a single-threaded, single-tasked server, that > to my eyes should be able to handle one client after another, however, I > seem to be unable to see any other client than the first one in the server, > netcat does not complain but listen.rs does not see the new client. > > Am I doing anything wrong? > > > > AFAIK, rust is not going to support traditional socket handling, > everything is going to go over libuv, is this statement correct? > > > > Thanks > > > > -- > > Arkaitz > > > > !DSPAM:50895448316022347716413! > _______________________________________________ > > Rust-dev mailing list > > Rust-dev at mozilla.org > > https://mail.mozilla.org/listinfo/rust-dev > > > > > > !DSPAM:50895448316022347716413! > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From gwillen at nerdnet.org Thu Oct 25 13:22:50 2012 From: gwillen at nerdnet.org (Glenn Willen) Date: Thu, 25 Oct 2012 16:22:50 -0400 Subject: [rust-dev] Rust simplest server In-Reply-To: References: <778F3C7D-F890-47F8-8039-126DC6F7DF19@nerdnet.org> Message-ID: <11B5E0DE-D424-4B07-9E44-897890B1E993@nerdnet.org> Well, in a real example where the server did actual work for each socket, concurrency would clearly be desirable, since you need a task for the actual work and another task to listen for new connections (and presumably a fresh task for each connection, to do the actual work.) But I agree that this seems non-ergonomic in its current form. Glenn On Oct 25, 2012, at 4:19 PM, arkaitzj at gmail.com wrote: > Hi, > > After some hours of hacking around finally pinpointed it in the destructor as you guessed it, I was mislead by an example where the accept wasn't being called and actually libuv was blocking the rest because its kind of low level interface here where it gives you a non accepted event on the listen port, so you are expected to accept always or obviously the client will remain the backlog of the listen port. But this is another story. > > What happens here, thanks to Niko Matsakis for helping me in the IRC, is that you cannot destroy a socket from the same thread where you run listen, basically the IO thread. There is a message exchange between the destructor and the listens task which obviously never finishes when they are in the same thread. > > So, the solution seems to be to spawn the listen in a different scheduler but then pass the sockets to their handlers spawning tasks in the main scheduler. > This situation doesn't look ideal to me and I don't think its intuitive but seems to be the way to go for the moment in rust. > Apparently a better/easier listen could be written on std::net::tcp that returns accepted sockets, but I am not too sure how would that play with the messaging destructor. > > To my eyes it should be possible to write a server without spawning any task since no concurrency is really needed, but things are like that atm. > > -- > Arkaitz > > > On Thu, Oct 25, 2012 at 10:07 PM, Glenn Willen wrote: > There's something weird going on in the original Rust example. > > The flow of control seems to never be leaving the 'if result.is_ok()' block. I suspect 'socket' has a blocking destructor that's hanging the task until the socket is closed. That would explain why it would work if a new task is spawned. > > Can someone familiar with the socket internals confirm that this is what's happening? > > It is interesting that this kind of blocking behavior is possible. Is it considered desirable? It's certainly non-intuitive. The same thing is certainly possible in C++ (though not in Java where finalizers are asynchronous.) I think it would be bad form there for a destructor to block, though. > > Glenn > > On Oct 25, 2012, at 11:05 AM, arkaitzj at gmail.com wrote: > > > I have tried more and more, hacking first on libuv c code, but noticed the problem is somewhere above. > > Check here: > > http://pastebin.com/ia0G5nwu > > > > Everything happens on rust code, the net_tcp::listen calls on_connect and on_connect executes, but NEVER returns, it just hangs there. > > The last thing that gets printed is "Finishing on_connect". > > So, I assume it cannot be uv or net_tcp related, it looks like when on_connect finishes executing somehow the task hangs in there... maybe some scheduling or return object copying or something. > > Could anybody help me on where could I trace this with GDB? At this point I am really curious about what the issue is. > > > > -- > > Arkaitz > > > > > > On Wed, Oct 24, 2012 at 9:41 AM, arkaitzj at gmail.com wrote: > > Hi, > > I'm starting with rust, although I've been looking inside for a while its the first time I try writing real rust code. > > So, I pulled from master yesterday and wrote this simple server http://pastebin.com/MMiNpXYG > > > > No tasks, no concurrency, a single-threaded, single-tasked server, that to my eyes should be able to handle one client after another, however, I seem to be unable to see any other client than the first one in the server, netcat does not complain but listen.rs does not see the new client. > > Am I doing anything wrong? > > > > AFAIK, rust is not going to support traditional socket handling, everything is going to go over libuv, is this statement correct? > > > > Thanks > > > > -- > > Arkaitz > > > > _______________________________________________ > > Rust-dev mailing list > > Rust-dev at mozilla.org > > https://mail.mozilla.org/listinfo/rust-dev > > > > > > !DSPAM:50895448316022347716413! > > > !DSPAM:50899dac130302097917617! -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 243 bytes Desc: This is a digitally signed message part URL: From arkaitzj at gmail.com Thu Oct 25 13:27:37 2012 From: arkaitzj at gmail.com (arkaitzj at gmail.com) Date: Thu, 25 Oct 2012 22:27:37 +0200 Subject: [rust-dev] Rust simplest server In-Reply-To: <11B5E0DE-D424-4B07-9E44-897890B1E993@nerdnet.org> References: <778F3C7D-F890-47F8-8039-126DC6F7DF19@nerdnet.org> <11B5E0DE-D424-4B07-9E44-897890B1E993@nerdnet.org> Message-ID: I agree with the desirable concurrency, but this should be orthogonal with what the server does, and as such, I understand a desirable implementation wouldn't need it, fastest http servers in the internet are monothread and not concurrent. Truth is with light tasks like in rust you would just spawn task/client anyway. -- Arkaitz On Thu, Oct 25, 2012 at 10:22 PM, Glenn Willen wrote: > Well, in a real example where the server did actual work for each socket, > concurrency would clearly be desirable, since you need a task for the > actual work and another task to listen for new connections (and presumably > a fresh task for each connection, to do the actual work.) > > But I agree that this seems non-ergonomic in its current form. > > Glenn > > On Oct 25, 2012, at 4:19 PM, arkaitzj at gmail.com wrote: > > > Hi, > > > > After some hours of hacking around finally pinpointed it in the > destructor as you guessed it, I was mislead by an example where the accept > wasn't being called and actually libuv was blocking the rest because its > kind of low level interface here where it gives you a non accepted event on > the listen port, so you are expected to accept always or obviously the > client will remain the backlog of the listen port. But this is another > story. > > > > What happens here, thanks to Niko Matsakis for helping me in the IRC, is > that you cannot destroy a socket from the same thread where you run listen, > basically the IO thread. There is a message exchange between the destructor > and the listens task which obviously never finishes when they are in the > same thread. > > > > So, the solution seems to be to spawn the listen in a different > scheduler but then pass the sockets to their handlers spawning tasks in the > main scheduler. > > This situation doesn't look ideal to me and I don't think its intuitive > but seems to be the way to go for the moment in rust. > > Apparently a better/easier listen could be written on std::net::tcp that > returns accepted sockets, but I am not too sure how would that play with > the messaging destructor. > > > > To my eyes it should be possible to write a server without spawning any > task since no concurrency is really needed, but things are like that atm. > > > > -- > > Arkaitz > > > > > > On Thu, Oct 25, 2012 at 10:07 PM, Glenn Willen > wrote: > > There's something weird going on in the original Rust example. > > > > The flow of control seems to never be leaving the 'if result.is_ok()' > block. I suspect 'socket' has a blocking destructor that's hanging the task > until the socket is closed. That would explain why it would work if a new > task is spawned. > > > > Can someone familiar with the socket internals confirm that this is > what's happening? > > > > It is interesting that this kind of blocking behavior is possible. Is it > considered desirable? It's certainly non-intuitive. The same thing is > certainly possible in C++ (though not in Java where finalizers are > asynchronous.) I think it would be bad form there for a destructor to > block, though. > > > > Glenn > > > > On Oct 25, 2012, at 11:05 AM, arkaitzj at gmail.com wrote: > > > > > I have tried more and more, hacking first on libuv c code, but noticed > the problem is somewhere above. > > > Check here: > > > http://pastebin.com/ia0G5nwu > > > > > > Everything happens on rust code, the net_tcp::listen calls on_connect > and on_connect executes, but NEVER returns, it just hangs there. > > > The last thing that gets printed is "Finishing on_connect". > > > So, I assume it cannot be uv or net_tcp related, it looks like when > on_connect finishes executing somehow the task hangs in there... maybe some > scheduling or return object copying or something. > > > Could anybody help me on where could I trace this with GDB? At this > point I am really curious about what the issue is. > > > > > > -- > > > Arkaitz > > > > > > > > > On Wed, Oct 24, 2012 at 9:41 AM, arkaitzj at gmail.com < > arkaitzj at gmail.com> wrote: > > > Hi, > > > I'm starting with rust, although I've been looking inside for a while > its the first time I try writing real rust code. > > > So, I pulled from master yesterday and wrote this simple server > http://pastebin.com/MMiNpXYG > > > > > > No tasks, no concurrency, a single-threaded, single-tasked server, > that to my eyes should be able to handle one client after another, however, > I seem to be unable to see any other client than the first one in the > server, netcat does not complain but listen.rs does not see the new > client. > > > Am I doing anything wrong? > > > > > > AFAIK, rust is not going to support traditional socket handling, > everything is going to go over libuv, is this statement correct? > > > > > > Thanks > > > > > > -- > > > Arkaitz > > > > > > _______________________________________________ > > > Rust-dev mailing list > > > Rust-dev at mozilla.org > > > https://mail.mozilla.org/listinfo/rust-dev > > > > > > > > > !DSPAM:50895448316022347716413! > > > > > > !DSPAM:50899dac130302097917617! > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From amitava.shee at gmail.com Thu Oct 25 16:04:07 2012 From: amitava.shee at gmail.com (Amitava Shee) Date: Thu, 25 Oct 2012 19:04:07 -0400 Subject: [rust-dev] curry function Message-ID: Is there a way to curry functions in rust? ============= fn printn(n: int, f:fn@(i: int)) { let mut i = 0; while i < n { f(i) } } fn main() { let print10: fn@(i:int) = printn(10, _); // does not compile } ============= -Amitava Shee -------------- next part -------------- An HTML attachment was scrubbed... URL: From dbp at riseup.net Thu Oct 25 16:19:52 2012 From: dbp at riseup.net (Daniel Patterson) Date: Thu, 25 Oct 2012 19:19:52 -0400 Subject: [rust-dev] curry function In-Reply-To: References: Message-ID: <27A3CE12-78AC-4A22-88A1-44D6386EC7A1@riseup.net> You can curry things, if you want, but it isn't done automatically. If you want to create one argument functions that return one argument functions, you need to do that explicitly. I'm not totally sure what you were trying to do with your example, but here is something similar (I think): fn applyn(n: int) -> fn@(fn@(i: int)) { return |f| { let mut i = 0; while i < n { f(i); i += 1; } }; } fn main() { let apply10 = applyn(10); apply10(|i| { io::println(i.to_str()); }); } On Oct 25, 2012, at 7:04 PM, Amitava Shee wrote: > fn printn(n: int, f:fn@(i: int)) { > let mut i = 0; > while i < n { > f(i) > } > } > > fn main() { > let print10: fn@(i:int) = printn(10, _); // does not compile > } From jon.mb at proinbox.com Sun Oct 28 04:55:35 2012 From: jon.mb at proinbox.com (John Mija) Date: Sun, 28 Oct 2012 11:55:35 +0000 Subject: [rust-dev] Is necessary the manual memory management? Message-ID: <508D1D37.2040309@proinbox.com> Does make sense to have a language with manual memory management since it's possible to create stuff of low level with a specialized garbage collector? It's good to create drivers, but it's already C. i.e. Both Native Oberon and Blue Bottle operating systems were implemented in languages, Oberon and Active Oberon, which have type safety and concurrent (at least in compiler ulm oberon) GC support. http://www.inf.ethz.ch/personal/wirth/books/ProjectOberon.pdf Then, Java is being used in embedded and real-time systems with a deterministic garbage collection: http://www.pr.com/press-release/226895 From pwalton at mozilla.com Sun Oct 28 08:46:53 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 28 Oct 2012 08:46:53 -0700 Subject: [rust-dev] Is necessary the manual memory management? In-Reply-To: <508D1D37.2040309@proinbox.com> References: <508D1D37.2040309@proinbox.com> Message-ID: <508D536D.6070907@mozilla.com> On 10/28/12 4:55 AM, John Mija wrote: > Does make sense to have a language with manual memory management since > it's possible to create stuff of low level with a specialized garbage > collector? > It's good to create drivers, but it's already C. Oberon was quite experimental. The Azul C4 collector (the state of the art, as I understand it) is not open source, would be a tremendous amount of work to try to replicate, and still has overhead. For Servo, we need to demonstrate competitive CPU-cycle-for-CPU-cycle performance against manually memory managed frameworks like Gecko and WebKit. Relying on global concurrent GC makes the project that much riskier. Patrick From pwalton at mozilla.com Sun Oct 28 09:11:06 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 28 Oct 2012 09:11:06 -0700 Subject: [rust-dev] Is necessary the manual memory management? In-Reply-To: References: <508D1D37.2040309@proinbox.com> <508D536D.6070907@mozilla.com> Message-ID: <508D591A.9090204@mozilla.com> On 10/28/12 9:03 AM, Bennie Kloosteman wrote: > AFAIK Azul is propitiatory and is not fast it makes a huge number of > small memory allocations and they make changes on linux to make i this > work rather than on specialized HW .. What is special though is the lack > of long GC pauses. > > That said GCs are getting better the only real issues are > 1, GC pauses . Which makes managing system memory eg for DMA / drivers > tricky. > 2 . Write performance , most GCs have a card table which halves memory > write performance. > > In quite a few cases GC give better performance than malloc ( since > nursery allocations are just a compare / exchange pointer increment with > no concern for fragmentation) and with GCs you can still create and > manage a static buffer pool if you need performance For places where it matters (e.g. the binarytrees shootout benchmark) we have an arena type in the standard library that provides bump allocation. Making memory pools without special language support isn't particularly safe; the code could incorrectly return an object to a pool and continue to hold on to it, creating in effect a dangling pointer. You really want a region system if you want memory pools to have the same safety guarantees as ordinary use of the garbage collector. Patrick From sebastian.sylvan at gmail.com Sun Oct 28 12:16:28 2012 From: sebastian.sylvan at gmail.com (Sebastian Sylvan) Date: Sun, 28 Oct 2012 12:16:28 -0700 Subject: [rust-dev] Is necessary the manual memory management? In-Reply-To: <508D1D37.2040309@proinbox.com> References: <508D1D37.2040309@proinbox.com> Message-ID: On Sun, Oct 28, 2012 at 4:55 AM, John Mija wrote: > Does make sense to have a language with manual memory management since it's > possible to create stuff of low level with a specialized garbage collector? IMO The problem with traditional non-GC languages isn't that it's not automatic, it's that it's not safe. In other words, the argument for GC is one for safety, not for "resource management is an unimportant detail that the system should do". Safety is the key, not the convenience of not having to think carefully about resource management. As long as the compiler tells you when you get it wrong the question is: does it make sense to take one of the most important performance aspects out of the hands of the programmer? Automating unnecessary detail is good, but also providing safe manual control for when you need it is even better. I think this will be even more the case in the future. Heap sizes are growing tremendously, and the cost of touching memory is growing too. GC performance is therefore, in the sense of being relative to the main CPU workloads, getting worse with time, it seems to me. Putting the programmer back in the loop here (safely) seems like the right call. Seb -- Sebastian Sylvan From niko at alum.mit.edu Sun Oct 28 12:48:54 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sun, 28 Oct 2012 12:48:54 -0700 Subject: [rust-dev] Is necessary the manual memory management? In-Reply-To: <508D1D37.2040309@proinbox.com> References: <508D1D37.2040309@proinbox.com> Message-ID: <508D8C26.8000004@alum.mit.edu> Regardless of whether manual memory management is desirable as an end goal, support for it is essentially required if you wish to permit tasks to exchange ownership of data without copies. For example, in Servo we have a double-buffered system where mutable memory buffers are exchanged between the various parts of the system. In order to make this safe, we have to guarantee that this buffer is unaliased at the point where it is sent---if you know it's unaliased, of course, you also know that you could safely free it. As a broader point, it turns out there are a LOT of type system things you can do if you know something about aliasing (or the lack thereof). Our current approach to freezing data structures for example is reliant on this. Safe array splitting for data parallelism---if we ever go in that direction---will be reliant on this. And so forth. So, supporting a unique-pointer-like construct makes a lot of sense. Niko > John Mija > October 28, 2012 4:55 AM > Does make sense to have a language with manual memory management since > it's possible to create stuff of low level with a specialized garbage > collector? > It's good to create drivers, but it's already C. > > > i.e. Both Native Oberon and Blue Bottle operating systems were > implemented in languages, Oberon and Active Oberon, which have type > safety and concurrent (at least in compiler ulm oberon) GC support. > > http://www.inf.ethz.ch/personal/wirth/books/ProjectOberon.pdf > > > Then, Java is being used in embedded and real-time systems with a > deterministic garbage collection: > > http://www.pr.com/press-release/226895 > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: From fw at deneb.enyo.de Sun Oct 28 13:41:47 2012 From: fw at deneb.enyo.de (Florian Weimer) Date: Sun, 28 Oct 2012 21:41:47 +0100 Subject: [rust-dev] Why does Rust compile slowly? In-Reply-To: (Nadav Vinik's message of "Mon, 15 Oct 2012 10:42:55 +0200") References: <1350235206.20889.140661140578849.45950E07@webmail.messagingengine.com> <507B61CC.5090202@mozilla.com> Message-ID: <87625ucos4.fsf@mid.deneb.enyo.de> * Nadav Vinik: > Why rust work with a special custom llvm instead of the standard? > > Will it change in the future? Upstream doesn't fix bugs in release branches (they don't do any branch maintenance at all), so if you hit a crippling bug, there isn't much choice, other than building with a custom LLVM (or at least a specific revision from LLVM trunk). From matthieu.monrocq at gmail.com Mon Oct 29 10:49:26 2012 From: matthieu.monrocq at gmail.com (Matthieu Monrocq) Date: Mon, 29 Oct 2012 18:49:26 +0100 Subject: [rust-dev] Is necessary the manual memory management? In-Reply-To: <508D8C26.8000004@alum.mit.edu> References: <508D1D37.2040309@proinbox.com> <508D8C26.8000004@alum.mit.edu> Message-ID: On Sun, Oct 28, 2012 at 8:48 PM, Niko Matsakis wrote: > Regardless of whether manual memory management is desirable as an end > goal, support for it is essentially required if you wish to permit tasks to > exchange ownership of data without copies. For example, in Servo we have a > double-buffered system where mutable memory buffers are exchanged between > the various parts of the system. In order to make this safe, we have to > guarantee that this buffer is unaliased at the point where it is sent?if > you know it's unaliased, of course, you also know that you could safely > free it. > > As a broader point, it turns out there are a LOT of type system things you > can do if you know something about aliasing (or the lack thereof). Our > current approach to freezing data structures for example is reliant on > this. Safe array splitting for data parallelism?if we ever go in that > direction?will be reliant on this. And so forth. So, supporting a > unique-pointer-like construct makes a lot of sense. > > > Niko > > I really think this is the core point: unique/borrowed/shared are less about memory management than about ownership semantics. It would be perfectly viable (albeit slower) to treat them all identically in terms of codegen (ie, GC'em all). On the other hand, ownership semantics provide both the developer and the compiler with *guarantees* upon which they can build. -- Matthieu > John Mija > October 28, 2012 4:55 AM > Does make sense to have a language with manual memory management since > it's possible to create stuff of low level with a specialized garbage > collector? > It's good to create drivers, but it's already C. > > > i.e. Both Native Oberon and Blue Bottle operating systems were implemented > in languages, Oberon and Active Oberon, which have type safety and > concurrent (at least in compiler ulm oberon) GC support. > > http://www.inf.ethz.ch/personal/wirth/books/ProjectOberon.pdf > > > Then, Java is being used in embedded and real-time systems with a > deterministic garbage collection: > > http://www.pr.com/press-release/226895 > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: From lindsey at rockstargirl.org Mon Oct 29 11:39:28 2012 From: lindsey at rockstargirl.org (Lindsey Kuper) Date: Mon, 29 Oct 2012 14:39:28 -0400 Subject: [rust-dev] Is necessary the manual memory management? In-Reply-To: <508D8C26.8000004@alum.mit.edu> References: <508D1D37.2040309@proinbox.com> <508D8C26.8000004@alum.mit.edu> Message-ID: On Sun, Oct 28, 2012 at 3:48 PM, Niko Matsakis wrote: > > Regardless of whether manual memory management is desirable as an end > goal, support for it is essentially required if you wish to permit tasks to > exchange ownership of data without copies. Is it fair to say that, in fact, you don't need to do manual memory management in Rust *unless* you care about efficiently exchanging data between tasks? Some people panic at the thought of having to do manual memory management, but (one might argue) it doesn't feel burdensome in Rust because the only times you have to use it are times when you'd need to be thinking low-level anyway -- so, really, it's good that the language supports reasoning at a low level at the appropriate times. > As a broader point, it turns out there are a LOT of type system things you > can do if you know something about aliasing (or the lack thereof). Our > current approach to freezing data structures for example is reliant on this. > Safe array splitting for data parallelism?if we ever go in that > direction?will be reliant on this. And so forth. So, supporting a > unique-pointer-like construct makes a lot of sense. +1. Say that, for instance, you want to have a mutable vector that can be split into two disjoint pieces (so that one task can write to one piece, and a parallel task to the other), such that an error is raised if either task touches the other one's piece. In Haskell, I think you could enforce this sort of disjoint access entirely at the type level, using something like the ST monad trick, but then you've got to layer the parallelism on top of that. It's possible (I think!), but it's really complicated. But! Rust isn't Haskell, it's a systems language, and if as Niko is saying, we could accomplish things like parallel disjoint array access so long as we're willing to expose a little bit of low-level stuff, then that seems like a strong argument for exposing that little bit of low-level stuff. It seems like a little low-level-ness in Rust will get you a long way. Lindsey From graydon at mozilla.com Mon Oct 29 11:52:28 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Mon, 29 Oct 2012 11:52:28 -0700 Subject: [rust-dev] Using char literals with non-char match In-Reply-To: <5086B356.9030201@mozilla.com> References: <50856F90.8010007@mozilla.com> <5086B356.9030201@mozilla.com> Message-ID: <508ED06C.1040101@mozilla.com> On 12-10-23 8:10 AM, Patrick Walton wrote: > Note that casts are considered const exprs, so "'x' as u8" does work in > a constant position. > > But yes, I've wanted a shorter syntax for char-literals-as-bytes as > well. Something like 'x'u8 perhaps? Or I guess we could just infer it, > but that adds a fair amount of complexity to the typechecker. Does it? I thought it'd just involve shifting char into the set of types subject to integer-literal type inference. Maybe the default (not enough information to infer) would have to change from int to char, for 'x', but otherwise I'd be surprised if it would be a deep change. Lindsey can probably enlighten us more here.. -Graydon From lindsey at rockstargirl.org Mon Oct 29 12:25:21 2012 From: lindsey at rockstargirl.org (Lindsey Kuper) Date: Mon, 29 Oct 2012 15:25:21 -0400 Subject: [rust-dev] Using char literals with non-char match In-Reply-To: <508ED06C.1040101@mozilla.com> References: <50856F90.8010007@mozilla.com> <5086B356.9030201@mozilla.com> <508ED06C.1040101@mozilla.com> Message-ID: On Mon, Oct 29, 2012 at 2:52 PM, Graydon Hoare wrote: > On 12-10-23 8:10 AM, Patrick Walton wrote: > >> Note that casts are considered const exprs, so "'x' as u8" does work in >> a constant position. >> >> But yes, I've wanted a shorter syntax for char-literals-as-bytes as >> well. Something like 'x'u8 perhaps? Or I guess we could just infer it, >> but that adds a fair amount of complexity to the typechecker. > > > Does it? I thought it'd just involve shifting char into the set of types > subject to integer-literal type inference. > > Maybe the default (not enough information to infer) would have to change > from int to char, for 'x', but otherwise I'd be surprised if it would be a > deep change. > > Lindsey can probably enlighten us more here.. It's been a while, but I think you'd just have to parse chars into lit_int_unsuffixed AST nodes rather than into lit_int. They would then be subject to integer-literal type inference. Unless I'm missing something, it wouldn't be hard. That said, I don't know if it's a good idea. Lindsey From niko at alum.mit.edu Mon Oct 29 12:41:48 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 29 Oct 2012 12:41:48 -0700 Subject: [rust-dev] Is necessary the manual memory management? In-Reply-To: References: <508D1D37.2040309@proinbox.com> <508D8C26.8000004@alum.mit.edu> Message-ID: <508EDBFC.1000207@alum.mit.edu> Lindsey Kuper wrote: > Is it fair to say that, in fact, you don't need to do manual memory > management in Rust*unless* you care about efficiently exchanging data > between tasks? Almost. pcwalton has been talking about implementing a simple data-exchange wrapper based around serialization and deserialization. This would allow you to just use managed pointers (`@`) everywhere. The pieces are all there but not put together into a simple library. Niko -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Tue Oct 30 23:27:54 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Tue, 30 Oct 2012 23:27:54 -0700 Subject: [rust-dev] Merge to master? Message-ID: <5090C4EA.2010408@mozilla.com> It's been nearly a month since we last merged from incoming to master. I realize one of the bots is down, but could we go ahead and do a merge anyway? The tree is green otherwise and check-fast should work now. I worry that if we wait too long that incoming will become a de facto master. That's already the case for Servo, for example; Servo depends on features that are only in incoming. Patrick From graydon at mozilla.com Wed Oct 31 07:55:31 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 31 Oct 2012 07:55:31 -0700 Subject: [rust-dev] Merge to master? In-Reply-To: <5090C4EA.2010408@mozilla.com> References: <5090C4EA.2010408@mozilla.com> Message-ID: <50913BE3.7000703@mozilla.com> On 30/10/2012 11:27 PM, Patrick Walton wrote: > It's been nearly a month since we last merged from incoming to master. I > realize one of the bots is down, but could we go ahead and do a merge > anyway? The tree is green otherwise and check-fast should work now. > > I worry that if we wait too long that incoming will become a de facto > master. That's already the case for Servo, for example; Servo depends on > features that are only in incoming. Yes. I've just bumped master to 4e5865f2ad13c4efe12a4c02f134ff761d16b26b which builds successfully on the new buildbot slaves. Sorry this month is such a mess automation-wise. The new stuff is coming online, promise. -Graydon