digitalmars.D - Rust updates
- bearophile (215/216) Jul 08 2012 On Reddit they are currently discussing again about the Rust
- deadalnix (4/205) Jul 08 2012 Thank for keeping us informed about Rust. i don't like the syntax, but
- Stefan Scholl (3/9) Jul 08 2012 Short keywords are only important with barebones editors like a default ...
- Paulo Pinto (11/25) Jul 08 2012 I started I long discussion on Reddit, because I complained that
- jerro (2/4) Jul 08 2012 I would expect the abbreviations that rust uses to be perfectly
- Stefan Scholl (6/8) Jul 09 2012 There is a lot of noise (lot of special characters) in Rust code. Togeth...
- Paulo Pinto (9/13) Jul 11 2012 I like a lot ML languages (Haskell, F#, OCaml), so I should
- David Piepgrass (28/36) Jul 11 2012 Short or long, I don't think it matters if the IDE can help you
- David Piepgrass (6/12) Jul 11 2012 Okay, I actually care a lot, just about the meaning of the
- Timon Gehr (2/8) Jul 11 2012 You could have a look at JavaScript.
- Max Samukha (2/13) Jul 11 2012 ... and CoffeeScript as an attempt to fix that.
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (7/15) Jul 11 2012 And Lua. And PHP. Possibly others I'm forgetting.
- David Piepgrass (4/15) Jul 11 2012 Ack! You got me. Dynamic languages aren't my thing. But JS being
- Marco Leise (5/14) Jul 11 2012 ... and Pascal/Delphi, which has no 'void' return, but distinguishes bet...
- Paulo Pinto (3/24) Jul 11 2012 I was a very happy Turbo Pascal and Delphi developer, until I
- bearophile (10/12) Jul 11 2012 Between APL/Ursala and Ada extremes there is a wide happy middle,
- Walter Bright (2/3) Jul 11 2012 I keep finding myself typing "redrum" !
- Guillaume Chatelet (2/6) Jul 11 2012 Good one :D
- Walter Bright (13/16) Jul 08 2012 The trouble with segmented stacks are:
- bearophile (16/34) Jul 08 2012 Walter Bright:
- Walter Bright (3/8) Jul 08 2012 I think you misunderstood. I meant there is no point to segmented stacks...
- Stefan Scholl (3/4) Jul 09 2012 There aren't many people using Go on 32 bit systems. That's why there is
- Caligo (2/6) Jul 09 2012 There aren't many people using Go, period.
- Stefan Scholl (6/14) Jul 09 2012 Don't know about this, but "Programming in Go" is a bad book (talks abou...
- Andrei Alexandrescu (10/23) Jul 10 2012 The book was released only in March; newer books usually have their
- Iain Buclaw (10/40) Jul 10 2012 D would be in GCC and Go would be trying to baby step over the hurdle
- Patrick Stewar (2/31) Jul 10 2012 It was under my impression that is because whole D thing was badly engin...
- Andrei Alexandrescu (4/44) Jul 10 2012 What I meant to say was that we're not writing enough about D, but I'll
- David Piepgrass (7/16) Jul 11 2012 Isn't it possible to auto-commit new pages when C code needs it?
- Walter Bright (3/18) Jul 11 2012 There's no way to predict how much stack arbitrary C code will use.
- David Piepgrass (7/17) Jul 11 2012 Presumably one does not call arbitrary C code. Usually one knows
- David Piepgrass (14/29) Jul 11 2012 Looks like I misunderstood what "Segmented stacks" are. From an
- Daniel (6/13) Jul 08 2012 Many good ideas... am just singling out this one, as you seem to
- Marco Leise (5/21) Jul 10 2012 Yes, this is the single most important Rust feature to me when typing. I...
- bearophile (7/11) Jul 11 2012 I am writing a lot of D2 code, but in my code the need of
- Marco Leise (46/60) Jul 11 2012 As an optional feature, I think it is nice to have them when you need th...
- bearophile (23/42) Jul 11 2012 Here b is an ubyte[] of length 5. I think this works:
- Marco Leise (7/15) Jul 12 2012 Me too, but then again "5l" could be read as 5 liters. I guess that is w...
- Marco Leise (5/23) Jul 12 2012 P.S.: There is no I or UI, just L and UL. Sorry for the confusion.
- Marco Leise (5/28) Jul 12 2012 I experimented a bit with it and the modifications to DMD are mostly str...
- Walter Bright (5/13) Jul 12 2012 I'd object. I've been programming in C, C++ and D for 30 years now, and ...
- Marco Leise (42/58) Jul 13 2012 Alright, I'll stow it away as a little experiment. But consider, that es...
- Walter Bright (4/9) Jul 13 2012 auto code() { return cast(ushort)42; }
- bearophile (11/14) Jul 17 2012 I have just found an example (reduced code):
- Timon Gehr (3/18) Jul 17 2012 Looks like a bug in std.typecons.Tuple. That constructor shouldn't be
- Geoffrey Biggs (8/14) Jul 12 2012 "L" is also an internationally-recognised symbol for litres.
- Marco Leise (6/12) Jul 13 2012 Please! This is a different story. You talk about declaring best fit dat...
- David Piepgrass (95/147) Jul 11 2012 As nice as kinds, typestates, typeclasses and several pointer
- Timon Gehr (2/7) Jul 11 2012 That is what D does : )
- Walter Bright (4/11) Jul 11 2012 bool test(int x) { return x & 2 > 0; }
- David Piepgrass (2/13) Jul 11 2012 Doh! You read my mind before I thought it :) I hadn't got around
- David Piepgrass (4/8) Jul 11 2012 That reminds me, I was so happy the first two times I got an
- Walter Bright (3/6) Jul 11 2012 I added a spelling checker to the undefined identifier code, using the v...
- deadalnix (3/12) Jul 11 2012 Yeah, that one is really nice and usually useful. However, you can get
- Jeff Nowakowski (4/13) Jul 12 2012 I remember you took some heat for this because of compiler slowdowns, as...
- Marco Leise (5/21) Jul 12 2012 I don't know the implementation, but compile time should not be a proble...
- Chad J (64/105) Jul 11 2012 I'm pretty sure this interoperability thing is solved in D, at least at
- Paulo Pinto (8/16) Jul 11 2012 I always find these type of comments strange due to my background.
- bearophile (4/4) Jul 13 2012 A blog post about one of the Rust pointers, the "borrowed" ones:
- SomeDude (3/7) Jul 17 2012 Rust is a much more interesting language than Go. At least they
- Marco Leise (5/15) Jul 18 2012 The irony is: "Rust intentionally does not include any novel or untested...
- Kagamin (2/4) Jul 20 2012 Does it handle angle brackets well?
- Marcel (6/14) Dec 17 2012 They aren't silly, they're consistent. We have int, char, auto,
- foobar (12/27) Dec 18 2012 Those are silly as well. Why be consistent with the wrong choice?
- bearophile (13/24) Dec 18 2012 They are a bad design choice. Using very shortened
- Walter Bright (4/6) Dec 18 2012 A red letter day for D! Bearophile says that D does something better tha...
On Reddit they are currently discussing again about the Rust language, and about the browser prototype written in Rust, named "Servo" (https://github.com/mozilla/servo ): http://www.reddit.com/r/programming/comments/w6h7x/the_state_of_servo_a_mozilla_experiment_in/ So I've taken another look at the Rust tutorial: http://dl.rust-lang.org/doc/tutorial.html and I've seen Rust is quite more defined compared to the last two times I've read about it. So below I put more extracts from the tutorial, with few comments of mine (but most text you find below is from the tutorial). On default in Rust types are immutable. If you want the mutable type you need to annotate it with "mut" in some way. Rust designers seems to love really short keywords, this is in my opinion a bit silly. On the other hand in D you have keywords like "immutable" that are rather long to type. So I prefer a mid way between those two. Rust has type classes from Haskell (with some simplifications for higher kinds), uniqueness typing, and typestates. In Haskell typeclasses are very easy to use. From my limited study, the Rust implementation of uniqueness typing doesn't look hard to understand and use. It statically enforced, it doesn't require lot of annotations and I think its compiler implementation is not too much hard, because it's a pure type system test. Maybe D designers should take a look, maybe for D3. Macros are planned, but I think they are not fully implemented. I think in Go the function stack is segmented and growable as in Go. This saves RAM if you need a small stack, and avoids stack overflows where lot of stack is needed. ------------------------- Instead of the 3 char types of D, Rust has 1 char type: char A character is a 32-bit Unicode code point. ------------------------- And only one string type: str String type. A string contains a UTF-8 encoded sequence of characters. For algorithms that do really need to index by character, there's the option to convert your string to a character vector (using str::chars). ------------------------- Tuples are rightly built-in. Tuple singletons are not supported (empty tuples are kind of supported with ()): (T1, T2) Tuple type. Any arity above 1 is supported. ------------------------- Despite Walter said that having more than a type of pointer is bad, both Ada and Rust have several pointer types. Rust has three of them (plus their mutable variants). Rust supports several types of pointers. The simplest is the unsafe pointer, written *T, which is a completely unchecked pointer type only used in unsafe code (and thus, in typical Rust code, very rarely). The safe pointer types are T for shared, reference-counted boxes, and ~T, for uniquely-owned pointers. All pointer types can be dereferenced with the * unary operator. Shared boxes never cross task boundaries. ------------------------- This seems a bit overkill to me: It's also possible to avoid any type ambiguity by writing integer literals with a suffix. The suffixes i and u are for the types int and uint, respectively: the literal -3i has type int, while 127u has type uint. For the fixed-size integer types, just suffix the literal with the type name: 255u8, 50i64, etc. ------------------------- This is very strict, maybe too much strict: No implicit conversion between integer types happens. If you are adding one to a variable of type uint, saying += 1u8 will give you a type error. ------------------------- Even more than Go: ++ and -- are missing And fixes a C problem: the logical bitwise operators have higher precedence. In C, x & 20 comes out as x & (2 > 0), in Rust, it means (x & 2) > 0,which is more likely to be what you expect (unless you are a C veteran). ------------------------- Enums are datatypes that have several different representations. For example, the type shown earlier: enum shape { circle(point, float), rectangle(point, point) } A value of this type is either a circle, in which case it contains a point record and a float, or a rectangle, in which case it contains two point records. The run-time representation of such a value includes an identifier of the actual form that it holds, much like the 'tagged union' pattern in C, but with better ergonomics. The above declaration will define a type shape that can be used to refer to such shapes, and two functions, circle and rectangle, which can be used to construct values of the type (taking arguments of the specified types). So circle({x: 0f, y: 0f}, 10f) is the way to create a new circle. Enum variants do not have to have parameters. This, for example, is equivalent to a C enum: enum direction { north, east, south, west } ------------------------- This is probably quite handy: A powerful application of pattern matching is destructuring, where you use the matching to get at the contents of data types. Remember that (float, float) is a tuple of two floats: fn angle(vec: (float, float)) -> float { alt vec { (0f, y) if y < 0f { 1.5 * float::consts::pi } (0f, y) { 0.5 * float::consts::pi } (x, y) { float::atan(y / x) } } } - - - - - - - - Records can be destructured in alt patterns. The basic syntax is {fieldname: pattern, ...}, but the pattern for a field can be omitted as a shorthand for simply binding the variable with the same name as the field. alt mypoint { {x: 0f, y: y_name} { /* Provide sub-patterns for fields */ } {x, y} { /* Simply bind the fields */ } } The field names of a record do not have to appear in a pattern in the same order they appear in the type. When you are not interested in all the fields of a record, a record pattern may end with , _ (as in {field1, _}) to indicate that you're ignoring all other fields. - - - - - - - - For enum types with multiple variants, destructuring is the only way to get at their contents. All variant constructors can be used as patterns, as in this definition of area: fn area(sh: shape) -> float { alt sh { circle(_, size) { float::consts::pi * size * size } rectangle({x, y}, {x: x2, y: y2}) { (x2 - x) * (y2 - y) } } } ------------------------- This is quite desirable in D too: To a limited extent, it is possible to use destructuring patterns when declaring a variable with let. For example, you can say this to extract the fields from a tuple: let (a, b) = get_tuple_of_two_ints(); ------------------------- Stack-allocated closures: There are several forms of closure, each with its own role. The most common, called a stack closure, has type fn& and can directly access local variables in the enclosing scope. let mut max = 0; [1, 2, 3].map(|x| if x > max { max = x }); Stack closures are very efficient because their environment is allocated on the call stack and refers by pointer to captured locals. To ensure that stack closures never outlive the local variables to which they refer, they can only be used in argument position and cannot be stored in structures nor returned from functions. Despite the limitations stack closures are used pervasively in Rust code. ------------------------- Unique closures: Unique closures, written fn~ in analogy to the ~ pointer type (see next section), hold on to things that can safely be sent between processes. They copy the values they close over, much like boxed closures, but they also 'own' them—meaning no other code can access them. Unique closures are used in concurrent code, particularly for spawning tasks. There are also heap-allocated closures (so there are 3 kinds of closures). - - - - - - - - In contrast to shared boxes, unique boxes are not reference counted. Instead, it is statically guaranteed that only a single owner of the box exists at any time. let x = ~10; let y <- x; This is where the 'move' (<-) operator comes in. It is similar to =, but it de-initializes its source. Thus, the unique box can move from x to y, without violating the constraint that it only has a single owner (if you used assignment instead of the move operator, the box would, in principle, be copied). Unique boxes, when they do not contain any shared boxes, can be sent to other tasks. The sending task will give up ownership of the box, and won't be able to access it afterwards. The receiving task will become the sole owner of the box. ------------------------- In D you control this adding "private" before names, but I think a centralized control point at the top of the module is safer and cleaner: By default, a module exports everything that it defines. This can be restricted with export directives at the top of the module or file. mod enc { export encrypt, decrypt; const super_secret_number: int = 10; fn encrypt(n: int) -> int { n + super_secret_number } fn decrypt(n: int) -> int { n - super_secret_number } } ------------------------- This is needed by the uniqueness typing: Evaluating a swap expression neither changes reference counts nor deeply copies any unique structure pointed to by the moved rval. Instead, the swap expression represents an indivisible exchange of ownership between the right-hand-side and the left-hand-side of the expression. No allocation or destruction is entailed. An example of three different swap expressions: x <-> a; x[i] <-> a[i]; y.z <-> b.c; ------------------------- For some info on the typestate system, from the Rust manual: http://dl.rust-lang.org/doc/rust.html#typestate-system This description is simpler than I have thought. It seems possible to create an experimental D compiler with just a similar typestate system, it looks like a purely additive change (but maybe it's not a small change). It seems to not even require new syntax, beside an assert-like check() that can't be disable and that uses a pure expression/predicate. Bye, bearophile
Jul 08 2012
Thank for keeping us informed about Rust. i don't like the syntax, but it is definitively an interesting language and something we should look at as D people. On 08/07/2012 15:49, bearophile wrote:On Reddit they are currently discussing again about the Rust language, and about the browser prototype written in Rust, named "Servo" (https://github.com/mozilla/servo ): http://www.reddit.com/r/programming/comments/w6h7x/the_state_of_servo_a_mozilla_experiment_in/ So I've taken another look at the Rust tutorial: http://dl.rust-lang.org/doc/tutorial.html and I've seen Rust is quite more defined compared to the last two times I've read about it. So below I put more extracts from the tutorial, with few comments of mine (but most text you find below is from the tutorial). On default in Rust types are immutable. If you want the mutable type you need to annotate it with "mut" in some way. Rust designers seems to love really short keywords, this is in my opinion a bit silly. On the other hand in D you have keywords like "immutable" that are rather long to type. So I prefer a mid way between those two. Rust has type classes from Haskell (with some simplifications for higher kinds), uniqueness typing, and typestates. In Haskell typeclasses are very easy to use. From my limited study, the Rust implementation of uniqueness typing doesn't look hard to understand and use. It statically enforced, it doesn't require lot of annotations and I think its compiler implementation is not too much hard, because it's a pure type system test. Maybe D designers should take a look, maybe for D3. Macros are planned, but I think they are not fully implemented. I think in Go the function stack is segmented and growable as in Go. This saves RAM if you need a small stack, and avoids stack overflows where lot of stack is needed. ------------------------- Instead of the 3 char types of D, Rust has 1 char type: char A character is a 32-bit Unicode code point. ------------------------- And only one string type: str String type. A string contains a UTF-8 encoded sequence of characters. For algorithms that do really need to index by character, there's the option to convert your string to a character vector (using str::chars). ------------------------- Tuples are rightly built-in. Tuple singletons are not supported (empty tuples are kind of supported with ()): (T1, T2) Tuple type. Any arity above 1 is supported. ------------------------- Despite Walter said that having more than a type of pointer is bad, both Ada and Rust have several pointer types. Rust has three of them (plus their mutable variants). Rust supports several types of pointers. The simplest is the unsafe pointer, written *T, which is a completely unchecked pointer type only used in unsafe code (and thus, in typical Rust code, very rarely). The safe pointer types are T for shared, reference-counted boxes, and ~T, for uniquely-owned pointers. All pointer types can be dereferenced with the * unary operator. Shared boxes never cross task boundaries. ------------------------- This seems a bit overkill to me: It's also possible to avoid any type ambiguity by writing integer literals with a suffix. The suffixes i and u are for the types int and uint, respectively: the literal -3i has type int, while 127u has type uint. For the fixed-size integer types, just suffix the literal with the type name: 255u8, 50i64, etc. ------------------------- This is very strict, maybe too much strict: No implicit conversion between integer types happens. If you are adding one to a variable of type uint, saying += 1u8 will give you a type error. ------------------------- Even more than Go: ++ and -- are missing And fixes a C problem: the logical bitwise operators have higher precedence. In C, x & 2 > 0 comes out as x & (2 > 0), in Rust, it means (x & 2) > 0, which is more likely to be what you expect (unless you are a C veteran). ------------------------- Enums are datatypes that have several different representations. For example, the type shown earlier: enum shape { circle(point, float), rectangle(point, point) } A value of this type is either a circle, in which case it contains a point record and a float, or a rectangle, in which case it contains two point records. The run-time representation of such a value includes an identifier of the actual form that it holds, much like the 'tagged union' pattern in C, but with better ergonomics. The above declaration will define a type shape that can be used to refer to such shapes, and two functions, circle and rectangle, which can be used to construct values of the type (taking arguments of the specified types). So circle({x: 0f, y: 0f}, 10f) is the way to create a new circle. Enum variants do not have to have parameters. This, for example, is equivalent to a C enum: enum direction { north, east, south, west } ------------------------- This is probably quite handy: A powerful application of pattern matching is destructuring, where you use the matching to get at the contents of data types. Remember that (float, float) is a tuple of two floats: fn angle(vec: (float, float)) -> float { alt vec { (0f, y) if y < 0f { 1.5 * float::consts::pi } (0f, y) { 0.5 * float::consts::pi } (x, y) { float::atan(y / x) } } } - - - - - - - - Records can be destructured in alt patterns. The basic syntax is {fieldname: pattern, ...}, but the pattern for a field can be omitted as a shorthand for simply binding the variable with the same name as the field. alt mypoint { {x: 0f, y: y_name} { /* Provide sub-patterns for fields */ } {x, y} { /* Simply bind the fields */ } } The field names of a record do not have to appear in a pattern in the same order they appear in the type. When you are not interested in all the fields of a record, a record pattern may end with , _ (as in {field1, _}) to indicate that you're ignoring all other fields. - - - - - - - - For enum types with multiple variants, destructuring is the only way to get at their contents. All variant constructors can be used as patterns, as in this definition of area: fn area(sh: shape) -> float { alt sh { circle(_, size) { float::consts::pi * size * size } rectangle({x, y}, {x: x2, y: y2}) { (x2 - x) * (y2 - y) } } } ------------------------- This is quite desirable in D too: To a limited extent, it is possible to use destructuring patterns when declaring a variable with let. For example, you can say this to extract the fields from a tuple: let (a, b) = get_tuple_of_two_ints(); ------------------------- Stack-allocated closures: There are several forms of closure, each with its own role. The most common, called a stack closure, has type fn& and can directly access local variables in the enclosing scope. let mut max = 0; [1, 2, 3].map(|x| if x > max { max = x }); Stack closures are very efficient because their environment is allocated on the call stack and refers by pointer to captured locals. To ensure that stack closures never outlive the local variables to which they refer, they can only be used in argument position and cannot be stored in structures nor returned from functions. Despite the limitations stack closures are used pervasively in Rust code. ------------------------- Unique closures: Unique closures, written fn~ in analogy to the ~ pointer type (see next section), hold on to things that can safely be sent between processes. They copy the values they close over, much like boxed closures, but they also 'own' them—meaning no other code can access them. Unique closures are used in concurrent code, particularly for spawning tasks. There are also heap-allocated closures (so there are 3 kinds of closures). - - - - - - - - In contrast to shared boxes, unique boxes are not reference counted. Instead, it is statically guaranteed that only a single owner of the box exists at any time. let x = ~10; let y <- x; This is where the 'move' (<-) operator comes in. It is similar to =, but it de-initializes its source. Thus, the unique box can move from x to y, without violating the constraint that it only has a single owner (if you used assignment instead of the move operator, the box would, in principle, be copied). Unique boxes, when they do not contain any shared boxes, can be sent to other tasks. The sending task will give up ownership of the box, and won't be able to access it afterwards. The receiving task will become the sole owner of the box. ------------------------- In D you control this adding "private" before names, but I think a centralized control point at the top of the module is safer and cleaner: By default, a module exports everything that it defines. This can be restricted with export directives at the top of the module or file. mod enc { export encrypt, decrypt; const super_secret_number: int = 10; fn encrypt(n: int) -> int { n + super_secret_number } fn decrypt(n: int) -> int { n - super_secret_number } } ------------------------- This is needed by the uniqueness typing: Evaluating a swap expression neither changes reference counts nor deeply copies any unique structure pointed to by the moved rval. Instead, the swap expression represents an indivisible exchange of ownership between the right-hand-side and the left-hand-side of the expression. No allocation or destruction is entailed. An example of three different swap expressions: x <-> a; x[i] <-> a[i]; y.z <-> b.c; ------------------------- For some info on the typestate system, from the Rust manual: http://dl.rust-lang.org/doc/rust.html#typestate-system This description is simpler than I have thought. It seems possible to create an experimental D compiler with just a similar typestate system, it looks like a purely additive change (but maybe it's not a small change). It seems to not even require new syntax, beside an assert-like check() that can't be disable and that uses a pure expression/predicate. Bye, bearophile
Jul 08 2012
"bearophile" <bearophileHUGS lycos.com> wrote:On default in Rust types are immutable. If you want the mutable type you need to annotate it with "mut" in some way. Rust designers seems to love really short keywords, this is in my opinion a bit silly. On the other hand in D you have keywords like "immutable" that are rather long to type. So I prefer a mid way between those two.Short keywords are only important with barebones editors like a default vi. Nobody would use this for real development.
Jul 08 2012
On Sunday, 8 July 2012 at 18:13:49 UTC, Stefan Scholl wrote:"bearophile" <bearophileHUGS lycos.com> wrote:I started I long discussion on Reddit, because I complained that the goal of 5 letter keywords is primitive, and brings back memories of the time the compilers were memory constraint. For example, I remember in Turbo C 2.0, the identifiers could not be longer than 32 bytes, and it was even possible to specify a lower default limit to get a bit more memory! As someone that values readable code, I don't understand this desire to turn every programming language into APL. -- PauloOn default in Rust types are immutable. If you want the mutable type you need to annotate it with "mut" in some way. Rust designers seems to love really short keywords, this is in my opinion a bit silly. On the other hand in D you have keywords like "immutable" that are rather long to type. So I prefer a mid way between those two.Short keywords are only important with barebones editors like a default vi. Nobody would use this for real development.
Jul 08 2012
As someone that values readable code, I don't understand this desire to turn every programming language into APL.I would expect the abbreviations that rust uses to be perfectly readable once you know the langauge.
Jul 08 2012
"jerro" <a a.com> wrote:I would expect the abbreviations that rust uses to be perfectly readable once you know the langauge.There is a lot of noise (lot of special characters) in Rust code. Together with short keywords like "fn" for function definition. It's hard to see a structure in it. You can read JAPHs, too, if you know Perl. But your brain parses it character for character. Rust is a bit better, though.
Jul 09 2012
On Sunday, 8 July 2012 at 21:04:05 UTC, jerro wrote:probably not be complaining like that. But those languages don't have as one of their goals to restrict the keywords to maximum 5 letters, Who knows, maybe if Rust catches on, I will be eating my own words and even using it. -- PauloAs someone that values readable code, I don't understand this desire to turn every programming language into APL.I would expect the abbreviations that rust uses to be perfectly readable once you know the langauge.
Jul 11 2012
...Short keywords are only important with barebones editors like a default vi. Nobody would use this for real development.I started I long discussion on Reddit, because I complained that the goal of 5 letter keywords is primitive, and brings back memories of the time the compilers were memory constraint.As someone that values readable code, I don't understand this desire to turn every programming language into APL.Short or long, I don't think it matters if the IDE can help you with the long ones. I don't mind typing immutable, once, but if I had to do it 50 times a day? And somehow, even though I have been programming for over 20 years, I still type "reutrn" and "retrun" all the damn time! So "ret" would save me time. Anyway I think short vs long is much ado about nothing. No one complains that we have to type "int" instead of "integer", after all. Most languages have only a few keywords, which people quickly learn. As long as all the standard library functions are well-named, I don't care about the language keywords. Actually I think "fn" for functions is great, why? 1. Greppability. With the C syntax there is no way to search for function definitions. Even if we had an IDE to find functions for us, you are not always looking at source code in an IDE (you could be browsing a repository on the web) 2. Easier to parse. When the compiler sees "fn", it knows it's dealing with a function and not a variable or an expression. It seems especially beneficial inside functions, where perhaps X * Y might begin an expression (or is that impossible in D?) 3. Googlability. "function" will find results across all PLs, "fn" will narrow the search down quite a bit if you want to see code in Rust. These benefits (except 3) all exist for "function" as well as "fn", but while many languages use "fun", requiring "function" for all functions is almost unheard of (at least I haven't heard of it), why? It's too damn long! We write functions constantly, we don't want to type "function" constantly.
Jul 11 2012
On Wednesday, 11 July 2012 at 16:45:17 UTC, David Piepgrass wrote:Anyway I think short vs long is much ado about nothing. No one complains that we have to type "int" instead of "integer", after all. Most languages have only a few keywords, which people quickly learn. As long as all the standard library functions are well-named, I don't care about the language keywords.Okay, I actually care a lot, just about the meaning of the keyword and not about whether it's abbreviated. I think D's use of "enum" for "static constant" and "static" for "thread singleton" (and three or four other things) is quite unfortunate, albeit understandable given the C heritage.
Jul 11 2012
On 07/11/2012 06:45 PM, David Piepgrass wrote:... These benefits (except 3) all exist for "function" as well as "fn", but while many languages use "fun", requiring "function" for all functions is almost unheard of (at least I haven't heard of it), why? It's too damn long! We write functions constantly, we don't want to type "function" constantly.You could have a look at JavaScript.
Jul 11 2012
On Wednesday, 11 July 2012 at 17:09:27 UTC, Timon Gehr wrote:On 07/11/2012 06:45 PM, David Piepgrass wrote:... and CoffeeScript as an attempt to fix that.... These benefits (except 3) all exist for "function" as well as "fn", but while many languages use "fun", requiring "function" for all functions is almost unheard of (at least I haven't heard of it), why? It's too damn long! We write functions constantly, we don't want to type "function" constantly.You could have a look at JavaScript.
Jul 11 2012
On 11-07-2012 19:09, Timon Gehr wrote:On 07/11/2012 06:45 PM, David Piepgrass wrote:And Lua. And PHP. Possibly others I'm forgetting. It's not that unheard of, really. -- Alex Rønne Petersen alex lycus.org http://lycus.org... These benefits (except 3) all exist for "function" as well as "fn", but while many languages use "fun", requiring "function" for all functions is almost unheard of (at least I haven't heard of it), why? It's too damn long! We write functions constantly, we don't want to type "function" constantly.You could have a look at JavaScript.
Jul 11 2012
On Wednesday, 11 July 2012 at 17:09:27 UTC, Timon Gehr wrote:On 07/11/2012 06:45 PM, David Piepgrass wrote:Ack! You got me. Dynamic languages aren't my thing. But JS being dynamically typed, it's not as bad since you don't have to specify the return type in addition.... These benefits (except 3) all exist for "function" as well as "fn", but while many languages use "fun", requiring "function" for all functions is almost unheard of (at least I haven't heard of it), why? It's too damn long! We write functions constantly, we don't want to type "function" constantly.You could have a look at JavaScript.
Jul 11 2012
Am Wed, 11 Jul 2012 19:09:26 +0200 schrieb Timon Gehr <timon.gehr gmx.ch>:On 07/11/2012 06:45 PM, David Piepgrass wrote:... and Pascal/Delphi, which has no 'void' return, but distinguishes between a 'procedure' and a 'function' with exactly those long keywords. Even better: When you declare a class, you have to use the long keywords in both the class declaration and the method implementation. Then again it also has 'begin' and 'end' instead of { and }. Masochists... -- Marco... These benefits (except 3) all exist for "function" as well as "fn", but while many languages use "fun", requiring "function" for all functions is almost unheard of (at least I haven't heard of it), why? It's too damn long! We write functions constantly, we don't want to type "function" constantly.You could have a look at JavaScript.
Jul 11 2012
On Wednesday, 11 July 2012 at 18:53:31 UTC, Marco Leise wrote:Am Wed, 11 Jul 2012 19:09:26 +0200 schrieb Timon Gehr <timon.gehr gmx.ch>:I was a very happy Turbo Pascal and Delphi developer, until I switched full time to C and C++.On 07/11/2012 06:45 PM, David Piepgrass wrote:... and Pascal/Delphi, which has no 'void' return, but distinguishes between a 'procedure' and a 'function' with exactly those long keywords. Even better: When you declare a class, you have to use the long keywords in both the class declaration and the method implementation. Then again it also has 'begin' and 'end' instead of { and }. Masochists...... These benefits (except 3) all exist for "function" as well as "fn", but while many languages use "fun", requiring "function" for all functions is almost unheard of (at least I haven't heard of it), why? It's too damn long! We write functions constantly, we don't want to type "function" constantly.You could have a look at JavaScript.
Jul 11 2012
Marco Leise:Then again it also has 'begin' and 'end' instead of { and }. Masochists...Between APL/Ursala and Ada extremes there is a wide happy middle, D, Pascal and probably Rust too are all usable. The 'begin' and 'end' of Pascal are not bad, they are short lowercase words written with common letters. I need to press 3 not easy keys at the same time to print a single { in a text file. So probably writing "end" is about as fast or faster for me :-) Bye, bearophile
Jul 11 2012
On 7/11/2012 9:45 AM, David Piepgrass wrote:I still type "reutrn" and "retrun" all the damn time!I keep finding myself typing "redrum" !
Jul 11 2012
On 07/11/12 20:32, Walter Bright wrote:On 7/11/2012 9:45 AM, David Piepgrass wrote:Good one :DI still type "reutrn" and "retrun" all the damn time!I keep finding myself typing "redrum" !
Jul 11 2012
On 7/8/2012 6:49 AM, bearophile wrote:I think in Go the function stack is segmented and growable as in Go. This saves RAM if you need a small stack, and avoids stack overflows where lot of stack is needed.The trouble with segmented stacks are: 1. they have a significant runtime penalty 2. interfacing to C code becomes problematic Also, they do not save RAM, they save address space. RAM is not committed until a stack memory page is actually used. Segmented stacks are useful for 32 bit address space. However, they are not useful for 64 bit address spaces. Heck, you can allocate 4 billion stacks of 4 billion bytes each! (Remember, allocating address space is not allocating actual memory.) Given that the programming world is moving rapidly to 64 bit exclusively, I think segmented stacks are a dead end technology. They would have been much more interesting 15 years ago.
Jul 08 2012
Walter Bright: Thank you for your answers Walter, as you guess I am ignorant about segmented stacks.The trouble with segmented stacks are: 1. they have a significant runtime penaltyAlso, they do not save RAM, they save address space. RAM is not committed until a stack memory page is actually used.Regarding performance and memory used they say: http://golang.org/doc/go_faq.html#goroutinesThe result, which we call goroutines, can be very cheap: unless they spend a lot of time in long-running system calls, they cost little more than the memory for the stack, which is just a few kilobytes. To make the stacks small, Go's run-time uses segmented stacks. A newly minted goroutine is given a few kilobytes, which is almost always enough. When it isn't, the run-time allocates (and frees) extension segments automatically. The overhead averages about three cheap instructions per function call. It is practical to create hundreds of thousands of goroutines in the same address space. If goroutines were just threads, system resources would run out at a much smaller number.<Segmented stacks are useful for 32 bit address space. However, they are not useful for 64 bit address spaces.I think Go is meant to be used mostly on 64 bit servers. Both the designers of Go and Rust are experienced people, and they plan to use their languages on 64 bit systems. Here they say Go avoid many stack overflows, because stack are limited by the available virtual memory: http://stackoverflow.com/questions/4226964/how-come-go-doesnt-have-stackoverflows I think LLVM supports segmented stacks, the example given is on x86-64: http://llvm.org/releases/3.0/docs/SegmentedStacks.html Bye, bearophile
Jul 08 2012
On 7/8/2012 2:32 PM, bearophile wrote:I think you misunderstood. I meant there is no point to segmented stacks on a 64 bit system.Segmented stacks are useful for 32 bit address space. However, they are not useful for 64 bit address spaces.I think Go is meant to be used mostly on 64 bit servers. Both the designers of Go and Rust are experienced people, and they plan to use their languages on 64 bit systems.
Jul 08 2012
"bearophile" <bearophileHUGS lycos.com> wrote:I think Go is meant to be used mostly on 64 bit servers.There aren't many people using Go on 32 bit systems. That's why there is (was?) a big memory leak on these systems which wasn't caught early on.
Jul 09 2012
On Mon, Jul 9, 2012 at 4:24 PM, Stefan Scholl <stesch no-spoon.de> wrote:"bearophile" <bearophileHUGS lycos.com> wrote:There aren't many people using Go, period.I think Go is meant to be used mostly on 64 bit servers.There aren't many people using Go on 32 bit systems. That's why there is (was?) a big memory leak on these systems which wasn't caught early on.
Jul 09 2012
Caligo <iteronvexor gmail.com> wrote:On Mon, Jul 9, 2012 at 4:24 PM, Stefan Scholl <stesch no-spoon.de> wrote:Don't know about this, but "Programming in Go" is a bad book (talks about OO in Go and the author was clearly paid by number of words) but has a higher ranking on Amazon than "The D Programming Language". And all the news sites and programmer blogs are nearly silent regarding D. Maybe this changes after Polanski finishes his movie about D. ;-)"bearophile" <bearophileHUGS lycos.com> wrote:There aren't many people using Go, period.I think Go is meant to be used mostly on 64 bit servers.There aren't many people using Go on 32 bit systems. That's why there is (was?) a big memory leak on these systems which wasn't caught early on.
Jul 09 2012
On 7/10/12 2:30 AM, Stefan Scholl wrote:Caligo<iteronvexor gmail.com> wrote:The book was released only in March; newer books usually have their highest rank during their first months. Also, TDPL has a paperback and a Kindle edition, which "compete" in rank with each other. As an aside, Gedankenexperiment: imagine D were created at Google and Go were created by Walter. How would they have fared? I honestly think things would have been quite, um, different. I believe quite strongly is Go wouldn't have received any attention, and D would have been a riot.On Mon, Jul 9, 2012 at 4:24 PM, Stefan Scholl<stesch no-spoon.de> wrote:Don't know about this, but "Programming in Go" is a bad book (talks about OO in Go and the author was clearly paid by number of words) but has a higher ranking on Amazon than "The D Programming Language"."bearophile"<bearophileHUGS lycos.com> wrote:There aren't many people using Go, period.I think Go is meant to be used mostly on 64 bit servers.There aren't many people using Go on 32 bit systems. That's why there is (was?) a big memory leak on these systems which wasn't caught early on.And all the news sites and programmer blogs are nearly silent regarding D.I agree that that's a problem, and it starts with us. Andrei
Jul 10 2012
On 10 July 2012 13:35, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 7/10/12 2:30 AM, Stefan Scholl wrote:D would be in GCC and Go would be trying to baby step over the hurdle and find grip in the GCC community. :o)Caligo<iteronvexor gmail.com> wrote:The book was released only in March; newer books usually have their highest rank during their first months. Also, TDPL has a paperback and a Kindle edition, which "compete" in rank with each other. As an aside, Gedankenexperiment: imagine D were created at Google and Go were created by Walter. How would they have fared? I honestly think things would have been quite, um, different. I believe quite strongly is Go wouldn't have received any attention, and D would have been a riot.On Mon, Jul 9, 2012 at 4:24 PM, Stefan Scholl<stesch no-spoon.de> wrote:Don't know about this, but "Programming in Go" is a bad book (talks about OO in Go and the author was clearly paid by number of words) but has a higher ranking on Amazon than "The D Programming Language"."bearophile"<bearophileHUGS lycos.com> wrote:There aren't many people using Go, period.I think Go is meant to be used mostly on 64 bit servers.There aren't many people using Go on 32 bit systems. That's why there is (was?) a big memory leak on these systems which wasn't caught early on.Any future plans on D programming language books? I must admit I'm more of a Pocket Reference guy though. Regards -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';And all the news sites and programmer blogs are nearly silent regarding D.I agree that that's a problem, and it starts with us.
Jul 10 2012
Andrei Alexandrescu Wrote:On 7/10/12 2:30 AM, Stefan Scholl wrote:It was under my impression that is because whole D thing was badly engineered from the start. Programming work was great, but whole other parts of this en devour are badly played. Just too much messed up priorities.Caligo<iteronvexor gmail.com> wrote:The book was released only in March; newer books usually have their highest rank during their first months. Also, TDPL has a paperback and a Kindle edition, which "compete" in rank with each other. As an aside, Gedankenexperiment: imagine D were created at Google and Go were created by Walter. How would they have fared? I honestly think things would have been quite, um, different. I believe quite strongly is Go wouldn't have received any attention, and D would have been a riot.On Mon, Jul 9, 2012 at 4:24 PM, Stefan Scholl<stesch no-spoon.de> wrote:Don't know about this, but "Programming in Go" is a bad book (talks about OO in Go and the author was clearly paid by number of words) but has a higher ranking on Amazon than "The D Programming Language"."bearophile"<bearophileHUGS lycos.com> wrote:There aren't many people using Go, period.I think Go is meant to be used mostly on 64 bit servers.There aren't many people using Go on 32 bit systems. That's why there is (was?) a big memory leak on these systems which wasn't caught early on.And all the news sites and programmer blogs are nearly silent regarding D.I agree that that's a problem, and it starts with us.
Jul 10 2012
On 7/10/12 10:59 AM, Patrick Stewar wrote:Andrei Alexandrescu Wrote:What I meant to say was that we're not writing enough about D, but I'll take a vote of non-confidence over that any day :o). AndreiOn 7/10/12 2:30 AM, Stefan Scholl wrote:It was under my impression that is because whole D thing was badly engineered from the start. Programming work was great, but whole other parts of this en devour are badly played. Just too much messed up priorities.Caligo<iteronvexor gmail.com> wrote:The book was released only in March; newer books usually have their highest rank during their first months. Also, TDPL has a paperback and a Kindle edition, which "compete" in rank with each other. As an aside, Gedankenexperiment: imagine D were created at Google and Go were created by Walter. How would they have fared? I honestly think things would have been quite, um, different. I believe quite strongly is Go wouldn't have received any attention, and D would have been a riot.On Mon, Jul 9, 2012 at 4:24 PM, Stefan Scholl<stesch no-spoon.de> wrote:Don't know about this, but "Programming in Go" is a bad book (talks about OO in Go and the author was clearly paid by number of words) but has a higher ranking on Amazon than "The D Programming Language"."bearophile"<bearophileHUGS lycos.com> wrote:There aren't many people using Go, period.I think Go is meant to be used mostly on 64 bit servers.There aren't many people using Go on 32 bit systems. That's why there is (was?) a big memory leak on these systems which wasn't caught early on.And all the news sites and programmer blogs are nearly silent regarding D.I agree that that's a problem, and it starts with us.
Jul 10 2012
On Sunday, 8 July 2012 at 19:28:11 UTC, Walter Bright wrote:On 7/8/2012 6:49 AM, bearophile wrote:Why?I think in Go the function stack is segmented and growable as in Go. This saves RAM if you need a small stack, and avoids stack overflows where lot of stack is needed.The trouble with segmented stacks are: 1. they have a significant runtime penalty2. interfacing to C code becomes problematicIsn't it possible to auto-commit new pages when C code needs it? I see that *moving* the stack would be a problem unless you have a means to adjust all pointers that point into the stack. If you need to call C code in 32-bit, you'd have to specify a maximum stack size.
Jul 11 2012
On 7/11/2012 9:57 AM, David Piepgrass wrote:On Sunday, 8 July 2012 at 19:28:11 UTC, Walter Bright wrote:Extra instructions generated for each function.On 7/8/2012 6:49 AM, bearophile wrote:Why?I think in Go the function stack is segmented and growable as in Go. This saves RAM if you need a small stack, and avoids stack overflows where lot of stack is needed.The trouble with segmented stacks are: 1. they have a significant runtime penaltyThere's no way to predict how much stack arbitrary C code will use.2. interfacing to C code becomes problematicIsn't it possible to auto-commit new pages when C code needs it? I see that *moving* the stack would be a problem unless you have a means to adjust all pointers that point into the stack. If you need to call C code in 32-bit, you'd have to specify a maximum stack size.
Jul 11 2012
Every function? Why?Extra instructions generated for each function.The trouble with segmented stacks are: 1. they have a significant runtime penaltyWhy?...2. interfacing to C code becomes problematicIsn't it possible to auto-commit new pages when C code needs it?There's no way to predict how much stack arbitrary C code will use.Presumably one does not call arbitrary C code. Usually one knows what one might call in advance and can plan accordingly (and even if it is arbitrary, one at least knows *that* one is going to call C code and plan accordingly. Most C code doesn't allocate more than a few megabytes on the stack).
Jul 11 2012
On Wednesday, 11 July 2012 at 18:31:23 UTC, David Piepgrass wrote:Looks like I misunderstood what "Segmented stacks" are. From an LLVM page:Every function? Why?Extra instructions generated for each function.The trouble with segmented stacks are: 1. they have a significant runtime penaltyWhy?Segmented stack allows stack space to be allocated incrementally than as a monolithic chunk (of some worst case size) at thread initialization. This is done by allocating stack blocks (henceforth called stacklets) and linking them into a doubly linked list. The function prologue is responsible for checking if the current stacklet has enough space for the function to execute; and if not, call into the libgcc runtime to allocate more stack space. Support for segmented stacks on x86 / Linux is currently being worked on.I envision a rather different implementation for 32-bit code. 1. Reserve a normal stack with one 4K page committed + some known minimum amount of uncommitted memory, e.g. another 8 KB uncommitted with a guard page that the program can trap via OS facilities (signals, etc.) 2. When the stack overflows, move the stack to a new, much larger region of Virtual Memory. Much like languages that support compacting garbage collectors, the language / runtime environment must be designed to support this. 3. If one needs to call C code, one preallocates the maximum expected virtual memory needed, e.g. 32 MB.
Jul 11 2012
On Sunday, 8 July 2012 at 13:49:50 UTC, bearophile wrote:This seems a bit overkill to me: It's also possible to avoid any type ambiguity by writing integer literals with a suffix. The suffixes i and u are for the types int and uint, respectively: the literal -3i has type int, while 127u has type uint. For the fixed-size integer types, just suffix the literal with the type name: 255u8, 50i64, etc.Many good ideas... am just singling out this one, as you seem to be of a different opinion in this particular case... I on the contrary wish D would have taken this route as well, because of the ubiquitous 'auto' and 'implicit template instantiation' features... furthermore vector simd types could also benefit.
Jul 08 2012
Am Sun, 08 Jul 2012 21:51:57 +0200 schrieb "Daniel" <wyrlon gmx.net>:On Sunday, 8 July 2012 at 13:49:50 UTC, bearophile wrote:Yes, this is the single most important Rust feature to me when typing. I've just had too many cases of mass-casts to ubyte or short where a suffix to the literal would only have cost one or two letters. 255ub = byte, 32000s = short -- MarcoThis seems a bit overkill to me: It's also possible to avoid any type ambiguity by writing integer literals with a suffix. The suffixes i and u are for the types int and uint, respectively: the literal -3i has type int, while 127u has type uint. For the fixed-size integer types, just suffix the literal with the type name: 255u8, 50i64, etc.Many good ideas... am just singling out this one, as you seem to be of a different opinion in this particular case... I on the contrary wish D would have taken this route as well, because of the ubiquitous 'auto' and 'implicit template instantiation' features... furthermore vector simd types could also benefit.
Jul 10 2012
Marco Leise:Yes, this is the single most important Rust feature to me when typing. I've just had too many cases of mass-casts to ubyte or short where a suffix to the literal would only have cost one or two letters. 255ub = byte, 32000s = shortI am writing a lot of D2 code, but in my code the need of explicit short or byte literals is very uncommon. That's why those Rust suffixes seem overkill to me. Do you want to show us some of your use cases? Bye, bearophile
Jul 11 2012
Am Wed, 11 Jul 2012 20:24:34 +0200 schrieb "bearophile" <bearophileHUGS lycos.com>:Marco Leise:As an optional feature, I think it is nice to have them when you need them. They are not a feature that has any downside I can think of, as we already have some other suffixes and the maintenance cost is practically zero. Here are some examples: DMD: (test42.d), array type inference: const short[] ct = cast(short[]) [cast(byte)1, 1]; => const short[] ct = cast(short[]) [1b, 1]; Phobos: (boxer.d): assert (box(1) == box(cast(byte)1)); => assert (box(1) == box(1b)); (algorithm.d): assert(b == [ cast(ubyte) 0, cast(ubyte)2, cast(ubyte)1, cast(ubyte)6, cast(ubyte)5], text(b)); => assert(b == [ 0ub, 2ub, 1ub, 6ub, 5ub], text(b)); (variant.d): a = cast(short) 5; => a = 5s; (gregorian.d): julianbegin = julianDay(tuple(cast(ushort)ymd._0, cast(ushort)1, cast(ushort)1)) => julianbegin = julianDay(tuple(cast(ushort)ymd._0, 1us, 1us)) (string.d): assert(isNumeric(cast(byte)0x57) == false); // 'W' => assert(isNumeric(0x57b) == false); // 'W' GtkD: (Color.d and several other occurences): _black = new Color(cast(ubyte)0,cast(ubyte)0,cast(ubyte)0); => _black = new Color(0ub,0ub,0ub); ScintillaD: (SciTEWin.d): SendMessage(HwndOf(wText), CB_SETEDITSEL, 0, MAKELPARAM(0, cast(ushort)-1)); => SendMessage(HwndOf(wText), CB_SETEDITSEL, 0, MAKELPARAM(0, -1us)); QtD: (Atomic.d): return llvm_atomic_load_add!(ubyte)(cast(ubyte*)&val, cast(ubyte)0) ? 1 : 0; => return llvm_atomic_load_add!(ubyte)(cast(ubyte*)&val, 0ub) ? 1 : 0; My code: write a literal (byte) number to a 'take anything' output stream: ostr.write(cast(ubyte) 0); => ostr.write(0ub); from a unittest for Unicode sequences: loadCycle(cast(char[]) [cast(ubyte) 0b11000111, cast(ubyte) 0b00111111]); => loadCycle(cast(char[]) [0b11000111ub, 0b00111111ub]); I thought there were more cases in my code, but it seems like often the casts were required because some intermediate result of 16-bit calculations is extended to 32-bits by the language (where the CPU can perform arithmetics faster). So I looked at the other projects I checked out and it seems like casts to byte or short are not frequent, but most projects need them once in a while. -- MarcoYes, this is the single most important Rust feature to me when typing. I've just had too many cases of mass-casts to ubyte or short where a suffix to the literal would only have cost one or two letters. 255ub = byte, 32000s = shortI am writing a lot of D2 code, but in my code the need of explicit short or byte literals is very uncommon. That's why those Rust suffixes seem overkill to me. Do you want to show us some of your use cases? Bye, bearophile
Jul 11 2012
Marco Leise:Phobos: (boxer.d): assert (box(1) == box(cast(byte)1)); => assert (box(1) == box(1b)); (algorithm.d): assert(b == [ cast(ubyte) 0, cast(ubyte)2, cast(ubyte)1, cast(ubyte)6, cast(ubyte)5], text(b)); => assert(b == [ 0ub, 2ub, 1ub, 6ub, 5ub], text(b));Here b is an ubyte[] of length 5. I think this works: assert(b == [0, 2, 1, 6, 5], text(b)); Because this works: void main() { ubyte[] a = [1, 2]; assert(a == [1, 2]); }=> a = 5s;I read that as "5 seconds" :-(GtkD: (Color.d and several other occurences): _black = new Color(cast(ubyte)0,cast(ubyte)0,cast(ubyte)0); => _black = new Color(0ub,0ub,0ub);This is a reduction of the Color class of GtkD: public class Color { this(ubyte red, ubyte green, ubyte blue) {} } There is no need to use those casts: void main() { auto _black = new Color(0, 0, 0); }ScintillaD: (SciTEWin.d): SendMessage(HwndOf(wText), CB_SETEDITSEL, 0, MAKELPARAM(0, cast(ushort)-1)); => SendMessage(HwndOf(wText), CB_SETEDITSEL, 0, MAKELPARAM(0, -1us));"cast(ushort)-1" isn't a good idiom in D. Better to write "ushort.max". I don't think your examples justify the increased language complexity. Bye, bearophile
Jul 11 2012
Am Wed, 11 Jul 2012 22:58:07 +0200 schrieb "bearophile" <bearophileHUGS lycos.com>:Me too, but then again "5l" could be read as 5 liters. I guess that is why the move is towards uppercase suffixes. 5S and 5L are not likely misread.=> a = 5s;I read that as "5 seconds" :-(I don't think your examples justify the increased language complexity. Bye, bearophileI understand that some of the examples have better alternatives. What I don't understand is why you term this as increased language complexity. This is not one of the "why not add" kind of requests. From my point of view the complexity is already there through U, UL, I and UI. So completing the set with B, UB, S and US seems only logical and solves an existing (attention: buzzword ahead) ... *inconsistency*. ;) To cut a long story short; if I added those suffixes and made a pull request would anyone be objected? -- Marco
Jul 12 2012
Am Thu, 12 Jul 2012 11:42:13 +0200 schrieb Marco Leise <Marco.Leise gmx.de>:Am Wed, 11 Jul 2012 22:58:07 +0200 schrieb "bearophile" <bearophileHUGS lycos.com>:P.S.: There is no I or UI, just L and UL. Sorry for the confusion. -- MarcoMe too, but then again "5l" could be read as 5 liters. I guess that is why the move is towards uppercase suffixes. 5S and 5L are not likely misread.=> a = 5s;I read that as "5 seconds" :-(I don't think your examples justify the increased language complexity. Bye, bearophileI understand that some of the examples have better alternatives. What I don't understand is why you term this as increased language complexity. This is not one of the "why not add" kind of requests. From my point of view the complexity is already there through U, UL, I and UI. So completing the set with B, UB, S and US seems only logical and solves an existing (attention: buzzword ahead) ... *inconsistency*. ;) To cut a long story short; if I added those suffixes and made a pull request would anyone be objected?
Jul 12 2012
Am Thu, 12 Jul 2012 12:08:07 +0200 schrieb Marco Leise <Marco.Leise gmx.de>:Am Thu, 12 Jul 2012 11:42:13 +0200 schrieb Marco Leise <Marco.Leise gmx.de>:I experimented a bit with it and the modifications to DMD are mostly straight forward copy,paste,modify. But then I face palmed: 'b' is of course a valid digit in hex notation already, meaning it would always be counted as part of the hex number, and not as a suffix. That would be a bit ... inconvenient. :D -- MarcoAm Wed, 11 Jul 2012 22:58:07 +0200 schrieb "bearophile" <bearophileHUGS lycos.com>:P.S.: There is no I or UI, just L and UL. Sorry for the confusion.Me too, but then again "5l" could be read as 5 liters. I guess that is why the move is towards uppercase suffixes. 5S and 5L are not likely misread.=> a = 5s;I read that as "5 seconds" :-(I don't think your examples justify the increased language complexity. Bye, bearophileI understand that some of the examples have better alternatives. What I don't understand is why you term this as increased language complexity. This is not one of the "why not add" kind of requests. From my point of view the complexity is already there through U, UL, I and UI. So completing the set with B, UB, S and US seems only logical and solves an existing (attention: buzzword ahead) ... *inconsistency*. ;) To cut a long story short; if I added those suffixes and made a pull request would anyone be objected?
Jul 12 2012
On 7/12/2012 2:42 AM, Marco Leise wrote:I understand that some of the examples have better alternatives. What I don't understand is why you term this as increased language complexity. This is not one of the "why not add" kind of requests. From my point of view the complexity is already there through U, UL, I and UI. So completing the set with B, UB, S and US seems only logical and solves an existing (attention: buzzword ahead) ... *inconsistency*. ;) To cut a long story short; if I added those suffixes and made a pull request would anyone be objected?I'd object. I've been programming in C, C++ and D for 30 years now, and I use u and L suffixes way less than 1% of the time, and have simply never found a use for b or s suffixes. I'm not convinced it solves a real problem.
Jul 12 2012
Am Thu, 12 Jul 2012 11:30:58 -0700 schrieb Walter Bright <newshound2 digitalmars.com>:On 7/12/2012 2:42 AM, Marco Leise wrote:Alright, I'll stow it away as a little experiment. But consider, that especially C and to some extend C++ had less cases of ambiguous data types than D. And the point of new suffixes here is to avoid cast(byte) and cast(short) as a means to disambiguate, namely in the cases of: method overloads using both byte/int, array type inference and the 'auto' keyword. C without name mangling for example wouldn't allow: void foo(ubyte x); void foo(int x); foo(128); // I'd often intuitively think, the ubyte version matches best This is a typical case in general stream classes that offer overloaded write methods for every supported data type, e.g.: std.stream.EndianStream stream; stream.write(cast(ubyte) 0x01); // Have written 4 bytes instead of 1 in the past, // especially when the IDE shows the first matching overload as "write(byte x)" (Mono-D) or with multiple constructors (here the earlier example from GtkD): // inside the Color class this(ubyte red, ubyte green, ubyte blue) { this(); set8(red, green, blue); } this(guint16 red, guint16 green, guint16 blue) { this(); set(red,green,blue); } // cannot call the 8-bit version without casts _black = new Color(cast(ubyte)0,cast(ubyte)0,cast(ubyte)0); _white = new Color(cast(ubyte)255,cast(ubyte)255,cast(ubyte)255); An example with D's array type inference is: void unicodeTest(char[] code) { ... } unicodeTest("abc"); unicodeTest(cast(char[]) [cast(ubyte) 0b11000111, cast(ubyte) 0b00111111]); // I think the second cast can be omitted here The cases of 'auto' return or assignment can be worked around by not using auto and may be artificial. Yet it feels like auto is partially broken, because I cannot directly write down 8- and 16-bit integer literals like so: auto code(...) { if (...) return 42us; return 123us; } immutable Magic = 0x1234us; -- MarcoI understand that some of the examples have better alternatives. What I don't understand is why you term this as increased language complexity. This is not one of the "why not add" kind of requests. From my point of view the complexity is already there through U, UL, I and UI. So completing the set with B, UB, S and US seems only logical and solves an existing (attention: buzzword ahead) ... *inconsistency*. ;) To cut a long story short; if I added those suffixes and made a pull request would anyone be objected?I'd object. I've been programming in C, C++ and D for 30 years now, and I use u and L suffixes way less than 1% of the time, and have simply never found a use for b or s suffixes. I'm not convinced it solves a real problem.
Jul 13 2012
On 7/13/2012 3:21 AM, Marco Leise wrote:The cases of 'auto' return or assignment can be worked around by not using auto and may be artificial. Yet it feels like auto is partially broken, because I cannot directly write down 8- and 16-bit integer literals like so: auto code(...) { if (...) return 42us; return 123us; } immutable Magic = 0x1234us;auto code() { return cast(ushort)42; } works fine. There isn't really a lack here, just some more typing. I just don't see the case coming up hardly at all.
Jul 13 2012
Walter Bright:auto code() { return cast(ushort)42; } works fine. There isn't really a lack here, just some more typing. I just don't see the case coming up hardly at all.I have just found an example (reduced code): import std.typecons; void main() { alias Tuple!(ubyte[]) Tu; auto x1 = Tu([cast(ubyte)0]); // OK auto x2 = Tu([0]); // Error } D tuples are very strict. Bye, bearophile
Jul 17 2012
On 07/17/2012 07:25 PM, bearophile wrote:Walter Bright:Looks like a bug in std.typecons.Tuple. That constructor shouldn't be templated on the argument types.auto code() { return cast(ushort)42; } works fine. There isn't really a lack here, just some more typing. I just don't see the case coming up hardly at all.I have just found an example (reduced code): import std.typecons; void main() { alias Tuple!(ubyte[]) Tu; auto x1 = Tu([cast(ubyte)0]); // OK auto x2 = Tu([0]); // Error } D tuples are very strict. Bye, bearophile
Jul 17 2012
On 12 July 2012 18:42, Marco Leise <Marco.Leise gmx.de> wrote:Am Wed, 11 Jul 2012 22:58:07 +0200 schrieb "bearophile" <bearophileHUGS lycos.com>:"L" is also an internationally-recognised symbol for litres. http://physics.nist.gov/cuu/Units/outside.html Personally, I think that if I need to care about the data size/maximum range of a value, I should be using a fixed-size data type rather than specifying it in the value. The language typically supports me in doing so without the need for prefixes except on rare occasions. GeoffMe too, but then again "5l" could be read as 5 liters. I guess that is why the move is towards uppercase suffixes. 5S and 5L are not likely misread.=> a = 5s;I read that as "5 seconds" :-(
Jul 12 2012
Am Fri, 13 Jul 2012 08:31:31 +0900 schrieb Geoffrey Biggs <geoffrey.biggs aist.go.jp>:Personally, I think that if I need to care about the data size/maximum range of a value, I should be using a fixed-size data type rather than specifying it in the value. The language typically supports me in doing so without the need for prefixes except on rare occasions. GeoffPlease! This is a different story. You talk about declaring best fit data types, something that Delphi has a good go on for integral types (numbers and enums): type TPercentValue : 0 .. 100; // cannot assign a value outside that range Just for the sake of clarification, the suffixes are there to disambiguate, since D - a little simplified - tries 32-bit types before 64-bit types and signed types before unsigned types; with no way to make a literal 8-bit or 16-bit for 'auto', function/method overloading or array type inference. -- Marco
Jul 13 2012
Rust has type classes from Haskell (with some simplifications for higher kinds), uniqueness typing, and typestates.As nice as kinds, typestates, typeclasses and several pointer types may be, I was in the Rust mailing list and felt unable to participate because they kept using terminology that only PhD in type systems understand. And googling for "kind" doesn't tell me a darn thing ;) That's why have gravitated to D, it's so much more familiar (sometimes too much so, e.g. I still need to 'break' in 'switch'? how many meanings for 'static'?) as well as very powerful. I would still like to learn about the mumbo-jumbo, though, and I know how nice pattern-matching can be from one Haskell-based course in university :)This seems a bit overkill to me: This is very strict, maybe too much strict:Agreed about the int suffixes, but I wonder what Marco meant about "mass-casts" in D.The safe pointer types are T for shared, reference-counted boxes, and ~T, for uniquely-owned pointers.I wonder how well these could be simulated in D. It seems to me Rust is carefully designed for performance, or at least real-time performance by avoiding garbage collection in favor of safely tracking ownership. That's good, but only now are they developing things like OOP support that I take for granted.++ and -- are missingRust, like Go, seems very focused on making a "simple" language. Another reason that I prefer D.the logical bitwise operators have higher precedence. In C, x & 2 > 0 comes out as x & (2 > 0), in Rust, it means (x & 2) > 0, which is more likely to be what you expect (unless you are a C veteran).Oh, I can't tell you what a pet peeve PITA the C precedence is. Ugh! I know it's against D philosophy to change the precedence w.r.t. C, but how about a compromise: give a warning or error for "x&2 > 0", with error message: "add parenthesis around x&2 to clarify your intention."Enums are datatypes that have several different representations. For example, the type shown earlier: enum shape { circle(point, float), rectangle(point, point) } fn angle(vec: (float, float)) -> float { alt vec { (0f, y) if y < 0f { 1.5 * float::consts::pi } (0f, y) { 0.5 * float::consts::pi } (x, y) { float::atan(y / x) } } } alt mypoint { {x: 0f, y: y_name} { /* Provide sub-patterns for fields */ } {x, y} { /* Simply bind the fields */ } } let (a, b) = get_tuple_of_two_ints();Records, tuples, and destructuring go so well together. I would love to have this. I am particularly a fan of structural typing. I don't know if Rust uses it but Opa and other functional languages often do. You see, there's a problem that pops up in .NET all the time, and probably the same problem exists in D. Any time two libraries want to use the same concept, but the concept is not in the standard library, they need to define it. For instance if there is no "Point" type in the standard library, but two unrelated libraries need points, they will both define their own (amazingly, Points are poorly thought out in .NET and tightly bound to GUI libraries, so people define their own in some cases): // JoesLibrary struct Point!T { T x, y; /* followed by some manipulation functions */ } // FunkyLibrary struct Point!T { T x, y; /* followed by other manipulation functions */ } Sadly, the two point types are not compatible with each other. A client that wants to use both libraries now has an interoperability problem when he wants to pass data between the. Even a client that uses only one of the library, let's call it "JoesLibrary" has to import Point from "JoesLibrary", even if its functionality is not quite what the client wants. It would be much nicer if the client could define his own Point struct that seamlessly interoperates with Joes'. In D this is currently impractical, but I would enjoy designing a way to make it work (before you point out that "what if x and y are in a different order in the two structs" and "it could be T X,Y in one and T x,y in the other", yes, I know, It's on my list of problems to cleverly solve) A similar problem exists with interfaces, where two unrelated libraries expose two similar classes with some common functions, but you can't cast them to a common type in D. This is a solved problem in Go (http://www.airs.com/blog/archives/277) and it's actually pretty easy for a compiler to magically cast a class to an interface that the class did not declare--if the underlying language is designed for that, anyway. In fact, in .NET at least, the same problem exists even if the libraries DO know about each other and are even written by the same person and use identical interfaces. The problem is, if I write two libraries A and B, and I want them to be interoperable, then I need to factor out the common structs and interfaces to a microscopic third library, I. But from the client's perspective, if a client only knows about A or B, he will think it's stupid that I require him to use and deploy two DLLs/so's (A and I, or B and I) instead of one. In D I guess it's not the same, though.Stack-allocated closures: There are several forms of closure, each with its own role. The most common, called a stack closure, has type fn& and can directly access local variables in the enclosing scope. let mut max = 0; [1, 2, 3].map(|x| if x > max { max = x });I seem to recall that D has the ability to optimize closures to make them stack-based when calling generic methods, or if the called method happens to be inlined, am I right? However, Rust's approach seems more powerful: - Since it uses explicit notation, it could work across library and DLL boundaries. The called function can promise it will not save a reference to the closure, so the closure can always be stack-based. - I think Rust developed a "do" syntax that allows "break" and "continue" (cont?) so that closures can be used in loops, so I guess you could write your own while-loop for example. The syntax is something like do While(|| x > 0) { ... if (...) cont; ... } if I'm not mistaken and going senile.Unique closures, written fn~ in analogy to the ~ pointer type (see next section), hold on to things that can safely be sent between processes. They copy the values they close over, much like boxed closures, but they also 'own' them—meaning no other code can access them. Unique closures are used in concurrent code, particularly for spawning tasks.Hmm, hmm. Is there anything analagous in D?By default, a module exports everything that it defines. This can be restricted with export directives at the top of the module or file. mod enc { export encrypt, decrypt; const super_secret_number: int = 10; fn encrypt(n: int) -> int { n + super_secret_number } fn decrypt(n: int) -> int { n - super_secret_number } }I much prefer D's approach. It's much more convenient for the code writer, and Rust's approach is better or worse for someone reading the code depending on whether one wants to know "what functions are public?" or "is this function I'm looking at public?"For some info on the typestate system, from the Rust manual: http://dl.rust-lang.org/doc/rust.html#typestate-systemOh, do I ramble on or what? I'd love to talk about that, but would you look at the time...
Jul 11 2012
On 07/11/2012 08:00 PM, David Piepgrass wrote:... Oh, I can't tell you what a pet peeve PITA the C precedence is. Ugh! I know it's against D philosophy to change the precedence w.r.t. C, but how about a compromise: give a warning or error for "x&2 > 0", with error message: "add parenthesis around x&2 to clarify your intention."That is what D does : )
Jul 11 2012
On 7/11/2012 11:00 AM, David Piepgrass wrote:bool test(int x) { return x & 2 > 0; } gives: foo.d(1): Error: 2 > 0 must be parenthesized when next to operator &the logical bitwise operators have higher precedence. In C, x & 2 > 0 comes out as x & (2 > 0), in Rust, it means (x & 2) > 0, which is more likely to be what you expect (unless you are a C veteran).Oh, I can't tell you what a pet peeve PITA the C precedence is. Ugh! I know it's against D philosophy to change the precedence w.r.t. C, but how about a compromise: give a warning or error for "x&2 > 0", with error message: "add parenthesis around x&2 to clarify your intention."
Jul 11 2012
Doh! You read my mind before I thought it :) I hadn't got around to bit fiddling in D yet.Oh, I can't tell you what a pet peeve PITA the C precedence is. Ugh! I know it's against D philosophy to change the precedence w.r.t. C, but how about a compromise: give a warning or error for "x&2 > 0", with error message: "add parenthesis around x&2 to clarify your intention."bool test(int x) { return x & 2 > 0; } gives: foo.d(1): Error: 2 > 0 must be parenthesized when next to operator &
Jul 11 2012
bool test(int x) { return x & 2 > 0; } gives: foo.d(1): Error: 2 > 0 must be parenthesized when next to operator &That reminds me, I was so happy the first two times I got an undefined symbol error in D. The compiler said: "Did you mean '<correct variable name>'?" LOL, don't tell me how it works... it's magic, right? I love a good error message.
Jul 11 2012
On 7/11/2012 11:54 AM, David Piepgrass wrote:That reminds me, I was so happy the first two times I got an undefined symbol error in D. The compiler said: "Did you mean '<correct variable name>'?" LOL, don't tell me how it works... it's magic, right? I love a good error message.I added a spelling checker to the undefined identifier code, using the variables in scope as the dictionary. It's a fun little nicety.
Jul 11 2012
On 11/07/2012 21:50, Walter Bright wrote:On 7/11/2012 11:54 AM, David Piepgrass wrote:Yeah, that one is really nice and usually useful. However, you can get really weird stuff if you forget an import for instance.That reminds me, I was so happy the first two times I got an undefined symbol error in D. The compiler said: "Did you mean '<correct variable name>'?" LOL, don't tell me how it works... it's magic, right? I love a good error message.I added a spelling checker to the undefined identifier code, using the variables in scope as the dictionary. It's a fun little nicety.
Jul 11 2012
On 07/11/2012 03:50 PM, Walter Bright wrote:On 7/11/2012 11:54 AM, David Piepgrass wrote:I remember you took some heat for this because of compiler slowdowns, as well as a public admonishment from Andrei because it wasn't a priority. Must be nice to get some positive feedback on it :)That reminds me, I was so happy the first two times I got an undefined symbol error in D. The compiler said: "Did you mean '<correct variable name>'?" LOL, don't tell me how it works... it's magic, right? I love a good error message.I added a spelling checker to the undefined identifier code, using the variables in scope as the dictionary. It's a fun little nicety.
Jul 12 2012
Am Thu, 12 Jul 2012 08:22:59 -0400 schrieb Jeff Nowakowski <jeff dilacero.org>:On 07/11/2012 03:50 PM, Walter Bright wrote:I don't know the implementation, but compile time should not be a problem. The dictionary is only needed one time and when the build fails anyway. This is indeed a cool feature ;). If Walter ever wants to refine it, it could try any proposal until valid code is created; unless code correctness is only checked at a later state (semantic analysis or what compiler gurus call it). -- MarcoOn 7/11/2012 11:54 AM, David Piepgrass wrote:I remember you took some heat for this because of compiler slowdowns, as well as a public admonishment from Andrei because it wasn't a priority. Must be nice to get some positive feedback on it :)That reminds me, I was so happy the first two times I got an undefined symbol error in D. The compiler said: "Did you mean '<correct variable name>'?" LOL, don't tell me how it works... it's magic, right? I love a good error message.I added a spelling checker to the undefined identifier code, using the variables in scope as the dictionary. It's a fun little nicety.
Jul 12 2012
On 07/11/2012 02:00 PM, David Piepgrass wrote:I am particularly a fan of structural typing. I don't know if Rust uses it but Opa and other functional languages often do. You see, there's a problem that pops up in .NET all the time, and probably the same problem exists in D. Any time two libraries want to use the same concept, but the concept is not in the standard library, they need to define it. For instance if there is no "Point" type in the standard library, but two unrelated libraries need points, they will both define their own (amazingly, Points are poorly thought out in .NET and tightly bound to GUI libraries, so people define their own in some cases): // JoesLibrary struct Point!T { T x, y; /* followed by some manipulation functions */ } // FunkyLibrary struct Point!T { T x, y; /* followed by other manipulation functions */ } Sadly, the two point types are not compatible with each other. A client that wants to use both libraries now has an interoperability problem when he wants to pass data between the. Even a client that uses only one of the library, let's call it "JoesLibrary" has to import Point from "JoesLibrary", even if its functionality is not quite what the client wants. It would be much nicer if the client could define his own Point struct that seamlessly interoperates with Joes'. In D this is currently impractical, but I would enjoy designing a way to make it work (before you point out that "what if x and y are in a different order in the two structs" and "it could be T X,Y in one and T x,y in the other", yes, I know, It's on my list of problems to cleverly solve) A similar problem exists with interfaces, where two unrelated libraries expose two similar classes with some common functions, but you can't cast them to a common type in D. This is a solved problem in Go (http://www.airs.com/blog/archives/277) and it's actually pretty easy for a compiler to magically cast a class to an interface that the class did not declare--if the underlying language is designed for that, anyway. In fact, in .NET at least, the same problem exists even if the libraries DO know about each other and are even written by the same person and use identical interfaces. The problem is, if I write two libraries A and B, and I want them to be interoperable, then I need to factor out the common structs and interfaces to a microscopic third library, I. But from the client's perspective, if a client only knows about A or B, he will think it's stupid that I require him to use and deploy two DLLs/so's (A and I, or B and I) instead of one. In D I guess it's not the same, though.I'm pretty sure this interoperability thing is solved in D, at least at compile time. Example: import std.traits; /// Returns true if T is a Point type. template isPoint(T) { enum bool isPoint = is(typeof( { T point; // (x,y) should be numeric. static assert ( isNumeric!(typeof(point.x)) ); static assert ( isNumeric!(typeof(point.y)) ); auto x = point.x; // x is readable point.x = x; // x is writable auto y = point.y; // y is readable point.y = y; // y is writable })); } struct MyPointType { float x; float y; } struct AnotherPointType { int x; int y; } struct NotAPoint { char[] x; char[] y; } // TODO: are x and y allowed to have differing types? static assert(isPoint!MyPointType); static assert(isPoint!AnotherPointType); static assert(!isPoint!NotAPoint); auto myPointCalculation(P1,P2)( P1 p1, P2 p2 ) if ( isPoint!P1 && isPoint!P2 ) { p1.x += p2.x; p1.y += p2.y; return p1; } import std.stdio; void main() { MyPointType p1; AnotherPointType p2; p1.x = 3.5; p1.y = 5.0; p2.x = 2; p2.y = 2; writefln("(before) p1 == (%s, %s)",p1.x,p1.y); p1 = myPointCalculation(p1,p2); writefln("(after) p1 == (%s, %s)",p1.x,p1.y); } At the command line: chad Hugin ~/dprojects/dtesting/points $ dmd points.d chad Hugin ~/dprojects/dtesting/points $ ./points (before) p1 == (3.5, 5) (after) p1 == (5.5, 7)
Jul 11 2012
"David Piepgrass" wrote in message news:jdyhfsxgucfglqgajezn forum.dlang.org...I always find these type of comments strange due to my background. In most Portuguese universities, functional and logic programming, type systems, theory of computation and compiler design are part of the normal curriculum. You don't need to do a Phd for them. -- PauloRust has type classes from Haskell (with some simplifications for higher kinds), uniqueness typing, and typestates.As nice as kinds, typestates, typeclasses and several pointer types may be, I was in the Rust mailing list and felt unable to participate because they kept using terminology that only PhD in type systems understand. And googling for "kind" doesn't tell me a darn thing ;)
Jul 11 2012
A blog post about one of the Rust pointers, the "borrowed" ones: http://smallcultfollowing.com/babysteps/blog/2012/07/10/borrowed-pointer-tutorial/ Bye, bearophile
Jul 13 2012
On Friday, 13 July 2012 at 14:58:57 UTC, bearophile wrote:A blog post about one of the Rust pointers, the "borrowed" ones: http://smallcultfollowing.com/babysteps/blog/2012/07/10/borrowed-pointer-tutorial/ Bye, bearophileRust is a much more interesting language than Go. At least they are taking some innovative paths and that's good.
Jul 17 2012
Am Tue, 17 Jul 2012 21:39:33 +0200 schrieb "SomeDude" <lovelydear mailmetrash.com>:On Friday, 13 July 2012 at 14:58:57 UTC, bearophile wrote:The irony is: "Rust intentionally does not include any novel or untested ideas." - Wikipedia -- MarcoA blog post about one of the Rust pointers, the "borrowed" ones: http://smallcultfollowing.com/babysteps/blog/2012/07/10/borrowed-pointer-tutorial/ Bye, bearophileRust is a much more interesting language than Go. At least they are taking some innovative paths and that's good.
Jul 18 2012
On Sunday, 8 July 2012 at 13:49:50 UTC, bearophile wrote:So I've taken another look at the Rust tutorial: http://dl.rust-lang.org/doc/tutorial.htmlDoes it handle angle brackets well?
Jul 20 2012
Rust designers seems to love really short keywords, this is in my opinion a bit silly. On the other hand in D you have keywords like "immutable" that are rather long to type. So I prefer a mid way between those two.They aren't silly, they're consistent. We have int, char, auto, they have fn, var, and val which are common these days, why not mut, pub, and priv? What is silly are the objections, such as someone saying that it's like limiting the length of identifiers. It's obviously NOTHING like that.Rust supports several types of pointers. The simplest is the unsafe pointer, written *T, which is a completely unchecked pointer type only used in unsafe code (and thus, in typical Rust code, very rarely).It's &T, and it has nothing to do with unsafety.
Dec 17 2012
On Tuesday, 18 December 2012 at 07:36:26 UTC, Marcel wrote:Those are silly as well. Why be consistent with the wrong choice? I really don't want to see pubs scattered around my code as my manager used to say - don't drink and code. I really like Rust's semantics and the way it progresses but there is really no valid nor sane argument for an APL inspired syntax. Syntax is meant for human consumption and should be designed accordingly. That's one of the main goals of a programming language, otherwise we all would just program straight in assembly. After all, assembly op codes and numeric addresses are much shorter than the equivalent human readable identifiers and function names.Rust designers seems to love really short keywords, this is in my opinion a bit silly. On the other hand in D you have keywords like "immutable" that are rather long to type. So I prefer a mid way between those two.They aren't silly, they're consistent. We have int, char, auto, they have fn, var, and val which are common these days, why not mut, pub, and priv? What is silly are the objections, such as someone saying that it's like limiting the length of identifiers. It's obviously NOTHING like that.Rust supports several types of pointers. The simplest is the unsafe pointer, written *T, which is a completely unchecked pointer type only used in unsafe code (and thus, in typical Rust code, very rarely).It's &T, and it has nothing to do with unsafety.
Dec 18 2012
Marcel:They are a bad design choice. Using very shortened identifiers/names is acceptable only when they are very common (time ago I even suggested in D to use "str" as in Python, instead of "string"). "mut", "pub", and "priv" optimize the wrong thing. There are of cases where D goes too much far (like "std.random.randomShuffle" or "schwartSort" in Phobos, or "immutable" among the keywords) but in general the naming choice of D is better than Rust.Rust designers seems to love really short keywords, this is in my opinion a bit silly. On the other hand in D you have keywords like "immutable" that are rather long to type. So I prefer a mid way between those two.They aren't silly, they're consistent. We have int, char, auto, they have fn, var, and val which are common these days, why not mut, pub, and priv?(This wasn't a quotation from me) Bye bearophileRust supports several types of pointers. The simplest is the unsafe pointer, written *T, which is a completely unchecked pointer type only used in unsafe code (and thus, in typical Rust code, very rarely).
Dec 18 2012
On 12/18/2012 4:35 AM, bearophile wrote:in general the naming choice of D is better than Rust.A red letter day for D! Bearophile says that D does something better than some other language! :-)
Dec 18 2012