digitalmars.D - D vs Rust: function signatures
- Narrator (24/24) Apr 29 2014 The unbelievable amount of time and energy that's been spent
- Nick Sabalausky (2/3) Apr 29 2014 That looks like line noise.
- Paulo Pinto (4/9) Apr 30 2014 Not if one is used to ML languages. Beauty is in the eyes of the
- Nick Sabalausky (3/12) Apr 30 2014 FWIW, I do agree (Not that I know much about ML-family). The "...to me"
- bearophile (21/26) Apr 30 2014 In D there is a lambda syntax:
- Vladimir Panteleev (26/50) Apr 29 2014 IIUC:
- Timon Gehr (10/17) Apr 30 2014 |A| -> B is the type of a closure mapping an A to a B. 'r is a lifetime
- John Colvin (5/29) Apr 30 2014 I don't think a single one of those signatures are equivalent.
The unbelievable amount of time and energy that's been spent discussing the smallest syntax, you would think that D would, at the very least, have better looking function signatures, but it doesn't. auto zip(Ranges...)(Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges)); auto zip(Ranges...)(StoppingPolicy sp, Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges)); fn zip<B, U: Iterator<B>>(self, other: U) -> Zip<Self, U> auto chain(Ranges...)(Ranges rs) if (Ranges.length > 0 && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && !is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void)); fn chain<U: Iterator<A>>(self, other: U) -> Chain<Self, U> template map(fun...) if (fun.length >= 1) auto map(Range)(Range r) if (isInputRange!(Unqual!Range)); fn map<'r, B>(self, f: |A|: 'r -> B) -> Map<'r, A, B, Self> template filter(alias pred) if (is(typeof(unaryFun!pred))) auto filter(Range)(Range rs) if (isInputRange!(Unqual!Range)); fn filter<'r>(self, predicate: |&A|: 'r -> bool) -> Filter<'r, A, Self> MaxType!(T1, T2, T) max(T1, T2, T...)(T1 a, T2 b, T xs) if (is(typeof(a < b))); pub fn max<T: TotalOrd>(v1: T, v2: T) -> T
Apr 29 2014
On 4/29/2014 9:38 PM, Narrator wrote:fn map<'r, B>(self, f: |A|: 'r -> B) -> Map<'r, A, B, Self>That looks like line noise.
Apr 29 2014
On Wednesday, 30 April 2014 at 01:49:01 UTC, Nick Sabalausky wrote:On 4/29/2014 9:38 PM, Narrator wrote:Not if one is used to ML languages. Beauty is in the eyes of the beholder. :)fn map<'r, B>(self, f: |A|: 'r -> B) -> Map<'r, A, B, Self>That looks like line noise.
Apr 30 2014
On 4/30/2014 3:26 AM, Paulo Pinto wrote:On Wednesday, 30 April 2014 at 01:49:01 UTC, Nick Sabalausky wrote:FWIW, I do agree (Not that I know much about ML-family). The "...to me" was carelessly left as implied. ;)On 4/29/2014 9:38 PM, Narrator wrote:Not if one is used to ML languages. Beauty is in the eyes of the beholder. :)fn map<'r, B>(self, f: |A|: 'r -> B) -> Map<'r, A, B, Self>That looks like line noise.
Apr 30 2014
Nick Sabalausky:On 4/29/2014 9:38 PM, Narrator wrote:In D there is a lambda syntax: auto F = (in int x) => x ^^ 2; void main() { int y; auto G = (in int x) => x + y; pragma(msg, typeof(F)); pragma(msg, typeof(G)); } That code contains the types (the pragma output is a little different): int function(in int) pure nothrow nogc safe int delegate(in int) nothrow nogc safe An alternative syntax can be similar to the way you write D lamdas: (in int) pure nothrow nogc safe => int (in int) nothrow nogc safe ==> int (I am not suggesting to introduce this syntax to D because its an useless duplication, but I find it a bit better.) Bye, bearophilefn map<'r, B>(self, f: |A|: 'r -> B) -> Map<'r, A, B, Self>That looks like line noise.
Apr 30 2014
On Wednesday, 30 April 2014 at 01:38:46 UTC, Narrator wrote:The unbelievable amount of time and energy that's been spent discussing the smallest syntax, you would think that D would, at the very least, have better looking function signatures, but it doesn't. auto zip(Ranges...)(Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges)); auto zip(Ranges...)(StoppingPolicy sp, Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges)); fn zip<B, U: Iterator<B>>(self, other: U) -> Zip<Self, U>IIUC: 1. The Rust function is non-variadic 2. The Rust function has no StoppingPolicy equivalent 3. The Rust function is a method of some type, such as Zip or Chain, which must be declared explicitly in every such type. Here is the equivalent D syntax: auto zip(R)(R other) if (isInputRange!R) It is shorter than the Rust version.auto chain(Ranges...)(Ranges rs) if (Ranges.length > 0 && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && !is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void)); fn chain<U: Iterator<A>>(self, other: U) -> Chain<Self, U>Same as points 1 and 3 above. Most of that boilerplate comes from validating the variadic parameter types.template map(fun...) if (fun.length >= 1) auto map(Range)(Range r) if (isInputRange!(Unqual!Range)); fn map<'r, B>(self, f: |A|: 'r -> B) -> Map<'r, A, B, Self>Same as points 1 and 3 above (D's version allows specifying multiple functions). Not sure what 'r or |A| means in Rust syntax, but I guess this would be the equivalent D syntax: auto map(R)(R delegate(T)) Note that D's real version has the function alias as a template parameter, and not as a runtime parameter, meaning that you will have a guarantee of a separate template instantiation for every different map predicate. This allows you to make assumptions about the performance of the generated code which don't rely as much on expected compiler optimizations (although I don't know what guarantees Rust makes about this).template filter(alias pred) if (is(typeof(unaryFun!pred))) auto filter(Range)(Range rs) if (isInputRange!(Unqual!Range)); fn filter<'r>(self, predicate: |&A|: 'r -> bool) -> Filter<'r, A, Self>As above, though D's filter also accepts only one predicate.MaxType!(T1, T2, T) max(T1, T2, T...)(T1 a, T2 b, T xs) if (is(typeof(a < b))); pub fn max<T: TotalOrd>(v1: T, v2: T) -> TSame as point 1 above. Also, the Rust version requires that the two values have exactly the same type.
Apr 29 2014
On 04/30/2014 04:04 AM, Vladimir Panteleev wrote:|A| -> B is the type of a closure mapping an A to a B. 'r is a lifetime parameter (there is another one in Self): I.e. that signature is roughly saying: The returned iterator lives at most as long as the closure context of f and the underlying iterator. This way you can eg. get an iterator over some mutable data structure, map it without allocations using a stack closure, and the type system verifies that the data structure is not changed while the mapped iterator is in use, and that there are no dangling references to stack memory left behind.fn map<'r, B>(self, f: |A|: 'r -> B) -> Map<'r, A, B, Self>Same as points 1 and 3 above (D's version allows specifying multiple functions). Not sure what 'r or |A| means in Rust syntax, but I guess this would be the equivalent D syntax: auto map(R)(R delegate(T))
Apr 30 2014
On Wednesday, 30 April 2014 at 01:38:46 UTC, Narrator wrote:The unbelievable amount of time and energy that's been spent discussing the smallest syntax, you would think that D would, at the very least, have better looking function signatures, but it doesn't. auto zip(Ranges...)(Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges)); auto zip(Ranges...)(StoppingPolicy sp, Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges)); fn zip<B, U: Iterator<B>>(self, other: U) -> Zip<Self, U> auto chain(Ranges...)(Ranges rs) if (Ranges.length > 0 && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && !is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void)); fn chain<U: Iterator<A>>(self, other: U) -> Chain<Self, U> template map(fun...) if (fun.length >= 1) auto map(Range)(Range r) if (isInputRange!(Unqual!Range)); fn map<'r, B>(self, f: |A|: 'r -> B) -> Map<'r, A, B, Self> template filter(alias pred) if (is(typeof(unaryFun!pred))) auto filter(Range)(Range rs) if (isInputRange!(Unqual!Range)); fn filter<'r>(self, predicate: |&A|: 'r -> bool) -> Filter<'r, A, Self> MaxType!(T1, T2, T) max(T1, T2, T...)(T1 a, T2 b, T xs) if (is(typeof(a < b))); pub fn max<T: TotalOrd>(v1: T, v2: T) -> TI don't think a single one of those signatures are equivalent. Also, bear in mind that those if() constraints contain arbitrary code (as long as it can be evaluated at compile-time), so they are very flexible.
Apr 30 2014