D - inferred types
- Kimberley Burchett (34/34) Jan 15 2003 A small, simple feature suggestion. The "var" keyword could introduce a
- Sean L. Palmer (47/83) Jan 15 2003 YES!!!
- Ilya Minkov (38/59) Jan 15 2003 Damn. It doesn't seem reliable to me. In Caml types are only inferred,
- Kimberley Burchett (47/76) Jan 15 2003 I should clarify. I was assuming that the right-hand-side was fully
- Ilya Minkov (66/140) Jan 17 2003 n=20
- Daniel Yokomiso (26/60) Jan 16 2003 Hi,
- Kimberley Burchett (22/34) Jan 16 2003 I agree that the feature can be used in ways that make code more opaque....
- Norbert Nemec (9/13) Jan 17 2003 That's nonsense. It is not deprecated at all. One maintainer didn't like...
- Daniel Yokomiso (28/55) Jan 17 2003 Hi,
- Russell Lewis (4/13) Jan 16 2003 Such a thing is where an IDE comes in to help. Put your mouse over
- Sean L. Palmer (45/68) Jan 17 2003 lead to
- Norbert Nemec (25/29) Jan 17 2003 Careful: I was the maintainer of Sather during that time. I've done lots...
- Sean L. Palmer (11/28) Jan 17 2003 of
- Kimberley Burchett (15/21) Jan 17 2003 I don't mind ::= and I generally like to use existing syntax if possible...
- Kimberley Burchett (16/23) Jan 17 2003 I don't mind ::= and I generally like to use existing syntax if possible...
- Walter (8/11) Feb 14 2003 Inferring the return type of functions requires that the compiler be abl...
- Walter (2/2) Feb 14 2003 But the var idea does have a lot of merit if constrained to be for local
- Norbert Nemec (11/22) Jan 17 2003 Please forget about using it for return types. One would need to take a ...
- Kimberley Burchett (14/21) Jan 17 2003 I said earlier in this thread that I would disallow it for recursive
- Norbert Nemec (6/30) Jan 18 2003 Guess, we are completely in line at that point. Leave the "inferred type...
- Russell Lewis (9/30) Jan 21 2003 Don't be so quick to judge it. Often, APIs return "handles" and such.
- Norbert Nemec (6/33) Jan 22 2003 But that doesn't fit at all with the meaning of "var" as discussed for l...
- Ilya Minkov (5/12) Jan 22 2003 Particularly, in templates where it *has* to change, but shall be known
- Walter (11/15) Feb 14 2003 There are two examples:
- Daniel Yokomiso (57/86) Jan 17 2003 Hi,
A small, simple feature suggestion. The "var" keyword could introduce a variable with an inferred type: void foo(int x) { var y = x + 1; printf("y is %d\n", y); } This feature is especially useful in situations where you don't *know* the type of an expression. For example, if the above example used a template so that x has some unspecified type T, and the + operator for T were overloaded, then there would be no way to know the type of T+int. One could of course just assume that it would be the same type as x itself, but that doesn't scale to letting y store the result of arbitrary expressions. Exploring the orthogonality of the feature... The "var" keyword could also be allowed for function arguments, where it could implicitly define a function template. Also, for functions with consistent return types, you could allow it for the return value (again, this would be important for situations where you don't know the result type of an overloaded operator). However, it would look a bit odd if used as a return type: var foo(int x) { return x+1; } It kind of looks like foo should be a variable, not a function. So you might want to rename the keyword. One choice would be to use "T" instead of "var", but then writing templates would be a bit more annoying because you'd have to come up with a name for your parameterized types. Even if this feature is not adopted, D should probably still have *some* way of dealing with situations where you don't know the type of an expression. I suppose you could allow use of a type() property wherever a type is expected: (x+1).type() foo(SomeType x) { return x+1; } But that strikes me as a lot uglier than using "var" or "T". Kimberley Burchett Endeca, Inc
Jan 15 2003
"Kimberley Burchett" <kimbly at kimbly.comKimberley_member pathlink.com> wrote in message news:b03d3k$2m8r$1 digitaldaemon.com...A small, simple feature suggestion. The "var" keyword could introduce a variable with an inferred type: void foo(int x) { var y = x + 1; printf("y is %d\n", y); }YES!!! for (var iter = container.begin(); iter != container.end(); ++iter) { *iter = 0; }This feature is especially useful in situations where you don't *know* thetypeof an expression. For example, if the above example used a template sothat xhas some unspecified type T, and the + operator for T were overloaded,thenthere would be no way to know the type of T+int. One could of course just assume that it would be the same type as x itself, but that doesn't scaletoletting y store the result of arbitrary expressions.Or if you don't want to type out a really lengthy type, or make a typedef for it. See C++ iterators. for (std::map<std::basic_string<char>, std::less<std::basic_string<char> >::const_iterator iter = container.begin(); iter != container.end(); ++iter){ foo(*iter); }Exploring the orthogonality of the feature... The "var" keyword could alsobeallowed for function arguments, where it could implicitly define afunctiontemplate.Interesting... you mean: x.type() add(var x, var y) { return x + y; } int u = add(2, 4); float n = add(0.5f, 1.0f); double j = add(2.5, 3.0); Sounds nice; it'd be even better if you can constrain the types to be derived from some interface x.type() add(var x : addable, var y : addable) { return x + y; }Also, for functions with consistent return types, you could allow it for the return value (again, this would be important for situations whereyoudon't know the result type of an overloaded operator). However, it wouldlook abit odd if used as a return type: var foo(int x) { return x+1; } It kind of looks like foo should be a variable, not a function. So youmightwant to rename the keyword. One choice would be to use "T" instead of"var",but then writing templates would be a bit more annoying because you'd havetocome up with a name for your parameterized types. Even if this feature is not adopted, D should probably still have *some*way ofdealing with situations where you don't know the type of an expression. I suppose you could allow use of a type() property wherever a type isexpected:(x+1).type() foo(SomeType x) { return x+1; } But that strikes me as a lot uglier than using "var" or "T".Yes. For one, you have to build the expression twice, once to get its type so you can declare the variable, and again for the actual value. for (container.begin().type() iter = container.begin(); iter != container.end(); ++iter) { *iter = 0; }Kimberley Burchett Endeca, Inc
Jan 15 2003
Sean L. Palmer wrote:"Kimberley Burchett" <kimbly at kimbly.comKimberley_member pathlink.com> wrote in message news:b03d3k$2m8r$1 digitaldaemon.com...NOT SIMPLE i guess!A small, simple feature suggestion. The "var" keyword could introduce aDamn. It doesn't seem reliable to me. In Caml types are only inferred, but it has to do with a number of design limitations: - there are different sets of operators for all types of data. EG: int + int, float +. float, bign +/ bign!!! If there's no such thing, you get error-prone situations. Well, that'd be no problem in Delphi, but in C derivates it is, because integer division and FP devision are the same operator here, but have a different meaning! - there are only two types of data structures: containing pointers and integers only, and containing no pointers. Each float is a memory block/sctucture itself, except for designated array types, which can only be processed with special (C-external or VM-internal) functions. Both floats and arrays belong to no-pointer-block types. - all integers are the size of pointers -1 bit (eg 31 bit), because they are mangled so that the GC can differ pointer from integer. - either a function handles a pointer-sized type and would work with any of them, or it works with numeric types and can be identified by the operators. - "generic" functions working with pointers and integers never clean up and never change them, they can only copy them, leaving a ton of work to the mega-efficient GC.variable with an inferred type: void foo(int x) { var y = x + 1; printf("y is %d\n", y); }YES!!!OUCH! safer: operator+ (T, int).type if one really wants to know. I agree there should be some mechanism, but it must work statically, and thus be semantically identical to this one. And what happenes if you take unspecified type of unspecified type of still not specified type? A function can not be compiled without a type. Thus it would turn into something like a macro or a template. Or into C++ overloaded functions. Either you bloat everything, or you have to assign all that funcs names. And here we go again.This feature is especially useful in situations where you don't *know* the type of an expression. For example, if the above example used a template so that x has some unspecified type T, and the + operator for T were overloaded, then there would be no way to know the type of T+int. One could of course just assume that it would be the same type as x itself, but that doesn't scale to letting y store the result of arbitrary expressions.Or if you don't want to type out a really lengthy type, or make a typedef for it. See C++ iterators.:/ why not create an iterator object and then: Iterator.Load("blah"); while (Iterator.While) { // action }
Jan 15 2003
In article <b04bav$6fd$1 digitaldaemon.com>, Ilya Minkov says...Damn. It doesn't seem reliable to me. In Caml types are only inferred, but it has to do with a number of design limitations: - there are different sets of operators for all types of data. EG: int + int, float +. float, bign +/ bign!!! If there's no such thing, you get error-prone situations. Well, that'd be no problem in Delphi, but in C derivates it is, because integer division and FP devision are the same operator here, but have a different meaning!I should clarify. I was assuming that the right-hand-side was fully typed. I'm not suggesting full Hindley-Milner-style type inference here. No unification is necessary. I probably shouldn't have used the word "infer" -- I meant something much simpler. The D compiler already has to compute the type of all expressions anyway, in order to know whether they're a compile error, or whether they require an implicit cast, etc. So this is just a shorthand to say that that type of the rhs should be used for the new variable. It would be perfectly reasonable to, say, prevent the use of a var return type for recursive (or mutually recursive) functions. Otherwise you'd have to solve for the type, instead of simply knowing it. However the original motivation for the feature didn't even involve return types -- it was just for local variables, which are syntactically prevented from having recursive definitions anyway.- all integers are the size of pointers -1 bit (eg 31 bit), because they are mangled so that the GC can differ pointer from integer.My proposal has nothing to do with tagged values.- either a function handles a pointer-sized type and would work with any of them, or it works with numeric types and can be identified by the operators.You're thinking I suggested type inference for function arguments. But I didn't -- I suggested that if used as a parameter, then the "var" keyword could actually introduce a *template*. And templates in D apparently have to be explicitly instantiated. So this objection is not relevant. I personally don't even know if I like the implicit template idea -- I was just exploring it for orthogonality reasons.- "generic" functions working with pointers and integers never clean up and never change them, they can only copy them, leaving a ton of work to the mega-efficient GC.You've jumped from the static type system into the runtime memory model, and implied that the first complicates the second. But all that I'm proposing is a syntactic shorthand for something that can be statically computed. If the compiler decides to replace a particular use of the "var" keyword with the type "float", then I could just as easily have typed "float" in the first place. Therefore there are no runtime implications beyond what the language already allows.OUCH! safer: operator+ (T, int).type if one really wants to know. I agree there should be some mechanism, but it must work statically, and thus be semantically identical to this one.This is the same as what I suggested with the .type() property. But I think it's ugly. Perhaps in my original post I should have emphasized the word "*consistent* return types". What I meant to imply by that was that return values could only be left omitted if the function returned a value whose type was completely determinable from the type of the arguments, and which if it has multiple return points, all return *exactly* the same static type.And what happenes if you take unspecified type of unspecified type of still not specified type?The compiler builds a DAG, and if it discovers a cycle, then you get a compile error.A function can not be compiled without a type. Thus it would turn into something like a macro or a template.Exactly! :) I was proposing that if the type of an argument was omitted, then you get a template. And if the type of the return value is omitted, then it must be deducible from the types of the arguments.:/ why not create an iterator object and then: Iterator.Load("blah"); while (Iterator.While) { // action }Because then you have to have a single iterator class that's capable of iterating over everything. Otherwise you'd have to use a more specific type than just "Iterator".
Jan 15 2003
Kimberley Burchett wrote:In article <b04bav$6fd$1 digitaldaemon.com>, Ilya Minkov says... =20Damn. It doesn't seem reliable to me. In Caml types are only inferred, =u=20but it has to do with a number of design limitations: - there are different sets of operators for all types of data. EG: int + int, float +. float, bign +/ bign!!! If there's no such thing, yo=n=20get error-prone situations. Well, that'd be no problem in Delphi, but i=e=20C derivates it is, because integer division and FP devision are the sam=True. OK. That settles most of it. It is a minor change then.operator here, but have a different meaning!=20 =20 I should clarify. I was assuming that the right-hand-side was fully typed. I'm not suggesting full Hindley-Milner-style type inference here. No unification is necessary. I probably shouldn't have used the word "infer" -- I meant something much simpler. =20 The D compiler already has to compute the type of all expressions anyway, in order to know whether they're a compile error, or whether they require an implicit cast, etc. So this is just a shorthand to say that that type of the rhs should be used for the new variable.However the original motivation for the feature didn't even involve return types -- it was just for local variables, which are syntacticall=yprevented from having recursive definitions anyway. =20 =20:/ It just explained how come that "generic" type is allowed in Caml. This=20 "generic" is simply either an integer, or a pointer to any kind of=20 object, so that so far no operations except for equality comparison and=20 copying are done on them, it can be done. But i don't think there should = be such a thing in D.- all integers are the size of pointers -1 bit (eg 31 bit), because=20 they are mangled so that the GC can differ pointer from integer.=20 =20 My proposal has nothing to do with tagged values.=20 If the compiler decides to replace a particular use of the "var" keyword with the type "float", then I could just as easily have typed "float" in the first place. Therefore there are no runtime implications beyond what the language already allows. =20OK. Set.=20t=20OUCH! safer: operator+ (T, int).type if one really wants to know. I agree there should be some mechanism, bu==2Eit must work statically, and thus be semantically identical to this one==20 =20 This is the same as what I suggested with the .type() property. But I think it's ugly. Perhaps in my original post I should have emphasize=dthe word "*consistent* return types". What I meant to imply by that=20 was that return values could only be left omitted if the function returned a value whose type was completely determinable from the type of the arguments, and which if it has multiple return points, all return *exactly* the same static type.A function can not be compiled without a type. Thus it would turn into =OK. A template then. I'm sorry, I guess a lot of misunderstanding comes=20 from my mistake, by which i was answering a reply to your message, not=20 your original one. In the satement: var name expression; expression is evaluated and a variable 'name' is created with the type=20 of expression, if it has a type. As if there stood typeof(expression) name; and typeof() would exist. :) It would be semantically the same as in my=20 earlier post, but much prettier. But then again: this may only be=20 allowed within explicit template instantion. The problem of '/' is rather of general nature. It is to my opinion=20 always undesired if someone writes '7/4' and gets '1', these may be some = variables, the type of which may be hidden behind something else... To=20 my opinion '/' has to *always* return an "extended" type. There has to=20 be another operator for integer devision. It's just like it was done with concatenation. Integer division is of a=20 different nature than FP-division, while other operations are of the=20 same and give the same results. Maybe take '\' for integer division,=20 since it's not used for line splicing like in C? I'd say it would be generally good if it was possible to use any=20 function, which takes two operands, with infix notation. Eg: first $chewTwo second instead of: chewTwo(first, second) Well, it has some problems. First, with infix notation some measure=20 needs to be taken to identify the function both visually and maybe also=20 enclosing between two symbols ( {chewTwo}, /chewTwo/, \chewTwo\ ), or=20 maybe by a postfix or even parenthesis: first chewTwo() second But if prefix or enclosing are chosen, it could also clarify the syntax=20 in some situations when used with one-parameter function, like: $chewOne input instead of: chewOne (input) which is though silly when standalone, may be of great use in=20 expressions already choking of parenthesis. Like in the old C=20 "(((((lisp)))))" joke. Another problem with infix notation is that the order of precedence is=20 not specified. Either it has to be explicitly stated in function=20 declarations, or all the functions would get the highest possible=20 precedence, and then... it would possibly save only one level of=20 parenthesis or not much more than that, which is though a lot in some cas= es.something like a macro or a template.=20 =20 Exactly! :) I was proposing that if the type of an argument was omitted, then you get a template. And if the type of the return value is omitted, then it must be deducible from the types of the arguments. =20=20Well, i have used a similar thing once. I just put such an iterator=20 functionality into a class, to iterate over data in that particular=20 class. Probably because of having no better solution. Though it was OK=20 for the situation, it is not generally usable, like over any kind of=20 everything.:/ why not create an iterator object and then: Iterator.Load("blah"); while (Iterator.While) { // action }=20 =20 Because then you have to have a single iterator class that's capable of iterating over everything. Otherwise you'd have to use a more specific type than just "Iterator".=20 =20
Jan 17 2003
In article <b03d3k$2m8r$1 digitaldaemon.com>, Kimberley Burchett <kimbly at kimbly.com> says...A small, simple feature suggestion. The "var" keyword could introduce a variable with an inferred type: void foo(int x) { var y = x + 1; printf("y is %d\n", y); } This feature is especially useful in situations where you don't *know* the type of an expression. For example, if the above example used a template so that x has some unspecified type T, and the + operator for T were overloaded, then there would be no way to know the type of T+int. One could of course just assume that it would be the same type as x itself, but that doesn't scale to letting y store the result of arbitrary expressions. Exploring the orthogonality of the feature... The "var" keyword could also be allowed for function arguments, where it could implicitly define a function template. Also, for functions with consistent return types, you could allow it for the return value (again, this would be important for situations where you don't know the result type of an overloaded operator). However, it would look a bit odd if used as a return type: var foo(int x) { return x+1; } It kind of looks like foo should be a variable, not a function. So you might want to rename the keyword. One choice would be to use "T" instead of "var", but then writing templates would be a bit more annoying because you'd have to come up with a name for your parameterized types. Even if this feature is not adopted, D should probably still have *some* way of dealing with situations where you don't know the type of an expression. I suppose you could allow use of a type() property wherever a type is expected: (x+1).type() foo(SomeType x) { return x+1; } But that strikes me as a lot uglier than using "var" or "T". Kimberley Burchett Endeca, IncHi, The first kind of var usage seems nice, but in practice I think it can lead to some obscure pieces of code. In the middle of a large method how are you going to interpret this: var foo = bar.testIt(baz, fred, 1, 1.9, "\"); With method overloading in D we need to verify the types of baz and fred so we can discover which version is used. If baz and fred are also var, it can be somewhat hard to understand what's going on. Some weeks ago a programming pissing contest was going on comp.arch and someone said var is no longer than int. I agree that it's true that var is smaller than almost anything else, but I don't think a new keyword is needed just for this half-baked type-inference system. Sather 1.2 provides a ::= assignment that declare lvalue with type and value of rvalue. In Sather 1.3 they are warning against this usage, because it can lead to maintanance problems. But Sather has saner type names than C++, and builtin iterators, so they don't have the std::ListIterator<std::Set<String>> problem ;-) The second usage is similar to current template mechanism, only terser. But this is a problem of template verbosity. IMO it's better to make a simpler template syntax than add another concept to to the same job. Just for the records, I like type system where inference is possible (e.g.: ML or Haskell), but without unification we must always restrict inference to some parts of the problem. Best regards, Daniel Yokomiso.
Jan 16 2003
The first kind of var usage seems nice, but in practice I think it can lead to some obscure pieces of code. In the middle of a large method how are you going to interpret this: var foo = bar.testIt(baz, fred, 1, 1.9, "\"); With method overloading in D we need to verify the types of baz and fred so we can discover which version is used. If baz and fred are also var, it can be somewhat hard to understand what's going on.I agree that the feature can be used in ways that make code more opaque. But then, so can pointers, templates, operator overloading, unions, exceptions, and many more! :) However I still think something like it is necessary, otherwise templates will be hampered by the type system. I'd like to point out that this: var foo = bar.testIt(baz, fred, 1, 1.9, "\"); print(foo); is completely equivalent to this: print(bar.testIt(baz, fred, 1, 1.9, "\")); However, by using the variable declaration you can avoid order of execution problems (e.g. if there were code between the assignment of foo and the call to print() that would change the return value of bar.testIt). Also, the variable declaration lets you reuse the value more than once without having to call bar.testIt() again. I've never heard anyone claim that you shouldn't be able to compose expressions because it's not clear what the type is of the intermediate values. So why is it a problem here?Sather 1.2 provides a ::= assignment that declare lvalue with type and value of rvalue. In Sather 1.3 they are warning against this usage, because it can lead to maintanance problems.That's interesting. I didn't know about that feature in Sather. It's also interesting that they're now deprecating it. However I somehow doubt that they're deprecating it just because somebody managed to use it to botch up their code.IMO it's better to make a simpler template syntax than add another concept to to the same job.I would tend to agree. I don't think I like it for function args.
Jan 16 2003
Kimberley Burchett wrote:That's interesting. I didn't know about that feature in Sather. It's also interesting that they're now deprecating it. However I somehow doubt that they're deprecating it just because somebody managed to use it to botch up their code.That's nonsense. It is not deprecated at all. One maintainer didn't like it (just like some people have objections about the feature on this list) and since he was the only one really investing time into Sather development, nobody really was in the position to speak up and argue against it. It was a decision of coding style by one person, and his style was mostly guided by high philosophical opinions rather than by real practicability. Ciao, Nobbi
Jan 17 2003
Hi, Comments embedded. "Kimberley Burchett" <kimbly at kimbly.comKimberley_member pathlink.com> escreveu na mensagem news:b07aek$1tv0$1 digitaldaemon.com... [snip]I agree that the feature can be used in ways that make code more opaque. But then, so can pointers, templates, operator overloading, unions, exceptions, and many more! :) However I still think something like it is necessary, otherwise templates will be hampered by the type system.You can program Fortran in any language ;-)I'd like to point out that this: var foo = bar.testIt(baz, fred, 1, 1.9, "\"); print(foo); is completely equivalent to this: print(bar.testIt(baz, fred, 1, 1.9, "\")); However, by using the variable declaration you can avoid order of execution problems (e.g. if there were code between the assignment of foo and the call to print() that would change the return value of bar.testIt). Also, the variable declaration lets you reuse the value more than once without having to call bar.testIt() again. I've never heard anyone claim that you shouldn't be able to compose expressions because it's not clear what the type is of the intermediate values. So why is it a problem here?No real problem I was just trying to make a point. Which point I leave as an exercise to the reader ;-)Sather 1.2 was develop by Berkeley http://www.icsi.berkeley.edu/~sather/index.html while 1.3 by Waikato http://www.cs.waikato.ac.nz/sather/ If you read the docs in both sites you operator now, and promoting the long usage: i.e. instead of #CPX(1,0) you use CPX.create(1,0). Like the Eiffel deprecated !! notation. Both languages are going towards explicit coding and verbosity IMO.Sather 1.2 provides a ::= assignment that declare lvalue with type and value of rvalue. In Sather 1.3 they are warning against this usage, because it can lead to maintanance problems.That's interesting. I didn't know about that feature in Sather. It's also interesting that they're now deprecating it. However I somehow doubt that they're deprecating it just because somebody managed to use it to botch up their code.If we can address the template problems first, we can focus our attention latter on other problems. Some kind of type inference would be wonderful but now it's too difficult to play with the type system and get something nice out of it. Best regards, Daniel Yokomiso. "Actually, C++ is being post-incremented, so this iteration C++ is the same as c, but next time around it'll be great!" - tfinniga at /. --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.443 / Virus Database: 248 - Release Date: 11/1/2003IMO it's better to make a simpler template syntax than add another concept to to the same job.I would tend to agree. I don't think I like it for function args.
Jan 17 2003
Daniel Yokomiso wrote:The first kind of var usage seems nice, but in practice I think it can lead to some obscure pieces of code. In the middle of a large method how are you going to interpret this: var foo = bar.testIt(baz, fred, 1, 1.9, "\");Such a thing is where an IDE comes in to help. Put your mouse over 'var', and the IDE will tell you the type. Or, if you prefer, just have the IDE display the underlying type even though you just typed 'var'.With method overloading in D we need to verify the types of baz and fred so we can discover which version is used. If baz and fred are also var, it can be somewhat hard to understand what's going on.
Jan 16 2003
"Daniel Yokomiso" <Daniel_member pathlink.com> wrote in message news:b06pjb$1kcf$1 digitaldaemon.com...Hi, The first kind of var usage seems nice, but in practice I think it canlead tosome obscure pieces of code. In the middle of a large method how are yougoingto interpret this:It's always possible to write obscure code. Doesn't mean you have to.var foo = bar.testIt(baz, fred, 1, 1.9, "\");You have the same problem anyway; lack of named parameters is confusing enough by itself.With method overloading in D we need to verify the types of baz and fredso wecan discover which version is used. If baz and fred are also var, it canbesomewhat hard to understand what's going on.You may not need to understand what's going on. IDE code browsing features are improving all the time anyway. Maybe your IDE would have an option to "bake in" all implicit variables, injecting the actual type name back into the source code. And not all uses are arcane. It'd probably find a lot of use when doing simple stuff.Some weeks ago a programming pissing contest was going on comp.arch andsomeonesaid var is no longer than int. I agree that it's true that var is smallerthanalmost anything else, but I don't think a new keyword is needed just forthishalf-baked type-inference system.:= would work fine.Sather 1.2 provides a ::= assignment that declare lvalue with type and value of rvalue. In Sather 1.3 they arewarningagainst this usage, because it can lead to maintanance problems. ButSather hassaner type names than C++, and builtin iterators, so they don't have the std::ListIterator<std::Set<String>> problem ;-)It may even *increase* maintainability of code. If you change the parameters, all the implicit temp variables automatically change too (and if they change in a way that doesn't work, the compiler will tell you). It'd be great for use in templates when you don't know the actual type name anyway. Most of that could be taken care of by a typeof(x) or x.type() feature though. The only difference between x.type() y = x and y ::= x is one of syntactical sugar. y ::= x looks alot sweeter. Especially if the actual x is a rather complicated expression. The programmer's intent is clear; they want a named temporary variable. The first form clutters up this intent with syntactical baggage. Sather looks interesting semantically but I find the flavor of the syntax disturbing. I'll have to look into it more.The second usage is similar to current template mechanism, only terser.But thisis a problem of template verbosity. IMO it's better to make a simplertemplatesyntax than add another concept to to the same job. Just for the records, I like type system where inference is possible(e.g.: MLor Haskell), but without unification we must always restrict inference tosomeparts of the problem.You could do some powerful stuff with type inference. So long as there are no declarative cycles. As with any feature that allows one to shoot themselves in the foot, care must be used to aim properly. Exercise: name one feature of C++ that can't possibly be used to shoot yourself in the foot, one way or another. ;) Sean
Jan 17 2003
Daniel Yokomiso wrote:Sather 1.2 provides a ::= assignment that declare lvalue with type and value of rvalue. In Sather 1.3 they are warning against this usage, because it can lead to maintanance problems.Careful: I was the maintainer of Sather during that time. I've done lots of code in Sather (a complete compiler written from scratch, at one time) and I can only speak in favor of that "::=" construct. I really urge everyone to consider the "var" suggestion. It definitely *improves* maintainability greatly. Of course, one can use that feature to produce unreadable code, but then, an expression where you can't infer the type by a quick glance is a bad idea anyway. If you've come to need the type written in variable declarations as documentation, you really have a much deeper problem. As an example for where I really hate the lack of such a possibility in C++ are iterators: for(Somecontainer<Sometype>::Reverse_iterator i = C.end();i;i--) { ... }; How about this: for(var i = C.end();i;i--) { ... }; Just consider you want to try out another container type and have to go through all your code to adjust the iterators. Of course, there are ways to avoid that, but they all need some overhead at some other place. Of course, in D, type inference is not always possible from an expression alone, but why not simply make the use of "var" an error in those cases? Ciao, Nobbi
Jan 17 2003
"Norbert Nemec" <nobbi_at_theorie3.physik.uni-erlangen.de NOSPAM.COM> wrote in message news:b09ad9$30q8$1 digitaldaemon.com...Daniel Yokomiso wrote:ofSather 1.2 provides a ::= assignment that declare lvalue with type and value of rvalue. In Sather 1.3 they are warning against this usage, because it can lead to maintanance problems.Careful: I was the maintainer of Sather during that time. I've done lotscode in Sather (a complete compiler written from scratch, at one time) and I can only speak in favor of that "::=" construct. I really urge everyone to consider the "var" suggestion. It definitely *improves* maintainability greatly. Of course, one can use that feature to produce unreadable code, but then, an expression where you can't infer the type by a quick glanceisa bad idea anyway. If you've come to need the type written in variable declarations as documentation, you really have a much deeper problem.That's what I thought. ;) I believe I prefer a new operator such as := or ::= over the "var" keyword. "var" is more in-line with how C, C++, and D parse declarations though.Of course, in D, type inference is not always possible from an expression alone, but why not simply make the use of "var" an error in those cases?Where is an D expression's type not 100% deterministic? It's never determined by the type of the result variable. So it must be determinable just from the expression itself and any declarations that are in scope. I can't think of a single example.Ciao, Nobbi
Jan 17 2003
In article <b09jar$5na$1 digitaldaemon.com>, Sean L. Palmer says...I believe I prefer a new operator such as := or ::= over the "var" keyword. "var" is more in-line with how C, C++, and D parse declarations though.I don't mind ::= and I generally like to use existing syntax if possible. However, it would look weird to use ::= for a return type. Example: ::= add(SomeType x, SomeType y) { return x+y; } versus this: var add(SomeType x, SomeType y) { return x + y; } I think the word "var" already sucks as a return type, but ::= is even worse.Where is an D expression's type not 100% deterministic? It's never determined by the type of the result variable. So it must be determinable just from the expression itself and any declarations that are in scope. I can't think of a single example.recursive functions, if you allow var return types: var foo(SomeType x) { return foo(x+1)+x; }
Jan 17 2003
Well I guess using didn't work. Here it is again, probably with all the indentation omitted :(In article <b09jar$5na$1 digitaldaemon.com>, Sean L. Palmer says... I believe I prefer a new operator such as := or ::= over the "var" keyword. "var" is more in-line with how C, C++, and D parse declarations though.I don't mind ::= and I generally like to use existing syntax if possible. However, it would look weird to use ::= for a return type. Example: ::= add(SomeType x, SomeType y) { return x+y; } versus this: var add(SomeType x, SomeType y) { return x + y; } I think the word "var" already sucks as a return type, but ::= is even worse.Where is an D expression's type not 100% deterministic? It's never determined by the type of the result variable. So it must be determinable just from the expression itself and any declarations that are in scope. I can't think of a single example.recursive functions, if you allow var return types: var foo(SomeType x) { return foo(x+1)+x; }
Jan 17 2003
"Kimberley Burchett" <kimbly at kimbly.comKimberley_member pathlink.com> wrote in message news:b0a8c3$iuq$1 digitaldaemon.com...::= add(SomeType x, SomeType y) { return x+y; }Inferring the return type of functions requires that the compiler be able to do the semantic analysis of the function before its type can be determined. This is a problem not only for the case of recursive function calls, but for the compiler when trying to figure out what order to do the semantic analysis of functions in. I don't think it will work.
Feb 14 2003
But the var idea does have a lot of merit if constrained to be for local variables.
Feb 14 2003
Kimberley Burchett wrote:In article <b09jar$5na$1 digitaldaemon.com>, Sean L. Palmer says...Please forget about using it for return types. One would need to take a look at the implementation to get the necessary information for the interface. It is nice for local variables, where declaration and "implementation" (i.e. the expression that actually determines the type) are always directly at the same place, but for nothing else. Allowing this "undeterminedness" to spread outside of the function scope woule really make the program unreadable, and in case of recursive functions, the compiler would not even able to determine any type at all.I believe I prefer a new operator such as := or ::= over the "var" keyword. "var" is more in-line with how C, C++, and D parse declarations though.I don't mind ::= and I generally like to use existing syntax if possible. However, it would look weird to use ::= for a return type. Example:OK, true, the thing I was thinking of were struct initializers, but those are not really standard expressions...Where is an D expression's type not 100% deterministic? It's never determined by the type of the result variable. So it must be determinable just from the expression itself and any declarations that are in scope. I can't think of a single example.
Jan 17 2003
Norbert Nemec wrote:Please forget about using it for return types. One would need to take a look at the implementation to get the necessary information for the interface.Well of course! I wasn't intending to allow it for interfaces.Allowing this "undeterminedness" to spread outside of the function scope woule really make the program unreadable, and in case of recursive functions, the compiler would not even able to determine any type at all.I said earlier in this thread that I would disallow it for recursive functions, because that would require some kind of type solver. I don't know why you think I suggested letting the thing "spread outside of the function scope". If you want to object to it based on the fact that it would be significantly harder to implement for return values than for local variables, then I'm willing to take the point. I don't expect the return value thing to actually make it into D at this point. But the local variable thing might have a chance, and when considering what keyword to use, we might as well take into account where the feature might go in the future. Kimberley Burchett
Jan 17 2003
Kimberley Burchett wrote:Norbert Nemec wrote:Guess, we are completely in line at that point. Leave the "inferred types" feature just for the declaration of variables and put everything beyond that ot the section "dreams about the future". Personally I like the original "var" syntax most. It fits into D syntax far better than "::=" or any of the other suggestions.Please forget about using it for return types. One would need to take a look at the implementation to get the necessary information for the interface.Well of course! I wasn't intending to allow it for interfaces.Allowing this "undeterminedness" to spread outside of the function scope woule really make the program unreadable, and in case of recursive functions, the compiler would not even able to determine any type at all.I said earlier in this thread that I would disallow it for recursive functions, because that would require some kind of type solver. I don't know why you think I suggested letting the thing "spread outside of the function scope". If you want to object to it based on the fact that it would be significantly harder to implement for return values than for local variables, then I'm willing to take the point. I don't expect the return value thing to actually make it into D at this point. But the local variable thing might have a chance, and when considering what keyword to use, we might as well take into account where the feature might go in the future.
Jan 18 2003
Norbert Nemec wrote:Kimberley Burchett wrote:Don't be so quick to judge it. Often, APIs return "handles" and such. The user is NEVER supposed to access them, although they often are just typedef's of void pointers or unsigned integers. A function that returned handle could return var. Not sure if I like the idea or not, but it's worth considering, at least. The example is problematic because most of the time, you need to save the handle in a struct for later use; how do you declare a member of a struct when it's type is inferred?In article <b09jar$5na$1 digitaldaemon.com>, Sean L. Palmer says...Please forget about using it for return types. One would need to take a look at the implementation to get the necessary information for the interface. It is nice for local variables, where declaration and "implementation" (i.e. the expression that actually determines the type) are always directly at the same place, but for nothing else. Allowing this "undeterminedness" to spread outside of the function scope woule really make the program unreadable, and in case of recursive functions, the compiler would not even able to determine any type at all.I believe I prefer a new operator such as := or ::= over the "var" keyword. "var" is more in-line with how C, C++, and D parse declarations though.I don't mind ::= and I generally like to use existing syntax if possible. However, it would look weird to use ::= for a return type. Example:
Jan 21 2003
Russell Lewis wrote:Norbert Nemec wrote:But that doesn't fit at all with the meaning of "var" as discussed for local variable declaration. "var" is not an unknown type, but a definite type to be determined at compile time. It is semantically identical to specifying the type by hand. Just saves typing and editing whenever the type might change.Kimberley Burchett wrote:Don't be so quick to judge it. Often, APIs return "handles" and such. The user is NEVER supposed to access them, although they often are just typedef's of void pointers or unsigned integers. A function that returned handle could return var.In article <b09jar$5na$1 digitaldaemon.com>, Sean L. Palmer says...Please forget about using it for return types. One would need to take a look at the implementation to get the necessary information for the interface. It is nice for local variables, where declaration and "implementation" (i.e. the expression that actually determines the type) are always directly at the same place, but for nothing else. Allowing this "undeterminedness" to spread outside of the function scope woule really make the program unreadable, and in case of recursive functions, the compiler would not even able to determine any type at all.I believe I prefer a new operator such as := or ::= over the "var" keyword. "var" is more in-line with how C, C++, and D parse declarations though.I don't mind ::= and I generally like to use existing syntax if possible. However, it would look weird to use ::= for a return type. Example:
Jan 22 2003
Norbert Nemec wrote:But that doesn't fit at all with the meaning of "var" as discussed for local variable declaration. "var" is not an unknown type, but a definite type to be determined at compile time. It is semantically identical to specifying the type by hand. Just saves typing and editing whenever the type might change.Particularly, in templates where it *has* to change, but shall be known at instantiation. And it might save one from picking up the CPUs native type to save the intermediate results of a calculation. -i.
Jan 22 2003
"Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message news:b09jar$5na$1 digitaldaemon.com...Where is an D expression's type not 100% deterministic? It's never determined by the type of the result variable. So it must be determinable just from the expression itself and any declarations that are in scope. I can't think of a single example.There are two examples: 1) &func, where func is an overloaded function. Which overloaded function it is gets determined by type inference. 2) "string", where whether it is a wchar[] or char[] is determined by type inference. I really don't like either of those, but never found a palatable alternative. The first exists in C++, the second does not (as L"string" is used). I have some experience with C++ L strings, and the clumsy use of macros to convert back and forth, and found the result unacceptable.
Feb 14 2003
Hi, Comments embedded, "Norbert Nemec" <nobbi_at_theorie3.physik.uni-erlangen.de NOSPAM.COM> escreveu na mensagem news:b09ad9$30q8$1 digitaldaemon.com...Daniel Yokomiso wrote:ofSather 1.2 provides a ::= assignment that declare lvalue with type and value of rvalue. In Sather 1.3 they are warning against this usage, because it can lead to maintanance problems.Careful: I was the maintainer of Sather during that time. I've done lotscode in Sather (a complete compiler written from scratch, at one time) and I can only speak in favor of that "::=" construct. I really urge everyone to consider the "var" suggestion. It definitely *improves* maintainability greatly. Of course, one can use that feature to produce unreadable code, but then, an expression where you can't infer the type by a quick glanceisa bad idea anyway. If you've come to need the type written in variable declarations as documentation, you really have a much deeper problem.Nice to hear that we have some Sather developer here. Most of people came from an strictly C++ OO/Generics model. I've came accross this warning at Waikato documentation about Sather 1.3. I just pointed the fact, not saying some eternal truth.As an example for where I really hate the lack of such a possibility inC++are iterators: for(Somecontainer<Sometype>::Reverse_iterator i = C.end();i;i--) { ... }; How about this: for(var i = C.end();i;i--) { ... };Well we can also do this: C.end().forEach(fun(i) {...}); or for (i in C.end()) { ... } or loop i ::= C.item! ... end ;-) Iteration is a problem when you have to create explicit "friend"-like classes to allow external iteration. IMO Sather iterators are one of the best possible ways of doing external iteration. If Sather had a simpler type system, where a Hindley-Milner unification was possible (and using streams with ! operator instead of anything ending with a !) it could have higher-order programming over iterators, using them as lazy languages use lazy lists. My pet language, Eon, has Sather-like iterators as basic types (along tuples and function types) so we can use map, filter, etc. with iterators, making any possible higher-order mapping over lists available to iterators. Someday I'll write a compiler for it. Iin D of course ;-) I know that multiple collection iteration is difficult with internal iterators, but Slate http://slate.tunes.org/ provides a multiple collection selector. But they're use dynamic typing and I think their implementation must be dynamically typed.Just consider you want to try out another container type and have to go through all your code to adjust the iterators. Of course, there are waystoavoid that, but they all need some overhead at some other place. Of course, in D, type inference is not always possible from an expression alone, but why not simply make the use of "var" an error in those cases? Ciao, NobbiI don't like the feel of some language feature that sometimes is invalid because it's ambiguous. That's why I'm playing devil's advocate over this feature. Best regards, Daniel Yokomiso. P.S.: I never thought that post would bring more than one response. I guess people really abhor type declarations ;-) "Boss: "D?" What happened to C? Or that other one, C++, that you're always harping about? Me: Well, D is a further refinement of C++, and ... Boss: Weren't you just telling me that "J" language was supposed to be the next big thing? Isn't J further along than D? Me: Yes and no ... [suddenly, a shot rang out]" - sunwukong at /. --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.443 / Virus Database: 248 - Release Date: 11/1/2003
Jan 17 2003