From marijnh at gmail.com Thu Dec 1 00:15:22 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Thu, 1 Dec 2011 09:15:22 +0100 Subject: [rust-dev] Interface / typeclass proposal In-Reply-To: <4ED6D685.70505@mozilla.com> References: <3EF691C1-2F2C-4A5F-B580-755D2AB632D3@mozilla.com> <4ED539FA.1050006@alum.mit.edu> <4ED5668C.1030200@mozilla.com> <1425DC23-16B4-4573-852D-E13582FBE994@mozilla.com> <4ED56FF4.5000809@mozilla.com> <4ED5928E.5080903@mozilla.com> <4ED6D685.70505@mozilla.com> Message-ID: > Do you feel (straw-vote) like ?you'd be sufficiently happy to be able to > override the former group but not the latter? Definitely. > (Also: please say you've no interest in permitting user-defined > operator-symbols with their own associativity and precedence. Right?) This is from my xmonad config: composeOne [ isDialog -?> manageHook defaultConfig, isKDETrayWindow -?> manageHook defaultConfig, return True -?> insertPosition End Newer <+> manageHook defaultConfig ] It seems to work, but I still don't really understand what it says. Let's not go there in Rust. From niko at alum.mit.edu Thu Dec 1 20:25:42 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 01 Dec 2011 20:25:42 -0800 Subject: [rust-dev] Addressing "the hashtable problem" with type classes Message-ID: <4ED85346.4000409@alum.mit.edu> Here is a proposal to work around a potentially serious problem with the modular type classes we have been discussing. The problem, as explained, is that collections (and possibly other data structures) can lose coherence if they are used with incompatible implementations of type classes like `hashable`. From : # The "Hashtable Problem" There is a danger with typeclasses only on functions because they permit a lack of coherence. This danger is particularly acute with collections, where the definition of a particular interface---such as hashable or ord---may be used in structuring the data structure. This renders the data structure corrupt when used with a different implementation. To see the problem, consider a hashtable defined something like this: mod ht { iface hash { fn hash() -> uint; fn eq(other: self) -> bool; } type t = { buckets: [bucket] } fn create() -> @t { ... } fn put(ht: @t, k: K, v: V) { ... } fn get(ht: @t, k: K) -> V { ... // fails if not present } } This looks reasonable. Now we create two modules, `Module1` and `Module2`, which both share a reference to the same hashtable, but which have different implementations of the `hash` interface in scope: mod Module1 { impl hash for uint { fn hash() -> uint { ret self; } fn eq(other: int) -> bool { ret self == other; } } ... fn foo() -> str { let h = ht::create(); ht::put(ht, 3u, "hi"); // 3u.hash() == 3u here ret Module2::bar(h); } } mod Module2 { impl hash for uint { fn hash() -> uint { ret self / 2; } fn eq(other: int) -> bool { ret self == other; } } ... fn bar(h: @ht::t) -> str { ret ht_get(ht, 3u); // fails because 3u.hash() == 1u here } } Here, `Module2::bar()` will fail to find any value for `3u` because it is using an incompatible hash implementation. The annoying problem here is that both modules are correct in and of themselves, they are just using mutually inconsistent definitions of `hash for uint`. # A solution of sorts We cannot completely rule out the possibility of writing code like this. I believe it is inherent in any solution that involves both scoped implementations (i.e., not global, as in Haskell) and open types (i.e., methods can be declared even after the type has been defined, unlike Java or C#). However, we *can* make it possible to write code that detects such mismatches. The idea has two parts. First, we allow type variables in types to have interfaces associated with them: type HT = { ... } Next, we say that the value for a type variable is not just a type, like `uint`, but rather a tuple `type : impl*` of a type and zero or more implementations, one for each interface bound. Therefore, the full type of the hashtable `h` in our example would not be `HT` but rather `HT`. However, the user does not (usually) have to write the implementations by hand; they are supplied by the compiler based on what is in scope for the given type. Now, armed with this new idea, the fully specified form of the function `bar()` from `Module2` would be: fn bar(h: @ht::t) { ... } As a result, the compiler will specify a type error at the call `Module2::bar(h)` in `Module1::foo()`, because the type of the parameter `h` in `bar()` does not match the type of the value being provided (the implementation modules do not match). ## Default implementations When the value of a type variable is written explicitly, it can be written either `ty:impl1,impl2` (explicit implementations for each interface) or just `ty`. If only a type is specified, the compiler will look for imported implementations and insert the default value. One important case is when the type is itself a bounded type variable, as here: fn put(ht: @t, k: K, v: V); The type `@t` does not provide an explicit implementation for `K`. The compiler defaults it to whichever implementation is provided as part of the type variable `K` by the caller. This is because, for a type variable, the implementations in scope are those that are supplied by the caller. # What if I don't care which hash function is being used? Now, you might argue that it is still weird that the imports in `Module2::bar()` are affecting what hash function is used for a hashtable that is being passed in as a parameter, for which the hash function has already (presumably) been specified when the hashtable was created. There are pluses and minuses to this. The plus is that this full specification would allow for a very high degree of optimization if we did monomorphizing: there would be no dynamic calls at all involved in using the hashtable. Also, so long as you use a consistent set of implementations across most of your methods, there is no annotation overhead since the detail implementations that the compiler supplies will all match. However, it would still be nice to be able to write a function that operates over any hashtable that uses `uint` as its key type, regardless of what hash function is in use. This is basically polymorphism. Thankfully, we have an answer to that: interfaces. So, we define an interface where the `K` type variant is not necessarily hashtable (after all, this interface could also be fulfilled by a binary tree or some other kind of map): iface map { fn put(k: K, v: V); fn get(k: K) -> V; } And now we have to implement the interface for the type `ht::t`: impl map for ht::t { fn put(k: K, v: V) { ret ht::put(self, k, v); } fn get(k: K) { ret ht::get(self, k); } } This interface hides the precise hash implementation, encapsulating it so to speak. There are some niggling implementation details to be worked out, as the compiler will (in a dynamic setting) have to stash the hash implementation pointer somewhere so it is available for use in the `put()` and `get()` functions. In a monomorphic setting, customized variants of `put()` and `get()` would be generated in any case. From graydon at mozilla.com Fri Dec 2 10:48:36 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 02 Dec 2011 10:48:36 -0800 Subject: [rust-dev] criteria for core lib Message-ID: <4ED91D84.8060403@mozilla.com> Hi, I'm in the process of adding a 'core' lib that will complement std in the following fashion: - core will be automatically 'use'd in any crate, unless you ask for --no-core when running the compiler. - everything in core will be automatically imported into the crate you're building, again, unless you pass --no-core The idea here is that some "library" code is so universal as to be not worth burdening every user with writing "use std;" and -lstd with every time they build a program, and that as libstd grows, the tension to "not have to link or distribute libstd" for small/simple programs grows stronger. Nobody wants a static-linked "hello world" to be 10mb. The interesting question is: what are the criteria for something to be in 'core' vs. 'std'? I've been thinking of the following criteria: - If it's a module that relates 1:1 with a built-in tycon, it goes in core. This means u8, u32, ..., str, vec, all go in core. - If it's a module that relates 1:1 with a built-in runtime service, it also goes in core. This means task, comm, os, fs, sys, dbg, rand, unsafe, test, time, uv, run_program all go in core. - If it's a module that covers a type we wind up using "in nearly every nontrivial program", it goes in core. This means option, either, result and extfmt go in core. This is quite a bit of the stdlib, but not all. It leaves: bitv, cmath, ctypes, c_vec, deque, ebml, four, fun_treemap, getopts, json, list, map, net, rope, sha1, smallintmap, sort, tempfile, term, treemap, tri, ufind, unicode, util all in std. And as we add more stdlib stuff over time (I think I'd prefer a big libstd -- see https://github.com/graydon/rust/wiki/Standard-library-notes) we will be making std larger, and core not-much-larger, possibly even smaller as we reimplement rt stuff in rust code. Are these agreeable criteria? Do you want fewer or more modules in core? (Alternatively: Do you think this is a terrible idea? Do you want to restart the conversation about large-vs-small libstd?) -Graydon From marijnh at gmail.com Fri Dec 2 11:32:05 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Fri, 2 Dec 2011 20:32:05 +0100 Subject: [rust-dev] criteria for core lib In-Reply-To: <4ED91D84.8060403@mozilla.com> References: <4ED91D84.8060403@mozilla.com> Message-ID: I agree with your categorization of what should be in core. I'd split the stdlib into different crates though -- most programs don't need json/rope/treemap/etc . We could put them in a standard distribution, as separate crates, or when the package manager is functional, simply rely on that for providing them. From fw at deneb.enyo.de Sat Dec 3 10:53:44 2011 From: fw at deneb.enyo.de (Florian Weimer) Date: Sat, 03 Dec 2011 19:53:44 +0100 Subject: [rust-dev] Addressing "the hashtable problem" with type classes In-Reply-To: <4ED85346.4000409@alum.mit.edu> (Niko Matsakis's message of "Thu, 01 Dec 2011 20:25:42 -0800") References: <4ED85346.4000409@alum.mit.edu> Message-ID: <874nxhij0n.fsf@mid.deneb.enyo.de> * Niko Matsakis: > Here is a proposal to work around a potentially serious problem with > the modular type classes we have been discussing. The problem, as > explained, is that collections (and possibly other data structures) > can lose coherence if they are used with incompatible implementations > of type classes like `hashable`. Is this to related to Weirich et al., "Generative Type Abstraction and Type-level Computation", in the sense that it is a precursor of the problems discussed there? From banderson at mozilla.com Sat Dec 3 15:41:24 2011 From: banderson at mozilla.com (Brian Anderson) Date: Sat, 03 Dec 2011 15:41:24 -0800 Subject: [rust-dev] criteria for core lib In-Reply-To: <4ED91D84.8060403@mozilla.com> References: <4ED91D84.8060403@mozilla.com> Message-ID: <4EDAB3A4.50601@mozilla.com> On 12/02/2011 10:48 AM, Graydon Hoare wrote: > > Are these agreeable criteria? Do you want fewer or more modules in core? > > (Alternatively: Do you think this is a terrible idea? Do you want to > restart the conversation about large-vs-small libstd?) > I agree with your criteria. With regard to the large vs. small std question, I'm beginning to agree with marijn (and I think patrick) that it would be better to have many small crates, and make rustc/cargo powerful enough to locate them automatically and add them to the compilation with little effort (primarily because of mobile considerations). I do think we want to provide these as 'standard' libraries, just not a single stdlib. -Brian From graydon at mozilla.com Sun Dec 4 08:25:23 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Sun, 04 Dec 2011 08:25:23 -0800 Subject: [rust-dev] criteria for core lib In-Reply-To: <4EDAB3A4.50601@mozilla.com> References: <4ED91D84.8060403@mozilla.com> <4EDAB3A4.50601@mozilla.com> Message-ID: <4EDB9EF3.7090508@mozilla.com> On 03/12/2011 3:41 PM, Brian Anderson wrote: > With regard to the large vs. small std question, I'm beginning to agree > with marijn (and I think patrick) that it would be better to have many > small crates, and make rustc/cargo powerful enough to locate them > automatically and add them to the compilation with little effort > (primarily because of mobile considerations). I do think we want to > provide these as 'standard' libraries, just not a single stdlib. Plausible. Keep in mind there are limitations: - A cross-crate call cannot inline. - A cross-crate call isn't even just direct! It's indirect through a PLT table on linux or import-table on windows. - A cross-crate definition can't be recursive. In general, my experience has been that projects that start with the "lots of little DLLs" approach tend towards "one big DLL" over time. Actually, now that I stare at it, the no-inlining issue might make the core/std split a pretty bad idea at this point. Maybe sometime in the future if we get crate-to-crate inline exports done. -Graydon From marijnh at gmail.com Sun Dec 4 13:19:59 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Sun, 4 Dec 2011 22:19:59 +0100 Subject: [rust-dev] criteria for core lib In-Reply-To: <4EDB9EF3.7090508@mozilla.com> References: <4ED91D84.8060403@mozilla.com> <4EDAB3A4.50601@mozilla.com> <4EDB9EF3.7090508@mozilla.com> Message-ID: > Actually, now that I stare at it, the no-inlining issue might make the > core/std split a pretty bad idea at this point. When platform limitations stand in the way of proper software design, I think we should be working on circumventing them. Telling people to write monolithic libraries because the linker model penalizes a more modular approach seems very unfortunate. From graydon at mozilla.com Sun Dec 4 14:02:50 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Sun, 04 Dec 2011 14:02:50 -0800 Subject: [rust-dev] criteria for core lib In-Reply-To: References: <4ED91D84.8060403@mozilla.com> <4EDAB3A4.50601@mozilla.com> <4EDB9EF3.7090508@mozilla.com> Message-ID: <4EDBEE0A.7000609@mozilla.com> On 04/12/2011 1:19 PM, Marijn Haverbeke wrote: >> Actually, now that I stare at it, the no-inlining issue might make the >> core/std split a pretty bad idea at this point. > > When platform limitations stand in the way of proper software design, > I think we should be working on circumventing them. Telling people to > write monolithic libraries because the linker model penalizes a more > modular approach seems very unfortunate. I agree it may be worth solving the cross-crate inlining thing eventually. The key phrase in what I wrote is "at this point". We don't have it solved *now*, so right now I might wind up mothballing the core/std split patch, for now, if it turns out to be very costly. I'll do some measurements to see. It not cost much at all. Modern CPUs predict indirect branches pretty well and inlining isn't always a win, due to cache pressure. We're already PLT-jumping into out-of-line librt code pretty frequently. I don't agree with the latter statement you make here, as a universal guideline. Perfect is the enemy of good. Sometimes we make sacrifices to the gods of platform limitations. Monolithic libraries are common in the C-linkage-model world, and it's not always for easy-to-circumvent reasons. There's a set of hard engineering tradeoffs within compilation models, linkage models, memory models, etc. I'm more interested in finding a reasonable balance. Cross-crate inlining (when and if we do it) is a mixed blessing anyways. It hurts data and procedural abstraction -- both virtues of "proper software design" -- in order to help compile-time (but not run-time) modularity. I'm happy to experiment with it, but I don't think it should be seen as a panacea either. The tradeoffs are numerous. -Graydon From graydon at mozilla.com Sun Dec 4 14:04:01 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Sun, 04 Dec 2011 14:04:01 -0800 Subject: [rust-dev] criteria for core lib In-Reply-To: <4EDBEE0A.7000609@mozilla.com> References: <4ED91D84.8060403@mozilla.com> <4EDAB3A4.50601@mozilla.com> <4EDB9EF3.7090508@mozilla.com> <4EDBEE0A.7000609@mozilla.com> Message-ID: <4EDBEE51.4040502@mozilla.com> On 04/12/2011 2:02 PM, Graydon Hoare wrote: > core/std split patch, for now, if it turns out to be very costly. I'll > do some measurements to see. It not cost much at all. Modern CPUs --> ... it ^might not cost much at all ... -Graydon From banderson at mozilla.com Sun Dec 4 15:07:08 2011 From: banderson at mozilla.com (Brian Anderson) Date: Sun, 04 Dec 2011 15:07:08 -0800 Subject: [rust-dev] LLVM upgraded to svn 145779 Message-ID: <4EDBFD1C.7040901@mozilla.com> For most people this should require little action. The first time you run make it will reconfigure, then the build will likely fail. Run make again and it should work. If things still don't work, then wipe the build directory and start from scratch and let me know what happened. This pulls in commits 145765 & 145766, which are required for split stacks. We are no longer compatible with LLVM 3.0. -Brian From niko at alum.mit.edu Sun Dec 4 20:14:59 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Sun, 04 Dec 2011 20:14:59 -0800 Subject: [rust-dev] do we need lambda? Message-ID: <4EDC4543.7060801@alum.mit.edu> Hello, I wanted to do a quick straw poll to ask whether we still need a lambda expression, given that we have blocks and named functions? Searching the rust code base, I found that *every* use of lambda was of the form: |let foo = lambda(...) {...}| which would (in my opinion) be better written: |fn foo(...) {...}|. I am not asking because I like stripping out unused expression forms, though I do, but rather because I am thinking about the precise design for unique closures (separate e-mail coming soon) and the fewer ways to declare closures the simpler the job becomes. Niko From pwalton at mozilla.com Sun Dec 4 21:39:07 2011 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 04 Dec 2011 21:39:07 -0800 Subject: [rust-dev] criteria for core lib In-Reply-To: <4EDBEE0A.7000609@mozilla.com> References: <4ED91D84.8060403@mozilla.com> <4EDAB3A4.50601@mozilla.com> <4EDB9EF3.7090508@mozilla.com> <4EDBEE0A.7000609@mozilla.com> Message-ID: <4EDC58FB.6080205@mozilla.com> On 12/04/2011 02:02 PM, Graydon Hoare wrote: > Cross-crate inlining (when and if we do it) is a mixed blessing anyways. > It hurts data and procedural abstraction -- both virtues of "proper > software design" -- in order to help compile-time (but not run-time) > modularity. I'm happy to experiment with it, but I don't think it should > be seen as a panacea either. The tradeoffs are numerous. Strongly disagree. If we cannot inline stuff like map, we cannot create a performant browser engine. There is no way around this. Patrick From pwalton at mozilla.com Sun Dec 4 22:00:29 2011 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 04 Dec 2011 22:00:29 -0800 Subject: [rust-dev] criteria for core lib In-Reply-To: <4EDC58FB.6080205@mozilla.com> References: <4ED91D84.8060403@mozilla.com> <4EDAB3A4.50601@mozilla.com> <4EDB9EF3.7090508@mozilla.com> <4EDBEE0A.7000609@mozilla.com> <4EDC58FB.6080205@mozilla.com> Message-ID: <4EDC5DFD.5070107@mozilla.com> On 12/04/2011 09:39 PM, Patrick Walton wrote: > Strongly disagree. If we cannot inline stuff like map, we cannot create > a performant browser engine. There is no way around this. I should elaborate: Short of just telling users they can't use the looping abstractions in the standard library if they want performant loops, which seems like a non-starter to me. I suspect that would just lead to systems programmers writing loops by hand, using macros, using the C preprocessor, or something like that. All of those options would result in relatively unstructured workarounds that miss out on the benefits of the functional abstractions we're offering. We already see high-profile projects like SQLite do so-called "unity builds" where they concatenate everything into one enormous .c file. This is in spite of the fact that C already has macros and static/inline functions. We could do measurements here with instrumenting rustc, but I'm not sure it would be relevant. What would be more relevant would be something like inserting two function calls (one direct, one indirect) around every pixel in pixman's alpha blending routines and seeing what the performance of Firefox becomes. But I think we already know what the results of this test would be. Sorry for wording this so strongly, but I feel that this is an important issue. Patrick From marijnh at gmail.com Mon Dec 5 05:27:18 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Mon, 5 Dec 2011 14:27:18 +0100 Subject: [rust-dev] do we need lambda? In-Reply-To: <4EDC4543.7060801@alum.mit.edu> References: <4EDC4543.7060801@alum.mit.edu> Message-ID: If bind is staying (there was talk of removing it in favour of lambda at some point), I think we can do without lambda. But the concept of shared closures (which is what bind creates) would still be there. From graydon at mozilla.com Mon Dec 5 08:00:26 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Mon, 05 Dec 2011 08:00:26 -0800 Subject: [rust-dev] do we need lambda? In-Reply-To: References: <4EDC4543.7060801@alum.mit.edu> Message-ID: <4EDCEA9A.4060805@mozilla.com> On 05/12/2011 5:27 AM, Marijn Haverbeke wrote: > If bind is staying (there was talk of removing it in favour of lambda > at some point), I think we can do without lambda. But the concept of > shared closures (which is what bind creates) would still be there. I don't have a strong feeling about it. I initially didn't want *any* direct environment capture forms, just bind, but I definitely have a higher level of pain tolerance on this issue than most :) I think blocks seem to be handling most of the "one-off throwaway function" uses in our code, most of the time, right now. But we're not done exploring the space of code-to-write. Compilers aren't everything. I think the use-case for shared lambda is registering persistent callbacks, such as in a GUI. I think the use-case for registering unique lambda is spawning tasks. We hack around this now but need it eventually. How awkward would these be without lambda? What do you have in mind for the unique closures? -Graydon From dteller at mozilla.com Mon Dec 5 08:33:52 2011 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Mon, 05 Dec 2011 17:33:52 +0100 Subject: [rust-dev] do we need lambda? In-Reply-To: References: <4EDC4543.7060801@alum.mit.edu> Message-ID: <4EDCF270.3040305@mozilla.com> On Mon Dec 5 14:27:18 2011, Marijn Haverbeke wrote: > If bind is staying (there was talk of removing it in favour of lambda > at some point), I think we can do without lambda. But the concept of > shared closures (which is what bind creates) would still be there. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev What would be removed exactly? I strongly believe that we need a form of closures, e.g. for registering event callback, whether to a GUI, or for network or system events. Now, of course, as long as we have some ability to pair a data structure and a function pointer, and a standard way to represent functions expecting this kind of data structure, we can always fallback to manual closure conversion, at the expense of some readability. I wonder, what exactly would be gained by removing lambdas? Cheers, 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 brendan at mozilla.org Mon Dec 5 10:15:17 2011 From: brendan at mozilla.org (Brendan Eich) Date: Mon, 5 Dec 2011 10:15:17 -0800 Subject: [rust-dev] criteria for core lib In-Reply-To: <4EDC5DFD.5070107@mozilla.com> References: <4ED91D84.8060403@mozilla.com> <4EDAB3A4.50601@mozilla.com> <4EDB9EF3.7090508@mozilla.com> <4EDBEE0A.7000609@mozilla.com> <4EDC58FB.6080205@mozilla.com> <4EDC5DFD.5070107@mozilla.com> Message-ID: <8A13D59C-C1BA-4F56-8602-79DE6B89A5A2@mozilla.org> Virtual methods all over Gecko (Raptor, originally) really hurt. QI, AddRef/Release (nonsensical for arena-allocated objects, but the COM disease was rampant), all the core rendering object methods were virtual. De-virtualization took years. KHTML (now WebKit) avoided this costly mistake. It's not the same as what's discussed here but I wanted to support the concern about indirect call overhead. It's not a premature optimization to consider at this juncture. /be On Dec 4, 2011, at 10:00 PM, Patrick Walton wrote: > On 12/04/2011 09:39 PM, Patrick Walton wrote: >> Strongly disagree. If we cannot inline stuff like map, we cannot create >> a performant browser engine. There is no way around this. > > I should elaborate: Short of just telling users they can't use the looping abstractions in the standard library if they want performant loops, which seems like a non-starter to me. I suspect that would just lead to systems programmers writing loops by hand, using macros, using the C preprocessor, or something like that. All of those options would result in relatively unstructured workarounds that miss out on the benefits of the functional abstractions we're offering. > > We already see high-profile projects like SQLite do so-called "unity builds" where they concatenate everything into one enormous .c file. This is in spite of the fact that C already has macros and static/inline functions. > > We could do measurements here with instrumenting rustc, but I'm not sure it would be relevant. What would be more relevant would be something like inserting two function calls (one direct, one indirect) around every pixel in pixman's alpha blending routines and seeing what the performance of Firefox becomes. But I think we already know what the results of this test would be. > > Sorry for wording this so strongly, but I feel that this is an important issue. > > Patrick > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From niko at alum.mit.edu Mon Dec 5 13:14:27 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 05 Dec 2011 13:14:27 -0800 Subject: [rust-dev] do we need lambda? In-Reply-To: <4EDCF270.3040305@mozilla.com> References: <4EDC4543.7060801@alum.mit.edu> <4EDCF270.3040305@mozilla.com> Message-ID: <4EDD3433.7080003@alum.mit.edu> Ah, I see now that nested functions cannot access upvars. I was under the impression this limitation had been removed. I did not intend to take away access to upvars (as you and Graydon said, crucial to event callbacks) but just the anonymous function syntax. However, I've been thinking it over more since last night and now I think that this is not a very good idea. It'll make the language feel heavy and we want it to feel light. What might be nice, then, is a less ponderous syntax than lambda syntax. In any case, I am still toying with what unique closures ought to be. One problem I have uncovered (and it's already a bug today) is that a unique closure must be very careful what it does with its unique, closed-over state. The problem is that a unique closure can be invoked multiple times. Not so good if you are moving or dropping unique variables. For example, this code crashes today: > fn foo(-x: ~int) { } > fn main() { > let b = bind foo(~3); > b(); > b(); > } The error is that bind needs to "re-copy" the ~3 each time `b()` is invoked, but it doesn't. In other words, that bind code is equivalent to `let x = ~3 in fn () -> foo(x)` (in some weird O'Caml/Rust hybrid) but it would need to be `fn() -> let x = ~3 in foo(x)` to be safe. This problem can be addressed in many ways and I am not sure what is best. One option is to say that unique closures cannot move or dispose of their upvars (here, bind is moving its upvar, essentially). Essentially upvars become like a field of a record or other immutable location, which must be accessed via swap. This is safe but somewhat disappointing, because most unique closures will be used to spawn a task and therefore executed only once. Another option is to specify that a unique closure can be invoked only once (calling it consumes itself). This is also limiting if that's not what you want, but it probably is. In particular it does not allow unique closures to become the foundation for a map/reduce library. All in all, I am just not sure that unique closures are the right tool for a "user-friendly", simple parallelism API, which I understood to be one of their goals. In other words, if you want to fork off a bunch of tasks to process the various elements in your array and then pull them back in, unique closures don't really give you the guarantees you want. On the other hand, unique closures do serve a useful purpose for spawning off a task and handing it data. This could also be simulated today using a wrapper that creates a channel, starts a new task, passes the value over the channel, and finally invokes your function. Of course this adds overhead for something that (may?) be a common case. But I am not sure if moving one-off data like that *is* a common case. Niko On 12/5/11 8:33 AM, David Rajchenbach-Teller wrote: > On Mon Dec 5 14:27:18 2011, Marijn Haverbeke wrote: >> If bind is staying (there was talk of removing it in favour of lambda >> at some point), I think we can do without lambda. But the concept of >> shared closures (which is what bind creates) would still be there. >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev > What would be removed exactly? I strongly believe that we need a form of > closures, e.g. for registering event callback, whether to a GUI, or for > network or system events. > > Now, of course, as long as we have some ability to pair a data structure > and a function pointer, and a standard way to represent functions > expecting this kind of data structure, we can always fallback to manual > closure conversion, at the expense of some readability. > > I wonder, what exactly would be gained by removing lambdas? > > Cheers, > David > From niko at alum.mit.edu Mon Dec 5 14:09:15 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 05 Dec 2011 14:09:15 -0800 Subject: [rust-dev] A proposal: No implicit copies Message-ID: <4EDD410B.3080007@alum.mit.edu> Hello, I've been working on writing up a proposal that modifies Rust to eliminate (most) implicit copies. http://smallcultfollowing.com/babysteps/rust/no-implicit-copies/ The idea is to separate types into implicitly copyable types and explicitly copyable types. Implicitly copyable types would be scalars, shared pointers (@), and tuples of implicitly copyable types. Explicitly copyable types would be everything else. Copies of explicitly copyable types only occur when there is an explicit `copy` keyword in the source text. Also in the proposal is that vectors and strings are no longer unique. Instead, they can be either shared or unique. Vectors become the more fundamental fixed-length arrays, with dynamically growable vectors becoming a library. This allows support for references into arrays, dynamically sized records, and other nice, C-like features. Feedback would be very welcome. Note: for those who saw the earlier, "reference type" draft, the functions with `new` return type in this proposal are a different beast from those in the previous "reference type" proposal. If you have no idea what I'm talking about, don't worry, it's not important. Niko From niko at alum.mit.edu Mon Dec 5 14:26:39 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 05 Dec 2011 14:26:39 -0800 Subject: [rust-dev] A proposal: No implicit copies In-Reply-To: <4EDD410B.3080007@alum.mit.edu> References: <4EDD410B.3080007@alum.mit.edu> Message-ID: <4EDD451F.9070904@alum.mit.edu> I should add that the ideas in the proposal are not (all) my own. I'm collecting ideas that have been floating around in various discussions and trying to get them together in one place and make sure that all the repercussions work out. Niko On 12/5/11 2:09 PM, Niko Matsakis wrote: > Hello, > > I've been working on writing up a proposal that modifies Rust to > eliminate (most) implicit copies. > > http://smallcultfollowing.com/babysteps/rust/no-implicit-copies/ > > The idea is to separate types into implicitly copyable types and > explicitly copyable types. Implicitly copyable types would be > scalars, shared pointers (@), and tuples of implicitly copyable > types. Explicitly copyable types would be everything else. Copies of > explicitly copyable types only occur when there is an explicit `copy` > keyword in the source text. > > Also in the proposal is that vectors and strings are no longer > unique. Instead, they can be either shared or unique. Vectors become > the more fundamental fixed-length arrays, with dynamically growable > vectors becoming a library. This allows support for references into > arrays, dynamically sized records, and other nice, C-like features. > > Feedback would be very welcome. > > Note: for those who saw the earlier, "reference type" draft, the > functions with `new` return type in this proposal are a different > beast from those in the previous "reference type" proposal. If you > have no idea what I'm talking about, don't worry, it's not important. > > > Niko > From niko at alum.mit.edu Mon Dec 5 15:19:56 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 05 Dec 2011 15:19:56 -0800 Subject: [rust-dev] Addressing "the hashtable problem" with type classes In-Reply-To: <874nxhij0n.fsf@mid.deneb.enyo.de> References: <4ED85346.4000409@alum.mit.edu> <874nxhij0n.fsf@mid.deneb.enyo.de> Message-ID: <4EDD519C.2030903@alum.mit.edu> On 12/3/11 10:53 AM, Florian Weimer wrote: > Is this to related to Weirich et al., "Generative Type Abstraction and > Type-level Computation", in the sense that it is a precursor of the > problems discussed there? I hadn't seen that paper before. I read through it. I don't know how related the problems they describe are to the problem that I describe. They mention that "newtype" is often used in Haskell as a way to workaround the absence of multiple implementations for a single interface. Using a scoped system like we've been discussing obviates the need for this workaround, which is good. Niko From marijnh at gmail.com Tue Dec 6 23:47:32 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Wed, 7 Dec 2011 08:47:32 +0100 Subject: [rust-dev] A proposal: No implicit copies In-Reply-To: <4EDD451F.9070904@alum.mit.edu> References: <4EDD410B.3080007@alum.mit.edu> <4EDD451F.9070904@alum.mit.edu> Message-ID: Looks good. I'd like to include immutable records of implicitly copyable types as implicitly copyable. > The primary use case for move mode arguments was to ?give away? a unique pointer: this is now achieved by having the callee simply declare a parameter of unique type and having the caller move it to them. When doing channel communication or data-structure construction, there'll probably be a lot of calls that are 'giving away' arguments. I fear that requiring callers to annotate every one of them will be cumbersome. How about changing the semantics of by-move and by-copy parameters to simply automatically insert the copy/move annotation into every call? When exactly would you want to have functions with a non-single-word-sized return value not be constructor functions? I still feel we'd be better off trying to make this implicit and not exposing it to the user. From niko at alum.mit.edu Wed Dec 7 06:43:40 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 07 Dec 2011 06:43:40 -0800 Subject: [rust-dev] A proposal: No implicit copies In-Reply-To: References: <4EDD410B.3080007@alum.mit.edu> <4EDD451F.9070904@alum.mit.edu> Message-ID: <4EDF7B9C.8060501@alum.mit.edu> On 12/6/11 11:47 PM, Marijn Haverbeke wrote: > I'd like to include immutable records of implicitly copyable types as > implicitly copyable. I am not necessarily opposed but I'd prefer to have nominal records and let the user specify per type (this could then apply to tags, too). My reasoning is that the more "special cases" we make the less users will understand. I could see the current rules being too complex, but I feel like tuples are fairly special. If we do decide to go this route, I'd like to see tags where all variants contain only implicitly copyable things also be implicitly copyable: in other words, be consistent across all kinds of types. >> The primary use case for move mode arguments was to ?give away? a unique pointer: this is now achieved by having the callee simply declare a parameter of unique type and having the caller move it to them. > When doing channel communication or data-structure construction, > there'll probably be a lot of calls that are 'giving away' arguments. > I fear that requiring callers to annotate every one of them will be > cumbersome. How about changing the semantics of by-move and by-copy > parameters to simply automatically insert the copy/move annotation > into every call? I think you and I just see this issue differently. I see it as burdensome if the caller does NOT specify that a variable is being moved (or, for that matter, passed by mutable reference). This is because I as reader of the code have no indication that this is not a simple, by value parameter passing. I think your optimization where the last use of a local variable is implicitly a move is a reasonable compromise, as this is still something I can deduce just from reading the caller method and without looking at the definitions of the functions that it calls. That said, I feel better about the idea of making `move` mode a suggestion to the caller (I would still say the caller should be able to write `copy` or `move` explicitly) than I do about mutable by-ref parameters. The reason is that if I try to use the variable after it has been moved, I'll get an error, and if I don't try to use the variable, then a move is reasonable. Still by this logic the "last use is a move" rule ought to be enough. > When exactly would you want to have functions with a > non-single-word-sized return value not be constructor functions? I > still feel we'd be better off trying to make this implicit and not > exposing it to the user. I agree: I did make it implicit. The `new` functions are not for this purpose anymore. A `new` function is used to return something on the heap without specifying which heap you are returning it on. It is needed for returning variably sized types like arrays, because they cannot be returned "by value", but at the same time you do not want to have to write two versions of every array construction function: fn map_shared(v: [T], b: block(T)->U) -> @[U] fn map_unique(v: [T], b: block(T)->U) -> ~[U] Using a `new` function allows you to write: fn map(v: [T], b: block(T)->U) -> new [U] That said, we *could* hide (the new version of) `new` functions from the user as well. Any function that returns a variably sized type would be compiled using the `new` ABI. This includes functions with generic type where the generic variable has the `var` capability/interface. I rather like that as well. The need to specify the ABI for the return type is one of the things I did not care for in this proposal. (In an earlier draft of the proposal, I did not have the `var` interface for type variables as I did not want to add a new kind. In that case, `new` functions were needed) Niko From robert at ocallahan.org Thu Dec 8 20:21:51 2011 From: robert at ocallahan.org (Robert O'Callahan) Date: Fri, 9 Dec 2011 17:21:51 +1300 Subject: [rust-dev] Strict style checking Message-ID: One of my pet peeves about programming languages is that they don't go far enough in mandating a particular coding style. Projects are forced to make up their own coding style rules, and their own tools and processes for enforcing those rules, which works OK until you try to move code from one project to another. In my experience those costs vastly outweigh the value of permitting personal coding styles as a means of self-expression. I would be thrilled if the Rust compiler enforced as many machine-checkable style rules as possible --- rules like "no tabs", standard indentation, placing of spaces and modifier characters, etc. I think it would really help when we come to use it in large projects. (I wrote more about this a while ago: http://robert.ocallahan.org/2010/07/coding-style-as-failure-of-language_21.html ) Rob -- "If we claim to be without sin, we deceive ourselves and the truth is not in us. If we confess our sins, he is faithful and just and will forgive us our sins and purify us from all unrighteousness. If we claim we have not sinned, we make him out to be a liar and his word is not in us." [1 John 1:8-10] -------------- next part -------------- An HTML attachment was scrubbed... URL: From dherman at mozilla.com Thu Dec 8 21:55:05 2011 From: dherman at mozilla.com (Dave Herman) Date: Thu, 8 Dec 2011 21:55:05 -0800 (PST) Subject: [rust-dev] Strict style checking In-Reply-To: Message-ID: <1750511400.36131.1323410105191.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> > One of my pet peeves about programming languages is that they don't go > far enough in mandating a particular coding style. I remember your blog post. I have to say I don't much agree. Here are my concerns: - Lint tools are a fine way for any group to enforce its preferred style. (Our compiler is designed to be modular and shared as a library, so we will make it pretty convenient to write lint tools. We could even provide hooks to allow the compiler to integrate a user-provided lint tool into the compiler pipeline. All of this would be fine with me.) - In my experience, different styles between projects don't really distract much. You get used to the style used there, and everyone's a grown-up and understands they stick with the style of that group, even if it's not their preferred style. - There are always stylistic things to disagree about. We can nail down some and people will still find other minutiae to disagree about. - I think there's as much danger of compiler pettiness wasting developers' time as arguments about style do. - There's a real danger of alienating our potential users by being too petty. And perhaps my biggest objection: - *Compilers* that are obnoxious about dotting every i and crossing every t are a very different thing from *tools* that enforce style. Running a lint tool, or tying a lint tool to a build process, or to a check-in process -- those things all make perfect sense to me. But yelling at me for indentation when I'm trying to hack? That sounds like a recipe for getting in the programmer's way for questionable gain. Restrictions need to have clear payoff. I just don't see this experiment as worthwhile when we have so many important problems to work on. Dave From robert at ocallahan.org Fri Dec 9 01:29:39 2011 From: robert at ocallahan.org (Robert O'Callahan) Date: Fri, 9 Dec 2011 22:29:39 +1300 Subject: [rust-dev] Strict style checking In-Reply-To: <1750511400.36131.1323410105191.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> References: <1750511400.36131.1323410105191.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: On Fri, Dec 9, 2011 at 6:55 PM, Dave Herman wrote: > - In my experience, different styles between projects don't really > distract much. You get used to the style used there, and everyone's a > grown-up and understands they stick with the style of that group, even if > it's not their preferred style. > That's fine when you work mostly on one project that has a consistent style. If you switch between projects, then you have to remember which style to use for each project, probably even look it up for more obscure issues. The kicker is if you move code between projects; then you're stuck with style inconsistencies or else reformatting the moved code ... which inhibits future merging. - *Compilers* that are obnoxious about dotting every i and crossing every t > are a very different thing from *tools* that enforce style. Running a lint > tool, or tying a lint tool to a build process, or to a check-in process -- > those things all make perfect sense to me. But yelling at me for > indentation when I'm trying to hack? > Do you really write code using arbitrary indentation and other style, and then reformat it to the project style when you submit patches? I've never noticed anyone doing that. On the contrary, I think I'd crank code out faster if I didn't have to keep checking that I'm using the correct style for the project I'm working in. > I just don't see this experiment as worthwhile when we have so many > important problems to work on. > That makes sense. I'll try again next language :-). Rob -- "If we claim to be without sin, we deceive ourselves and the truth is not in us. If we confess our sins, he is faithful and just and will forgive us our sins and purify us from all unrighteousness. If we claim we have not sinned, we make him out to be a liar and his word is not in us." [1 John 1:8-10] -------------- next part -------------- An HTML attachment was scrubbed... URL: From joseph.h.garvin at gmail.com Fri Dec 9 01:34:42 2011 From: joseph.h.garvin at gmail.com (Joseph Garvin) Date: Fri, 9 Dec 2011 03:34:42 -0600 Subject: [rust-dev] Semantics/tutorial feedback Message-ID: Hi all, Rust was recently mentioned on reddit again (http://www.reddit.com/r/programming/comments/n4zsy/rust_a_safe_concurrent_practical_language_made/) so I decided to check in on its development by reading the tutorial. In general Rust looks to be progressing very nicely, and I had a few thoughts. I haven't searched the archives, so apologies if some of these suggestions have already been considered. 1. Supporting the ternary operator "?:" when "if" is already an expression seems redundant. "?:" causes confusion for C beginners, so I think it would in rust as well. If there is a behavior difference between the two that merits them both existing it would probably be worth mentioning this in the tutorial. If there is no difference I'd strongly suggest just sticking to "if"; operators are a rare commodity and there are lots of semantics "?" could be intuitive for (e.g. builtin optional) 2. Inferring the type of 'x' in "let x = []" is neat, but is this type of inference a privilege restricted to the builtin types? (i.e. are you pulling a Go with generics inference instead of generics? ;) Can a user define a generic data structure where the type arguments can be inferred based on the structure's usage? If not I'd consider making it mandatory that the type is obvious from the constructor (you could still come up with ways that it needn't be explicitly specified, like passing the 'default' value and inferring on that). 3. The subject says semantics but this is really a syntax objection. I think "3 as float" will ultimately be a language wart, because 'as' will be the only operator that operates on a runtime value (3) and a compile time type (float) with the same infix syntax as regular operators that only operate on runtime values. For generics you've already established the C++/Java style Foo syntax, so why not use this for 'as' as well: "as(3)" . As an added bonus the syntax becomes more intuitive for C++ users accustomed to static_cast, etc. 4. target_os and similar attributes may seem convenient but I suspect will have Rust biting off more than it can chew. What version of win32 does target_os="win32" mean? It's typical for projects to have separate builds for Win95, Vista, etc. Generally speaking the whole approach of toggling things based on the OS target is frowned upon compared to testing for features with configure tests. Getting results of configure tests into the compiler and having them affect the code in a more robust way than the C preprocessor's text snipping and find-replace hackery (e.g. config.h and #ifdefs) seems like a better problem to solve. If you could make the inclusion of a function definition dependent on looking up a value in a dictionary file, something like "#get_config_result(has_pthreads)", that might be sufficient. The idea of an attributes mechanism in general though is a good one. 5. bind as described (using only _ to indicate a missing argument) doesn't let you change argument order, which you can do with boost::bind. I don't whether or not this is an essential feature, I'm just pointing it out. With boost::bind you can do "auto print_args_reverse = boost::boost_bind(&print_args, _3, _2, _1);" Looks like you guys are already considering removing bind, just using lambdas instead would solve this, but I haven't thought the memory management implications through so I'm holding back from suggesting bind be removed. 6. Having curly braces after a function act as an implicit block parameter is sweet. If I'm not mistaken though, you can use them to build python like context handlers. Instead of using a resource, you can write a function that takes a block, allocates some resource, executes the block, then frees the resource. Though maybe this is frowned on due to exceptions (if the block throws the free will never run)? The tutorial didn't mention whether Rust is going to have them. Anyway, if it is useful for inserting before/after behavior (e.g. glBegin/glEnd) that seems worth mentioning. 7. Not sure if this is intentional or an oversight: but it looks like there's no way to extend a polymorphic data type while maintaining independent compilation. Tags let you make an abstract type with several concrete subtypes, but all possible subtypes have to be declared where the tag is declared. This is the trade off between variants and abstract bases with virtual functions -- the former you can know if you've covered all types when destructuring, but the latter you can extend outside of the original declaration. 8. Having a 'cycle collector' for shared box types seems as bad as having a garbage collector. The advantage of having reference counting is supposed to be determinism -- if you're going to have something nondeterministically freeing some objects (or is there a predictable semantics for when cycle detection will run?) you may as well go whole hog. I'm not sure if Rust's semantics make it possible to statically detect if cycles are possible, though that would be nice. The compiler could check for cycles in the types, so that a shared Foo couldn't directly or indirectly point to other shared Foo's, or at least only weakly to them (adding a concept of weak references), but that could be tricky depending on your compilation model and you could be forced to use weak references in instances where you know a cycle will really never occur. 9. I'm curious as to the justification for making log a builtin keyword rather than a builtin library. What is gained by giving the compiler direct awareness of logging? Having a mechanism for converting types and expressions to pretty string representations is definitely worthwhile (I've contributed code to the Toast C++ library to add this capability to C++ and it was invaluable for serialization and log messages when doing policy based programming where the type can totally describe a class's behavior), but seems oddly conflated with logging. Unless you have plans for the compiler to say, patch the code at runtime based on log level to overwrite log calls with nop instructions (like the Linux kernel) to avoid the performance hit of branching, then this seems like an odd choice (and even then it'd be cooler to provide a non-logging specific mechanism for patching away branches). Most heavy duty apps will need fairly customized logging and you don't want the compiler to have to support all the possible output types (file, syslog, zeromq, database, etc.). From marijnh at gmail.com Fri Dec 9 02:08:42 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Fri, 9 Dec 2011 11:08:42 +0100 Subject: [rust-dev] Semantics/tutorial feedback In-Reply-To: References: Message-ID: > 1. Supporting the ternary operator "?:" when "if" is already an > expression seems redundant. As a compulsive code golfer, I'm kind of attached to ?: -- but the point about the '?' and ':' symbols being useful for other things is very valid (we're definitely running out glyphs). > 2. Inferring the type of 'x' in "let x = []" is neat, but is this type > of inference a privilege restricted to the builtin types? No. 'let x = none;' also works (and none is defined as a regular sum type in the stdlib). > 3. The subject says semantics but this is really a syntax objection. I > think "3 as float" will ultimately be a language wart Good call. I've been noticing this too -- there are a bunch of special cases in the parser and pretty-printer to work around this. Added to that, the low precedence on 'as' keeps surprising me. I'd be okay with using a different syntax -- though as(3) seems overly ugly. > 4. target_os and similar attributes may seem convenient but I suspect > will have Rust biting off more than it can chew. What version of win32 > does target_os="win32" mean? It is possible for users to define and check against their own flags. I think there is no harm in providing some basic ones in the compiler. > 7. Not sure if this is intentional or an oversight: but it looks like > there's no way to extend a polymorphic data type while maintaining > independent compilation. We're trying to avoid subtyping. We're working on something akin to type classes, which might address your point here. > 8. Having a 'cycle collector' for shared box types seems as bad as > having a garbage collector. I don't know the details of our cycle collector, but I think we can statically determine which types *might* contain cycles, and only run it on those. Most programs won't have any cyclic types in them. > 9. I'm curious as to the justification for making log a builtin > keyword rather than a builtin library. There are plans to add some reflection features that would make it possible to implement log in the stdlib (and allow people to implement and use alternatives). Best, Marijn From joseph.h.garvin at gmail.com Fri Dec 9 02:33:01 2011 From: joseph.h.garvin at gmail.com (Joseph Garvin) Date: Fri, 9 Dec 2011 04:33:01 -0600 Subject: [rust-dev] Semantics/tutorial feedback In-Reply-To: References: Message-ID: On Fri, Dec 9, 2011 at 4:08 AM, Marijn Haverbeke wrote: >> 2. Inferring the type of 'x' in "let x = []" is neat, but is this type >> of inference a privilege restricted to the builtin types? > > No. 'let x = none;' also works (and none is defined as a regular sum > type in the stdlib). I'm not sure that's equivalent. If you remove the syntactic sugar, this: let x = []; Is basically this: let x = List(); Where MysteryT gets inferred based on what's put in the container. I'm sure if I write: let x = none; x = List(); That it will work, but I'm less confident that this will work for user types: let x = MyContainer(); x.insert(3); // now infer that x is really a MyContainer How would the compiler infer that? From marijnh at gmail.com Fri Dec 9 02:39:05 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Fri, 9 Dec 2011 11:39:05 +0100 Subject: [rust-dev] Semantics/tutorial feedback In-Reply-To: References: Message-ID: Ah, I should have clarified. 'none' refers to the std::option type, which is defined as `tag option { none; some(T); }`. > let x = MyContainer(); > x.insert(3); // now infer that x is really a MyContainer > > How would the compiler infer that? Well, you can't write there, but you can leave off the <> part, and the type parameter will be unified with the type of the 3, and things will Just Work. From joseph.h.garvin at gmail.com Fri Dec 9 03:49:13 2011 From: joseph.h.garvin at gmail.com (Joseph Garvin) Date: Fri, 9 Dec 2011 05:49:13 -0600 Subject: [rust-dev] Semantics/tutorial feedback In-Reply-To: References: Message-ID: On Fri, Dec 9, 2011 at 4:39 AM, Marijn Haverbeke wrote: > Ah, I should have clarified. 'none' refers to the std::option type, > which is defined as `tag option { none; some(T); }`. > >> let x = MyContainer(); >> x.insert(3); // now infer that x is really a MyContainer >> >> How would the compiler infer that? > > Well, you can't write there, but you can leave off the <> > part, and the type parameter will be unified with the type of the 3, > and things will Just Work. Oh, nifty :) From marijnh at gmail.com Fri Dec 9 04:25:37 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Fri, 9 Dec 2011 13:25:37 +0100 Subject: [rust-dev] Emacs rust-mode updated Message-ID: It now handles blocks better, and should no longer get confused about objects so easily. Get it from https://github.com/marijnh/rust-mode (Don't forget to byte-compile it!) From dherman at mozilla.com Fri Dec 9 07:44:38 2011 From: dherman at mozilla.com (Dave Herman) Date: Fri, 9 Dec 2011 07:44:38 -0800 (PST) Subject: [rust-dev] Strict style checking In-Reply-To: Message-ID: <811209354.40626.1323445478786.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> >> - *Compilers* that are obnoxious about dotting every i and crossing >> every t are a very different thing from *tools* that enforce style. >> Running a lint tool, or tying a lint tool to a build process, or to a >> check-in process -- those things all make perfect sense to me. But >> yelling at me for indentation when I'm trying to hack? > > Do you really write code using arbitrary indentation and other style, > and then reformat it to the project style when you submit patches? > I've never noticed anyone doing that. On the contrary, I think I'd > crank code out faster if I didn't have to keep checking that I'm using > the correct style for the project I'm working in. It's just been my experience that over-strict compiler errors get in the way of the development process because I often need to try things out before they're finished. For example, back in the bootstrap compiler days, we had Ocaml configured to fail if there were any dead variables. This was incredibly frustrating and distracting. But one alternative we could consider, that would largely have the social effect you're looking for (enforcing a standard style and eliminating annoying style differences between projects) would be a tool like gofmt: http://golang.org/cmd/gofmt/ This is not part of the go compiler, but by shipping a tool with the language that enforces a particular style, it sends a clear message that this is the language's official style. And by making the tool useful, it provides a carrot to use that style. But it doesn't have the danger of interrupting the edit-compile-run workflow by nagging the user about syntactic nits. I believe they've also used it as a refactoring tool to help programmers migrate their code when the language changes, which is a useful trick, too. You could worry that some projects would still adopt their own style, but a) there are practical benefits to using the official language style, and b) we could still set cultural norms about using the official language style. In practice, I think there would be so much more uniformity of style that it would probably make non-conformists look silly and stubborn. Dave From niko at alum.mit.edu Fri Dec 9 08:25:00 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Fri, 09 Dec 2011 08:25:00 -0800 Subject: [rust-dev] Strict style checking In-Reply-To: <811209354.40626.1323445478786.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> References: <811209354.40626.1323445478786.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: <4EE2365C.2090601@alum.mit.edu> We already have a pretty printer, maybe we should just make it a bit better and run with it as the "official style"? On 12/9/11 7:44 AM, Dave Herman wrote: >>> - *Compilers* that are obnoxious about dotting every i and crossing >>> every t are a very different thing from *tools* that enforce style. >>> Running a lint tool, or tying a lint tool to a build process, or to a >>> check-in process -- those things all make perfect sense to me. But >>> yelling at me for indentation when I'm trying to hack? >> Do you really write code using arbitrary indentation and other style, >> and then reformat it to the project style when you submit patches? >> I've never noticed anyone doing that. On the contrary, I think I'd >> crank code out faster if I didn't have to keep checking that I'm using >> the correct style for the project I'm working in. > It's just been my experience that over-strict compiler errors get in the way of the development process because I often need to try things out before they're finished. For example, back in the bootstrap compiler days, we had Ocaml configured to fail if there were any dead variables. This was incredibly frustrating and distracting. > > But one alternative we could consider, that would largely have the social effect you're looking for (enforcing a standard style and eliminating annoying style differences between projects) would be a tool like gofmt: > > http://golang.org/cmd/gofmt/ > > This is not part of the go compiler, but by shipping a tool with the language that enforces a particular style, it sends a clear message that this is the language's official style. And by making the tool useful, it provides a carrot to use that style. But it doesn't have the danger of interrupting the edit-compile-run workflow by nagging the user about syntactic nits. > > I believe they've also used it as a refactoring tool to help programmers migrate their code when the language changes, which is a useful trick, too. > > You could worry that some projects would still adopt their own style, but a) there are practical benefits to using the official language style, and b) we could still set cultural norms about using the official language style. In practice, I think there would be so much more uniformity of style that it would probably make non-conformists look silly and stubborn. > > Dave > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From sebastian.sylvan at gmail.com Fri Dec 9 08:48:09 2011 From: sebastian.sylvan at gmail.com (Sebastian Sylvan) Date: Fri, 9 Dec 2011 08:48:09 -0800 Subject: [rust-dev] Rust experience report Message-ID: Greetings, Over the thanksgiving break I took some time to write an application of medium complexity in Rust in order to get a better understanding of how the language works in practice (up to this point I had never even installed the compiler, and was merely an interested spectator of the language's progress). So I wrote a ray tracer, capable of loading up a restricted set of .obj model (only triangles, no normals, colours or textures), and then ray tracing it using a kd-tree for performance. Here's a picture of a cow, as an example of the output http://i.imgur.com/80E2F.png (this image took about 6 seconds to render, on a single thread on my core i7 2600.. although I wouldn't read too much into perf. numbers for now) I've attached the code. It's a mixture of quick-n-dirty hacks, and some attempts at trying out various kinds of modularity. Hardly a paragon of code quality, but I really don't have time to clean it up. (the cow model referred to in the source code was downloaded from here http://groups.csail.mit.edu/graphics/classes/6.837/F03/models/). I figure I'd write up a quick experience report. The point of this is for me to point out the rough edges I experienced in the hopes that they would be considered for future revisions, so it will necessarily be somewhat negative in tone. This is simply because positive feedback is less actionable, and not because my overall impression is negative. And I'm sure you're well aware of positive aspects already (it would've been part of your design rationale, in most cases). I mention this in advance in hopes that you won't take the following as any kind of sweeping criticism, but merely the few things I felt were getting in my way. Also, I'm not 100% sure of all of these points. Quite a few of them might just simply be me not being able to figure out how to do what I wanted. I was hoping to go back and look into each of them in some detail to be more certain that there's actually an issue with all of these things, but it's already been a couple of weeks and I simply haven't found the time, so I figured I'd write up my concerns such as they are, and if some of them aren't valid then you can just ignore them. Without further ado, here's the summary of things I ran into: 1. Purity, or lack thereof. Firstly, I found the "pure" keyword went mostly unused. I tried using it initially, but very quickly ran into places where I couldn't (e.g. the sqrt function isn't pure, so now my vector length function can't be either). So after an initial attempt at always defaulting to "pure" I basically gave up and used it nowhere. That's a shame. Also, I can't use the pure keyword for functions with local mutable state. For a language with such imperative feel as Rust, it seems that disallowing even local mutation would make most functions impure, even though they're not actually impure in any real sense. Something like the ST monad in Haskell (which allows you local mutable state, so long as it doesn't leak), but less in-your-face would be nice. In other words, I'd like not only local mutable stack variables, but also local heap allocations/modifications, so long as none of that memory "leaks out" outside the function. Second, I'd caution about making purity the exception, rather than the default. Having the ability to specify that you expect a function to be pure is great (e.g. for parallelism, or laziness), and it's likely that this will enforce quite alot of cascading purity throughout your program. However, I worry that this will happen "after the fact", in other words that you will ocassionally have critical moments in your code when some library call requires purity and you have to go back and modify hundreds of functions because of the cascading ramifications of making a single function pure. It would be better if everything was pure by default (assuming that local modifications are allowed, as mentioned above), with the very few truly impure functions around being explicitly tagged as such. This is somewhat fuzzy, but I got the same kind of uneasiness I get in C where I'm not quite sure that something is pure or not because the compiler won't enforce it (in Rust's case because I didn't add the pure keyword, for reasons stated above). It doesn't feel quite as safe, because calling a function may or may not have subtle hidden effects, and you can't really rely on the "pure" keyword to make this distinction, because even things that actually are pure are likely to have missed adding the flag (see "const" in C++), so you'll still find yourself wondering "is this actually pure where the author forgot to mark it as such, or is it impure?". In general, when asking about what the default behaviour should be, I feel like there are two criteria to consider: a) Which is the most common case b) Which case will cause mistakes to show up faster If purity worked with local mutable state, I feel that pure-by-default would win both of these (most of my functions were certainly pure, and using impurities in a pure function would cause an immediate compiler error, whereas you could go months forgetting to tag functions with "pure" without the compiler giving any indication that you're at risk of a major "purity-cascade" if a future revision needs one of the toplevel functions to be pure). 2. Mutable locals I found it annoying that local slots were mutable by default, for a few reasons. Firstly, it's inconsistent. Rust documentation states that things are immutable by default, but that doesn't actually apply to local variables. So it's inconsistent w.r.t. parameters, as well as w.r.t. record/obj fields. Second, because mutable locals incur a fairly high tax on readability, IME. This is again due to the fact that you can't really rely on immutable locals to be marked up as such (side note: I don't even know how to do this, is it possible?). Again, witness const in C++; nobody I know bothers tagging local variables as const. The result is that when reading a new function, you have to spend considerable effort scanning through the code to find all the places each variable is modified (even though most of them never are), in order to understand the data flow. By the criteria above for choosing a default, immutable-by-default wins both criteria for my code. Over 90% of my local variables were actually immutable (though none were tagged as such). And mistakenly forgetting to tag something as mutable would give an immediate compiler error, whereas forgetting to tag something as immutable would go unnoticed until someone in the far future gets annoyed by unclear data flow and adds the right annotations in bulk (which I do on occasion in C++, but is a rare occurence!). 3. Ownership of unique-ptr I find that it's quite common to want to say "this is a pointer to a heap box that is both uniquely owned, and will never change owner". E.g. where you really want something conceptually close to just storing the value "in-line", but need to put it on the heap because you're referring to yourself recursively (e.g. a tree). Unique pointers give you a way to say that there's only one owner at a given time, but I'm not sure if there's a way to make sure ownership is non-transferable. In fact, this should probably be the default (i.e. only mutable unique pointers can lose ownership of their memory). Also, I had a few instance where I wanted to work with unique pointers in a bit more flexible way than just passing them to a function, but I didn't want to copy or take ownership of them. E.g. in kd-tree tracing you want to traverse the two sub-spaces in different orders depending on which is closest to the ray origin, the rest of the code is the same so it's nice to say something like: let (near,far) = origin < splitter ? (node.left_tree, node.right_tree) : (node.right_tree, node.left_tree); And have near and far simply be immutable references to the two sub-trees. Unfortunately this causes a copy of the unique pointers (resulting in an order-of-magnitude perf. hit for this application). There may be some way using explicit types to do what I want here, but really it seems like copying shouldn't be the default. Perhaps if locals were immutable (see point 2), they could also be immutable references by default if the value you assign to it is immutable. I ended up switching to shared pointers, even though I really would've preferred to specify unique ownership of the sub-trees in the kd-tree data structure. 4. I got tripped up by the mandatory literal postfixes about a million times. This may be just a habit thing. 5. Linear algebra looks really clunky without operator overloading. I mean, look at this: add(scale(n, dot(view_vec, n)*2f), view_vec) 6. I seriously couldn't figure out how to use the pow function. No amount of importing/using seemed to bring it into scope. :-/ Overall, I found Rust to be quite enjoyable to work with, even though I'm used to a higher level of tooling support (oh how I miss intellisense). Look forward to seeing where it goes in the future! Regards, -- Sebastian Sylvan -------------- next part -------------- A non-text attachment was scrubbed... Name: main.rs Type: application/octet-stream Size: 1029 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: math3d.rs Type: application/octet-stream Size: 2255 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: model.rs Type: application/octet-stream Size: 5297 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: raytracer.rc Type: application/octet-stream Size: 59 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: raytracer.rs Type: application/octet-stream Size: 8097 bytes Desc: not available URL: From niko at alum.mit.edu Fri Dec 9 09:27:43 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Fri, 09 Dec 2011 09:27:43 -0800 Subject: [rust-dev] Rust experience report In-Reply-To: References: Message-ID: <4EE2450F.8040501@alum.mit.edu> Hi, Thanks for the experience report. This kind of feedback is *really helpful*. > 1. Purity, or lack thereof. The idea of purity by default is interesting. I am not sure whether it makes sense or not, I guess that depends on experience. I have some ideas around allowing local mutable state; it will require some type system extensions to make it work well. This is very important for parallelism as well (as you pointed out). > 2. Mutable locals I tend to agree that locals should be immutable by default. There is this proposal: https://github.com/graydon/rust/issues/1273 > 3. Ownership of unique-ptr > I find that it's quite common to want to say "this is a pointer to a > heap box that is both uniquely owned, and will never change owner". I think you can achieve this with an immutable field of unique type. > Also, I had a few instance where I wanted to work with unique pointers > in a bit more flexible way than just passing them to a function, but > I didn't want to copy or take ownership of them. E.g. in kd-tree > tracing you want to traverse the two sub-spaces in different orders > depending on which is closest to the ray origin, the rest of the code > is the same so it's nice to say something like: > > let (near,far) = origin< splitter ? (node.left_tree, node.right_tree) > : (node.right_tree, node.left_tree); You can do this with references. Something like: if origin < splitter { process(*node.left_tree, *node.right_tree); } else { process(*node.right_tree, *node.left_tree); } where |process| is defined |fn process(&&fst: tree, &&snd: tree) { ... }| (actually the |&&| are the default for non-trivial types). It would also be possible to permit such borrowing using |let|; the effect would be that |node.left_tree| and |node.right_tree| are not accessible for the remainder of the scope. > 4. I got tripped up by the mandatory literal postfixes about a million > times. This may be just a habit thing. I find I can remember signed vs unsigned but I always forget i32 or u32 etc. I've been thinking about suggesting something like what D does, where the type of "x & 0xFF" would be u8, "x >> 16" would be u16, and u8 can be promoted to u32 and so forth (it only works with literals). It's neat. On the other hand, I *really* appreciate knowing explicitly what is happening, unlike in C and Java where things are implicitly promoted and so forth. I particularly like keeping a strong division between signed and unsigned. > 5. Linear algebra looks really clunky without operator overloading. I > mean, look at this: > add(scale(n, dot(view_vec, n)*2f), view_vec) I think there is general agreement on supporting operator overloading for a limited set of operators, including the arithmetic operators, [] and so forth. > 6. I seriously couldn't figure out how to use the pow function. No > amount of importing/using seemed to bring it into scope. :-/ Not sure what's going on here! > Overall, I found Rust to be quite enjoyable to work with, even though > I'm used to a higher level of tooling support (oh how I miss > intellisense). Look forward to seeing where it goes in the future! Great to hear! Niko From dherman at mozilla.com Fri Dec 9 10:42:29 2011 From: dherman at mozilla.com (Dave Herman) Date: Fri, 9 Dec 2011 10:42:29 -0800 (PST) Subject: [rust-dev] Rust experience report In-Reply-To: Message-ID: <1452835231.45385.1323456149517.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Hi Sebastian, I'm sure we'll all discuss the points in greater detail but I just wanted to take a moment and thank you for taking the time to do this, and for your thoughtful attention to the user experience of writing real code. Experience/usability reports are incredibly valuable. Thanks!! Cheers, Dave ----- Original Message ----- From: "Sebastian Sylvan" To: rust-dev at mozilla.org Sent: Friday, December 9, 2011 8:48:09 AM Subject: [rust-dev] Rust experience report Greetings, Over the thanksgiving break I took some time to write an application of medium complexity in Rust in order to get a better understanding of how the language works in practice (up to this point I had never even installed the compiler, and was merely an interested spectator of the language's progress). So I wrote a ray tracer, capable of loading up a restricted set of .obj model (only triangles, no normals, colours or textures), and then ray tracing it using a kd-tree for performance. Here's a picture of a cow, as an example of the output http://i.imgur.com/80E2F.png (this image took about 6 seconds to render, on a single thread on my core i7 2600.. although I wouldn't read too much into perf. numbers for now) I've attached the code. It's a mixture of quick-n-dirty hacks, and some attempts at trying out various kinds of modularity. Hardly a paragon of code quality, but I really don't have time to clean it up. (the cow model referred to in the source code was downloaded from here http://groups.csail.mit.edu/graphics/classes/6.837/F03/models/). I figure I'd write up a quick experience report. The point of this is for me to point out the rough edges I experienced in the hopes that they would be considered for future revisions, so it will necessarily be somewhat negative in tone. This is simply because positive feedback is less actionable, and not because my overall impression is negative. And I'm sure you're well aware of positive aspects already (it would've been part of your design rationale, in most cases). I mention this in advance in hopes that you won't take the following as any kind of sweeping criticism, but merely the few things I felt were getting in my way. Also, I'm not 100% sure of all of these points. Quite a few of them might just simply be me not being able to figure out how to do what I wanted. I was hoping to go back and look into each of them in some detail to be more certain that there's actually an issue with all of these things, but it's already been a couple of weeks and I simply haven't found the time, so I figured I'd write up my concerns such as they are, and if some of them aren't valid then you can just ignore them. Without further ado, here's the summary of things I ran into: 1. Purity, or lack thereof. Firstly, I found the "pure" keyword went mostly unused. I tried using it initially, but very quickly ran into places where I couldn't (e.g. the sqrt function isn't pure, so now my vector length function can't be either). So after an initial attempt at always defaulting to "pure" I basically gave up and used it nowhere. That's a shame. Also, I can't use the pure keyword for functions with local mutable state. For a language with such imperative feel as Rust, it seems that disallowing even local mutation would make most functions impure, even though they're not actually impure in any real sense. Something like the ST monad in Haskell (which allows you local mutable state, so long as it doesn't leak), but less in-your-face would be nice. In other words, I'd like not only local mutable stack variables, but also local heap allocations/modifications, so long as none of that memory "leaks out" outside the function. Second, I'd caution about making purity the exception, rather than the default. Having the ability to specify that you expect a function to be pure is great (e.g. for parallelism, or laziness), and it's likely that this will enforce quite alot of cascading purity throughout your program. However, I worry that this will happen "after the fact", in other words that you will ocassionally have critical moments in your code when some library call requires purity and you have to go back and modify hundreds of functions because of the cascading ramifications of making a single function pure. It would be better if everything was pure by default (assuming that local modifications are allowed, as mentioned above), with the very few truly impure functions around being explicitly tagged as such. This is somewhat fuzzy, but I got the same kind of uneasiness I get in C where I'm not quite sure that something is pure or not because the compiler won't enforce it (in Rust's case because I didn't add the pure keyword, for reasons stated above). It doesn't feel quite as safe, because calling a function may or may not have subtle hidden effects, and you can't really rely on the "pure" keyword to make this distinction, because even things that actually are pure are likely to have missed adding the flag (see "const" in C++), so you'll still find yourself wondering "is this actually pure where the author forgot to mark it as such, or is it impure?". In general, when asking about what the default behaviour should be, I feel like there are two criteria to consider: a) Which is the most common case b) Which case will cause mistakes to show up faster If purity worked with local mutable state, I feel that pure-by-default would win both of these (most of my functions were certainly pure, and using impurities in a pure function would cause an immediate compiler error, whereas you could go months forgetting to tag functions with "pure" without the compiler giving any indication that you're at risk of a major "purity-cascade" if a future revision needs one of the toplevel functions to be pure). 2. Mutable locals I found it annoying that local slots were mutable by default, for a few reasons. Firstly, it's inconsistent. Rust documentation states that things are immutable by default, but that doesn't actually apply to local variables. So it's inconsistent w.r.t. parameters, as well as w.r.t. record/obj fields. Second, because mutable locals incur a fairly high tax on readability, IME. This is again due to the fact that you can't really rely on immutable locals to be marked up as such (side note: I don't even know how to do this, is it possible?). Again, witness const in C++; nobody I know bothers tagging local variables as const. The result is that when reading a new function, you have to spend considerable effort scanning through the code to find all the places each variable is modified (even though most of them never are), in order to understand the data flow. By the criteria above for choosing a default, immutable-by-default wins both criteria for my code. Over 90% of my local variables were actually immutable (though none were tagged as such). And mistakenly forgetting to tag something as mutable would give an immediate compiler error, whereas forgetting to tag something as immutable would go unnoticed until someone in the far future gets annoyed by unclear data flow and adds the right annotations in bulk (which I do on occasion in C++, but is a rare occurence!). 3. Ownership of unique-ptr I find that it's quite common to want to say "this is a pointer to a heap box that is both uniquely owned, and will never change owner". E.g. where you really want something conceptually close to just storing the value "in-line", but need to put it on the heap because you're referring to yourself recursively (e.g. a tree). Unique pointers give you a way to say that there's only one owner at a given time, but I'm not sure if there's a way to make sure ownership is non-transferable. In fact, this should probably be the default (i.e. only mutable unique pointers can lose ownership of their memory). Also, I had a few instance where I wanted to work with unique pointers in a bit more flexible way than just passing them to a function, but I didn't want to copy or take ownership of them. E.g. in kd-tree tracing you want to traverse the two sub-spaces in different orders depending on which is closest to the ray origin, the rest of the code is the same so it's nice to say something like: let (near,far) = origin < splitter ? (node.left_tree, node.right_tree) : (node.right_tree, node.left_tree); And have near and far simply be immutable references to the two sub-trees. Unfortunately this causes a copy of the unique pointers (resulting in an order-of-magnitude perf. hit for this application). There may be some way using explicit types to do what I want here, but really it seems like copying shouldn't be the default. Perhaps if locals were immutable (see point 2), they could also be immutable references by default if the value you assign to it is immutable. I ended up switching to shared pointers, even though I really would've preferred to specify unique ownership of the sub-trees in the kd-tree data structure. 4. I got tripped up by the mandatory literal postfixes about a million times. This may be just a habit thing. 5. Linear algebra looks really clunky without operator overloading. I mean, look at this: add(scale(n, dot(view_vec, n)*2f), view_vec) 6. I seriously couldn't figure out how to use the pow function. No amount of importing/using seemed to bring it into scope. :-/ Overall, I found Rust to be quite enjoyable to work with, even though I'm used to a higher level of tooling support (oh how I miss intellisense). Look forward to seeing where it goes in the future! Regards, -- Sebastian Sylvan _______________________________________________ Rust-dev mailing list Rust-dev at mozilla.org https://mail.mozilla.org/listinfo/rust-dev From banderson at mozilla.com Fri Dec 9 11:27:44 2011 From: banderson at mozilla.com (Brian Anderson) Date: Fri, 9 Dec 2011 11:27:44 -0800 (PST) Subject: [rust-dev] Emacs rust-mode updated In-Reply-To: Message-ID: <691114780.46935.1323458864876.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Thank you! So glad to have nicely-formatted blocks. ----- Original Message ----- From: "Marijn Haverbeke" To: rust-dev at mozilla.org Sent: Friday, December 9, 2011 4:25:37 AM Subject: [rust-dev] Emacs rust-mode updated It now handles blocks better, and should no longer get confused about objects so easily. Get it from https://github.com/marijnh/rust-mode (Don't forget to byte-compile it!) _______________________________________________ Rust-dev mailing list Rust-dev at mozilla.org https://mail.mozilla.org/listinfo/rust-dev From banderson at mozilla.com Fri Dec 9 13:37:23 2011 From: banderson at mozilla.com (Brian Anderson) Date: Fri, 9 Dec 2011 13:37:23 -0800 (PST) Subject: [rust-dev] Rust experience report In-Reply-To: Message-ID: <1004294274.51859.1323466643652.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> This is fantastic. Thank you. I rendered a teapot: http://imgur.com/C0kd4 And I saved a copy of your code here: https://github.com/brson/rustray ----- Original Message ----- > From: "Sebastian Sylvan" > To: rust-dev at mozilla.org > Sent: Friday, December 9, 2011 8:48:09 AM > Subject: [rust-dev] Rust experience report > Greetings, > Over the thanksgiving break I took some time to write an application > of medium complexity in Rust in order to get a better understanding of > how the language works in practice (up to this point I had never even > installed the compiler, and was merely an interested spectator of the > language's progress). > > Without further ado, here's the summary of things I ran into: > > 1. Purity, or lack thereof. > Firstly, I found the "pure" keyword went mostly unused. I tried using > it initially, but very quickly ran into places where I couldn't (e.g. > the sqrt function isn't pure, so now my vector length function can't > be either). So after an initial attempt at always defaulting to "pure" > I basically gave up and used it nowhere. That's a shame. Pure functions currently exist to support typestate (as predicates), which is not much loved right now. It's interesting that this is your number one criticism. I wonder how hard it would be to make purity more pervasive. > > Second, I'd caution about making purity the exception, rather than the > default. Purity by default is attractive. I don't know what's involved to make it happen. It would be an interesting project to go through the rust code base and see how much can be made pure. > > In general, when asking about what the default behaviour should be, I > feel like there are two criteria to consider: > a) Which is the most common case > b) Which case will cause mistakes to show up faster > > If purity worked with local mutable state, I feel that pure-by-default > would win both of these (most of my functions were certainly pure, and > using impurities in a pure function would cause an immediate compiler > error, whereas you could go months forgetting to tag functions with > "pure" without the compiler giving any indication that you're at risk > of a major "purity-cascade" if a future revision needs one of the > toplevel functions to be pure). > > 2. Mutable locals > I found it annoying that local slots were mutable by default, for a > few reasons. Firstly, it's inconsistent. Rust documentation states > that things are immutable by default, but that doesn't actually apply > to local variables. So it's inconsistent w.r.t. parameters, as well as > w.r.t. record/obj fields. Second, because mutable locals incur a > fairly high tax on readability, IME. This is again due to the fact > that you can't really rely on immutable locals to be marked up as such > (side note: I don't even know how to do this, is it possible?). Again, > witness const in C++; nobody I know bothers tagging local variables as > const. The result is that when reading a new function, you have to > spend considerable effort scanning through the code to find all the > places each variable is modified (even though most of them never are), > in order to understand the data flow. > > By the criteria above for choosing a default, immutable-by-default > wins both criteria for my code. Over 90% of my local variables were > actually immutable (though none were tagged as such). And mistakenly > forgetting to tag something as mutable would give an immediate > compiler error, whereas forgetting to tag something as immutable would > go unnoticed until someone in the far future gets annoyed by unclear > data flow and adds the right annotations in bulk (which I do on > occasion in C++, but is a rare occurence!). > > 3. Ownership of unique-ptr > I find that it's quite common to want to say "this is a pointer to a > heap box that is both uniquely owned, and will never change owner". > E.g. where you really want something conceptually close to just > storing the value "in-line", but need to put it on the heap because > you're referring to yourself recursively (e.g. a tree). Unique > pointers give you a way to say that there's only one owner at a given > time, but I'm not sure if there's a way to make sure ownership is > non-transferable. In fact, this should probably be the default (i.e. > only mutable unique pointers can lose ownership of their memory). Immutable locals would make this possible. > > Also, I had a few instance where I wanted to work with unique pointers > in a bit more flexible way than just passing them to a function, but > I didn't want to copy or take ownership of them. E.g. in kd-tree > tracing you want to traverse the two sub-spaces in different orders > depending on which is closest to the ray origin, the rest of the code > is the same so it's nice to say something like: > > let (near,far) = origin < splitter ? (node.left_tree, node.right_tree) > : (node.right_tree, node.left_tree); > > And have near and far simply be immutable references to the two > sub-trees. Unfortunately this causes a copy of the unique pointers > (resulting in an order-of-magnitude perf. hit for this application). > There may be some way using explicit types to do what I want here, but > really it seems like copying shouldn't be the default. Copying by default is becoming a problem in lots of ways, and there's a strong desire by everybody to make copying of expensive things explicit in the next round of design. Unique pointers are basically impossible to use correctly right now because they are so easy to deep copy. > > 4. I got tripped up by the mandatory literal postfixes about a million > times. This may be just a habit thing. Yep. This happens to everybody and it's frustrating. I'm scared of making the language more liberal here though because it's such a potential source of errors. Maybe there's a middle-ground. > > 5. Linear algebra looks really clunky without operator overloading. I > mean, look at this: > add(scale(n, dot(view_vec, n)*2f), view_vec) > Agreed. Rust may get some form of overloading. > 6. I seriously couldn't figure out how to use the pow function. No > amount of importing/using seemed to bring it into scope. :-/ > > > Overall, I found Rust to be quite enjoyable to work with, even though > I'm used to a higher level of tooling support (oh how I miss > intellisense). Look forward to seeing where it goes in the future! > > > Regards, > > -- > Sebastian Sylvan > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From brendan at mozilla.org Fri Dec 9 15:11:16 2011 From: brendan at mozilla.org (Brendan Eich) Date: Fri, 9 Dec 2011 15:11:16 -0800 Subject: [rust-dev] Strict style checking In-Reply-To: <4EE2365C.2090601@alum.mit.edu> References: <811209354.40626.1323445478786.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> <4EE2365C.2090601@alum.mit.edu> Message-ID: <504EC990-8FDC-4627-8569-0C871C853DF3@mozilla.org> Graydon wrote (private correspondence with roc and me in late 2009): "I'm sympathetic to the second point [roc argued for style enforcement especially to ease (semi-)automatic refactoring]. Go has gofmt and elective use of it before checkin. Refactoring is still too hard even with our impressive pork-based patch generation tools. As am I. I initially baked this sort of requirement into Rust but thought it would sound too pedantic so dropped it at first. Happy to revive. There are a few peculiarities of course: - Formatting trivial differences. 0xff should pretty-print back as 0xff not 15. Likewise 0xffff_ffff should not decay to 0xffffffff nor should "hel\u006c\u006co" decay to "hello". - Preservation or elision of comments. Comment <-> documentation relationship, and/or comment <-> unit test (cf. python doctests) I have no clear ideas here. At the moment Rust fe strips whitespace and comments but I'm not at all wedded to that. - Preservation of staged compilation. Rust's design has a (conservative) syntax-extension system, a bit like lisp readtables or camlp4 extensions, so these change the source text. Preserving text in a compiled artifact entails preserving multiple texts if some of them are staged output. The easiest approach I could come up with that would be practical would be (a) a gofmt-like formatting-enforcer mode on the frontend and (b) an option to simply embed a gzipped text-of-the-program in the binary output with the dwarf info pointing into it rather than into external files. Would be a small dwarf enhancement to teach gdb to use this. *shrug* or just use a symbol-server approach. -Graydon" Things have progressed since then but this still seemed fresh and I thought worth sharing -- hope it's ok to cite, wasn't really meant to be narrowcast back in the day (my fault probably). /be On Dec 9, 2011, at 8:25 AM, Niko Matsakis wrote: > We already have a pretty printer, maybe we should just make it a bit better and run with it as the "official style"? > > On 12/9/11 7:44 AM, Dave Herman wrote: >>>> - *Compilers* that are obnoxious about dotting every i and crossing >>>> every t are a very different thing from *tools* that enforce style. >>>> Running a lint tool, or tying a lint tool to a build process, or to a >>>> check-in process -- those things all make perfect sense to me. But >>>> yelling at me for indentation when I'm trying to hack? >>> Do you really write code using arbitrary indentation and other style, >>> and then reformat it to the project style when you submit patches? >>> I've never noticed anyone doing that. On the contrary, I think I'd >>> crank code out faster if I didn't have to keep checking that I'm using >>> the correct style for the project I'm working in. >> It's just been my experience that over-strict compiler errors get in the way of the development process because I often need to try things out before they're finished. For example, back in the bootstrap compiler days, we had Ocaml configured to fail if there were any dead variables. This was incredibly frustrating and distracting. >> >> But one alternative we could consider, that would largely have the social effect you're looking for (enforcing a standard style and eliminating annoying style differences between projects) would be a tool like gofmt: >> >> http://golang.org/cmd/gofmt/ >> >> This is not part of the go compiler, but by shipping a tool with the language that enforces a particular style, it sends a clear message that this is the language's official style. And by making the tool useful, it provides a carrot to use that style. But it doesn't have the danger of interrupting the edit-compile-run workflow by nagging the user about syntactic nits. >> >> I believe they've also used it as a refactoring tool to help programmers migrate their code when the language changes, which is a useful trick, too. >> >> You could worry that some projects would still adopt their own style, but a) there are practical benefits to using the official language style, and b) we could still set cultural norms about using the official language style. In practice, I think there would be so much more uniformity of style that it would probably make non-conformists look silly and stubborn. >> >> Dave >> _______________________________________________ >> 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 graydon at mozilla.com Fri Dec 9 16:00:05 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 9 Dec 2011 16:00:05 -0800 (PST) Subject: [rust-dev] Strict style checking In-Reply-To: <504EC990-8FDC-4627-8569-0C871C853DF3@mozilla.org> Message-ID: <357218012.55910.1323475205651.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> > Things have progressed since then but this still seemed fresh and I > thought worth sharing -- hope it's ok to cite, wasn't really meant to > be narrowcast back in the day (my fault probably). It's fine, but thankfully we have fixed all the above points in the fe and pp layers -- we preserve literals and comments verbatim through pretty printing -- aside from a few corner cases where comments get extra spaces stuck in around them. The current source code has been pretty-printed multiple times and we have a small (but ever-expandable) portion of the testsuite dedicated to testing pretty printing round trips. For "enforcement" I'm still in favour of telling users they can easily pretty print, but accepting ugly-format stuff during parsing. For the following reasons: - The pp algorithm is complex enough that we can't tell, during parsing, exactly where a wrap would occur. We'd have to pp each source unit in-memory after parsing and do a memcmp to see if you and the pp agree. This would slow things down a fair bit. - The pp algorithm isn't the world's most stable thing anyways. It was chosen from a lot of existing ones based on producing average-good looks in most cases, but it's an ancient and imperative algorithm and I don't really want to be breaking users any time we tweak it. - Wrap-width is something I expect people will always disagree over, depending on the sizes of their terminals and monitors, and I think forcing it will just make users angry. -Graydon From graydon at mozilla.com Fri Dec 9 16:01:49 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 9 Dec 2011 16:01:49 -0800 (PST) Subject: [rust-dev] Emacs rust-mode updated In-Reply-To: <691114780.46935.1323458864876.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: <813462285.55950.1323475309014.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Is there a reason marijn's emacs mode isn't in-tree at this point? I realize it was experimental long ago, but by now it's the only reasonable mode we have. -Graydon From graydon at mozilla.com Fri Dec 9 16:07:51 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 9 Dec 2011 16:07:51 -0800 (PST) Subject: [rust-dev] Strict style checking In-Reply-To: <357218012.55910.1323475205651.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: <33108931.56048.1323475671790.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> > For "enforcement" I'm still in favour of telling users they can easily > pretty print, but accepting ugly-format stuff during parsing. For the > following reasons: As a slight expansion of this point: the pp has been left in the position of "printing to stdout". I think a command-line flag that does an in-memory pp, and rewrites the input file in-place if there was any change, will make it that much more likely to come into common use. We currently do this with a makefile rule that's *slightly* unintuitive. Filed this as bug https://github.com/graydon/rust/issues/1282 -Graydon From graydon at mozilla.com Fri Dec 9 16:13:38 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 9 Dec 2011 16:13:38 -0800 (PST) Subject: [rust-dev] Rust experience report In-Reply-To: Message-ID: <1198583935.56197.1323476018667.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> > Over the thanksgiving break I took some time to write an application > of medium complexity in Rust in order to get a better understanding of > how the language works in practice (up to this point I had never even > installed the compiler, and was merely an interested spectator of the > language's progress). This is great feedback! Thanks! Some are already-open issues, some are known design sore-spots we have longer-term things in progress to address. We'll try to address as many as possible. Thanks again. -Graydon From banderson at mozilla.com Sun Dec 11 22:57:10 2011 From: banderson at mozilla.com (Brian Anderson) Date: Sun, 11 Dec 2011 22:57:10 -0800 (PST) Subject: [rust-dev] Upgrading LLVM to segmented stacks branch Message-ID: <592083389.77854.1323673030097.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> I've upgraded our LLVM submodule to point to a temporary branch[1] containing some patches to enable stack growth. As before, this should not require any special action on your part. This fork should be short-lived. I expect to start upstreaming our LLVM patches next week. [1] https://github.com/brson/llvm/tree/rust From graham.fawcett at gmail.com Tue Dec 13 12:38:38 2011 From: graham.fawcett at gmail.com (Graham Fawcett) Date: Tue, 13 Dec 2011 15:38:38 -0500 Subject: [rust-dev] Emacs flymake-mode Message-ID: Hi folks, I'd like to share a snippet of Elisp, which activates Emacs' flymake-mode whenever rust-mode is activated. Flymake is a minor mode for background-compiling the current source file, and highlighting errors in the buffer, with a pop-up (invoked by C-c C-d, in this case) to show the error message. It works well enough for small toy programs (the kind of stuff I'm doing). It might need some adjustments for crates, or larger-scale applications (for example, it just calls "rustc --no-trans" on the current buffer, it doesn't hunt for Makefiles etc.). If anyone has a better flymake configuration, I'd love to have it! Cheers, Graham ;; flymake-rust.el (require 'flymake) (require 'rust-mode) (defun flymake-rust-init () (let* ((temp-file (flymake-init-create-temp-buffer-copy 'flymake-create-temp-inplace)) (local-file (file-relative-name temp-file (file-name-directory buffer-file-name)))) (list "/usr/local/bin/rustc" (list "--no-trans" local-file)))) (add-to-list 'flymake-allowed-file-name-masks '(".+\\.r[cs]$" flymake-rust-init flymake-simple-cleanup flymake-get-real-file-name)) (defun flymake-rust-load () (flymake-mode t) ;; change these bindings as you see fit (local-set-key (kbd "C-c C-d") 'flymake-display-err-menu-for-current-line) (local-set-key (kbd "C-c C-n") 'flymake-goto-next-error) (local-set-key (kbd "C-c C-p") 'flymake-goto-prev-error)) (add-hook 'rust-mode-hook 'flymake-rust-load) (provide 'flymake-rust) From niko at alum.mit.edu Wed Dec 14 14:02:09 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 14 Dec 2011 14:02:09 -0800 Subject: [rust-dev] using issues to track proposals Message-ID: <4EE91CE1.5030809@alum.mit.edu> We have a number of issues that are kind of "proposals" or "suggestions". Is there a standard tag to use for categorizing such issues? I didn't see one in the list. If not, can I propose "proposal"? Niko From jws at csse.unimelb.edu.au Wed Dec 14 17:49:53 2011 From: jws at csse.unimelb.edu.au (Jeff Schultz) Date: Thu, 15 Dec 2011 12:49:53 +1100 Subject: [rust-dev] Interface / typeclass proposal In-Reply-To: <4ED6D685.70505@mozilla.com> References: <4ED539FA.1050006@alum.mit.edu> <4ED5668C.1030200@mozilla.com> <1425DC23-16B4-4573-852D-E13582FBE994@mozilla.com> <4ED56FF4.5000809@mozilla.com> <4ED5928E.5080903@mozilla.com> <4ED6D685.70505@mozilla.com> Message-ID: <20111215014953.GA23956@mulga.csse.unimelb.edu.au> On Wed, Nov 30, 2011 at 05:21:09PM -0800, Graydon Hoare wrote: > I often mentally differentiate these operators: > + - * / ^ % < <= == => > ! || && [] > From these operators: > . () ~ @ # &(unary) *(unary) > In the sense that the former group are "more ALU-like" and the latter group > are "more load/store/jump-like". Values vs. memory-and-control. > Do you feel (straw-vote) like you'd be sufficiently happy to be able to > override the former group but not the latter? Languages vary on how far > down the rabbit hole of operator overloading they permit, and I wonder > where each proponent of the concept draws the line. The former group is > enough to implement most intuitively-arithmetic-ish types, which seems to > be the big use-case. I agree that the most pressing need is to provide arithmetic operators for user-defined types. I'd want the logical operators too. However, I fear that artificial limitations will simply lead programmers to re-use the operators they are allowed to overload for other semantic operations. E.g. message sending as target <= message, and multi-send as target1 & target2 & ... <= message. (Doesn't even need parentheses!) This can be taken as either a good reason not to allow operator overloading at all, or a good reason to provide user-defined operators to relieve this temptation. > (Also: please say you've no interest in permitting user-defined > operator-symbols with their own associativity and precedence. Right?) I'm used to them in other languages. They can look confusing when they're used to express a genuinely difficult concept, but it's usually the concept that's the problem, not the syntax. My experience is that macros cause more work for the reader than user-defined operators. Jeff Schultz From niko at alum.mit.edu Wed Dec 14 19:00:33 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 14 Dec 2011 19:00:33 -0800 Subject: [rust-dev] runtime libraries and stage1 Message-ID: <4EE962D1.5090206@alum.mit.edu> So, if I am not mistaken, we currently execute the stage1 compiler using the runtime sources that we compile out of the user's directory. As the stage1 binary is built using the snapshot, this doesn't seem quite right: we ought to be executing it using the snapshot runtime. The stage2 and stage3 binaries, then, ought to execute using the runtime from the user's directory. The way things are setup now, if I want to make a change to the runtime, I have to ensure that the rt code will still execute with what is being produced by the snapshot compiler. Under my proposed setup, the runtime would only have to work with the code produced by the stage1 compiler (i.e., with the code produced by the sources in the user's directory, not the code produced by the snapshot). This ought to make migration significantly easier! Does this seem correct to everyone else, or am I missing something? If others agree, I will modify the buildsystem so that stage0/lib/$(TRIPLE)/$(CFG_RUNTIME) (on mac) comes from the snapshot, and stage1/lib/$(TRIPLE)/$(CFG_RUNTIME) comes from rt/$(TRIPLE)/$(CFG_RUNTIME). Niko From banderson at mozilla.com Wed Dec 14 20:07:52 2011 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 14 Dec 2011 20:07:52 -0800 (PST) Subject: [rust-dev] using issues to track proposals In-Reply-To: <4EE91CE1.5030809@alum.mit.edu> Message-ID: <1843700601.47066.1323922072780.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> I'm in favor of this. I have completely lost track of where they all live. ----- Original Message ----- > From: "Niko Matsakis" > To: rust-dev at mozilla.org > Sent: Wednesday, December 14, 2011 2:02:09 PM > Subject: [rust-dev] using issues to track proposals > We have a number of issues that are kind of "proposals" or > "suggestions". Is there a standard tag to use for categorizing such > issues? I didn't see one in the list. If not, can I propose > "proposal"? > > > Niko > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From banderson at mozilla.com Wed Dec 14 20:34:59 2011 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 14 Dec 2011 20:34:59 -0800 (PST) Subject: [rust-dev] runtime libraries and stage1 In-Reply-To: <4EE962D1.5090206@alum.mit.edu> Message-ID: <1829515453.47247.1323923699752.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> ----- Original Message ----- > From: "Niko Matsakis" > To: rust-dev at mozilla.org > Sent: Wednesday, December 14, 2011 7:00:33 PM > Subject: [rust-dev] runtime libraries and stage1 > So, if I am not mistaken, we currently execute the stage1 compiler > using > the runtime sources that we compile out of the user's directory. As > the > stage1 binary is built using the snapshot, this doesn't seem quite > right: we ought to be executing it using the snapshot runtime. The > stage2 and stage3 binaries, then, ought to execute using the runtime > from the user's directory. With Rust having to bootstrap itself there will always be some situations that are difficult to make incompatible changes. The current arrangement is definitely the best we've had so far (in the past things have been occassionally truly frustrating), so I'm ambivalent about this. And I like that the current snapshot only requires the bare minimum of host artifacts, no target artifacts. With this change it will be easy to modify upcalls. On the other hand, any time std or core need to modify a runtime interface it will require creating temporary runtime methods, snapshotting, etc. So maybe we also snapshot core & std for each target. Now you promote the stage0 target snapshots to stage1. At this point we've reproduced the existing stage0 problems, but are calling them stage1. Intrinsics and libmorestack have similar dependencies on the runtime as std and core, though they change rarely. I'm totally fine with trying, but I don't think there's anything we can do that will be definitively 'right'. -Brian From niko at alum.mit.edu Wed Dec 14 20:47:50 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 14 Dec 2011 20:47:50 -0800 Subject: [rust-dev] runtime libraries and stage1 In-Reply-To: <1829515453.47247.1323923699752.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> References: <1829515453.47247.1323923699752.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: <4EE97BF6.10506@alum.mit.edu> Your point about std/core is well taken and basically convinces me that my idea is not good. It would definitely still be nice if there were a way to "quarantine" the original runtime, but perhaps just preserving the old definitions for a time is the best we can do. If nothing else, we could make this a bit more automatic by having the runtime functions "namespaced" with some sort of prefix, like "rust4_" or what have you. Then when we make backwards incompatible changes, we literally copy the entire runtime into a new subdirectory with a new prefix ("rust5_"). We make changes liberally to rust5_ and delete rust4_ once the new snapshot is in place. (In the compiler this prefix would be automatically added, of course) Such a system would also allow us to keep backwards compatibility with binaries generated by older versions of the compiler, once Rust becomes widely used and hugely popular. It's certainly not the smartest way to handle that particular situation, though, as it would also lead to a maintenance nightmare as there would be many versions of the same code in the codebase. That said, we do probably want to start thinking about how we will version the runtime for backwards compatibility, and maybe we can use whatever scheme we come up with to ease the bootstrapping pain as well. Niko On 12/14/11 8:34 PM, Brian Anderson wrote: > > ----- Original Message ----- >> From: "Niko Matsakis" >> To: rust-dev at mozilla.org >> Sent: Wednesday, December 14, 2011 7:00:33 PM >> Subject: [rust-dev] runtime libraries and stage1 >> So, if I am not mistaken, we currently execute the stage1 compiler >> using >> the runtime sources that we compile out of the user's directory. As >> the >> stage1 binary is built using the snapshot, this doesn't seem quite >> right: we ought to be executing it using the snapshot runtime. The >> stage2 and stage3 binaries, then, ought to execute using the runtime >> from the user's directory. > With Rust having to bootstrap itself there will always be some situations that are difficult to make incompatible changes. The current arrangement is definitely the best we've had so far (in the past things have been occassionally truly frustrating), so I'm ambivalent about this. And I like that the current snapshot only requires the bare minimum of host artifacts, no target artifacts. > > With this change it will be easy to modify upcalls. On the other hand, any time std or core need to modify a runtime interface it will require creating temporary runtime methods, snapshotting, etc. So maybe we also snapshot core& std for each target. Now you promote the stage0 target snapshots to stage1. At this point we've reproduced the existing stage0 problems, but are calling them stage1. > > Intrinsics and libmorestack have similar dependencies on the runtime as std and core, though they change rarely. > > I'm totally fine with trying, but I don't think there's anything we can do that will be definitively 'right'. > > -Brian From niko at alum.mit.edu Wed Dec 14 21:08:02 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 14 Dec 2011 21:08:02 -0800 Subject: [rust-dev] runtime libraries and stage1 In-Reply-To: <4EE97BF6.10506@alum.mit.edu> References: <1829515453.47247.1323923699752.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> <4EE97BF6.10506@alum.mit.edu> Message-ID: <4EE980B2.7020309@alum.mit.edu> I just realized that all this work on getting a good naming scheme for Rust libraries will probably address backwards compatibility for the runtime as well...? In other words, we won't need any sort of name mangling scheme because we'll ship multiple libraries and the older code will select the older library (assuming the runtime is not statically compiled in, which it may well be anyhow). Anyway, I'm sure this has been discussed before, and I'm just coming late to the party, so I'll stop writing e-mail and get back to what I was doing... Niko On 12/14/11 8:47 PM, Niko Matsakis wrote: > Your point about std/core is well taken and basically convinces me > that my idea is not good. It would definitely still be nice if there > were a way to "quarantine" the original runtime, but perhaps just > preserving the old definitions for a time is the best we can do. > > If nothing else, we could make this a bit more automatic by having the > runtime functions "namespaced" with some sort of prefix, like "rust4_" > or what have you. Then when we make backwards incompatible changes, > we literally copy the entire runtime into a new subdirectory with a > new prefix ("rust5_"). We make changes liberally to rust5_ and delete > rust4_ once the new snapshot is in place. (In the compiler this > prefix would be automatically added, of course) > > Such a system would also allow us to keep backwards compatibility with > binaries generated by older versions of the compiler, once Rust > becomes widely used and hugely popular. It's certainly not the > smartest way to handle that particular situation, though, as it would > also lead to a maintenance nightmare as there would be many versions > of the same code in the codebase. > > That said, we do probably want to start thinking about how we will > version the runtime for backwards compatibility, and maybe we can use > whatever scheme we come up with to ease the bootstrapping pain as well. > > > Niko > > On 12/14/11 8:34 PM, Brian Anderson wrote: >> >> ----- Original Message ----- >>> From: "Niko Matsakis" >>> To: rust-dev at mozilla.org >>> Sent: Wednesday, December 14, 2011 7:00:33 PM >>> Subject: [rust-dev] runtime libraries and stage1 >>> So, if I am not mistaken, we currently execute the stage1 compiler >>> using >>> the runtime sources that we compile out of the user's directory. As >>> the >>> stage1 binary is built using the snapshot, this doesn't seem quite >>> right: we ought to be executing it using the snapshot runtime. The >>> stage2 and stage3 binaries, then, ought to execute using the runtime >>> from the user's directory. >> With Rust having to bootstrap itself there will always be some >> situations that are difficult to make incompatible changes. The >> current arrangement is definitely the best we've had so far (in the >> past things have been occassionally truly frustrating), so I'm >> ambivalent about this. And I like that the current snapshot only >> requires the bare minimum of host artifacts, no target artifacts. >> >> With this change it will be easy to modify upcalls. On the other >> hand, any time std or core need to modify a runtime interface it will >> require creating temporary runtime methods, snapshotting, etc. So >> maybe we also snapshot core& std for each target. Now you promote >> the stage0 target snapshots to stage1. At this point we've reproduced >> the existing stage0 problems, but are calling them stage1. >> >> Intrinsics and libmorestack have similar dependencies on the runtime >> as std and core, though they change rarely. >> >> I'm totally fine with trying, but I don't think there's anything we >> can do that will be definitively 'right'. >> >> -Brian > From banderson at mozilla.com Wed Dec 14 21:27:23 2011 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 14 Dec 2011 21:27:23 -0800 (PST) Subject: [rust-dev] runtime libraries and stage1 In-Reply-To: <4EE980B2.7020309@alum.mit.edu> Message-ID: <968546428.47802.1323926843237.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> ----- Original Message ----- > From: "Niko Matsakis" > To: "Brian Anderson" > Cc: rust-dev at mozilla.org > Sent: Wednesday, December 14, 2011 9:08:02 PM > Subject: Re: [rust-dev] runtime libraries and stage1 > I just realized that all this work on getting a good naming scheme for > Rust libraries will probably address backwards compatibility for the > runtime as well...? In other words, we won't need any sort of name > mangling scheme because we'll ship multiple libraries and the older > code > will select the older library (assuming the runtime is not statically > compiled in, which it may well be anyhow). Anyway, I'm sure this has > been discussed before, and I'm just coming late to the party, so I'll > stop writing e-mail and get back to what I was doing... I don't recall any discussion of how to version the runtime itself, except that we do have some notion of an ABI version. From banderson at mozilla.com Wed Dec 14 21:37:01 2011 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 14 Dec 2011 21:37:01 -0800 (PST) Subject: [rust-dev] runtime libraries and stage1 In-Reply-To: <4EE97BF6.10506@alum.mit.edu> Message-ID: <1367420000.47870.1323927421352.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> ----- Original Message ----- > From: "Niko Matsakis" > To: "Brian Anderson" > Cc: rust-dev at mozilla.org > Sent: Wednesday, December 14, 2011 8:47:50 PM > Subject: Re: [rust-dev] runtime libraries and stage1 > Your point about std/core is well taken and basically convinces me > that > my idea is not good. It would definitely still be nice if there were a > way to "quarantine" the original runtime, but perhaps just preserving > the old definitions for a time is the best we can do. Something you said on IRC made me realize that the absolute hardest changes to make are to structures shared by the compiler and the runtime - so much so that we often just leave unused fields. That situation would be improved by your proposal. > > If nothing else, we could make this a bit more automatic by having the > runtime functions "namespaced" with some sort of prefix, like "rust4_" > or what have you. Then when we make backwards incompatible changes, we > literally copy the entire runtime into a new subdirectory with a new > prefix ("rust5_"). We make changes liberally to rust5_ and delete > rust4_ once the new snapshot is in place. (In the compiler this prefix > would be automatically added, of course) As a bonus, implementing this would provide an opportunity to clean up the inconsistent runtime interface. From marijnh at gmail.com Wed Dec 14 22:53:46 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Thu, 15 Dec 2011 07:53:46 +0100 Subject: [rust-dev] runtime libraries and stage1 In-Reply-To: <1367420000.47870.1323927421352.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> References: <4EE97BF6.10506@alum.mit.edu> <1367420000.47870.1323927421352.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: What I've been doing for difficult snapshots is to temporarily modify the makefiles to do the thing Niko describes (use stdlib and runtime from snapshot for stage1), building the snapshot, and then reverting the changes to the makefile again. It would be nice if this was something that could be simply turned on and off with a single switch somewhere, but my Makefile-fu wasn't strong enough to actually implement it that way. From graham.fawcett at gmail.com Fri Dec 16 12:15:12 2011 From: graham.fawcett at gmail.com (Graham Fawcett) Date: Fri, 16 Dec 2011 15:15:12 -0500 Subject: [rust-dev] types for statically-sized arrays (for FFI)? Message-ID: Hi folks, Can you express a statically-sized array type in Rust? I'm thinking mainly about FFI applications... for example, a sockaddr struct is typically something like { sa_family: u16, sa_data: u8[14] }. If not, how would you model something like a sockaddr? Could it be a first-class record in Rust? Be stack allocated? etc. Best, Graham From erick.tryzelaar at gmail.com Fri Dec 16 18:37:26 2011 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Fri, 16 Dec 2011 18:37:26 -0800 Subject: [rust-dev] would sending a unique value across a channel trigger a memory barrier? Message-ID: I need a memory barrier to transfer a zeromq socket from one thread to another. Will I automatically get one with our implementation of tasks, channels, and ports? From niko at alum.mit.edu Fri Dec 16 20:27:42 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Fri, 16 Dec 2011 20:27:42 -0800 Subject: [rust-dev] would sending a unique value across a channel trigger a memory barrier? In-Reply-To: References: Message-ID: <4EEC1A3E.1080509@alum.mit.edu> On 12/16/11 6:37 PM, Erick Tryzelaar wrote: > I need a memory barrier to transfer a zeromq socket from one thread to > another. Will I automatically get one with our implementation of > tasks, channels, and ports? Yes. 99% sure you do today (there must be some locks somewhere...have to review the path) but if not we have to add one or else the code is just buggy. Niko From banderson at mozilla.com Sat Dec 17 03:07:56 2011 From: banderson at mozilla.com (Brian Anderson) Date: Sat, 17 Dec 2011 03:07:56 -0800 (PST) Subject: [rust-dev] would sending a unique value across a channel trigger a memory barrier? In-Reply-To: <4EEC1A3E.1080509@alum.mit.edu> Message-ID: <2108982239.98020.1324120076597.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> 5 locks acquisitions to transfer something over a channel. ----- Original Message ----- > From: "Niko Matsakis" > To: "Erick Tryzelaar" > Cc: rust-dev at mozilla.org > Sent: Friday, December 16, 2011 8:27:42 PM > Subject: Re: [rust-dev] would sending a unique value across a channel trigger a memory barrier? > On 12/16/11 6:37 PM, Erick Tryzelaar wrote: > > I need a memory barrier to transfer a zeromq socket from one thread > > to > > another. Will I automatically get one with our implementation of > > tasks, channels, and ports? > Yes. 99% sure you do today (there must be some locks somewhere...have > to review the path) but if not we have to add one or else the code is > just buggy. > > > Niko > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From erick.tryzelaar at gmail.com Sat Dec 17 08:45:11 2011 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Sat, 17 Dec 2011 08:45:11 -0800 Subject: [rust-dev] would sending a unique value across a channel trigger a memory barrier? In-Reply-To: <2108982239.98020.1324120076597.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> References: <2108982239.98020.1324120076597.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: <85C0E6A2-8D95-4FA2-B8E2-CB6B67B641BE@gmail.com> Great thanks. On Dec 17, 2011, at 3:07 AM, Brian Anderson wrote: > 5 locks acquisitions to transfer something over a channel. > > ----- Original Message ----- >> From: "Niko Matsakis" >> To: "Erick Tryzelaar" >> Cc: rust-dev at mozilla.org >> Sent: Friday, December 16, 2011 8:27:42 PM >> Subject: Re: [rust-dev] would sending a unique value across a channel trigger a memory barrier? >> On 12/16/11 6:37 PM, Erick Tryzelaar wrote: >>> I need a memory barrier to transfer a zeromq socket from one thread >>> to >>> another. Will I automatically get one with our implementation of >>> tasks, channels, and ports? >> Yes. 99% sure you do today (there must be some locks somewhere...have >> to review the path) but if not we have to add one or else the code is >> just buggy. >> >> >> Niko >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev From jim at uazu.net Mon Dec 19 08:19:58 2011 From: jim at uazu.net (Jim Peters) Date: Mon, 19 Dec 2011 11:19:58 -0500 Subject: [rust-dev] Strict style checking In-Reply-To: References: Message-ID: <20111219161957.GA18274@uazu.net> Robert O'Callahan wrote: > One of my pet peeves about programming languages is that they don't > go far enough in mandating a particular coding style [...] I've been thinking about a slightly different approach to this problem, which I've written up here: http://uazu.net/notes/astlang.html Basically it is to make the language 'source code' an AST dump and then format the AST to the user's preference in the editor. This means each coder gets to see everyone else's code in their own preferred style, wrapped to their own preferred width, and so on. There is more to it, though -- see the page above. This is (partly) my solution to the 'itch' which is Java source code, where some people code with 160-column terminals, 80-column terminals, 4-space tabs, 8-space tabs, spaces present or missing in random places, and it all ends up being completely unreadable on my screen. So I'm working on a Java AST-based editor right now, so I can see the code as I want to see it (even with an alternative syntax if I want), and save back a minimal patch of conventional Java to the original source code (i.e. minimise 'git blame'). This way I can try out the ideas and see how well it can be made to work. I've got a contract in Java starting in a few months, so that is a good motivator. I'm quite fussy about wrapping long expressions with nested parens nicely so that the structure is evident (which Eclipse fails at completely), so getting the formatting good enough is a priority, although it will always be a compromise to some extent. It seems like Rust can get a lot of similar benefits if the pretty printer is good enough that people are happy to run it regularly on their code. If it is the editor that is pretty printing, they'll have no choice though (nor will I!), which is what I'm experimenting with right now. Then there is no opportunity to get precious about some particular bit of code layout, and no need to do so either if the pretty printer does a good enough job. Hopefully I can make it work. Jim -- Jim Peters (_)/=\~/_(_) jim at uazu.net (_) /=\ ~/_ (_) Uaz? (_) /=\ ~/_ (_) http:// in Peru (_) ____ /=\ ____ ~/_ ____ (_) uazu.net From niko at alum.mit.edu Tue Dec 20 10:16:47 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 20 Dec 2011 10:16:47 -0800 Subject: [rust-dev] minor things that annoy you about Rust? Message-ID: <4EF0D10F.9090702@alum.mit.edu> Hi, In preparation for the 0.1 release, Brian and I were thinking it might be nice to try to address small, annoying problems that come up in everyday Rust programming. Of course, a lot of these are already the result of compromises over contentious issues (e.g., trailing dot for nullary tag in a pattern), but I'd still like to know what the set of annoying things are; some of them may be easier to resolve now. Can you please e-mail me your favorite pet peeve(s). Thanks. Niko From erick.tryzelaar at gmail.com Tue Dec 20 12:37:30 2011 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Tue, 20 Dec 2011 12:37:30 -0800 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <4EF0D10F.9090702@alum.mit.edu> References: <4EF0D10F.9090702@alum.mit.edu> Message-ID: On Tue, Dec 20, 2011 at 10:16 AM, Niko Matsakis wrote: > Hi, > > In preparation for the 0.1 release, Brian and I were thinking it might be > nice to try to address small, annoying problems that come up in everyday > Rust programming. ?Of course, a lot of these are already the result of > compromises over contentious issues (e.g., trailing dot for nullary tag in a > pattern), but I'd still like to know what the set of annoying things are; > some of them may be easier to resolve now. ?Can you please e-mail me your > favorite pet peeve(s). ?Thanks. Here's a couple: 1) I keep forgetting to specify the return type of a function. Any chance that could be inferred? 2) Could integer literals be implicitly casted to the appropriate type if they're within bounds of the type? Things get especially noisy when using libcore::mtypes, as in "1 as m_int". 3) I'd love type inference :) 4) For-loop over integers would be great. 5) I can't exit early out of map::items. 6) map::hashmap needs a couple other functions: map, fold, eq. 7) A fixed size c array type would let me model c structures in rust. 8) I haven't been bit by it yet, but I see fail being used when it'd be better to use option::t, such as in int::str. I can imagine some pain in the future if we have to swap the return type, so might as well do a pass through the code to make sure fail is being used appropriately. 9) I'm not sure whether or not I should be using [u8] or pretend strs are byte strings when processing IO. From banderson at mozilla.com Tue Dec 20 13:47:18 2011 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 20 Dec 2011 13:47:18 -0800 (PST) Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <4EF0D10F.9090702@alum.mit.edu> Message-ID: <988832620.17388.1324417638902.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> ----- Original Message ----- > From: "Niko Matsakis" > To: rust-dev at mozilla.org > Sent: Tuesday, December 20, 2011 10:16:47 AM > Subject: [rust-dev] minor things that annoy you about Rust? > Hi, > > In preparation for the 0.1 release, Brian and I were thinking it might > be nice to try to address small, annoying problems that come up in > everyday Rust programming. Of course, a lot of these are already the > result of compromises over contentious issues (e.g., trailing dot for > nullary tag in a pattern), but I'd still like to know what the set of > annoying things are; some of them may be easier to resolve now. Can > you > please e-mail me your favorite pet peeve(s). Thanks. x::y vs x::y:: came up on IRC recently and I agree that every time I need to write the type param I have to think about it. The situation with semi-colons on the tail end of blocks comes up sometimes, but I personally don't have a problem with it. 1000-page error messages. The syntactic differences between 'tag { a; b; }' and 'type t = {a, b};'. Not being able to refer to variables in patterns comes up frequently, but we have a story for it with guards. The proliferation of function types is the first thing mentioned in every reddit thread. From niko at alum.mit.edu Tue Dec 20 14:13:49 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 20 Dec 2011 14:13:49 -0800 Subject: [rust-dev] names needed for function types Message-ID: <4EF1089D.4040007@alum.mit.edu> Per recent conversations, my current plan with regard to function types is to pare us back to three: - Unique closures (currently written "sendfn"), which can only close over sendable state, which is either copied or moved into the closure; - Shared closures (currently written "lambda" or "fn@"), which can copy or move arbitrary state off the stack frame and access it; - Blocks (currently written "block"), which access state from their creator's stack frame by reference and therefore cannot be used once their creator returns. Native and bare functions can act as any sort of closure and will be implicitly cast as needed. There will be some sort of library or perhaps magic language feature to access get a native function as a pointer (some sort of opaque pointer type) for interfacing with C libraries. That part is hand wavy. Currently, the sugar syntax "{ |x, y| x+y }" represents a block, but I have a patch that is *almost* ready where the sugar syntax will represent any sort of closure. The correct kind will be chosen using inference. The question is: what should we call the various closure types? I think we need both good prose names and good keywords, ideally those are the same. Some critiques of the current names: - The original proposal was `fn~`, `fn@`, and `fn&`, which used to be consistent with kinds; as the kinds have become words (`copy`, `send`), these names are no longer consistent. - Lambda is long and ? is unicode and not on my keyboard. - Block is a homonym for plain old blocks like `{ foo(); bar(); }` which is bad. - I don't like the name "shared" in general, which we use for task-local, boxed state, as it seems to imply sharing between threads. Some suggestions for alternative names: - Local or box closure for shared closure? - Stack closure for block? Niko From erick.tryzelaar at gmail.com Tue Dec 20 14:44:54 2011 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Tue, 20 Dec 2011 14:44:54 -0800 Subject: [rust-dev] names needed for function types In-Reply-To: <4EF1089D.4040007@alum.mit.edu> References: <4EF1089D.4040007@alum.mit.edu> Message-ID: On Tue, Dec 20, 2011 at 2:13 PM, Niko Matsakis wrote: > > The question is: what should we call the various closure types? I think we > need both good prose names and good keywords, ideally those are the same. I like stack and unique closues. What about just boxed closures instead of shared? From banderson at mozilla.com Tue Dec 20 14:50:43 2011 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 20 Dec 2011 14:50:43 -0800 (PST) Subject: [rust-dev] names needed for function types In-Reply-To: <4EF1089D.4040007@alum.mit.edu> Message-ID: <1875284772.18652.1324421443332.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> ----- Original Message ----- > From: "Niko Matsakis" > To: rust-dev at mozilla.org > Sent: Tuesday, December 20, 2011 2:13:49 PM > Subject: [rust-dev] names needed for function types > Per recent conversations, my current plan with regard to function > types > is to pare us back to three: > > - Unique closures (currently written "sendfn"), which can only close > over sendable state, which is either copied or moved into the closure; > - Shared closures (currently written "lambda" or "fn@"), which can > copy > or move arbitrary state off the stack frame and access it; > - Blocks (currently written "block"), which access state from their > creator's stack frame by reference and therefore cannot be used once > their creator returns. This will mean 'fn' can't be used as a type, unless it means two different things - I don't think it should both mean 'shared closure' and this non-type thing that can be instantiated as any type of closure. It's a shame that we have to think of a different name for the most common function type, but maybe not a big problem since you often want to use it as a block. > > The question is: what should we call the various closure types? I > think > we need both good prose names and good keywords, ideally those are the > same. > Rename 'block' to 'fn'. Reason: this is the type that most higher order functions take; it has symmetry with your proposal for fn declarations, in that fn declarations can be instantiated as either shared closures or unique closures. In common practice you would write 'fn' most everywhere. Only when you need to put a closure into a data structure or send it would you have to be more specific about the type. Still thinking about the other two. From elly at leptoquark.net Tue Dec 20 14:55:53 2011 From: elly at leptoquark.net (Elly Jones) Date: Tue, 20 Dec 2011 16:55:53 -0600 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <4EF0D10F.9090702@alum.mit.edu> References: <4EF0D10F.9090702@alum.mit.edu> Message-ID: <20111220225553.GE19880@leptoquark.net> On Tue, Dec 20, 2011 at 10:16:47AM -0800, Niko Matsakis wrote: > Hi, > > In preparation for the 0.1 release, Brian and I were thinking it > might be nice to try to address small, annoying problems that come > up in everyday Rust programming. Of course, a lot of these are > already the result of compromises over contentious issues (e.g., > trailing dot for nullary tag in a pattern), but I'd still like to > know what the set of annoying things are; some of them may be easier > to resolve now. Can you please e-mail me your favorite pet > peeve(s). Thanks. 1. Type suffixes on integer literals. I trip _constantly_ over the fact that I must say 'vec::slice(..., 0u, ...)' instead of 'vec::slice(..., 0, ...)'. I wish these were automatically cast to the appropriate type if within range. This is the biggest single drag to writing Rust code day-to-day for me. 2. The dot after the nullary tag. In general I want to write a nullary tag a LOT more often than I want to write a wildcard binder, so I feel like this is the wrong way for this choice to go, but I'll understand if this is a decided issue already. 3. The use of alt in situations which would be handled with a guard clause in C. For example, in C, I might write: if (!foo->is_bar()) { return OOPS; } bar = foo->get_bar(); Whereas in Rust, I have to write: let mybar = alt foo { bar(_v) { _v } _ { fail "OOPS"; } } This is okay, but it's an operation I do a _lot_, so I'd sort of like a lighter syntax for it, like: let bar(mybar) = foo else { fail "OOPS"; } With the restriction that the else {} block may not continue execution, I don't think this is terribly semantically incoherent. 4. I wish a lot more of the standard library was object-oriented. I realize this is somewhat of a slippery slope, but writing 'vec::len(thing)' is less nice (to me) than thing.len(). I think that things in the standard library that are object-like (vec, str, ...) should be objects. 5. I do not like the mk_foo()/obj foo {} idiom; it forces code another tabstop to the right. 6. Having to export all the members of a tag you're exporting seems bizarre; when would you ever want the tag but not its members? > Niko > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -- elly -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 490 bytes Desc: Digital signature URL: From erick.tryzelaar at gmail.com Tue Dec 20 15:38:10 2011 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Tue, 20 Dec 2011 15:38:10 -0800 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <20111220225553.GE19880@leptoquark.net> References: <4EF0D10F.9090702@alum.mit.edu> <20111220225553.GE19880@leptoquark.net> Message-ID: On Tue, Dec 20, 2011 at 2:55 PM, Elly Jones wrote: > > 6. Having to export all the members of a tag you're exporting seems bizarre; > when would you ever want the tag but not its members? I would imagine it'd accomplish pretty much the same thing as ocaml's private variant types: http://caml.inria.fr/pub/docs/manual-ocaml/manual021.html#toc76 However, I think private tags would be the exception, not the default, so I'd rather change things so you have to opt-in to not export the tag members. From sebastian.sylvan at gmail.com Tue Dec 20 15:56:55 2011 From: sebastian.sylvan at gmail.com (Sebastian Sylvan) Date: Tue, 20 Dec 2011 15:56:55 -0800 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <20111220225553.GE19880@leptoquark.net> References: <4EF0D10F.9090702@alum.mit.edu> <20111220225553.GE19880@leptoquark.net> Message-ID: On Tue, Dec 20, 2011 at 2:55 PM, Elly Jones wrote: > > 3. The use of alt in situations which would be handled with a guard clause in C. > For example, in C, I might write: > > if (!foo->is_bar()) { return OOPS; } > bar = foo->get_bar(); > > Whereas in Rust, I have to write: > > let mybar = alt foo { > ? ? ? ?bar(_v) { _v } > ? ? ? ?_ { fail "OOPS"; } > } > > This is okay, but it's an operation I do a _lot_, so I'd sort of like a lighter > syntax for it, like: > > let bar(mybar) = foo else { fail "OOPS"; } > > With the restriction that the else {} block may not continue execution, I don't > think this is terribly semantically incoherent. It could also just supply a default: let bar(mybar) = foo else { bar(5) } Then fail would be a special case that would be valid too since control doesn't leave the block. Not sure I like this though. Wouldn't it be quite rare for failure to be the right option when a tag doesn't have the right arm? Wouldn't you rather chain the values together using the functions in the option module to propagate the "none" further up? > 6. Having to export all the members of a tag you're exporting seems bizarre; > when would you ever want the tag but not its members? The majority of the time, I'd think? Wouldn't you usually want to keep the internals of data types opaque to other modules so that you're forced to call the functions in the module to operate on it? Would be nice to have a shorthand for just exporting all the members though, a la Haskell. -- Sebastian Sylvan From niko at alum.mit.edu Tue Dec 20 21:20:00 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 20 Dec 2011 21:20:00 -0800 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <20111220225553.GE19880@leptoquark.net> References: <4EF0D10F.9090702@alum.mit.edu> <20111220225553.GE19880@leptoquark.net> Message-ID: <4EF16C80.40106@alum.mit.edu> On 12/20/11 2:55 PM, Elly Jones wrote: > This is okay, but it's an operation I do a _lot_, so I'd sort of like a lighter > syntax for it, like: > > let bar(mybar) = foo else { fail "OOPS"; } > > With the restriction that the else {} block may not continue execution, I don't > think this is terribly semantically incoherent. If I may ask, why are you doing this so often? Is it that you often write functions which are handling a specific case of a tag and you pass in the tag value to the function, then need to extract the relevant data? I do find it happens frequently that, in a particular context, I know that the tag value may only take on some subset of the possible variants. I would personally like to find a way to extend the type system to let me express that (and thus prove that my intuition is true). I think we shouldn't have to write `fail "OOPS"` except in extreme cases. Scala's case classes offer such flexibility but maybe there is a lighter way to get something similar. Anyhow, can you maybe point me at some of the code where you find a need for extracting a particular variant in this way? Niko From marijnh at gmail.com Wed Dec 21 03:20:06 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Wed, 21 Dec 2011 12:20:06 +0100 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <20111220225553.GE19880@leptoquark.net> References: <4EF0D10F.9090702@alum.mit.edu> <20111220225553.GE19880@leptoquark.net> Message-ID: > 2. The dot after the nullary tag. In general I want to write a nullary tag a LOT > more often than I want to write a wildcard binder, so I feel like this is the > wrong way for this choice to go, but I'll understand if this is a decided issue > already. I agree the dot is problematic, but I'm *very* skeptical about your assertion that you're writing more nullary tag patterns than binders. At least in the compiler, I think we see at least ten times more binders than nullary tags. > 4. I wish a lot more of the standard library was object-oriented. I realize this > is somewhat of a slippery slope, but writing 'vec::len(thing)' is less nice (to > me) than thing.len(). I think that things in the standard library that are > object-like (vec, str, ...) should be objects. This is part of the reason we're implementing interfaces (type classes). > 5. I do not like the mk_foo()/obj foo {} idiom; it forces code another tabstop > to the right. If interfaces work out, they'll probably replace the current obj system. From marijnh at gmail.com Wed Dec 21 03:20:53 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Wed, 21 Dec 2011 12:20:53 +0100 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <988832620.17388.1324417638902.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> References: <4EF0D10F.9090702@alum.mit.edu> <988832620.17388.1324417638902.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: > 1000-page error messages. These should be solved now. If you're still seeing them, submit a bug with the code that triggers one. From elly+rd at leptoquark.net Wed Dec 21 06:50:07 2011 From: elly+rd at leptoquark.net (Elly Jones) Date: Wed, 21 Dec 2011 08:50:07 -0600 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: References: <4EF0D10F.9090702@alum.mit.edu> <20111220225553.GE19880@leptoquark.net> Message-ID: <20111221145007.GG19880@leptoquark.net> On Wed, Dec 21, 2011 at 12:20:06PM +0100, Marijn Haverbeke wrote: > > 2. The dot after the nullary tag. In general I want to write a nullary tag a LOT > > more often than I want to write a wildcard binder, so I feel like this is the > > wrong way for this choice to go, but I'll understand if this is a decided issue > > already. > > I agree the dot is problematic, but I'm *very* skeptical about your > assertion that you're writing more nullary tag patterns than binders. > At least in the compiler, I think we see at least ten times more > binders than nullary tags. Sorry, I meant wildcard bindings at the top level of a match only. I vastly more often mean: alt thing { some(...) { ... } none. { ... } } than: alt thing { some(...) { ... } none { ... } } That said, hmm. Asking for this is making me start to worry that anything we did change would make the syntax inconsistent, since I use non-top-level match bindings way more often than nullary tags. > > 4. I wish a lot more of the standard library was object-oriented. I realize this > > is somewhat of a slippery slope, but writing 'vec::len(thing)' is less nice (to > > me) than thing.len(). I think that things in the standard library that are > > object-like (vec, str, ...) should be objects. > > This is part of the reason we're implementing interfaces (type classes). Yay! > > 5. I do not like the mk_foo()/obj foo {} idiom; it forces code another tabstop > > to the right. > > If interfaces work out, they'll probably replace the current obj system. Double yay! -- elly -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 490 bytes Desc: Digital signature URL: From marijnh at gmail.com Wed Dec 21 06:59:49 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Wed, 21 Dec 2011 15:59:49 +0100 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <20111221145007.GG19880@leptoquark.net> References: <4EF0D10F.9090702@alum.mit.edu> <20111220225553.GE19880@leptoquark.net> <20111221145007.GG19880@leptoquark.net> Message-ID: > Sorry, I meant wildcard bindings at the top level of a match only. We've been thinking down the road of making binders at the top of a pattern special a few times, but as you say, that'd cause inconsistency and probably make things even more confusing than they are now. From niko at alum.mit.edu Wed Dec 21 07:04:30 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 21 Dec 2011 07:04:30 -0800 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: References: <4EF0D10F.9090702@alum.mit.edu> <20111220225553.GE19880@leptoquark.net> <20111221145007.GG19880@leptoquark.net> Message-ID: <4EF1F57E.7010501@alum.mit.edu> On 12/21/11 6:59 AM, Marijn Haverbeke wrote: >> Sorry, I meant wildcard bindings at the top level of a match only. > We've been thinking down the road of making binders at the top of a > pattern special a few times, but as you say, that'd cause > inconsistency and probably make things even more confusing than they > are now. A good summary of the previous discussion is here: https://github.com/graydon/rust/wiki/Syntactic-issues-in-pattern-matching Specifically "How to distinguish variables from tags." Niko From marijnh at gmail.com Wed Dec 21 08:19:54 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Wed, 21 Dec 2011 17:19:54 +0100 Subject: [rust-dev] Proposal: different alt form flavours Message-ID: This was prompted by the 'minor annoyances thread'. A big annoyance for me is the recurring `_ {}` at the end of alt patterns that fall through. A worse form is `_ { fail "this is a bug"; }` (alt already fails when not matching, with a line number reference to the alt that blew up, so this kind of `fail` statements mostly just muddle up the code). Instead, I propose: // This one falls through without failing alt myoption pass { some(x) { do_something_with(x); } } // This one explicitly says that is is non-exhaustive, and that // it will fail for bad input alt myoption fail { some(x) { ... } } Normal alt would be required to be exhaustive, and give a compile-time error if it isn't. This is more self-documenting (you're explicitly annotating what you're trying to do when writing a non-exhaustive alt), and somewhat more succinct. I'm not terribly attached to those keywords (`pass` and `fail`), would happily hear alternatives. Best, Marijn From stefan.plantikow at googlemail.com Wed Dec 21 10:44:06 2011 From: stefan.plantikow at googlemail.com (Stefan Plantikow) Date: Wed, 21 Dec 2011 19:44:06 +0100 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <4EF0D10F.9090702@alum.mit.edu> References: <4EF0D10F.9090702@alum.mit.edu> Message-ID: Am 20.12.2011 um 19:16 schrieb Niko Matsakis: > Hi, > > In preparation for the 0.1 release, Brian and I were thinking it might be nice to try to address small, annoying problems that come up in everyday Rust programming. Of course, a lot of these are already the result of compromises over contentious issues (e.g., trailing dot for nullary tag in a pattern), but I'd still like to know what the set of annoying things are; some of them may be easier to resolve now. Can you please e-mail me your favorite pet peeve(s). Thanks. > Hi, great idea! First, hello on the mailing list, most of you probably have already seen me on irc. So here's my list of scratches, surely not all of them are for 0.1: 1. I support being able to drop mandatory literal type specifiers on values that are within the range of their expected type Related: I'd like contributed source highlighting code for vim, emacs etc. to highlight all literal type specifiers (very long f32, f64 literal constants can be difficult to read otherwise, e.g. -XXXX.YYYYe-Zf32) 2. Some kind of match or fail or default statement/library utility function as suggested by elly would be nice. Would be volunteering to do it. Possible idea in this direction let pat = expr1 or expr2 or ... or { fail|ret|default value that statically is known to match pat } First match wins. This is like an inverse of alt: instead of matching the same experession against different patterns this matches different expressions against the same pattern 3. Some way to deal with nullary tags in patterns. The problem for a good syntax seems to be that we want to write patterns in the same way as regular code as much as possible. I feel for consistency it may be the better road to mark variables somehow, as pattern variables are actually a bit of a different construct than regular variables. Alternatively, the established "constr." syntax should just do fine. 4. Lack of break, continue, and labels. I know this is a big one but some loops are difficult to write without. Anything more than what is there today will be much apreciated. I hit this when writing bench/sudoku.rs which is a port from some Java code of mine. Any code conversion to rust may suffer from lack of these features (same holds for C style for loops). Also common in numeric code. 5. import/export - support for (at least trivial) type casting, i.e. import XY as TYP, export XY as TYP Rationale: Would help me drop a lot of wrapper functions in core::float and seems clearer to me than the wrappers that are in place now. Haven't looked into how hard it would be to do this. - syntax for exporting all or no constructor(s) of a tag, perhaps using a special export clause "export* tag") 6. Support for consts refering to other consts from the same crate (again, for math). 7. Some form of tail calls, please :) I'v written up an idea around this in the wiki, please feel free to edit there. 8. a bit more documentation in the compiler on how things are supposed to work, especially the central data structures could use a few comments So much for now, Greetings, Stefan From marijnh at gmail.com Wed Dec 21 11:19:21 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Wed, 21 Dec 2011 20:19:21 +0100 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: References: <4EF0D10F.9090702@alum.mit.edu> Message-ID: > 4. Lack of break, continue, and labels. ?I know this is a big one but some loops are difficult to write without. Anything > ? more than what is there today will be much apreciated. 'break' and 'cont' exist (though without labels, and not able to break out of a block function). From stefan.plantikow at googlemail.com Wed Dec 21 11:26:12 2011 From: stefan.plantikow at googlemail.com (Stefan Plantikow) Date: Wed, 21 Dec 2011 20:26:12 +0100 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: References: <4EF0D10F.9090702@alum.mit.edu> Message-ID: Am 21.12.2011 um 20:19 schrieb Marijn Haverbeke: >> 4. Lack of break, continue, and labels. I know this is a big one but some loops are difficult to write without. Anything >> more than what is there today will be much apreciated. > > 'break' and 'cont' exist (though without labels, and not able to break > out of a block function). Thanks, I should have been more clear, I specifically ment breaking out of blocks and using labels. Stefan. From stefan.plantikow at googlemail.com Wed Dec 21 11:52:52 2011 From: stefan.plantikow at googlemail.com (Stefan Plantikow) Date: Wed, 21 Dec 2011 20:52:52 +0100 Subject: [rust-dev] Proposal: different alt form flavours In-Reply-To: References: Message-ID: Am 21.12.2011 um 17:19 schrieb Marijn Haverbeke: > This was prompted by the 'minor annoyances thread'. A big annoyance > for me is the recurring `_ {}` at the end of alt patterns that fall > through. A worse form is `_ { fail "this is a bug"; }` (alt already > fails when not matching, with a line number reference to the alt that > blew up, so this kind of `fail` statements mostly just muddle up the > code). > > Instead, I propose: > > // This one falls through without failing > alt myoption pass { > some(x) { do_something_with(x); } > } > // This one explicitly says that is is non-exhaustive, and that > // it will fail for bad input > alt myoption fail { > some(x) { ... } > } > > Normal alt would be required to be exhaustive, and give a compile-time > error if it isn't. This is more self-documenting (you're explicitly > annotating what you're trying to do when writing a non-exhaustive > alt), and somewhat more succinct. > > I'm not terribly attached to those keywords (`pass` and `fail`), would > happily hear alternatives. I like the general idea of giving the default behaviour of alt (pass, fail, default value) a special status in the form of some "else" construct because it will allow extending alt to try multiple values until one matches before moving on to the else-branch (imagine `alt val1, val2, ... or even alt over vectors). However: - alt now can be a statement or an expression, maybe as a statement, it should use a different keyword altogether "on myopt { ... }" - it is quite unsusual control flow, normally one would expect either an else branch (i.e. alt { } else { }) or `fail`, and `pass` to be the last clauses int the alt block, i.e. `alt myopt { branch1; branch2; fail }` - at first glance it is not clear what is meant by this (I would at least add an mandatory `else` keyword to help) - I think this should be extended with a more terse way to specify a default value that is statically guaranteed to match the left side Beyond that it feels quite right and is nicely terse. Stefan. From niko at alum.mit.edu Wed Dec 21 12:14:54 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 21 Dec 2011 12:14:54 -0800 Subject: [rust-dev] easier closures Message-ID: <4EF23E3E.3080006@alum.mit.edu> Hello all, Just a quick note that it is now possible to use the Smalltalk-like block syntax "{ |args| ... }" to represent any kind of closure. The compiler will (attempt to) infer if you mean a block/lambda/sendfn (proper names pending) based on context, just as it infers the type of the arguments and return type. Niko From lihaitao at gmail.com Wed Dec 21 18:53:11 2011 From: lihaitao at gmail.com (Haitao Li) Date: Thu, 22 Dec 2011 10:53:11 +0800 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <4EF0D10F.9090702@alum.mit.edu> References: <4EF0D10F.9090702@alum.mit.edu> Message-ID: > pattern), but I'd still like to know what the set of annoying things are; > some of them may be easier to resolve now. ?Can you please e-mail me your > favorite pet peeve(s). ?Thanks. > This is really a complaint of style. I don't like placing all branches of an alt expression in one line. For example, alt p.peek() { token::IDENT(_, false) { true } _ { false } }; It's slower for me to brain parse it, especially with the less obvious "_" symbol. And why upper case is not used consistently for tags? That may help get rid of the trailing dot of nullary tag in patterns. Also I find myself forgot type suffix of numbers all the time, but I'm fine with it and believe I can get used to it over time. Cheers, Haitao From arcata at gmail.com Wed Dec 21 21:10:09 2011 From: arcata at gmail.com (Joe Groff) Date: Wed, 21 Dec 2011 21:10:09 -0800 Subject: [rust-dev] Fwd: minor things that annoy you about Rust? In-Reply-To: References: <4EF0D10F.9090702@alum.mit.edu> Message-ID: On Wed, Dec 21, 2011 at 10:44 AM, Stefan Plantikow < stefan.plantikow at googlemail.com> wrote: > 1. I support being able to drop mandatory literal type specifiers on > values that are within the range of their expected type > > Related: I'd like contributed source highlighting code for vim, emacs > etc. to highlight all literal type specifiers > (very long f32, f64 literal constants can be difficult to read > otherwise, e.g. -XXXX.YYYYe-Zf32) > Think also of hex literals (e.g. 0xabcdefi32). Syntax highlighting seems like a hack to get around syntax that just plain sucks. If you guys are open to changing the literal suffix syntax, the C tradition of magic letters may not be theoretically appealing but it would be much more ergonomic. -Joe -------------- next part -------------- An HTML attachment was scrubbed... URL: From arcata at gmail.com Wed Dec 21 21:11:06 2011 From: arcata at gmail.com (Joe Groff) Date: Wed, 21 Dec 2011 21:11:06 -0800 Subject: [rust-dev] Fwd: Rust experience report In-Reply-To: References: <1004294274.51859.1323466643652.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: On Fri, Dec 9, 2011 at 1:37 PM, Brian Anderson wrote: > Purity by default is attractive. I don't know what's involved to make it > happen. It would be an interesting project > to go through the rust code base and see how much can be made pure. In addition to mutating their own local state, would it be tenable if 'pure' functions were also allowed to modify inout arguments explicitly passed by mutable reference? It would be like an effect type encoded in the argument kinds of the function. I think this would allow mutator functions to be applied to a pure function's local state without propagating impurity. -Joe -------------- next part -------------- An HTML attachment was scrubbed... URL: From marijnh at gmail.com Thu Dec 22 11:43:56 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Thu, 22 Dec 2011 20:43:56 +0100 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <4EF0D10F.9090702@alum.mit.edu> References: <4EF0D10F.9090702@alum.mit.edu> Message-ID: Here's another one: The fact that, when changing a tag variant, you have to update every single place that matches against it. We might want to revisit the idea of named variant args, that you match by name, so that A) you can leave off all the '_' placeholders, and B) you only need to update your patterns when the actual fields you're interested in change. From graydon at mozilla.com Thu Dec 22 11:55:11 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 22 Dec 2011 11:55:11 -0800 Subject: [rust-dev] Fwd: minor things that annoy you about Rust? In-Reply-To: References: <4EF0D10F.9090702@alum.mit.edu> Message-ID: <4EF38B1F.7040904@mozilla.com> On 11-12-21 09:10 PM, Joe Groff wrote: > 1. I support being able to drop mandatory literal type specifiers on > values that are within the range of their expected type > > Related: I'd like contributed source highlighting code for vim, > emacs etc. to highlight all literal type specifiers > (very long f32, f64 literal constants can be difficult to read > otherwise, e.g. -XXXX.YYYYe-Zf32) > > > Think also of hex literals (e.g. 0xabcdefi32). Syntax highlighting seems > like a hack to get around syntax that just plain sucks. If you guys are > open to changing the literal suffix syntax, the C tradition of magic > letters may not be theoretically appealing but it would be much more > ergonomic. I'm curious how many of the people upset at the literal suffixes know the number-literal syntax permits inserting underscores, so you can write this as (say): 0x_00ab_cdef_i32 Which is how I tend to write any suffixed literal that's not a very simple one (eg. 0u or such). The fact is that "being in range" is a fair bit heuristic and the more you guess the more likely you are to burn the user. 0xff means -1 as a signed octet and 255 as either an unsigned octet *or* a signed integer. Unless I sign-extend, which I have to decide whether or not I'm going to do when reading "0xff". Personally I still find the literal suffixes quite comforting and preferable to their absence in C, specifically because I have so much more mental work to do in C to guess whether-or-when I'm going to be accidentally truncating / wrapping / sign-extending etc. due to a conversion from the literal-I-said to the number-it-decided-to-use. I'm really only keen on discussing an alternative that doesn't reintroduce the C nightmare of "guess which boundary condition of 2s complement arithmetic you're going to burn yourself on today". -Graydon From sebastian.sylvan at gmail.com Thu Dec 22 12:12:39 2011 From: sebastian.sylvan at gmail.com (Sebastian Sylvan) Date: Thu, 22 Dec 2011 12:12:39 -0800 Subject: [rust-dev] Fwd: minor things that annoy you about Rust? In-Reply-To: <4EF38B1F.7040904@mozilla.com> References: <4EF0D10F.9090702@alum.mit.edu> <4EF38B1F.7040904@mozilla.com> Message-ID: On Thu, Dec 22, 2011 at 11:55 AM, Graydon Hoare wrote: > On 11-12-21 09:10 PM, Joe Groff wrote: > >> ? ?1. I support being able to drop mandatory literal type specifiers on >> ? ?values that are within the range of their expected type >> >> ? ? ? Related: I'd like contributed source highlighting code for vim, >> ? ?emacs etc. to highlight all literal type specifiers >> ? ? ? (very long f32, f64 literal constants can be difficult to read >> ? ?otherwise, e.g. -XXXX.YYYYe-Zf32) >> >> >> Think also of hex literals (e.g. 0xabcdefi32). Syntax highlighting seems >> like a hack to get around syntax that just plain sucks. If you guys are >> open to changing the literal suffix syntax, the C tradition of magic >> letters may not be theoretically appealing but it would be much more >> ergonomic. > > > I'm curious how many of the people upset at the literal suffixes know the > number-literal syntax permits inserting underscores, so you can write this > as (say): > > ?0x_00ab_cdef_i32 > > Which is how I tend to write any suffixed literal that's not a very simple > one (eg. 0u or such). > > The fact is that "being in range" is a fair bit heuristic and the more you > guess the more likely you are to burn the user. 0xff means -1 as a signed > octet and 255 as either an unsigned octet *or* a signed integer. IMO literals shouldn't take into account the fact that the underlying bit representation may also have other interpretations. So 255 would mean 255, not -1, under any circumstances. The fact that -1 can be represented in the same way on the level of bits doesn't make 255 equivalent to -1 when you decide what types it's compatible with (in this signed integers of more than 8 bits, and unsigned integers of 8 bits or more, plus floats). If you want -1, you have to write -1, or do some kind of reinterpret_cast on 255 to a type where that bit patterns means -1. Same goes for hex. 0xff means 0xff, not -0x01. The fact that the literal->bits translation may not be injective doesn't mean that any two values that happen to have the same bit representation should be considered the same for the purposes of inferring type. With that in place, I don't think that leaving off suffixes would be an issue for literals that fit. Seb -- Sebastian Sylvan From graydon at mozilla.com Thu Dec 22 12:09:42 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 22 Dec 2011 12:09:42 -0800 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <20111220225553.GE19880@leptoquark.net> References: <4EF0D10F.9090702@alum.mit.edu> <20111220225553.GE19880@leptoquark.net> Message-ID: <4EF38E86.8090605@mozilla.com> On 11-12-20 02:55 PM, Elly Jones wrote: > 2. The dot after the nullary tag. In general I want to write a nullary tag a LOT > more often than I want to write a wildcard binder, so I feel like this is the > wrong way for this choice to go, but I'll understand if this is a decided issue > already. Agreed. There's a wiki page showing options on this. > 3. The use of alt in situations which would be handled with a guard clause in C. > For example, in C, I might write: ... > let bar(mybar) = foo else { fail "OOPS"; } This is called a "refutable pattern" in some languages and .. I'd be somewhat-ok with adding it as a way to do a let-destructuring in general, w/o an else clause. Just treat it as an implicit fail (reporting location) the way we do a fallthrough in an alt. Hermes did something interesting here, which is that a variant type defined typestate predicates along the lines of "value x is variant y", so you could check one and make it a typestate precondition. I'm not sure that's any less syntactically awkward though. > 4. I wish a lot more of the standard library was object-oriented. I realize this > is somewhat of a slippery slope, but writing 'vec::len(thing)' is less nice (to > me) than thing.len(). I think that things in the standard library that are > object-like (vec, str, ...) should be objects. Typeclasses will probably give us a hammer to hit a lot of this stuff with. > 5. I do not like the mk_foo()/obj foo {} idiom; it forces code another tabstop > to the right. And this. > 6. Having to export all the members of a tag you're exporting seems bizarre; > when would you ever want the tag but not its members? When you want a nominal type that you want to Greatly Discourage clients from trying to construct or inspect themselves. I think we can probably do something with globbing here though. I don't mind making "export tagname::*" mean "export all the constructors". It's a special case in the export-glob logic but not a particularly strange-looking one. -Graydon From elly+rd at leptoquark.net Thu Dec 22 12:19:04 2011 From: elly+rd at leptoquark.net (Elly Jones) Date: Thu, 22 Dec 2011 14:19:04 -0600 Subject: [rust-dev] Fwd: minor things that annoy you about Rust? In-Reply-To: References: <4EF0D10F.9090702@alum.mit.edu> <4EF38B1F.7040904@mozilla.com> Message-ID: <20111222201904.GA7192@leptoquark.net> On Thu, Dec 22, 2011 at 12:12:39PM -0800, Sebastian Sylvan wrote: > On Thu, Dec 22, 2011 at 11:55 AM, Graydon Hoare wrote: > > On 11-12-21 09:10 PM, Joe Groff wrote: > > > >> ? ?1. I support being able to drop mandatory literal type specifiers on > >> ? ?values that are within the range of their expected type > >> > >> ? ? ? Related: I'd like contributed source highlighting code for vim, > >> ? ?emacs etc. to highlight all literal type specifiers > >> ? ? ? (very long f32, f64 literal constants can be difficult to read > >> ? ?otherwise, e.g. -XXXX.YYYYe-Zf32) > >> > >> > >> Think also of hex literals (e.g. 0xabcdefi32). Syntax highlighting seems > >> like a hack to get around syntax that just plain sucks. If you guys are > >> open to changing the literal suffix syntax, the C tradition of magic > >> letters may not be theoretically appealing but it would be much more > >> ergonomic. > > > > > > I'm curious how many of the people upset at the literal suffixes know the > > number-literal syntax permits inserting underscores, so you can write this > > as (say): > > > > ?0x_00ab_cdef_i32 > > > > Which is how I tend to write any suffixed literal that's not a very simple > > one (eg. 0u or such). > > > > The fact is that "being in range" is a fair bit heuristic and the more you > > guess the more likely you are to burn the user. 0xff means -1 as a signed > > octet and 255 as either an unsigned octet *or* a signed integer. > > IMO literals shouldn't take into account the fact that the underlying > bit representation may also have other interpretations. So 255 would > mean 255, not -1, under any circumstances. The fact that -1 can be > represented in the same way on the level of bits doesn't make 255 > equivalent to -1 when you decide what types it's compatible with (in > this signed integers of more than 8 bits, and unsigned integers of 8 > bits or more, plus floats). > > If you want -1, you have to write -1, or do some kind of > reinterpret_cast on 255 to a type where that bit patterns means -1. > > Same goes for hex. 0xff means 0xff, not -0x01. The fact that the > literal->bits translation may not be injective doesn't mean that any > two values that happen to have the same bit representation should be > considered the same for the purposes of inferring type. Very, very much agreed with this. I don't think we want to expose the fact that the machine represents (-1 as u8) as 0xff because rust code mostly shouldn't care, and if it does care, it can write '0xffu8' or whatever. We should certainly still support suffixes, but I think inferring them would help. > With that in place, I don't think that leaving off suffixes would be > an issue for literals that fit. > > Seb > -- > Sebastian Sylvan > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -- elly -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 490 bytes Desc: Digital signature URL: From arcata at gmail.com Thu Dec 22 13:16:31 2011 From: arcata at gmail.com (Joe Groff) Date: Thu, 22 Dec 2011 13:16:31 -0800 Subject: [rust-dev] Fwd: minor things that annoy you about Rust? In-Reply-To: <4EF38B1F.7040904@mozilla.com> References: <4EF0D10F.9090702@alum.mit.edu> <4EF38B1F.7040904@mozilla.com> Message-ID: On Thu, Dec 22, 2011 at 11:55 AM, Graydon Hoare wrote: > I'm curious how many of the people upset at the literal suffixes know the > number-literal syntax permits inserting underscores, so you can write this > as (say): > > 0x_00ab_cdef_i32 > > Which is how I tend to write any suffixed literal that's not a very simple > one (eg. 0u or such). > I definitely agree that explicitly typed literals are worth the pain to adapt to. I would suggest trying suffixes that don't have digits in them, maybe 'b'yte 's'hort 'i'nt 'l'ong instead of 'i8' 'i16' 'i32' 'i64' (except 'b' is a hex digit, so, I dunno). Underscores are a great bit of sugar, but you shouldn't feel like you absolutely have to use them every time you use a suffix, and there'll always be that one jerk on your team who runs their literals together without the separator. -Joe -------------- next part -------------- An HTML attachment was scrubbed... URL: From marijnh at gmail.com Thu Dec 22 13:22:05 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Thu, 22 Dec 2011 22:22:05 +0100 Subject: [rust-dev] Fwd: minor things that annoy you about Rust? In-Reply-To: References: <4EF0D10F.9090702@alum.mit.edu> <4EF38B1F.7040904@mozilla.com> Message-ID: > and there'll always be that one jerk on your team who runs their literals together without the separator. *raises hand* But seriously, I think that if our approach to type inference supported it, inferring the type of literals (with warning for overflows) would be great. But it doesn't -- or rather, it doesn't to the extend where the result would be pleasant to program with -- so I'm okay with just living with the suffixes. I do prefer 'u8' to 'b' (or similar), simply because it's easier to remember. From pwalton at mozilla.com Thu Dec 22 16:13:31 2011 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 22 Dec 2011 16:13:31 -0800 (PST) Subject: [rust-dev] Fwd: minor things that annoy you about Rust? In-Reply-To: <4EF38B1F.7040904@mozilla.com> Message-ID: <114149653.49922.1324599211944.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> How about inferring the type of unadorned literals only, and allow an "i" suffix to force regular int interpretation? That way the programmer is free to make the judgment call of readability of code vs. clarity of intent herself. We could also potentially investigate making the machine integer types have shorter suffixes. There are plenty of letters to go around. Patrick ----- Original Message ----- From: "Graydon Hoare" To: rust-dev at mozilla.org Sent: Thursday, December 22, 2011 2:55:11 PM Subject: Re: [rust-dev] Fwd: minor things that annoy you about Rust? I'm curious how many of the people upset at the literal suffixes know the number-literal syntax permits inserting underscores, so you can write this as (say): 0x_00ab_cdef_i32 Which is how I tend to write any suffixed literal that's not a very simple one (eg. 0u or such). The fact is that "being in range" is a fair bit heuristic and the more you guess the more likely you are to burn the user. 0xff means -1 as a signed octet and 255 as either an unsigned octet *or* a signed integer. Unless I sign-extend, which I have to decide whether or not I'm going to do when reading "0xff". Personally I still find the literal suffixes quite comforting and preferable to their absence in C, specifically because I have so much more mental work to do in C to guess whether-or-when I'm going to be accidentally truncating / wrapping / sign-extending etc. due to a conversion from the literal-I-said to the number-it-decided-to-use. I'm really only keen on discussing an alternative that doesn't reintroduce the C nightmare of "guess which boundary condition of 2s complement arithmetic you're going to burn yourself on today". -Graydon _______________________________________________ Rust-dev mailing list Rust-dev at mozilla.org https://mail.mozilla.org/listinfo/rust-dev From pwalton at mozilla.com Thu Dec 22 16:27:31 2011 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 22 Dec 2011 16:27:31 -0800 (PST) Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: Message-ID: <566812896.50140.1324600051195.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> I would really like to advocate once again for Standard ML's solution: simply disambiguate variable bindings and tag constructors at the name resolution phase. It does mean that you can't have a variable with the same name as a tag constructor, and I know that there are a lot of fears that it would be confusing and lead to subtle bugs, but I've never heard of a case when a Standard ML programmer was confused. In my experience, few Standard ML programmers even know the rule exists. What *does* lead to confusion and subtle bugs is accidentally using a variable binding instead of a nullary tag, or vice versa. Using a variable binding instead of a nullary tag is somewhat worse than using a nullary tag instead of a variable binding, because the typechecker will be more likely to catch the mistake. Experience suggests that the current regime leads to the worst outcome far more often than the Standard ML rule does, simply because it's easy to forget to add the dot and that leads to the compiler doing the wrong thing, and the typechecker won't catch it. Conversely, the Standard ML rule makes the compiler attempt to do the right thing by default. The only way it can go wrong (which I've never seen in practice) results in the nullary tag interpretation, which is an error that the typechecker has a good chance of catching. Thus the Standard ML solution has the nice properties of being both the most aesthetically pleasing and the most reliable solution to the prob lem. Patrick ----- Original Message ----- From: "Stefan Plantikow" To: "Niko Matsakis" Cc: rust-dev at mozilla.org Sent: Wednesday, December 21, 2011 1:44:06 PM Subject: Re: [rust-dev] minor things that annoy you about Rust? Am 20.12.2011 um 19:16 schrieb Niko Matsakis: 3. Some way to deal with nullary tags in patterns. From graydon at mozilla.com Thu Dec 22 16:29:03 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 22 Dec 2011 16:29:03 -0800 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <566812896.50140.1324600051195.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> References: <566812896.50140.1324600051195.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: <4EF3CB4F.6020509@mozilla.com> On 11-12-22 04:27 PM, Patrick Walton wrote: > I would really like to advocate once again for Standard ML's solution: simply disambiguate variable bindings and tag constructors at the name resolution phase. Yeah. I'm not as horrified by this as I was the first time I heard it. Especially now that we have (say) 3 namespaces and now a form of static overloading. It seems like we are growing "too hard for trivial tools" name resolution anyways. Was nice while it existed. Marijn's note on the wiki[1] about this says he is not a fan. Is this still true? Is the opposition strong or weak? https://github.com/graydon/rust/wiki/Syntactic-issues-in-pattern-matching -Graydon From arcata at gmail.com Thu Dec 22 16:35:48 2011 From: arcata at gmail.com (Joe Groff) Date: Thu, 22 Dec 2011 16:35:48 -0800 Subject: [rust-dev] Fwd: minor things that annoy you about Rust? In-Reply-To: <114149653.49922.1324599211944.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> References: <4EF38B1F.7040904@mozilla.com> <114149653.49922.1324599211944.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: On Thu, Dec 22, 2011 at 4:13 PM, Patrick Walton wrote: > How about inferring the type of unadorned literals only, and allow an "i" > suffix to force regular int interpretation? That way the programmer is free > to make the judgment call of readability of code vs. clarity of intent > herself. > > We could also potentially investigate making the machine integer types > have shorter suffixes. There are plenty of letters to go around. As a game engine and numerics nerd I could see spraying '_f32' or '_f80' everywhere getting old fast too. Repurposing 'f' to mean 'f32' would be a nice olive branch to C programmers (with type checking to catch when you forget it!), especially when current '1f' can just as well be written '1.' . -Joe -------------- next part -------------- An HTML attachment was scrubbed... URL: From jws at csse.unimelb.edu.au Thu Dec 22 18:01:36 2011 From: jws at csse.unimelb.edu.au (Jeff Schultz) Date: Fri, 23 Dec 2011 13:01:36 +1100 Subject: [rust-dev] Fwd: minor things that annoy you about Rust? In-Reply-To: <4EF38B1F.7040904@mozilla.com> References: <4EF0D10F.9090702@alum.mit.edu> <4EF38B1F.7040904@mozilla.com> Message-ID: <20111223020136.GA9368@mulga.csse.unimelb.edu.au> On Thu, Dec 22, 2011 at 11:55:11AM -0800, Graydon Hoare wrote: > I'm curious how many of the people upset at the literal suffixes know the > number-literal syntax permits inserting underscores, so you can write this > as (say): > 0x_00ab_cdef_i32 > Which is how I tend to write any suffixed literal that's not a very simple > one (eg. 0u or such). I expect that for every 0x_00ab_cdef_i32, there will be many 0x00abcdefi32, and I, for one, will find it difficult to notice the i32 suffix. Perhaps an '_' should be required. I.e. 0x00abcdef_i32 would be a valid literal and 0x00abcdefi32 would not. Jeff Schultz From graydon at mozilla.com Thu Dec 22 18:09:46 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 22 Dec 2011 18:09:46 -0800 Subject: [rust-dev] log modified somewhat Message-ID: <4EF3E2EA.8020209@mozilla.com> Hi, I've changed the interpretation of 'log' a bit, and removed log_err. Since this is relatively user-visible I thought I'd mention it here. Full detail is in the end of the bug: https://github.com/graydon/rust/issues/1087 I'll update documentation tomorrow. -Graydon From marijnh at gmail.com Fri Dec 23 01:15:31 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Fri, 23 Dec 2011 10:15:31 +0100 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <4EF3CB4F.6020509@mozilla.com> References: <566812896.50140.1324600051195.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> <4EF3CB4F.6020509@mozilla.com> Message-ID: > Marijn's note on the wiki[1] about this says he is not a fan. Is this still > true? Is the opposition strong or weak? I'm still not optimistic. I think we'll want to extend pattern matching to also handle matching against constants and maybe even local variables. So probably the rule would end up being that you can't shadow something with a pattern binding. I'm okay with trying that and seeing how it works out, but I *am* worried that it'd introduce a new problem -- the set of names that you can bind will be much reduced, and adding something somewhere up the scope chain will invalidate code further down. From me at kevincantu.org Fri Dec 23 03:52:18 2011 From: me at kevincantu.org (Kevin Cantu) Date: Fri, 23 Dec 2011 03:52:18 -0800 Subject: [rust-dev] names needed for function types In-Reply-To: <1875284772.18652.1324421443332.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> References: <4EF1089D.4040007@alum.mit.edu> <1875284772.18652.1324421443332.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: If I understand things right, a block has a mutable closure, while either a lambda or a sendfn has an immutable closure? The idea that a fn (no closure) could implicitly turn into a block (mutable closure) seemed freaky when I read the tutorial. For immutability by default, wouldn't a lambda or sendfn be better? If an immutable, sendable default makes the most sense, rename "sendfn" to "fn". If every new user like me writes fn, where will the performance and readability penalties fall? Cheers, Kevin -------------- next part -------------- An HTML attachment was scrubbed... URL: From marijnh at gmail.com Fri Dec 23 04:06:53 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Fri, 23 Dec 2011 13:06:53 +0100 Subject: [rust-dev] names needed for function types In-Reply-To: References: <4EF1089D.4040007@alum.mit.edu> <1875284772.18652.1324421443332.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: > The idea that a fn (no closure) could implicitly turn into a block (mutable > closure) seemed freaky when I read the tutorial. There is no actual allocation going on -- the function pointer is paired with a null environment pointer, and that's the closure. You pay nothing, and since a (non-closing) fn can't do anything that a closure couldn't do, I'm not sure why you'd call this freaky. From me at kevincantu.org Fri Dec 23 04:39:48 2011 From: me at kevincantu.org (Kevin Cantu) Date: Fri, 23 Dec 2011 04:39:48 -0800 Subject: [rust-dev] names needed for function types In-Reply-To: References: <4EF1089D.4040007@alum.mit.edu> <1875284772.18652.1324421443332.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: I wasn't saying the implementation sounded freaky. I was just imagining looking at a 30,000 line Rust source file with large fn definitions and trying to figure out whether each one is a block with interesting side effects through the mutable closure or not. On Fri, Dec 23, 2011 at 4:06 AM, Marijn Haverbeke wrote: > > The idea that a fn (no closure) could implicitly turn into a block > (mutable > > closure) seemed freaky when I read the tutorial. > > There is no actual allocation going on -- the function pointer is > paired with a null environment pointer, and that's the closure. You > pay nothing, and since a (non-closing) fn can't do anything that a > closure couldn't do, I'm not sure why you'd call this freaky. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From marijnh at gmail.com Fri Dec 23 05:24:58 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Fri, 23 Dec 2011 14:24:58 +0100 Subject: [rust-dev] names needed for function types In-Reply-To: References: <4EF1089D.4040007@alum.mit.edu> <1875284772.18652.1324421443332.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: > I wasn't saying the implementation sounded freaky. ?I was just imagining > looking at a 30,000 line Rust source file with large fn definitions and > trying to figure out whether each one is a block with interesting side > effects through the mutable closure or not. They don't become closures. They just can be passed to functions that expect closures. From graydon at mozilla.com Fri Dec 23 11:16:33 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 23 Dec 2011 11:16:33 -0800 Subject: [rust-dev] unicode support and core Message-ID: <4EF4D391.90804@mozilla.com> Hi, I've been poking around with the issue of unicode support, which I think is very important in the language, but carries a bit of a ... tension in terms of what we include and at-what-level of the libraries. Namely: the canonical "unicode implementation" in the world is libicu, in terms of completeness and correctness and such, and it's *huge*. A full build of it is like 16mb or so. So while I'd love to expose all of libicu as core::char and core::str -- to take the needs of unicode-text-as-advertized seriously -- part of me thinks that making such a physically-large dependency part of the "minimum library for nontrivial rust programs" might offend as many people as it pleases. I see a few possible solutions to this: 1. Manually convert (using helper scripts of such) a small "important" chunk of the unicode data tables into rust code and include that in core, with a binding to the "full" libicu as a component of std or even an external crate in cargo. 2. Integrate libicu as a submodule but make a minimalist build of it part of our core library. There are a lot of optional parts; leave out the less-important parts. 3. Integrate libicu as a submodule and build the whole thing, unicode is too important to skimp on. 4. ??? some other option I'm going to be exploring #2 today in the sense of finding out how small a build I can make while still including "the important parts". I'll report further here when I find out. But in the meantime I'm curious what people think about this issue. I'm also curious what people think are "the important parts" of unicode. This is more of a solicitation for input from actual unicode experts. It's a giant standard and I'm curious who, if anyone on this list, has a clear picture of sensible ways to divide it up. -Graydon From pwalton at mozilla.com Fri Dec 23 11:34:06 2011 From: pwalton at mozilla.com (Patrick Walton) Date: Fri, 23 Dec 2011 11:34:06 -0800 (PST) Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: Message-ID: <1038365900.56132.1324668846697.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> I do agree that the action-at-a-distance is a potential problem, but experience suggests that the Standard ML rule leads to the bad outcome less often than the other alternatives. At this point I've tried all four alternatives (variable-by-default, tag-by-default, case sensitivity, and the Standard ML rule) and in my experience the last two avoid mixups far more than the first two do. If I'm not mistaken, the Standard ML rule makes it impossible to allow local variable matching in patterns, because you'd be unable to shadow local variables and I suspect we probably don't want to go down that road. But I'm okay with using guards for matching against local variables. Patrick ----- Original Message ----- From: "Marijn Haverbeke" To: "Graydon Hoare" Cc: rust-dev at mozilla.org Sent: Friday, December 23, 2011 4:15:31 AM Subject: Re: [rust-dev] minor things that annoy you about Rust? > Marijn's note on the wiki[1] about this says he is not a fan. Is this still > true? Is the opposition strong or weak? I'm still not optimistic. I think we'll want to extend pattern matching to also handle matching against constants and maybe even local variables. So probably the rule would end up being that you can't shadow something with a pattern binding. I'm okay with trying that and seeing how it works out, but I *am* worried that it'd introduce a new problem -- the set of names that you can bind will be much reduced, and adding something somewhere up the scope chain will invalidate code further down. _______________________________________________ Rust-dev mailing list Rust-dev at mozilla.org https://mail.mozilla.org/listinfo/rust-dev From graydon at mozilla.com Fri Dec 23 11:34:04 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 23 Dec 2011 11:34:04 -0800 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <1038365900.56132.1324668846697.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> References: <1038365900.56132.1324668846697.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: <4EF4D7AC.7010005@mozilla.com> On 11-12-23 11:34 AM, Patrick Walton wrote: > I do agree that the action-at-a-distance is a potential problem, but experience suggests that the Standard ML rule leads to the bad outcome less often than the other alternatives. At this point I've tried all four alternatives (variable-by-default, tag-by-default, case sensitivity, and the Standard ML rule) and in my experience the last two avoid mixups far more than the first two do. > > If I'm not mistaken, the Standard ML rule makes it impossible to allow local variable matching in patterns, because you'd be unable to shadow local variables and I suspect we probably don't want to go down that road. But I'm okay with using guards for matching against local variables. Yeah. One thing that concerns me about that is that it means we lose the ability to write rebind-the-variable functional-style code: let x = foo(bleh); let x = thing(x); let x = other(x); ... Personally I find this style ... cute enough, in languages where local mutation is syntactically clunky, but for us I think it's not super important to support. We can just re-assign to the same local; it's terrible form to be changing the type of a variable part way through a function anyways. (I'm warming up to the concept of differentiating locally-mutable and locally-immutable variables using 'mut ...' and 'let ...' though) -Graydon From marijnh at gmail.com Fri Dec 23 12:00:06 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Fri, 23 Dec 2011 21:00:06 +0100 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: <4EF4D7AC.7010005@mozilla.com> References: <1038365900.56132.1324668846697.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> <4EF4D7AC.7010005@mozilla.com> Message-ID: > Yeah. One thing that concerns me about that is that it means we lose the > ability to write rebind-the-variable functional-style code: Oh. You'd make this apply to irrevocable patterns as well? Or do you intend to get rid of the restriction that let patterns are irrevocable? In the second case, I think I'd prefer a 'you can shadow anything, except consts and tag variants' rule to a blanket 'no shadowing' one. From marijnh at gmail.com Fri Dec 23 12:03:11 2011 From: marijnh at gmail.com (Marijn Haverbeke) Date: Fri, 23 Dec 2011 21:03:11 +0100 Subject: [rust-dev] unicode support and core In-Reply-To: <4EF4D391.90804@mozilla.com> References: <4EF4D391.90804@mozilla.com> Message-ID: > I'm also curious what people think are "the important parts" of unicode. Character classification is very important, and should be in core I think (if only to encourage people to actually use it instead of rolling their own... badly). Encodings are something people will occasionally need, but a much less important thing. This doesn't have to be in core, I think. (And, if I understand correctly, much of libicu is encoding tables.) From graydon at mozilla.com Fri Dec 23 19:00:13 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 23 Dec 2011 19:00:13 -0800 Subject: [rust-dev] unicode support and core In-Reply-To: References: <4EF4D391.90804@mozilla.com> Message-ID: <4EF5403D.3000905@mozilla.com> On 11-12-23 12:03 PM, Marijn Haverbeke wrote: >> I'm also curious what people think are "the important parts" of unicode. > > Character classification is very important, and should be in core I > think (if only to encourage people to actually use it instead of > rolling their own... badly). Yeah. I looked at ways of doing a minimalist build of libicu today and it just gets really, really gross. Also it's a lot of layers of indirection for something that ought to be pretty fast (core lexing routines and such). So I just did a python-conversion monstrosity into rust code. Adds about 80kb to libcore optimized and gets us the general categories and a couple important derived properties (XID_Start / Continue, Alphabetic). > Encodings are something people will occasionally need, but a much less > important thing. This doesn't have to be in core, I think. (And, if I > understand correctly, much of libicu is encoding tables.) Agreed. I think it's fine if we keep this stuff in a "full" binding to libicu outside core. I'll keep updating the char API and munged unicode data tables as needed, but this seems semi-workable. (We'll probably need NFKC and a couple other bits in core, but hopefully not *too* much.) -Graydon From rust at kudling.de Sat Dec 24 02:03:36 2011 From: rust at kudling.de (Rust) Date: Sat, 24 Dec 2011 11:03:36 +0100 (CET) Subject: [rust-dev] unicode support and core Message-ID: <1483334211.983263.1324721016998.JavaMail.open-xchange@email.1und1.de Hi, ? I've opened pull request #1382 to add is_lower/uppercase() to "char". ? I wonder if and how we will be implementing to_lower/uppercase() 1) without including libicu in libcore 2) without replicating libicu functionality ? Can you point me to a specification of libcore's aim and scope? I don't yet see why we need to have the modules "char" and "str" in there at all.? ? I start to think we should have only one correct and complete char/str implementation and that would be ontop of libicu in libstd. ? Bye, Lenny -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Sat Dec 24 05:45:09 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 24 Dec 2011 05:45:09 -0800 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: References: <1038365900.56132.1324668846697.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> <4EF4D7AC.7010005@mozilla.com> Message-ID: What about "disallow shadowing unless you use the `let` keyword"? Sometimes shadowing is nice and sometimes (think macros) you want to use a name and know its meaning without regard to existing exterior bindings. So you could write: let a = ...; let b = ...; alt foo { bar(a, let b) { ... } } this would match a `bar` whose first argument is equal to `a` and with any second argument. We could also allow the `let` to be used at different levels: alt foo { let bar(a, b) { ... } } This would also allow `let x = y;` to continue shadowing bindings. We could also then permit things like: (a, let b) = ...; which I think Marijn was asking for a while back. After having hacked trans for a while, I can see why! I'm always writing: let foo = trans_this_or_that(); bcx = foo.bcx; and it would be nicer to write: (bcx, let val) = trans_this_or_that(); Niko On Fri, Dec 23, 2011 at 12:00 PM, Marijn Haverbeke wrote: > > Yeah. One thing that concerns me about that is that it means we lose the > > ability to write rebind-the-variable functional-style code: > > Oh. You'd make this apply to irrevocable patterns as well? Or do you > intend to get rid of the restriction that let patterns are > irrevocable? > > In the second case, I think I'd prefer a 'you can shadow anything, > except consts and tag variants' rule to a blanket 'no shadowing' one. > _______________________________________________ > 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 Sat Dec 24 05:52:14 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 24 Dec 2011 05:52:14 -0800 Subject: [rust-dev] minor things that annoy you about Rust? In-Reply-To: References: <1038365900.56132.1324668846697.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> <4EF4D7AC.7010005@mozilla.com> Message-ID: Now that I sent the mail, I'm already second guessing this suggestion. It introduces an asymmetry in that new variable names can be introduced in an `alt` block without a `let` prefix, but not in a normal assignment (in a normal assignment). And I'm sure Dave will point out that much better solutions exist to avoid having macros capture outside names. On Sat, Dec 24, 2011 at 5:45 AM, Niko Matsakis wrote: > What about "disallow shadowing unless you use the `let` keyword"? > Sometimes shadowing is nice and sometimes (think macros) you want to use a > name and know its meaning without regard to existing exterior bindings. > > So you could write: > > let a = ...; > let b = ...; > alt foo { > bar(a, let b) { ... } > } > > this would match a `bar` whose first argument is equal to `a` and with any > second argument. > > We could also allow the `let` to be used at different levels: > > alt foo { > let bar(a, b) { ... } > } > > This would also allow `let x = y;` to continue shadowing bindings. We > could also then permit things like: > > (a, let b) = ...; > > which I think Marijn was asking for a while back. After having hacked > trans for a while, I can see why! I'm always writing: > > let foo = trans_this_or_that(); > bcx = foo.bcx; > > and it would be nicer to write: > > (bcx, let val) = trans_this_or_that(); > > > Niko > > > On Fri, Dec 23, 2011 at 12:00 PM, Marijn Haverbeke wrote: > >> > Yeah. One thing that concerns me about that is that it means we lose the >> > ability to write rebind-the-variable functional-style code: >> >> Oh. You'd make this apply to irrevocable patterns as well? Or do you >> intend to get rid of the restriction that let patterns are >> irrevocable? >> >> In the second case, I think I'd prefer a 'you can shadow anything, >> except consts and tag variants' rule to a blanket 'no shadowing' one. >> _______________________________________________ >> 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 rust at kudling.de Mon Dec 26 14:34:27 2011 From: rust at kudling.de (Rust) Date: Mon, 26 Dec 2011 23:34:27 +0100 (CET) Subject: [rust-dev] Typestate 2.0 ? Message-ID: <1069466229.985379.1324938867926.JavaMail.open-xchange@email.1und1.de Hi, ? I've been thinking about the unhappiness with Typestate (see e.g. issue #1105). ? Let me first give a naive example: I want to access the second element of a vector using "head()"/"tail()": ? ? let a = [1, 2, 3]; ? let b = vec::head(vec::tail(a)); ? But Typestate wants me to write: ? ? let a = [1, 2, 3]; ? check vec::is_not_empty(a); ? let b = vec::tail(a); ? check vec::is_not_empty(b); ? let c = vec::head(b); ? Here is a dopey idea: ? First let's replace "head"'s predicate "is_not_empty()" with a different predicate "has_minimum_length_one()".?Let's now look at the above example in reverse: ? ? let c = vec::head(b); // b's length must be >= 1, in order to satisfy "has_minimum_length_one(b)" ? let b = vec::tail(a); // "tail()" drops the head element, thus a's length must be >= 2 ? let a = [1, 2, 3]; // a's length is 3, which is >= 2, everything is fine ? So ? ? let a = [1, 2, 3];?? let b = vec::head(vec::tail(a)); ? could be deduced to compile and be correct, if we could 1) make Typestate know that some functions ("tail()" in this example)?change properties, which are relevant to the predicates it verifies 2) make Typestate backtrack those property changes and predicates. ? Does that make sense? Bye, Lenny -------------- next part -------------- An HTML attachment was scrubbed... URL: From graydon at mozilla.com Wed Dec 28 14:26:23 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 28 Dec 2011 14:26:23 -0800 Subject: [rust-dev] Typestate 2.0 ? In-Reply-To: <1069466229.985379.1324938867926.JavaMail.open-xchange@email.1und1.de References: <1069466229.985379.1324938867926.JavaMail.open-xchange@email.1und1.de Message-ID: <4EFB978F.8020608@mozilla.com> On 11-12-26 02:34 PM, Rust wrote: > I've been thinking about the unhappiness with Typestate (see e.g. issue > #1105). I think the example in that bug is probably not a good candidate for typestate, at least as it currently stands. Lists are constantly being destructured and empty-list is a valid return from 'tail' when working with lists, even if we had working function postconditions. > So > > let a = [1, 2, 3]; let b = vec::head(vec::tail(a)); > > could be deduced to compile and be correct, if we could > > 1) make Typestate know that some functions ("tail()" in this example) > change properties, which are relevant to the predicates it verifies > > 2) make Typestate backtrack those property changes and predicates. > > Does that make sense? It "makes sense" in the sense that people have designed systems that do this and you could design such a system for Rust. It would not use any of the mechanisms of the existing typestate system. The road you're going down is called 'dependent types', and we're not going to be writing a dependent-typed language here; it's more cognitive load than we can possibly cram in while maintaining coherence, IMO. You probably want ATS, which is Hongwei Xi's current research vehicle. It's a great language. It's also far more complex than Rust, and we're not going to be emulating most of those features here. If typestate turns out to be unusable for anything interesting in its current level-of-power -- plus or minus minor usability adjustments -- we're more likely to remove it altogether than try to enhance it to the theoretical level of dependent types. They're a Big Deal. There's still a lot of unfinished work in typestate-as-designed though. We need function postconditions and some form of constraint-carrying types, and may well want to have a careful kind of check-inference pass for simple predicates. The feature's not done yet, it's just resting. -Graydon From sebastian.sylvan at gmail.com Wed Dec 28 15:10:00 2011 From: sebastian.sylvan at gmail.com (Sebastian Sylvan) Date: Wed, 28 Dec 2011 15:10:00 -0800 Subject: [rust-dev] Typestate 2.0 ? In-Reply-To: <4EFB978F.8020608@mozilla.com> References: <4EFB978F.8020608@mozilla.com> Message-ID: On Wed, Dec 28, 2011 at 2:26 PM, Graydon Hoare wrote: > If typestate turns out to be unusable for anything interesting in its > current level-of-power -- plus or minus minor usability adjustments -- we're > more likely to remove it altogether than try to enhance it to the > theoretical level of dependent types. They're a Big Deal. An alternative would be to special case support for integers in types/predicates, as they seem to cover the vast majority of the use cases for "simple" dependent types (i.e. the ones you'd actually want to write). For example, you'd be able to track that the length of a list is within some static bounds, and adjust them after each operation that may modify the list's length so that the bounds remain conservative, and then when passing it to something that requires that it has >1 element in it, you can determine if this is true or false or not statically knowable (the latter would require a runtime check). So simple logic, special cased for just integers (and maybe some handful of other simple things), but not a full dependent type system. It's ad-hoc, but it may be that some simple "hacks" like this covers the majority of the benefit of dependent types without the complexity of a general system. -- Sebastian Sylvan From dherman at mozilla.com Wed Dec 28 15:18:11 2011 From: dherman at mozilla.com (David Herman) Date: Wed, 28 Dec 2011 15:18:11 -0800 Subject: [rust-dev] Typestate 2.0 ? In-Reply-To: References: <4EFB978F.8020608@mozilla.com> Message-ID: On Dec 28, 2011, at 3:10 PM, Sebastian Sylvan wrote: > So simple logic, special cased for just integers (and maybe some > handful of other simple things), but not a full dependent type system. Sounds like Hongwei Xi's dissertation. I.e., *way* more complicated than you're making it out to be. :) This direction sounds too researchy for Rust. I don't think it's the right direction. Dave From graydon at mozilla.com Wed Dec 28 15:34:31 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 28 Dec 2011 15:34:31 -0800 Subject: [rust-dev] unicode support and core In-Reply-To: <1483334211.983263.1324721016998.JavaMail.open-xchange@email.1und1.de References: <1483334211.983263.1324721016998.JavaMail.open-xchange@email.1und1.de Message-ID: <4EFBA787.2030505@mozilla.com> On 11-12-24 02:03 AM, Rust wrote: > Hi, > > I've opened pull request #1382 to add is_lower/uppercase() to "char". > > I wonder if and how we will be implementing to_lower/uppercase() > > 1) without including libicu in libcore > > 2) without replicating libicu functionality My aim at the moment is to make a version of libcore that can do "reasonable" versions of "basic" operations on unicode str and char types, without requiring that a very-large and complete implementation of unicode such as libicu accompany all rust programs. So that would be a violation of your #2 point: we're duplicating *some* (minimal, modest) libicu functionality in libcore. I would then like to provide a binding to libicu -- either in std or as a separately-packaged crate -- that exposes the "full" set of unicode operations (regular expressions, date/time formatting, locale-specific collation, etc. etc.) > Can you point me to a specification of libcore's aim and scope? https://mail.mozilla.org/pipermail/rust-dev/2011-December/001037.html > I don't yet see why we need to have the modules "char" and "str" in > there at all. Because they are support modules corresponding to built-in types in the language. Some operations on them will be much more common than others. The decision of what is "common" or "basic" is, I admit, a matter of taste, influenced by many factors. Code-footprint of the logic is one of them. > I start to think we should have only one correct and complete char/str > implementation and that would be ontop of libicu in libstd. I disagree. This is analogous to saying that the math library in libcore (or even libstd) ought to do everything GSL[1] does because that's what a "real" math library does. It's certainly *nice* to provide such a "full" library, but it's also nice to provide a more-common subset that can be shipped without imposing the same code-footprint costs. (Example: people will likely be shipping rust code on phones. We'd like them to be able to make a rust program that can be redistributed in a download size that's less than 16mb, which is how big libicu is.) -Graydon [1] http://www.gnu.org/software/gsl/ From graydon at mozilla.com Wed Dec 28 15:52:49 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 28 Dec 2011 15:52:49 -0800 Subject: [rust-dev] Typestate 2.0 ? In-Reply-To: References: <4EFB978F.8020608@mozilla.com> Message-ID: <4EFBABD1.2060509@mozilla.com> On 11-12-28 03:10 PM, Sebastian Sylvan wrote: > So simple logic, special cased for just integers (and maybe some > handful of other simple things), but not a full dependent type system. > It's ad-hoc, but it may be that some simple "hacks" like this covers > the majority of the benefit of dependent types without the complexity > of a general system. This gets Very Hard, much faster than it seems. Recall how small a language has to be before it crosses the decidability threshold; the hacks are very likely to stumble from Presburger into Robinson arithmetic without meaning it. Even if they don't, it's effectively injecting a first-order theorem prover in the middle of the compiler; we don't have the complexity budget in our syntax, semantics, implementation footprint or user cognitive load to begin going there. Our existing typechecker is confusing enough! There *are* people doing this work, but it's a lot more care required than a collection of hacks, and as Dave says it's very researchy, not a direction we're likely to take Rust. You want ATS or the Boogie verifier on Spec# or something. -Graydon From me at kevincantu.org Thu Dec 29 04:06:07 2011 From: me at kevincantu.org (Kevin Cantu) Date: Thu, 29 Dec 2011 04:06:07 -0800 Subject: [rust-dev] names needed for function types In-Reply-To: References: <4EF1089D.4040007@alum.mit.edu> <1875284772.18652.1324421443332.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: Ahh, I think I understand how things work much better now. There are, as listed before, four function types now: ?- fn: no closure ?- sendfn: unique, immutable closure ?-?lambda: shared, immutable closure (a.k.a. fn@) ?-?block: mutable stack reference (a.k.a. fn&) These types can be used in a?hierarchy, where fn (having no closure) is the most general, and block is the least general. ?That is, a fn can be used as an argument where any of the other three are expected, but a block can only be used where a block is expected. ?There's currently a quirk to this: sendfn and lambda are not?interchangeable either way, so there are really two hierarchies: ?- fn < lambda < block ?- fn < sendfn < block There are also currently three ways to define these functions, too, they can't each be defined each way: ?- fn xyz (arg) {...} ? ? ? ? ? ? - for fn only ?- let xyz = fn (arg) {...} ? ? ?- for fn, sendfn, or lambda ?- {|arg| ...} ? ? ? ? ? ? ? ? ? ? ? - for all (in progress) So, if Rust did away with block, renaming block to fn, would the behavior of fn definitions be preserved? ?Could the unified fn become a type that could sometimes be used in places requiring a sendfn or a lambda, but not always?? Earlier, I was imagining a hierarchy like fn < sendfn < lambda < block, where it would seem logical to just knock it down to fn < lambda < block. But there are things I have to learn about sendfn vs. lambda... Kevin From niko at alum.mit.edu Thu Dec 29 12:48:34 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 29 Dec 2011 12:48:34 -0800 Subject: [rust-dev] syntactic sugar for blocks in expressions Message-ID: <4EFCD222.1040606@alum.mit.edu> I've been working for a while now on making it possible to use the syntactic sugar for blocks within expressions. I've been doing various iterations, trying to find the formulation that was both (a) easy enough to explain and (b) made minimal changes to the existing language syntax / code. Although I think my changes only affect corner cases, they are not backwards compatible, so I wanted to run the proposal by the list before pushing it to master. First, the goal of the change is to allow expressions like: let v = vec::map(v) { |e| ... }; Currently, these must be written: let v = vec::map(v, { |e| ... }); The syntactic sugar which allows the final block argument to appear outside the parentheses is only currently permitted for top-level statements. Furthermore, the result of such a sugared statement is *always* ignored. So something like this would parse but not type check: fn foo(v: [T]) -> bool { vec::any(v) { |e| test_some_condition(e) } } Here the `vec::any(v) {||}` call would not be interpreted as the result of the block but rather as a call whose result should be discarded, similar to how a `while` loop would be interpreted. To fix I made the following changes: 1. Dual-mode expressions like `if`, `while`, `do-while`, blocks, and of course sugared calls cannot be followed by binary operators or further calls when they appear at the top level (i.e., not nested within some other statement or expression). 2. All blocks may have tail expressions. The type checker will guarantee that the tail expressions have unit type when they appear in the body of a while loop or other similar context. This used to be enforced by the parser. Across the entire compiler, two changes were required as a result of these rules. As it happens, one change was required by rule #1 and one by rule #2, so they also serve as a good way to explain the rules. ## Change #1: combining a dual-mode expression with a binary operator ## This function fn companion_file(prefix: str, suffix: option::t) -> str { alt suffix { option::some(s) { fs::connect(prefix, s) } option::none. { prefix } } + ".rs" } no longer parses. This is because the `alt suffix {...}` is parsed as a statement because it begins the statement. Therefore, the `+".rs"` is parsed as an expression, and `+` is not a legal unary operator. This function had to be changed as follows: fn companion_file(prefix: str, suffix: option::t) -> str { ret alt suffix { option::some(s) { fs::connect(prefix, s) } option::none. { prefix } } + ".rs"; } Here I used a `ret` to place the `alt` into expression position. You could also have used parentheses: fn companion_file(prefix: str, suffix: option::t) -> str { (alt suffix { option::some(s) { fs::connect(prefix, s) } option::none. { prefix } } + ".rs") } ## Change #2: ignoring the result value ## The following function from rope.rs no longer type checks: fn iter_chars(rope: rope, it: block(char)) { loop_chars(rope) {|x| it(x); true } } The type check fails because the `loop_chars()` function returns a boolean value. The call appears in the tail position of the function `iter_chars()` which has a unit return type. So there is a type error "expected `()` but found`boolean`". The fix is simply to introduce an explicit semicolon to ignore the result: fn iter_chars(rope: rope, it: block(char)) { loop_chars(rope) {|x| it(x); true }; } ## More details ## If you want more details, I wrote up the various options I considered here: Ok, that's it, thoughts? Niko From rust at kudling.de Fri Dec 30 02:50:46 2011 From: rust at kudling.de (Rust) Date: Fri, 30 Dec 2011 11:50:46 +0100 (CET) Subject: [rust-dev] "make install" problems Message-ID: <18213988.1104367.1325242247139.JavaMail.open-xchange@email.1und1.de Hi, if i do a "../configure --prefix=$HOME && make check && make install" i see the following problems: 1) cargo is not found: install: /Users/lenny/bin/rustc install: /Users/lenny/bin/cargo cp: x86_64-apple-darwin/stage3/bin/cargo: No such file or directory?make: *** [install-host] Error 1 2) if i call rustc it says: "error: can't find crate for 'core'" ~/lib gets created, but it's empty. The rustc from stage3 seems to be fine. Any idea what is wrong? Bye, Lenny -------------- next part -------------- An HTML attachment was scrubbed... URL: From lihaitao at gmail.com Fri Dec 30 03:25:42 2011 From: lihaitao at gmail.com (Haitao Li) Date: Fri, 30 Dec 2011 19:25:42 +0800 Subject: [rust-dev] "make install" problems In-Reply-To: <4efd978e.6a32440a.7e87.ffffed95SMTPIN_ADDED@mx.google.com> References: <4efd978e.6a32440a.7e87.ffffed95SMTPIN_ADDED@mx.google.com> Message-ID: > > if i do a "../configure --prefix=$HOME && make check && make install" > You need to run a `make' before `make check'. `make all' will build cargo. I'm not sure if this is a bug of the Makefile or wiki page, since there are no test for cargo, yet. /Haitao From rust at kudling.de Fri Dec 30 05:03:59 2011 From: rust at kudling.de (Rust) Date: Fri, 30 Dec 2011 14:03:59 +0100 (CET) Subject: [rust-dev] N-Body Performance Message-ID: <1784492833.1111840.1325250240131.JavaMail.open-xchange@email.1und1.de Hi, ? i know, we should not look too seriously at micro-benchmarks. But i was tempted to see how Rust handles the Shootout N-Body benchmark. ? Here are my numbers: ? Java: ? -0.169075164 -0.169059907 real 0m12.238s user 0m11.935s sys 0m0.053s ? Rust: ? -0.169075163 -0.169059906 real 0m25.037s user 0m25.027s sys 0m0.015s ? Haskell/GHC: ? -0.169075164 -0.169059907 real 0m30.237s user 0m30.036s sys 0m0.076s ? Rust (--opt-level 3 --no-verify) currently seems to be slower than Java (1.6.0), but slightly faster than GHC (7.0.4) on my machine. ? Bye, Lenny -------------- next part -------------- An HTML attachment was scrubbed... URL: From graydon at mozilla.com Fri Dec 30 07:16:59 2011 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 30 Dec 2011 07:16:59 -0800 Subject: [rust-dev] "make install" problems In-Reply-To: References: <4efd978e.6a32440a.7e87.ffffed95SMTPIN_ADDED@mx.google.com> Message-ID: <4EFDD5EB.7010703@mozilla.com> On 30/12/2011 3:25 AM, Haitao Li wrote: > You need to run a `make' before `make check'. `make all' will build cargo. > > I'm not sure if this is a bug of the Makefile or wiki page, since > there are no test for cargo, yet. That's a bug. Check and install should both have 'all' as a prereq. Filed as #1395, blocking (it's easy). -Graydon From niko at alum.mit.edu Fri Dec 30 10:00:16 2011 From: niko at alum.mit.edu (Niko Matsakis) Date: Fri, 30 Dec 2011 10:00:16 -0800 Subject: [rust-dev] names needed for function types In-Reply-To: <1875284772.18652.1324421443332.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> References: <1875284772.18652.1324421443332.JavaMail.root@zimbra1.shared.sjc1.mozilla.com> Message-ID: <4EFDFC30.7030706@alum.mit.edu> So I've been thinking about this naming issue since at the moment I am somewhat blocked for names. It seems to me that there are two orthogonal features which are somewhat tied together in our current closure system: - how the environment is referenced; - what data the environment contains. A unique closure references its environment by a unique pointer (~) and only permits the environment to contain sendable data. A boxed closure (lambda) references the environment via a box pointer (@) and only permits the environment to contain copyable data. I am not proposing we separate these things: I don't think there is a need to have a unique pointer to an environment that closes over copyable data nor boxed closures that close over only sendable data. However, the choice of names for unique/boxed closures will probably depend on which of these two features we wish to emphasize. I like the idea that "fn" is just the type of a general closure (i.e., "block"). I agree it's what you want most of the time. I think that there are then three logical choices for boxed/unique closures: 1. `fn@` and `fn~`: this is intended to emphasize the fact that the environment is referenced by a boxed/unique pointer. I don't know how intuitive it is and it makes heavy use of sigils. 2. `copyfn` or `sendfn`: this emphasizes the kind restrictions. This is also nice because a `copyfn` is copyable and a `sendfn` is sendable, whereas a plain `fn` is neither. 3. `fn[copy]` and `fn[send]`: an alternate version of #2 that I find more visually appealing. Of these, I prefer `fn[copy]` and `fn[send]`. My only reservation is that the syntax meshes reasonably somewhat awkwardly with capture clauses in the copy case. A capture clause is used to specify variables you wish to copy/move out of the environment; if we moved to `fn[copy]` and `fn[send]`, it will also specify the kind restriction. So, you would write: let block_1 = fn(x: T, y: U) -> V { ... }; // currently not legal but should be, I think let boxed_closure_1 = fn[copy](x: T, y: U) -> V { ... }; let unique_closure_1 = fn[send](x: T, y: U) -> V { ... }; and if you wanted to copy the variable `a` out of the environment explicitly and move the variable `b`, you would write: let boxed_closure_2 = fn[copy a; move b](x: T, y: U) -> V { ... }; let unique_closure_2 = fn[send; copy a; move b](x: T, y: U) -> V { ... }; Here you can see that the kind restriction melded with the request to `copy a`. At the moment, explicit copies are unnecessary anyhow, but I personally would like to make them required for mutable local variables or for variables whose types are not implicitly copyable (per the no copies proposal I sent out a while back). Thoughts? Niko On 12/20/11 2:50 PM, Brian Anderson wrote: > > ----- Original Message ----- >> From: "Niko Matsakis" >> To: rust-dev at mozilla.org >> Sent: Tuesday, December 20, 2011 2:13:49 PM >> Subject: [rust-dev] names needed for function types >> Per recent conversations, my current plan with regard to function >> types >> is to pare us back to three: >> >> - Unique closures (currently written "sendfn"), which can only close >> over sendable state, which is either copied or moved into the closure; >> - Shared closures (currently written "lambda" or "fn@"), which can >> copy >> or move arbitrary state off the stack frame and access it; >> - Blocks (currently written "block"), which access state from their >> creator's stack frame by reference and therefore cannot be used once >> their creator returns. > This will mean 'fn' can't be used as a type, unless it means two different things - I don't think it should both mean 'shared closure' and this non-type thing that can be instantiated as any type of closure. It's a shame that we have to think of a different name for the most common function type, but maybe not a big problem since you often want to use it as a block. > >> The question is: what should we call the various closure types? I >> think >> we need both good prose names and good keywords, ideally those are the >> same. >> > Rename 'block' to 'fn'. Reason: this is the type that most higher order functions take; it has symmetry with your proposal for fn declarations, in that fn declarations can be instantiated as either shared closures or unique closures. In common practice you would write 'fn' most everywhere. Only when you need to put a closure into a data structure or send it would you have to be more specific about the type. > > Still thinking about the other two.