Re: [rust-dev] Using Default Type Parameters
On Mon, Feb 3, 2014 at 7:55 AM, Corey Richardson wrote: > Default typarams are awesome, but they're gated, and there's some > concern that they'll interact unpleasantly with extensions to the type > system (most specifically, I've seen concern raised around HKT, where > there is conflicting tension about whether to put the "defaults" at > the start or end of the typaram list). > Just for reference, this was discussed here: https://github.com/mozilla/rust/pull/11217 (The tension is essentially that with default type args you want to put the "least important" types at the end, so they can be defaulted, while with HKT you want to put them at the front, so they don't get in the way of abstracting over the important ones.) ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] Using Default Type Parameters
Default typarams are awesome, but they're gated, and there's some concern that they'll interact unpleasantly with extensions to the type system (most specifically, I've seen concern raised around HKT, where there is conflicting tension about whether to put the "defaults" at the start or end of the typaram list). I've already come across situations where default typarams will make for a nicer API, but I'm wondering whether I should use them without hesitation, looking forward to when they are no longer gated, or whether I should shun them because they will make my code incompatible with future changes to the language. Is there any thoughts on this so far? This question also applies to other feature gatess; the level of assurance one can use a given feature with without having to deal with explosive breakage down the line. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Deprecating rustpkg
A general observation (not particularly replying to your post, Thomas). For both python and haskell (just to name two languages), distribution (where things end up on the filesystem ready to be used) can be done by both the built-in tools (cabal-install, pip) and the distribution-specific tools. Gentoo even has a tool to take a cabal package and generate an ebuild from it - https://github.com/gentoo-haskell/hackport. In the Haskell world cabal and cabal-install are separated ( http://ivanmiljenovic.wordpress.com/2010/03/15/repeat-after-me-cabal-is-not-a-package-manager/) - which is probably a good thing and maybe something we can consider for rustpkg. (The link btw is quite interesting in its own right and perhaps some more inspiration could be taken from there). My point is that a building tool should be able to either fetch or look up dependencies that already exist in a well-specified layout on the filesystem (for the case of development and production deployment using a distro package manager respectively). Whether that is a single tool or two tools is a point of design; I think both are necessary. I feel there is enough that's been discussed on this thread for a write-up on a wiki or the beginnings of a design/goals document that can later be presented for another discussion. I don't see an existing place on the wiki for this though - where should it go? On Sun, Feb 2, 2014 at 7:47 PM, Thomas Leonard wrote: > [ I don't want to start another argument, but since you guys are > discussing 0install, maybe I can provide some useful input... ] > > ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Deprecating rustpkg
[ I don't want to start another argument, but since you guys are discussing 0install, maybe I can provide some useful input... ] On 2014-02-02 07:20, Vladimir Matveev wrote: How will it handle external dependencies? I don't think it should. External dependencies are way too complex. They come in different flavors on different systems. On Windows, for example, you don't have a package manager, and you'll have to ship these dependencies with the program using an installer. On each Linux distro there is custom package manager, each having its own strategy of naming things and its own versioning policy. It is impossible to unify them, and I don't think that Rust package manager should attempt to do this. I don't understand this. A package manager specific to Rust is additional software, just like 0install. 0install has full support for installing dependencies via the system package manager on many systems if desired. *End users* won't need Rust package manager at all (unless they want to install development versions of Rust software). Only package maintainers and developers have to use it. End users just use their native package manager to obtain packages created by maintainers. If Rust would depend on zero install, however, end user will be *forced* to use zero install. I don't follow this. Whether the developer uses 0install to get the build dependencies doesn't make any difference to the generated binary. Of course, you *can* distribute the binary using 0install too, but you're not required to. I'm against of using zero install for the following reasons. First, it is just a packaging system. It is not supposed to help in building Rust software. But resolving build dependencies and invoking the compiler with correct paths to installed dependencies is crucial. How, for example, zero install would handle dependency to master branch of some source repository? 0install doesn't automatically check out Git repositories (although that would be handy). Here's how we currently do it: - Your program depends on libfoo >= 1.0-post - The latest released version of libfoo is only 1.0 - You "git clone" the libfoo repository yourself and register the metadata (feed) file inside it: $ git clone git://.../libfoo $ 0install add-feed libfoo/feed.xml - 0install now sees that libfoo 1.0 and 1.0-post are both available. Since your program requires libfoo >= 1.0-post, it will select the Git checkout version. > What if I'm developing several packages which depend on different versions of the same package? Zero install allows installing multiple versions of the same package, yes, but how should I specify where these libraries are located to the compiler? Given a set of requirements, 0install will tell you where some suitable versions of the dependencies are. For example: $ cd /tmp $ git clone https://github.com/0install/hello-scons.git $ cd hello-scons $ 0install download Hello-scons.xml --source --show - URI: /tmp/hello-scons/Hello-scons.xml Version: 1.1-post Path: /tmp/hello-scons - URI: http://0install.net/2006/3rd-party/SCons.xml Version: 2.0.1 Path: /var/cache/0install.net/implementations/sha1new=86311df9d410de36d75bc51762d2927f2f045ebf - URI: http://repo.roscidus.com/python/python Version: 2.7.6-1 Path: (package:arch:python2:2.7.6-1:x86_64) This says that the build dependencies are: - This package's source code (in /tmp/hello-scons) - The SCons build tool (which 0install has placed in /var/cache) - Python (provided by the distribution) The source could also specify library dependencies. How do you get this information to the build tool? The usual way is to tell 0install how to run the build tool in the XML. In this case, by running SCons on the project's SConstruct file. But you could get the information to it some other way. For example, a "rustpkg" tool that invokes "0install download ... --source --xml" behind the scenes and does something with the machine-readable selections document produced. How should I specify build dependencies for people who want to hack on my package? List them in the XML file that is in your project's source repository. Users should then be able to clone your git repository and build, with build dependencies handled for them. Majority of direct dependencies will be from the Rust world, and dedicated building/packaging tool would be able to download and build them automatically as a part of build process, and only external dependencies would have to be installed manually. With zero install you will have to install everything, including Rust-world dependencies, by yourself. 0install should be able to handle all build dependencies (e.g. libraries, the Rust compiler, build tools, documentation tools, etc). Second, it is another package manager which is foreign to the system (unless the system uses zero install as its package manager, but I think only ver
Re: [rust-dev] Proposal: Change Parametric Polymorphism Declaration Syntax
Also after sleeping on it I'm not as big of a fan of this proposal. But, I find the idea raised earlier of having "generic blocks" to group implementations etc that have the same implementation nice. Fully backwards compat though, so I'm not going to worry about it. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Proposal: Change Parametric Polymorphism Declaration Syntax
On Sun, Feb 2, 2014 at 6:08 PM, Benjamin Striegel wrote: > After sleeping on it I'm not convinced that this would be a net > improvement over our current situation. With a few caveats I'm really > rather happy with the syntax as it is. > > > On Sun, Feb 2, 2014 at 8:55 AM, Jason Fager wrote: > >> I'm not a huge fan of this proposal. It makes declarations longer, and >> it removes the visual consistency of Foo everywhere, which I think >> introduces its own pedagogical issue. >> >> The recent addition of default type parameters, though, makes me think >> there's a reasonable change that increases consistency and shortens >> declarations in a few common cases. >> >> From what I understand, the reason we can't just have >> >> impl Trait for Foo >> >> is because it's ambiguous whether T and U are intended to be concrete or >> generic type names; i.e., >> >> impl Trait for Foo >> >> tells the compiler that we expect U to be a concrete type name. >> >> Our new default type parameter declarations look like: >> >> struct Foo >> >> So what if to actually make generic types concrete, we always used the >> '='? >> >> struct Foo >> impl Trait for Foo >> >> This saves a character over 'impl Trait for Foo', solves >> the greppability problem, and makes intuitive sense given how defaults are >> declared. >> >> It also has a nice parallel with how ':' is used - ':' adds restrictions, >> '=' fully locks in place. So what is today something like >> >> impl Trait for Foo >> >> would become >> >> impl Trait for Foo >> >> The rule would be that the first use of a type variable T would introduce >> its bounds, so for instance: >> >> impl Trait for Foo >> >> would be fine, and >> >> impl Trait for Foo >> >> would be an error. >> >> More nice fallout: >> >> struct Foo >> impl Foo { >> fn one(a: A) -> B >> fn two(a: A) -> B >> fn three(a: A) -> B >> } >> >> means that if I ever want to go back and change the name of Bar, I only >> have to do it in one place, or if Bar is actually some complicated type, I >> only had to write it once, like a little local typedef. >> >> I'm sure this has some glaring obvious flaw I'm not thinking of. It >> would be nice to have less syntax for these declarations, but honestly I'm >> ok with how it is now. >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> On Sat, Feb 1, 2014 at 5:39 PM, Corey Richardson wrote: >> >>> Hey all, >>> >>> bjz and I have worked out a nice proposal[0] for a slight syntax >>> change, reproduced here. It is a breaking change to the syntax, but it >>> is one that I think brings many benefits. >>> >>> Summary >>> === >>> >>> Change the following syntax: >>> >>> ``` >>> struct Foo { ... } >>> impl Trait for Foo { ... } >>> fn foo(...) { ... } >>> ``` >>> >>> to: >>> >>> ``` >>> forall struct Foo { ... } >>> forall impl Trait for Foo { ... } >>> forall fn foo(...) { ... } >>> ``` >>> >>> >From a readability point of view, I am afraid this might be awkward though. Coming from a C++, I have welcome the switch from `typedef` to `using` (aliases) because of alignment issues; consider: typedef std::map MapType; typedef std::vector> VectorType; vs using MapType = std::map; using VectorType = std::vector>; In the latter, the entities being declared are at a constant offset from the left-hand margin; and close too; whereas in the former, the eyes are strained as they keep looking for what is declared. And now, let's look at your proposal: fn foo(a: int, b: int) -> int { } fn foo(a: T, b: U) -> T { } forall fn foo(a: T, b: U) -> T { } See how "forall" causes a "bump" that forces you to start looking where that name is ? It was so smooth until then ! So, it might be a net win in terms of grep-ability, but to be honest it seems LESS readable to me. -- Matthieu > The Problem >>> === >>> >>> The immediate, and most pragmatic, problem is that in today's Rust one >>> cannot >>> easily search for implementations of a trait. Why? `grep 'impl Clone'` is >>> itself not sufficient, since many types have parametric polymorphism. >>> Now I >>> need to come up with some sort of regex that can handle this. An easy >>> first-attempt is `grep 'impl(<.*?>)? Clone'` but that is quite >>> inconvenient to >>> type and remember. (Here I ignore the issue of tooling, as I do not find >>> the >>> argument of "But a tool can do it!" valid in language design.) >>> >>> A deeper, more pedagogical problem, is the mismatch between how `struct >>> Foo<...> { ... }` is read and how it is actually treated. The >>> straightforward, >>> left-to-right reading says "There is a struct Foo which, given the types >>> ... >>> has the members ...". This might lead one to believe that `Foo` is a >>> single >>> type, but it is not. `Foo` (that is, type `Foo` instantiated with >>> type >>> `int`) is not the same type as `Foo` (that is, type `Foo` >>> instantiated >>> with type `uint`). Of course, with a small amount of experience or a very >>> simple explanation, that becomes obvious. >>> >>> S
Re: [rust-dev] Proposal: Change Parametric Polymorphism Declaration Syntax
After sleeping on it I'm not convinced that this would be a net improvement over our current situation. With a few caveats I'm really rather happy with the syntax as it is. On Sun, Feb 2, 2014 at 8:55 AM, Jason Fager wrote: > I'm not a huge fan of this proposal. It makes declarations longer, and it > removes the visual consistency of Foo everywhere, which I think > introduces its own pedagogical issue. > > The recent addition of default type parameters, though, makes me think > there's a reasonable change that increases consistency and shortens > declarations in a few common cases. > > From what I understand, the reason we can't just have > > impl Trait for Foo > > is because it's ambiguous whether T and U are intended to be concrete or > generic type names; i.e., > > impl Trait for Foo > > tells the compiler that we expect U to be a concrete type name. > > Our new default type parameter declarations look like: > > struct Foo > > So what if to actually make generic types concrete, we always used the '='? > > struct Foo > impl Trait for Foo > > This saves a character over 'impl Trait for Foo', solves > the greppability problem, and makes intuitive sense given how defaults are > declared. > > It also has a nice parallel with how ':' is used - ':' adds restrictions, > '=' fully locks in place. So what is today something like > > impl Trait for Foo > > would become > > impl Trait for Foo > > The rule would be that the first use of a type variable T would introduce > its bounds, so for instance: > > impl Trait for Foo > > would be fine, and > > impl Trait for Foo > > would be an error. > > More nice fallout: > > struct Foo > impl Foo { > fn one(a: A) -> B > fn two(a: A) -> B > fn three(a: A) -> B > } > > means that if I ever want to go back and change the name of Bar, I only > have to do it in one place, or if Bar is actually some complicated type, I > only had to write it once, like a little local typedef. > > I'm sure this has some glaring obvious flaw I'm not thinking of. It would > be nice to have less syntax for these declarations, but honestly I'm ok > with how it is now. > > > > > > > > > > > > > > > On Sat, Feb 1, 2014 at 5:39 PM, Corey Richardson wrote: > >> Hey all, >> >> bjz and I have worked out a nice proposal[0] for a slight syntax >> change, reproduced here. It is a breaking change to the syntax, but it >> is one that I think brings many benefits. >> >> Summary >> === >> >> Change the following syntax: >> >> ``` >> struct Foo { ... } >> impl Trait for Foo { ... } >> fn foo(...) { ... } >> ``` >> >> to: >> >> ``` >> forall struct Foo { ... } >> forall impl Trait for Foo { ... } >> forall fn foo(...) { ... } >> ``` >> >> The Problem >> === >> >> The immediate, and most pragmatic, problem is that in today's Rust one >> cannot >> easily search for implementations of a trait. Why? `grep 'impl Clone'` is >> itself not sufficient, since many types have parametric polymorphism. Now >> I >> need to come up with some sort of regex that can handle this. An easy >> first-attempt is `grep 'impl(<.*?>)? Clone'` but that is quite >> inconvenient to >> type and remember. (Here I ignore the issue of tooling, as I do not find >> the >> argument of "But a tool can do it!" valid in language design.) >> >> A deeper, more pedagogical problem, is the mismatch between how `struct >> Foo<...> { ... }` is read and how it is actually treated. The >> straightforward, >> left-to-right reading says "There is a struct Foo which, given the types >> ... >> has the members ...". This might lead one to believe that `Foo` is a >> single >> type, but it is not. `Foo` (that is, type `Foo` instantiated with >> type >> `int`) is not the same type as `Foo` (that is, type `Foo` >> instantiated >> with type `uint`). Of course, with a small amount of experience or a very >> simple explanation, that becomes obvious. >> >> Something less obvious is the treatment of functions. What does `fn >> foo<...>(...) { ... }` say? "There is a function foo which, given types >> ... >> and arguments ..., does the following computation: ..." is not very >> adequate. >> It leads one to believe there is a *single* function `foo`, whereas there >> is >> actually a single `foo` for every substitution of type parameters! This >> also >> holds for implementations (both of traits and of inherent methods). >> >> Another minor problem is that nicely formatting long lists of type >> parameters >> or type parameters with many bounds is difficult. >> >> Proposed Solution >> = >> >> Introduce a new keyword, `forall`. This choice of keyword reads very well >> and >> will not conflict with any identifiers in code which follows the [style >> guide](https://github.com/mozilla/rust/wiki/Note-style-guide). >> >> Change the following declarations from >> >> ``` >> struct Foo { ... } >> impl Trait for Foo { ... } >> fn foo(...) { ... } >> ``` >> >> to: >> >> ``` >> forall struct Foo { ... } >> forall impl Trait for Foo { ... } >
Re: [rust-dev] Proposal: Change Parametric Polymorphism Declaration Syntax
I'm not a huge fan of this proposal. It makes declarations longer, and it removes the visual consistency of Foo everywhere, which I think introduces its own pedagogical issue. The recent addition of default type parameters, though, makes me think there's a reasonable change that increases consistency and shortens declarations in a few common cases. >From what I understand, the reason we can't just have impl Trait for Foo is because it's ambiguous whether T and U are intended to be concrete or generic type names; i.e., impl Trait for Foo tells the compiler that we expect U to be a concrete type name. Our new default type parameter declarations look like: struct Foo So what if to actually make generic types concrete, we always used the '='? struct Foo impl Trait for Foo This saves a character over 'impl Trait for Foo', solves the greppability problem, and makes intuitive sense given how defaults are declared. It also has a nice parallel with how ':' is used - ':' adds restrictions, '=' fully locks in place. So what is today something like impl Trait for Foo would become impl Trait for Foo The rule would be that the first use of a type variable T would introduce its bounds, so for instance: impl Trait for Foo would be fine, and impl Trait for Foo would be an error. More nice fallout: struct Foo impl Foo { fn one(a: A) -> B fn two(a: A) -> B fn three(a: A) -> B } means that if I ever want to go back and change the name of Bar, I only have to do it in one place, or if Bar is actually some complicated type, I only had to write it once, like a little local typedef. I'm sure this has some glaring obvious flaw I'm not thinking of. It would be nice to have less syntax for these declarations, but honestly I'm ok with how it is now. On Sat, Feb 1, 2014 at 5:39 PM, Corey Richardson wrote: > Hey all, > > bjz and I have worked out a nice proposal[0] for a slight syntax > change, reproduced here. It is a breaking change to the syntax, but it > is one that I think brings many benefits. > > Summary > === > > Change the following syntax: > > ``` > struct Foo { ... } > impl Trait for Foo { ... } > fn foo(...) { ... } > ``` > > to: > > ``` > forall struct Foo { ... } > forall impl Trait for Foo { ... } > forall fn foo(...) { ... } > ``` > > The Problem > === > > The immediate, and most pragmatic, problem is that in today's Rust one > cannot > easily search for implementations of a trait. Why? `grep 'impl Clone'` is > itself not sufficient, since many types have parametric polymorphism. Now I > need to come up with some sort of regex that can handle this. An easy > first-attempt is `grep 'impl(<.*?>)? Clone'` but that is quite > inconvenient to > type and remember. (Here I ignore the issue of tooling, as I do not find > the > argument of "But a tool can do it!" valid in language design.) > > A deeper, more pedagogical problem, is the mismatch between how `struct > Foo<...> { ... }` is read and how it is actually treated. The > straightforward, > left-to-right reading says "There is a struct Foo which, given the types > ... > has the members ...". This might lead one to believe that `Foo` is a single > type, but it is not. `Foo` (that is, type `Foo` instantiated with type > `int`) is not the same type as `Foo` (that is, type `Foo` > instantiated > with type `uint`). Of course, with a small amount of experience or a very > simple explanation, that becomes obvious. > > Something less obvious is the treatment of functions. What does `fn > foo<...>(...) { ... }` say? "There is a function foo which, given types ... > and arguments ..., does the following computation: ..." is not very > adequate. > It leads one to believe there is a *single* function `foo`, whereas there > is > actually a single `foo` for every substitution of type parameters! This > also > holds for implementations (both of traits and of inherent methods). > > Another minor problem is that nicely formatting long lists of type > parameters > or type parameters with many bounds is difficult. > > Proposed Solution > = > > Introduce a new keyword, `forall`. This choice of keyword reads very well > and > will not conflict with any identifiers in code which follows the [style > guide](https://github.com/mozilla/rust/wiki/Note-style-guide). > > Change the following declarations from > > ``` > struct Foo { ... } > impl Trait for Foo { ... } > fn foo(...) { ... } > ``` > > to: > > ``` > forall struct Foo { ... } > forall impl Trait for Foo { ... } > forall fn foo(...) { ... } > ``` > > These read very well. "for all types T and U, there is a struct Foo ...", > "for > all types T and U, there is a function foo ...", etc. These reflect that > there > are in fact multiple functions `foo` and structs `Foo` and implementations > of > `Trait`, due to monomorphization. > > > [0]: > http://cmr.github.io/blog/2014/02/01/polymorphic-declaration-syntax-in-rust/ > __
Re: [rust-dev] Proposal: Change Parametric Polymorphism Declaration Syntax
On 02/01/2014 11:39 PM, Corey Richardson wrote: ``` forall struct Foo { ... } forall impl Trait for Foo { ... } forall fn foo(...) { ... } ``` Why not ``` fn foo: pub unsafe => (f: |T| -> U, arg: T) -> U { f(arg) } struct foo: => { ... } impl Foo: => Trait { ... } ``` Can we please not put more stuff in front of the identifier? Have we ran out of space after it? What will this look like once the types start looking like `templatePred, typename SuperMeta,typename TagList, typename Category> class hashed_index`? Do we really need all that in front of a function name? The immediate, and most pragmatic, problem is that in today's Rust one cannot easily search for implementations of a trait. Why? Because the only existing Rust parser is geared towards a native Rust compiler, not a non-Rust IDE. That's the problem, not `grep`, and syntax changes won't help unless you want to redesign the language to be completely regex-compatible. Write a C-bindable parser, plug it into `ack`, `ctags` and a couple of IDEs, and everyone will be happy. (Here I ignore the issue of tooling, as I do not find the argument of "But a tool can do it!" valid in language design.) Then why have such a parsing-oriented grammar in the first place? Following this logic, Rust should look more like Haskell, with a Hello Kitty binop `(=^.^=)`. (I swear I've seen this in real code somewhere) ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Proposal: Change Parametric Polymorphism Declaration Syntax
On Sun, 2014-02-02 at 14:45 +1300, Nick Cameron wrote: > - The change adds boilerplate and nomenclature that is likely > unfamiliar to our target audience - 'for all' is well known to > functional programmers, but I believe that is not true for most users > of C++ (or Java). Being closer to the C++/Java syntax for generics is > probably more 'intuitive So instead of 'for all', use 'template', and we're closer to C++ syntax than ever! template struct Foo { ... } template impl Trait for Foo { ... } template fn foo(...) { ... } ;-) fwiw, like C++, Java generic methods also put the <> type parameter list in front of the function signature rather than behind the function name: public static > int countGreaterThan(T[] anArray, T elem) { ... } ... while C# apparently compromises and puts the type parameters between the function name and value parameter list, but leaves the bounds for later: public static bool Contains(IEnumerable collection, T item) where T : IComparable; Neither approach translates too well into Rust, but that Rust is almost the odd one out here makes me sympathetic to the desire to avoid breaking up particularly function declarations between the name and the value parameter list too much, in spite of the familiarity argument. Of course, like everything else, that has to be balanced with avoiding superficial but far-reaching overhauls of the language at the eleventh hour. Alas! -benh ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev