Чем-то напомнило Стругацких «Понедельник начинается в субботу». Как будто, интервьюируемый — один из тех печальных профессоров, что имеют огромный опыт, но применять его уже особо некуда за давностью лет, разве что от Выбегалло мир спасать. Написано красиво и нарочито наивно, так же, как и у Стругацких.
Не совсем понятно, как расширяются условные столы и кошки. Если расстояние между двумя связанными молекулами увеличится за счёт расширения пространства, разве не должны они будут компенсировать это расширение притягиванием друг к другу? Ведь считается, что константы и законы не меняются при расширении. Так же и с электронами и ядрами атомов, и с расстоянием между протонами и нейтронами, и ещё глубже. Или я чего-то не понимаю?
Всех давно достал этот JS с его нелогичностями, поэтому есть TypeScript и пилят сейчас WebAssembly. Занесло меня недавно случайно на конференцию HolyJS. Там крутые дядьки с умным видом рассказывали про семафоры и хэшкоды. Примерно те же темы обсуждали на конференциях C#/Java лет 10-15 назад. Как будто во что-то мягкое наступил.
Выстрелить себе в ногу можно было всегда, и это один из примеров, да. При разработке компиляторов надо взвешивать все за и против. Наверняка, вопрос пустых var-ов поднимался, и было принято решение пока оставить всё как есть. Лично я был бы согласен терпеть неоднозначности вроде той, что вы привели (благо, они не выходят за пространство имён метода).
P.S. Прошу прощения за долгий ответ. Читал ветку с имейлов, не мог ответить сразу, забыл ответить потом.
В C# вообще всё не так очевидно c типами. Компилятор пытается вывести тип переменной, исходя из числового значения лексемы. Если, скажем, мы напишем «var x = -2147483648;» то тип будет int, но если убрать минус, то это будет уже uint, т.к. минимальное и максимальное значения отличаются на единицу).
Дальше больше: если мы захотим написать «var y = (double)1000000000000000000000000000;», то будет синтаксическая ошибка. Но если добавить литеру «d» и убрать каст (var y = 1000000000000000000000000000d;), то всё скомпилируется, и типом ожидаемо будет double.
Так что, отказаться от использования суффиксов не получится пока.
Да, хорошо, что не стали плодить жестких ключевых слов. По большому счёту, ключевые слова — это атавизм. Не могу придумать примера, когда синтаксис языка (Java/JS/C#) может быть воспринят двояко, но, наверно, такие примеры есть. На мой взгляд, удобство ключевых слов заключается в упрощении синтаксического анализа и более внятных ошибках при разборе.
Кстати, вот ссылка на контекстно-зависимые ключевые слова в C#: docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/contextual-keywords
Список интересен тем, что все новые ключевые слова, добавленные в язык после версии 2.0, являются контекстно-зависимыми. (Не совсем ясно, почему в списке нет select, from и where.)
Java идёт тем же путём: чем меньше ключевых слов, тем лучше. Следующий этап — добавление "@" к лексемам для обозначения того, что это не ключевое слово (как это сделано в C#). Надеюсь, до этого не дойдёт, но извечный джавовый мем — называть переменные «clazz», из-за того, что слово «class» зарезервировано — тоже не круто.
Исходя из этой таблицы, в JS (ECMAScript 5/6) всего 50 зарезервированных ключевых слов, которые нельзя применять в качестве переменных.
А здесь представлены ключевые слова в Java. Их тоже 50. Но! в JS количество слов сокращают, а в Java увеличивают.
По-моему, всё гораздо проще. Если после инициализации переменной её не переприсваивают, то можно оставить изначальный тип. А если, скажем, будет такой код:
var names = GetNames(); // GetNames возвращает string[]
if (dropBob)
{
names = names.Where(name => name != "Bob");
}
то компилятор может понять, что names должен быть общим типом IEnumerable<string>. Не надо анализировать вызываемые методы. Достаточно посмотреть, значения каких типов присваиваются переменной.
Естественно, в этом случае свойство Length будет уже недоступно после if-а, т.к. тип может поменяться.
И как быть, когда некоторая функция возвращает экземпляр некоторого типа, но мы сознательно хотим редуцировать тип возвращенного значения до базового типа или интерфейса, реализованного в типе возвращаемого значения?
В принципе, это не такая уж и сложная задача для компилятора — вывести наиболее конкретный обобщённый тип, необходимый в данном контексте. TypeScript успешно с этим справляется. Почему это до сих пор не реализовано в C# — не понятно. Тем более не понятно, почему это не добавили в Java, учитывая, что var ещё только в проекте и можно учесть все минусы существующих языков.
Про Long согласен — в таких случаях лучше явно указывать тип. Это один из примеров кривоватой лексики языка (особенно учитывая неоднозначности типа 11 versus 1l). Да и в целом числовые суффиксные литералы, на мой взгляд, довольно кривое решение. Для каких-то типов они есть (m, f, d, l, ul), а для каких-то забыли придумать (byte, short, ushort). Странно.
Но если речь идёт о bool, string и char, то я всё же предпочитаю использовать var. Зачем писать «bool b = true;», если и так очевидно, что это bool?
Что касается моего примера с if-else — да, result не надо инициализировать null-ом. Писал без IDE, пропустил этот момент. Но выносить такое в отдельный метод тоже не всегда правильно, так как это засоряет private scope класса. Вложенные функции решают эту проблему, но их пока не везде можно использовать.
И вдруг мы решили вместо double использовать decimal. Если бы мы сразу написали var arg2, то рефакторинг был бы минимальным — надо было бы только переписать сигнатуру метода. А теперь придётся лезть в тело метода и изменять все double на decimal. В этом примере всё не так страшно — всего одно изменение, но если это был бы какой-то сложный расчёт, пришлось бы помучиться.
На сколько помню, в IDEA можно написать «new URL(...).new» и нажать Tab, чтобы она создала новую переменную и сама сгенерировала имя. Решарпер умеет так же, вместо типа подставляет var (можно настроить, чтобы подставлял тип).
Это вопрос вкуса и договорённостей внутри команды. У нас в команде принято использовать var везде, где это возможно, даже для примитивных типов. Иногда приходится явно обозначать тип, и это меня убивает. Например, такой код:
IEnumerable<string> result = null;
if (someCondition)
{
result = new List<string>();
// логика по добавлению элементов.
}
else
{
result = Enumerable.Empty<string>();
}
Или вот ещё проблема с тернарной записью:
int? result = someCondition ? 42 : null;
Теоретически, компилятор способен сам вывести тип переменной result, но сейчас этого нет. Думаю, когда-нибудь добавят и это (на сколько знаю, в C#8 проблему с Nullable побороли).
Вообще, вывод типов — это ключевая фича всех функциональных языков, а C# и Java к ним постепенно приближаются. В последнем Шарпе уже можно использовать кортежи в качестве возвращаемых значений методов, а в перспективе, думаю, в некоторых случаях можно будет вообще не указывать тип возвращаемых значений или писать «var».
Я, как C#-программист, тоже скептически относился к var-ам, когда их добавили. Аргументация была ровно как у Вас. Сейчас настолько привык, что без них уже не представляю жизнь.
Простите за вопрос, но зачем? ClickOnce не поддерживается ни одним браузером, кроме IE (плагины в расчёт не беру). Это устаревшая технология, годится только для корпоративных решений с жёсткими политиками безопасности в стиле полного запрета других браузеров, кроме IE. Это ваш случай?
a-->b
этоb(a)
илиa-- > b
www.asus.com/ru/All-in-One-PCs/Zen-AiO-Pro-Z240IC
Покажите моноблок от эппл с зионом и ценой «от 59 920 руб.»
Не совсем понятно, как расширяются условные столы и кошки. Если расстояние между двумя связанными молекулами увеличится за счёт расширения пространства, разве не должны они будут компенсировать это расширение притягиванием друг к другу? Ведь считается, что константы и законы не меняются при расширении. Так же и с электронами и ядрами атомов, и с расстоянием между протонами и нейтронами, и ещё глубже. Или я чего-то не понимаю?
P.S. Прошу прощения за долгий ответ. Читал ветку с имейлов, не мог ответить сразу, забыл ответить потом.
Дальше больше: если мы захотим написать «var y = (double)1000000000000000000000000000;», то будет синтаксическая ошибка. Но если добавить литеру «d» и убрать каст (var y = 1000000000000000000000000000d;), то всё скомпилируется, и типом ожидаемо будет double.
Так что, отказаться от использования суффиксов не получится пока.
Кстати, вот ссылка на контекстно-зависимые ключевые слова в C#: docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/contextual-keywords
Список интересен тем, что все новые ключевые слова, добавленные в язык после версии 2.0, являются контекстно-зависимыми. (Не совсем ясно, почему в списке нет select, from и where.)
Java идёт тем же путём: чем меньше ключевых слов, тем лучше. Следующий этап — добавление "@" к лексемам для обозначения того, что это не ключевое слово (как это сделано в C#). Надеюсь, до этого не дойдёт, но извечный джавовый мем — называть переменные «clazz», из-за того, что слово «class» зарезервировано — тоже не круто.
Исходя из этой таблицы, в JS (ECMAScript 5/6) всего 50 зарезервированных ключевых слов, которые нельзя применять в качестве переменных.
А здесь представлены ключевые слова в Java. Их тоже 50. Но! в JS количество слов сокращают, а в Java увеличивают.
то компилятор может понять, что names должен быть общим типом IEnumerable<string>. Не надо анализировать вызываемые методы. Достаточно посмотреть, значения каких типов присваиваются переменной.
Естественно, в этом случае свойство Length будет уже недоступно после if-а, т.к. тип может поменяться.
В принципе, это не такая уж и сложная задача для компилятора — вывести наиболее конкретный обобщённый тип, необходимый в данном контексте. TypeScript успешно с этим справляется. Почему это до сих пор не реализовано в C# — не понятно. Тем более не понятно, почему это не добавили в Java, учитывая, что var ещё только в проекте и можно учесть все минусы существующих языков.
11
versus1l
). Да и в целом числовые суффиксные литералы, на мой взгляд, довольно кривое решение. Для каких-то типов они есть (m, f, d, l, ul), а для каких-то забыли придумать (byte, short, ushort). Странно.Но если речь идёт о bool, string и char, то я всё же предпочитаю использовать var. Зачем писать «bool b = true;», если и так очевидно, что это bool?
Что касается моего примера с if-else — да, result не надо инициализировать null-ом. Писал без IDE, пропустил этот момент. Но выносить такое в отдельный метод тоже не всегда правильно, так как это засоряет private scope класса. Вложенные функции решают эту проблему, но их пока не везде можно использовать.
И вдруг мы решили вместо double использовать decimal. Если бы мы сразу написали var arg2, то рефакторинг был бы минимальным — надо было бы только переписать сигнатуру метода. А теперь придётся лезть в тело метода и изменять все double на decimal. В этом примере всё не так страшно — всего одно изменение, но если это был бы какой-то сложный расчёт, пришлось бы помучиться.
Или вот ещё проблема с тернарной записью:
Теоретически, компилятор способен сам вывести тип переменной result, но сейчас этого нет. Думаю, когда-нибудь добавят и это (на сколько знаю, в C#8 проблему с Nullable побороли).
Вообще, вывод типов — это ключевая фича всех функциональных языков, а C# и Java к ним постепенно приближаются. В последнем Шарпе уже можно использовать кортежи в качестве возвращаемых значений методов, а в перспективе, думаю, в некоторых случаях можно будет вообще не указывать тип возвращаемых значений или писать «var».
Простите за вопрос, но зачем? ClickOnce не поддерживается ни одним браузером, кроме IE (плагины в расчёт не беру). Это устаревшая технология, годится только для корпоративных решений с жёсткими политиками безопасности в стиле полного запрета других браузеров, кроме IE. Это ваш случай?