Hacker News new | past | comments | ask | show | jobs | submit login

It looks like they've added a lot of rope to hang ourselves with typos.

    int myvar, I;
    foo(out int mvar); // oops, not myvar; maybe caused by a refactor?
    bar(out *); // oops, not I; was up too late coding
And so on. Things like this would be easily missed when reading code at-a-glance, and it's this sort of bug that arises often in languages that allow implicit declaration of variants.



Hi there, C# language designer here.

I don't really see your example in that way. Let's start with the latter one first:

> bar(out *); // oops, not I; was up too late coding

I'm not sure how this situation is any differnet from any other case where you need to pass some variable, and you pass the incorrect name. This is already possible all over the language. For example, you might have written "bar(out J)" when you meant "bar(out I)". As usual, the recommendations here are to use strong types and good names to help keep your code clear in intent and to allow the compiler to tell you when something seems awry.

Now let's look at your first example:

> foo(out int mvar);

This version immmediately screams at me that something is happening that requires my attention. First off, just the presence of 'out' is an immediate call that this is not a normal call. Nearly all calls pass by value, so out/ref stick out like a sore thumb (esp. in an IDE that classifies them accordingly). Second, the "out int" is another large indicator that this is doing stuff very special.

Finally, i'd point out that the mispelled name problem is really no different than what you might experience today with code like:

  int myvar;
  ...
  // much later and indented a bit ...
         int mvar;
         Foo (out mvar);
Here you've unintentionally introduced a new variable that you may or may not have intended to. Without a collision, there's no way to tell.

> it's this sort of bug that arises often in languages that allow implicit declaration of variants.

No implicit declarations are allowed. All declarations are explicit. We just don't force you to have to declare in one location and use in another. This is a pattern that many people hate, and which goes against a desire to immediately declare and initialize, and thus not have to track down how a variable is written to.


> I'm not sure how this situation is any different from any other case where you need to pass some variable, and you pass the incorrect name.

It's a wildcard. Passing in any other variable name would ideally raise an error about the use of an undeclared variable or a mismatched type. The use of a wildcard disposes of those errors.

> the mispelled name problem is really no different than what you might experience today

Not quite; your modified examples includes two declarations on their own lines. Being on their own line gives them greater visual presence at-a-glance than the new syntax which buries the declarations within a parameter list.

Worth noting is that my trivial example managed to confuse at least one reader who was unable to see the issue[0].

> All declarations are explicit.

While true, you've muddied the lines a little by moving declarations into the syntax of other expressions. Where previously a declaration sat on its own line or at the beginning of an assignment, they may now be peppered throughout the syntax in ways that are not so easy to observe at-a-glance.

0: https://news.ycombinator.com/item?id=12356681


The first one requires 2 errors. Reinitializing a variable (if you intended to use myvar then you wouldn't need to put int after your out) and compounding it with a misspelling. This is no different from how you'd make the same mistake today.

I'm not happy about wild cards. It seems like taking what is a very powerful character in software development and using it for a pretty minor usability improvement. Besides it seems misleading. When I see an asterisk I don't think throwaway. I can see how that aligns with "anything can go here" meaning from regex, but I feel there is a difference in "value". Using a * in a regex seems to increase the power and heft of the regex, where as using it here, seems to decrease the value, which is almost the opposite effect. Another way of putting it is that the point should be to let me ignore this while reading code, but the asterisk draws my attention to it instead.

Compare this to the Haskell convention of using an _ for throwaway items, which disappears just enough, instead of attracting attention. And by simply being a convention, it isn't giving the character too much power.

Not sure if lack of Haskell style type inference prevents C# from using convention for throwaways instead of wildcard chars, but I think it would be much less overhead on the Dev.


It does seem silly, considering that F# already uses _ as a "don't care" wildcard, and it's a pretty common pattern already in C# lambda-heavy code to use the underscore for the same idea.


R# should warn "unused variable myvar" on the first one.

You'll get a compiler error if you try and use `I` uninitialized.

Not saying you're wrong, just having trouble getting worried about this. You can make typos now:

    int x, y;
    foo(out x, out x); // oops, not y; was up too late coding


In a non-trivial example it's likely that `myvar` or `I` would see themselves used elsewhere, perhaps even as an out value to another method, and so raise no warnings. The source of the problem won't be so obvious at-a-glance because the new declaration syntax aren't so different from existing syntax, and could easily go unnoticed when shadowing existing values deep within a function.

Sure, you can make typos now, but these changes expand the possibilities of errors arising from typos or incomplete refactoring; while reducing the discoverability of the issue at-a-glance.


> foo(out int mvar); // oops, not myvar; maybe caused by a refactor?

This should fail to compile, it's the equivalent of declaring a variable twice int the same scope.


If that were int myvar you'd be correct, in this case the typo introduces a new variable mvar that won't conflict with the original declaration.


Whoops, I missed the typo. Inadvertently proving your point.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: