In defense of declaring variables at the top

In defense of declaring variables at the top

Reasons I like it:

1) It obliges you to reason beforehand about what goes in the algorithm

2) If you have to add a new variable, everything is there for you to read

3) Minimizes mistakes

A

Comments

  1. Declaring variables beforehand is not making code any safer or cleaner - its just adding ceremony. Keeping methods short, using good names and having a compiler that is smart enough to infer the type of a variable from its first assignment is doing so.

    ReplyDelete
  2. Agree with Stefan Glienke , except the last one; i still like writing types everywhere just to keep it clear and safe

    ReplyDelete
  3. Agustin Ortu I am really amazed that people think that writing types everywhere makes anything safer. Not writing a type but letting the compiler figure it out by its first assignment is not any less safe. It does not suddenly turn into Java Script that does weird type conversions that go out of control. If I could write var i := 42 the compiler knows ok, i is an Integer (lets leave aside the fact that Delphi has Byte and SmallInt and all that) and I cannot then in the next line assign 'Hello World' to it. The language would still be strongly typed.

    ReplyDelete
  4. Can't agree... how do you assign a pointer with no type declarations? or classes/child classes?

    ReplyDelete
  5. Heinz Toskano Where did I say that I want to prevent that? I said there is no need to force them. All languages that support type inference (that I know) allow specifying the type but in fact in the majority of cases they are simply not needed because the compiler can infer them from the right side expression of the assignment.

    ReplyDelete
  6. Stefan Glienke Correct. Look at TypeScript or even the latest iteration of C#. TypeScript is strongly typed even if you don't see very many types in the declarations. Even when returning anonymous types from a function, they are no less type safe.

    ReplyDelete
  7. Heck even C++ has "auto" these days.Though in C++ it makes a lot more sense than in Delphi, due to templates.

    ReplyDelete
  8. That said, I still like being explicit with my types. I feel it documents my intentions when writing the code.

    ReplyDelete
  9. Mind if I point to PHP's type inference and the hell that created?

    ReplyDelete
  10. Allen Bauer no need to invoke C-languages :) several Pascal dialects support type inference.

    ReplyDelete
  11. I think type inference is only part of the equation and, honestly, not even the most important one in my view.
    For a start, let's agree on the meaning of "safe": what I mean by "safe" is that it is more difficult to write incorrect code.
    Imagine a situation such as this:

    var MyInterface := MyOtherInterface.NewSubOject; // <-- What ACTUAL interface is this if TSubObject implements multiple interfaces? What if it returns the TSubObject instance? What if it returns the WRONG implementation because MyOtherInterface for some reason was typed incorrectly through the inference? What if the developer doing that does not even KNOW that TSubObject implements multiple interfaces?

    Also, documentation is part of writing "safe" code. The fact we have to be explicit means that we may catch incorrect or clunky designs more easily. Removing types means we have less visibility.

    Personally, if this is ever done, I'd like to see several compiler directives:
    1) To make it a compilation error if the type is ambiguous
    2) Emit warnings when you are in an inference chain that is some levels deep (with the number configurable at the module level) and ANY of the types implements multiple compatible interfaces.
    3) Turn it off entirely at the module level

    And I would also like to see a new keyword or class attribute to stop developers from doing inference on particular types.

    A

    ReplyDelete
  12. > var MyInterface := MyOtherInterface.NewSubOject; // <-- What ACTUAL interface is this if TSubObject implements multiple interfaces?

    In your case MyInterface would be a TSubObject, not an interface.

    > What if the developer doing that does not even KNOW that TSubObject implements multiple interfaces?

    In the grand scheme of things, the developer should always assume every object can implements every interface, because even if TSubObject does not implement ISomeInterface at the time the code is written, it could implement it a few days (or months, or years) later, and the code will still compile without errors or warning when that happens.

    Also on a side note, while interfaces in Delphi are often used just as an ersatz for automatic memory management, they are much more than that.

    ReplyDelete
  13. Andrea Raimondi Feel free to declare your variables where you like. I don't think anybody would propose removing that choice from a programmer.

    What I don't like about Delphi is that I cannot impose a lifetime smaller than a function.

    ReplyDelete
  14. David Heffernan Then make your functions smaller ;)

    ReplyDelete
  15. Specific rejoinders to your points.

    Point 1. Declaring variables in one place or another does not oblige more or less thought and design.

    Point 3. That's quite a big claim. Minimize is a very precise word that means "find the smallest possible value". I think you rather mean to say "reduces mistakes". In which case you need to say what you are comparing with. Presumably C++ style declarations which can appear in the body of a function. Even that is a very serious claim. Does you have any evidence? I can't think of any reason why errors would be reduced by forcing all local variables to be listed in one block.

    ReplyDelete
  16. Willo van der Merwe That's fine. But you cannot apply that rule indefinitely. There comes a point where splitting a method up into smaller and smaller pieces becomes counter productive. At some point, if you go too far, then you have too much indirection and the logic becomes harder to comprehend.

    ReplyDelete
  17. IMO, PHP doesn't really have type inference - more like ducktype inference :P

    I like declaring types for the same reasons as Asbjørn i.e. code readability - but there are clearly places where type inference can work.  One such place is "index" variables in for loops. Automatically declared type inferenced loop variables  would eliminate things like "index not valid after loop" and remove the ceremonial declaration.  Another is argument / result type declarations in inline anonymous method implementations.

    I do love Generics, but miss being able to limit T to f.x. an enumerated value to able to use Set of T / Ord(T) - as well as a "math" type limit to be able to do arithmetics - provided that T supports the necessary basic operators (+-*/, assignment and comparators, etc)

    What I most often miss is the ability to reference an object property as exactly that - a reference - i.e. the ability to pass a property as an argument - not it's value - but as a method which can be accessed later from where the reference is kept (both for read and for write).  That would greatly reduce the need for string constant + RTTI trickery.
    Yes, it is a stretch - since an attribute is per class - but there is only one type - and it's structure is fixed - even though it may have several instances - so conceptually this should work - given enough compiler intelligence.

    ReplyDelete
  18. It is impossible to claim that declaring variables at the top reduces error, because there are two cases where it allows errors that tighter scoping can prevent:
    A) using a variable before it has been initialized (but without compiler error because the variable has a default initialization, such as for interfaces)
    B) reusing the same variables for different purposes in different portions of a function, without proper re-initialization or cleaning up in between

    With tighter scoping and "declaration just before use", those tow errors are minimized.

    And there are no errors that tighter scoping opens up.

    ReplyDelete
  19. Ability to declare variables anywhere in the code would be fine with me. But I don't miss that functionality much.

    As far as type inference is concerned my take is road to hell is paved with good intentions. It seems like a good idea and then before you know it you are swamped with tons of unreadable code where you have to jump back and forth trying to understand with what type are you exactly dealing with.

    Type inference is fine only in small number of use cases where type is plain obvious, like for loops variables, unwrapping optionals (nullables) like in Swift with if let constructions... 

    var obj: TSomeObject = TSomeObject.Create construction also looks like place where type can be inferred without reducing code readability, but that is the place where I would draw the line. Constructors - can do, but anything else not.

    Type inference based on function results is just horrible when it comes to code readability and maintenance. Thanks but no thanks.

    ReplyDelete
  20. Willo van der Merwe PHP is not a strongly typed language.

    ReplyDelete
  21. Dalija Prasnikar Adding a feature to a language does not force you to use it at all times to the exclusion of other features.

    If type inference of expressions for inline variable declarations was added, you would be free not to use it.

    ReplyDelete
  22. David Heffernan I don't have to use it, but others will. And more often than not you have to deal with other people's code.

    ReplyDelete
  23. Markus Müller Exactly. That's why the type extensions were added.

    ReplyDelete
  24. Dalija Prasnikar The correct way to deal with that is not to cripple the language, but to use procedure and education and supervision and code review to enforce coding standards within your team. You have to do that anyway.

    ReplyDelete
  25. David Heffernan It goes beyond your team. For start, if nothing else, you have to deal with core Delphi libraries. Going through code of that complexity is hard enough as-is. Additional obscuring is not something I would welcome. 

    While you do have to educate and impose certain coding standards, the less you have to do in that department, the better. You don't have to spend time on education and reviewing for parts where compiler does the job for you.

    ReplyDelete
  26. Dalija Prasnikar  That argument leads to a language of the lowest common denominator. I'm not keen on that. I don't want to go back to Delphi 7.

    ReplyDelete
  27. David Heffernan I am not arguing that we have to go back to Delphi 7. But full spread type inference does not bring enough to justify all unreadable code you can write with it.

    ReplyDelete
  28. Dalija Prasnikar That's not my point. My point is that arguing that others might write code that you do not like is an invalid argument.

    ReplyDelete
  29. David Heffernan I agree with your point to a point ;-) And any feature can be abused, that is for sure.

    My point is that introducing type inference everywhere compiler can infer type is bad. It is not as bad as 'with', but nevertheless bad.

    I have mentioned few cases where type inference can be used safely without diminishing code readability. 

    In case of type inference that is basically keystrokes saving syntax sugar, you don't have other arguments besides people can and will write unreadable code using it. And that someday one will have to deal with such code.

    ReplyDelete
  30. Dalija Prasnikar -  How can a working type inference be bad, as long as it actually works?

    ReplyDelete
  31. Dalija Prasnikar So you say that people write unreadable code in C# because of this? Especially when dealing with collections or arrays how is writing IEnumerable myBlablas = GetBlablas() instead of var MyBlablas = GetBlablas() any more readable?

    ReplyDelete
  32. Lars Fosdal Because compiler can infer types in way more places than human can. That makes your code less readable.

    For instance, inferring type based on function result.

    function ReturnSomething: string;
    ...

    var x = ReturnSomething;

    Compiler can easily know what type should be used, but person reading code would have to go to ReturnSomething declaration to know what is actual x type.

    ReplyDelete
  33. Stefan Glienke Yes, I have no idea what GetBlablas() returns and I want to have that information in place and not lying somewhere else.

    ReplyDelete
  34. Stefan Glienke BTW, I think you meant other way around.

    To make it clear, the way I see it
     IEnumerable myBlablas = GetBlablas() - good
    var MyBlablas = GetBlablas() - bad

    ReplyDelete
  35. Dalija Prasnikar That is why you name your variables and methods properly.

    var Item = ReturnItem;
    var txt = ReturnText;

    There is also the context in which the variable is used which adds further understanding.

    ReplyDelete
  36. Some examples where type inferring does not have negative impact on code readability (IMO):

    inferring in for loops
    for item in Some Collection do
    for i := 0 to Count - 1 do
    for enum in TEnum do

    inferring in optional unwrapping - the Swift way
    if let x = SomeOptional 

    inferring in generics
    var list: TList
    list := Tlist<>.Create

    calling constructor
    var x = TSomeObject.Create

    ReplyDelete
  37. Dalija Prasnikar in Delphi with top-level variable declaration it's not so clear-cut

    var
       myBlablas :  IEnumerable;
       ... some
           other
           variables ...
    begin
       ... some
           lines
           of 
           code ...
       myBlablas := GetBlablas();
       ...
    end;

    So unless the code is trivially short, the type declaration is not obvious, only the naming as Lars Fosdal pointed is important.

    And if the code is trivially short, the explicit typing is just ceremony and does not matter much (and neither does the naming tbh).

    ReplyDelete
  38. Lars Fosdal That's not Pascal. Looks more like BASIC. ((shiver))

    ReplyDelete
  39. Lars Fosdal I understand what you mean. I just don't agree that is enough.

    ReplyDelete
  40. Dalija Prasnikar Again, that a feature can be used poorly does not mean that it cannot be used well. We are all free to write whatever code we like. The argument that because a feature can be badly used is not a valid argument.

    The only reasonable argument to make has to relate to the merits, or otherwise, of using the feature properly.

    To illustrate. A huge amount of terrible abuse of inheritance can be found in many code bases. I know my code base has plenty, and I'm sure yours does too. That's due to a failure on the parts of the developers and not evidence to support removing inheritance from the language.

    It's easy to think of many more examples. Almost every language feature will serve up its own potential for abuse. If you reject all features that can be abused, you will have nothing left.

    ReplyDelete
  41. Eric Grange I said I have no objections with inline variables. And top-level declarations are still more local to the code in question, than some distant function from who knows where.

    ReplyDelete
  42. David Heffernan I already said that in principle I agree. Any feature can be abused. But I also think there is huge difference between features that bring something substantial like inheritance, and mere syntax sugar like type inference.

    And again, I don't have issues with declaring variables inside code, nor limited type inference.

    ReplyDelete
  43. I would like to declare my variable anywhere in the code. I found this really practical !

    ReplyDelete
  44. Willo van der Merwe I was merely reusing the same syntax as Stefan and Dalija.

    I would prefer
      var Variable := Source;
    and even allow
      var Variable: TExplicitType := Source;
    for inline declarations.

    For inline variables that are not bound to a loop  - I think their scope should be limited to the current block.

    I.e.
    if Condition
    then begin
      var Ref := Source;
    end
    else begin
      // no Ref here
    end;
    // no Ref here

    ReplyDelete
  45. Dalija Prasnikar In context of Generics, type inference is waaay more than syntactic sugar, IMO.

    ReplyDelete
  46. Dalija Prasnikar So your argument should be about the merits or otherwise, and not about the fact that any tool can be abused in the hands of the right (wrong?) person

    ReplyDelete
  47. Lars Fosdal I agree with that.

    I said I accept limited (as in where type can be inferred without compromising code readability) type inference.

    ReplyDelete
  48. Lars Fosdal Willo van der Merwe
    I am currently living in Java and Swift more than in Delphi, so I have maybe used non pascalish syntax in some places more by mistake than intention.

    ReplyDelete
  49. David Heffernan Not in general, but in this case yes.

    Because it is kind of feature that will be misused at large. Even by good developers. You will write code, and few years later you will find yourself having hard time understanding it. And as far as merits are concerned it is really insignificant feature except in few cases I have mentioned earlier - maybe there are more such exceptions, but I cannot think of any at the moment.

    ReplyDelete
  50. Dalija Prasnikar  I think I'd like to be the judge of whether or not I will write good code if it's alright by you.

    ReplyDelete
  51. David Heffernan Yes, it is alright with me. 

    I am not saying that anyone (or everyone) should agree with me, but I also want to be able to state my opinion. In this case it is not likely I will change my POV.

    ReplyDelete
  52. Dalija Prasnikar Clearly everyone has their own opinions. And of course they differ. But the argument that you used against inference is just as applicable to other features such as inheritance. But you won't apply it there.

    It's fine to argue on the basis of how much benefit a feature might have, but specious to argue on the basis that a feature might be misused.

    ReplyDelete
  53. David Heffernan I think I stated why it is not applicable to other features. You are missing my point completely. I am not sure if I can explain properly.

    You mentioned writing bad code, this is not about writing bad code and even not about misusing feature. You will be writing good code but that code will lose readability comparing to code without type inference.

    And it is almost impossible not to use type inference if it would be available. Because it is so damn convenient.

    Maybe another example will help you understand what I mean. Swift forces you to write parameter names when calling functions like sum(x: 10, y: 20). If you ask me it is nuisance. If Delphi would have such thing, we would all be cheering now to get rid of that. But no matter how I dislike it, it does make code more readable.

    Basically, I know why people would like to have type inference and I would like to have it in some places. But I have enough experience (also with using type inference myself) to see that in the long run having it everywhere would not be so good at all.

    I think that is a feature one should be very careful with.

    ReplyDelete
  54. Dalija Prasnikar In general I'm agreeing with you. I too am weary of the type inference addition. I understand what David Heffernan​ and friends have to say, but do you guys realise what you're sacrificing because you're too lazy to add a type definition?

    ReplyDelete
  55. Willo van der Merwe Do you use Generics extensively?

    ReplyDelete
  56. +Willo Feel free to continue declaring your variables the way you please

    ReplyDelete
  57. Lars Fosdal Not extensively, no. How extensively do you use it?

    ReplyDelete
  58. David Heffernan It's not that simple. No developer operates on an island. Pascal has certain restrictions imposed to assist a developer. Like Swift's parameter naming and Python's forced indentation, these are features intended to assist the developer. Declaring variables upfront were designed to assist the developer to think and plan about what they're about to do, and forms part of what makes pascal, pascal. Remove that and you start to venture down the Modula-2 road.

    ReplyDelete
  59. +Willo I really don't understand that. I don't use goto. Even though it exists in the language. I understand that there are very rare scenarios where goto is effective and think the language is better for its existence even though my code never uses it.

    I never use single statement, always compound statement. The entire codebase that I work on, alongside a team of developers, adheres to this standard.

    I don't use the new extended exit function that sets Result and then exits. I personally regard it as confusing to have two quite different ways to set Result. That's a choice that my team makes.

    It is perfectly possible to choose what features you use. I don't believe that you are incapable of exercising choice. Why do you feel that you won't be able to do that?

    Aside: Modula-2 variable declaration is identical to Pascal.

    ReplyDelete
  60. +Willo Declaring variables upfront were designed to assist the developer to think and plan about what they're about to do

    Do you have evidence to back that statement? Personally I suspect that the original motivation was to help make it easy for the compiler author to work out how large the function's stack frame was. An awful lot of language features were motivated like that in the old days. But, like you, I'm just speculating.

    ReplyDelete
  61. David Heffernan 
    Why do you feel that you won't be able to do that?
    Sure, I'll be able to control it my own code base, but, that's not really the point. The point is that you're sacrificing readability and stability for something an IDE can assist you with quite easily.

    _Aside: Modula-2 variable declaration is identical to Pascal. _
    I know that, I was trying to show how drastically a language can change, since Modula-2 was based on Pascal.

    Do you have evidence to back that statement?
    No hard evidence, but that's the way it's been punted to me for years (Since Turbo Pascal vs C wars). The fact that it allowed for single pass compilation was a happy side-effect. :)

    ReplyDelete
  62. > The point is that you're sacrificing readability and stability for something an IDE can assist you with quite easily.

    Actually you are not really sacrificing readability, just ceremony, for trivial cases, variable declaration does not bring anything, and for complex cases, you just end up with a long list of loosely related variable declarations (the RTL & VCL have many "good" examples demonstrating how this is actually detrimental to readability).

    Stability is also not enhanced by declaring variables on top for simple reasons: it allows use of variable before initialization, and it encourages same-variable reuse for different purposes. Both these reasons ARE detrimental to stability. Late, in-place and tightly scoped declaration can on the other hand be leveraged to minimize those issues.

    > The fact that it allowed for single pass compilation was a happy side-effect. :)

    Type inference does not prevent single-pass compilation, provided you do not go for a "backtracking" type inference (but that one usually comes with more downsides than upsides)

    ReplyDelete
  63. Willo van der Merwe We have a generics based class hierarchy with some 230 different classes - and numerous other support classes that uses generics heavily.
    It cut down our source #LOC by 15-20% when we introduced it - and a lot of code has since been written. I guess you can say it is relatively extensive use - and sometimes abuse, according to Stefan G :P

    ReplyDelete
  64. Willo van der Merwe For Generics - type inference can in some cases simplify the use of the fairly verbose generics syntax - and makes the code easier to read and to maintain.

    ReplyDelete
  65. For me the prime benefit of inline declarations is that the variable scope can be limited more narrowly. I don't understand why so many people are arguing in favour of wider scope. I thought that debate was resolved long ago.

    ReplyDelete
  66. Lars Fosdal Not abuse but overuse that can lead to more use (seen and done that myself) ;) And I did not make it a fact I just guessed you might. Especially when the generic type parameter is restricted to classes you can easily forget about the good old class of in Delphi.

    ReplyDelete
  67. Just short reminder, we are discussing two separate things here. Declaring variables upfront is one and type inference is another.

    ReplyDelete
  68. To sum up my position:
    YES to inline declarations with limited scope
    YES to type inference where possible.
    YES to inline declaration with type inference

    ReplyDelete
  69. My position summary:
    YES to inline variables 
    YES to type inference in few cases like: for loops, generics, constructors var item := TSomeObject.Create; instead of var item: TSomeObject := TSomeObject.Create;

    NO to type inference everywhere compiler can deduce the type, especially NO to type inference based on function result

    ReplyDelete
  70. +Dalija difficult to know what you mean by type inference for generics

    ReplyDelete
  71. David Heffernan for instance: 
    var list: TList := TList<>.Create

    This is kind of generic type inference Java has. It can most likely be expanded to some other use cases, but I don't have time to invent them at the moment.

    ReplyDelete
  72. Dalija Prasnikar IMO, your suggestion to disallow type inference for function results is strange. You need this for functions in factories, f.x.

    var Structure := Factory.Build;

    ReplyDelete
  73. Lars Fosdal While it may be fine for well defined factories, type inference in function results is what makes your code harder to read and understand later on. 

    I am talking from experience here. I have my own 6 months old Swift code where I have hard time reading it. It is not bad code and it is quite simple, but if it takes me 3 minutes longer to understand what code does because I don't see variable type, then it is 3 minutes too much.

    And problem is while you can say that you are not going to use it in some places, you will. It is almost impossible not to use it while you are writing code. Also while you are writing code everything is so obvious, but when you return to that code after a while you will find yourself jumping back and forth trying to deduct types. And imagine reading someone else's code.

    That is primary reason why I am against it. It seems like good idea, but actually it is not.

    ReplyDelete
  74. Lars Fosdal In your example if inference can be done other way around the I am for it 

    var Structure: TStructure := Factory.Build<>;

    ReplyDelete
  75. Would you like
    var Instance: TClass = Create;
    as well?

    ReplyDelete
  76. Lars Fosdal Yep, that is fine. There is no need to repeat information twice, problem is when you miss information completely.

    ReplyDelete
  77. The variable may be an abstract base type - and what you want to create is a different type.  IMO, the right side of the assignment should be the one to decide the type.

    ReplyDelete
  78. Lars Fosdal I wonder why you come up with syntax that is far from what we currently have. Why suddenly make changes to the way we call a constructor?

    ReplyDelete
  79. Stefan Glienke To point out why it needs to be the right side of the assignment which controls the actual type - inferred or explicitly.

    ReplyDelete
  80. Lars Fosdal In that case you would have to use var Instance := TClass.Create;

    BTW, Swift has type inference all the way, but now when I think of it does not allow construction (cannot check right now)

    var Instance: TClass = Create;

    I am currently in the middle of release cycle so I am not thinking clearly. Just FYI, if I say something stupid ;-)

    ReplyDelete
  81. Lars Fosdal You don't know that Factory is Factory (it is just a function) and you don't know what type it will return. When you call constructor you have actual type written right there.

    ReplyDelete
  82. var list: TList := TList<>.Create;

    looks pretty lame to me. Not at all keen on the rhs depending on the lhs.  To me 

        var list := TList.Create;

    makes far more sense.

    I honestly cannot see what's wrong with allowing inference everywhere. If you don't want to use it, don't.

    When I code in C# I use var infrequently.  Typically in statements like this:

        var arr = new double[666];

    But naturally I prefer

        FooBar x = obj.getThing();

    to

        var x = obj.getThing();

    It's just seems pretty obvious when inferring variable type is a good thing to do, and when it is not.

    As I've said many times, if all language features that could be misused were reject for that reason, we'd have nothing.

    ReplyDelete
  83. Dalija Prasnikar  In the IDE, when at the code, you see the base type returned by the function (should it not be obvious by the factory/function name) by hovering the cursor over the function - as well as any xml doc present. In the debugger, you can see the actual type returned by hovering over instance.

    ReplyDelete
  84. David Heffernan Java has it like this, I am fine with either way as long as you have the type there. 

    And I will repeat again this is not kind of feature you can easily ignore if you have it available. 

    var or no var is irrelevant here. Java does not have var, Swift forces you to use var or let, but both is fine with me.

    ReplyDelete
  85. Lars Fosdal and when IDE goes berserk on you, or you read code outside the IDE... I don't like to depend on IDE too much while reading code.

    ReplyDelete
  86. Dalija Prasnikar I have no problem choosing when to use var when I code in C#. I don't think I'm particularly special. I think any competent coder will be able to make good judgement calls. I bet you would be able to get this right.

    ReplyDelete
  87. Lars Fosdal As a general rule, in my view, if code is only readable when you have support from an IDE, then such code should not be written in that way.

    ReplyDelete
  88. David Heffernan I am a bit lost right now, so maybe I misunderstood what you mean by var, what I want to say is that I am against 

    var x = obj.getThing(); 

    because it has no explicit type.

    ReplyDelete
  89. Dalija Prasnikar Now you are clutching at straws.  I search/browse code outside the IDE as well, but when I am really digging into a piece of code - I am always in the IDE to be able Ctrl-Click jump, get hover hints, etc.

    ReplyDelete
  90. David Heffernan Well, obviously I am not able to do this right ;-)

    ReplyDelete
  91. David Heffernan In general, I can agree - but if that is the case, the code is not well written. Proper naming is important.

    (edit: which is why foo:bar examples annoy the heck out of me)

    ReplyDelete
  92. Lars Fosdal _which is why foo:bar examples annoy the heck out of me_

    It's interesting you say that given that you habitually offer up example code that is not valid.....

        property ThisCodeIsNotValid;

    ReplyDelete
  93. Dalija Prasnikar My point is that I don't give a dang what type x is. Its the thing that I got from obj.getThing. You are too focused on knowing what type everything is.

    ReplyDelete
  94. Dalija Prasnikar In C#, since 3.0, the var keyword is used to declare variables whose types are inferred by the rhs of the initialization statement. So,

        var foo = 42;

    is equivalent to
      
        int foo = 42;

    This is obviously a very simple example.  My point is that any half competent developer is perfectly capable of understanding that

        var arr = new double[666];

    is just as clear as

        double[] arr = new double[666];

    and avoids the repetition.  And that half competent developer is just as capable of understanding that

        var x = obj.getThing(); 

    is unclear.

    Where var comes into its own is with complex expression whose types are actually hard to express.  The use case that pushed the C# designers into this route was LINQ which has a tendency to produce exceedingly verbose types that nobody ever wants to name explicitly.  

    I'm a 100% confident that you are capable of known when to use such a feature, and when to shun it.

    ReplyDelete
  95. Stefan Glienke I think the point is that sometimes you want to know the type when you read the code, and sometimes you don't want to know the type.  It's not an either or. I'm sure that there are plenty of times when you do want to be able to know what type a variable is.

    ReplyDelete
  96. Stefan Glienke exactly.

    In GC'ed environments, there is also a trend to not only not having to care what the type is, but also not caring about the memory management implications. In Delphi you still have to care whether it's an instance or an interface, and if you're going to keep a reference to it, if it might not create a circular reference.

    ReplyDelete
  97. David Heffernan What are we exactly arguing about? From what I can see, examples of code that you want to write are exactly in line with kind of code I want to write. IMO compiler is perfectly capable in distinguishing between that kind of code and the code you said it is unclear. All I want is that compiler prevents me from writing unclear code. 

    Why? Because, I have too many times caught myself writing unclear code with type inference. I can tell the difference between good and bad code, but somehow I have hard time writing proper code when compiler does not forces me to. Maybe it is just matter of getting used to it, and with time I will get better. I don't know.

    ReplyDelete
  98. Dalija Prasnikar My opinion differs. I think if you don't allow language features that can be abused then you won't allow anything. I don't believe that the compiler can stop us writing bad code. That's our job to do right.

    ReplyDelete
  99. David Heffernan And I generally agree with you. Compiler cannot stop us from writing bad code, but it can be helpful. And I like that help. If my views in this matter would prevent someone from writing code they really, really want to write, then let it be type inference everywhere. But I still think it is a not a good thing to have.

    ReplyDelete
  100. Stefan Glienke can you create a New Feature request entry at Quality Portal? I think your explanation would be very appreciated :D

    ReplyDelete

Post a Comment