Наши любимые C# и Java имеют избыточный синтаксис для создания объекта — оба этих языка используют ключевое слово new для создания объектов в куче. Спрашивается, зачем оно (ключевое слово) нужно, если всё равно создавать на стеке объекты ссылочных типов невозможно, так что приписывание лишнего new не несёт никакого дополнительного смысла.
Не лучше ли использовать просто:
MyClass c = MyClass(10, 20);
В Джаве new было введено исключительно по политическим причинам, чтобы облегчить переход C++ программистов на Джаве облегчив им узнавание привычных конструкций (создание объектов в куче). В Шарп, вероятно, new было содрано с Джавы, дабы облегчить переход C++ и Джава — программистов на Шарп
Вопрос: согласны ли вы, что new избыточен? Нет ли каких-нибудь синтаксических косяков (гипотетическое) исключение new из этих языков?
Здравствуйте, L.C.R., Вы писали:
LCR>Речь пойдет о new.
[skip]
LCR>Вопрос: согласны ли вы, что new избыточен? Нет ли каких-нибудь синтаксических косяков (гипотетическое) исключение new из этих языков?
По опыту языков Python, Boo. Могу сказать что слово new помогает визуально отделить создание объекта от вызова функции, что помогает при чтении кода. Хотя в этом случае может помочь и контекстно зависимая подстветка, но я такого не видел ( + требуется специализированный редактор).
Здравствуйте, Александр Сергеевич, Вы писали:
VD>>static void Main() VD>>{ VD>> MyClass c = MyClass(10, 20); VD>>} VD>>[/c#]
АС>Этим. Тем что обычная функция(конструктор ведь тоже функция) не может совпадать с именем класса...
void f(MyClass mc)
{}
// много кода
f(MyClass(10, 20));
В данном случае сложно так сходу сказать что это, создание нового объекта или вызов функции класса. Конечно соглашения о кодировании могут разрулить эту ситуацию, но вообще говоря слово new никого не напрягает
Здравствуйте, Александр Сергеевич, Вы писали:
АС>Этим. Тем что обычная функция(конструктор ведь тоже функция) не может совпадать с именем класса...
Боюсь тебя разочаровать — еще как может.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, L.C.R., Вы писали:
LCR>Вопрос: согласны ли вы, что new избыточен? Нет ли каких-нибудь синтаксических
косяков (гипотетическое) исключение new из этих языков?
нет, несогласны. Что здесь действительно избыточно — так это двойное повторение MyClass
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Александр Сергеевич, Вы писали:
АС>>Этим. Тем что обычная функция(конструктор ведь тоже функция) не может совпадать с именем класса... S>Боюсь тебя разочаровать — еще как может.
Не видел такого, покажи на примере 8)
Здравствуйте, Александр Сергеевич, Вы писали:
АС>Здравствуйте, Sinclair, Вы писали:
S>>Здравствуйте, Александр Сергеевич, Вы писали:
АС>>>Этим. Тем что обычная функция(конструктор ведь тоже функция) не может совпадать с именем класса... S>>Боюсь тебя разочаровать — еще как может. АС>Не видел такого, покажи на примере 8)
public class Test {
int FunctionName()
{
return 1;
}
public static void main(String[] args)
{
System.out.println("Hello, world");
}
}
class FunctionName
{
public void doF()
{
}
}
VladD2,
VD>И чем это будет отличаться от вызова функции? VD>
VD>MyClass MyClass()
VD>{
VD> return new MyClass();
VD>}
VD>static void Main()
VD>{
VD> MyClass c = MyClass(10, 20);
VD>}
VD>
Да, действительно, введение new разрешает совпадение имён классов и методов. Так что при отказе от new придётся и отказаться от соблазна называть классы и методы одними именами...
LCR>Наши любимые C# и Java имеют избыточный синтаксис для создания объекта — оба этих языка используют ключевое слово new для создания объектов в куче. Спрашивается, зачем оно (ключевое слово) нужно, если всё равно создавать на стеке объекты ссылочных типов невозможно, так что приписывание лишнего new не несёт никакого дополнительного смысла.
LCR>Не лучше ли использовать просто: LCR>MyClass c = MyClass(10, 20);
LCR>Вопрос: согласны ли вы, что new избыточен? Нет ли каких-нибудь синтаксических косяков (гипотетическое) исключение new из этих языков?
Согласен, но ты не там копаешь. Лучше так:
var c = new MyClass(10, 20);
Т.е. дать возможность компилятору автоматически определять тип создаваемой переменной по типу (typeof) правой части. Если бы в С++ был typeof, это можно было бы выразить макросом:
#define DEF_VAR(name, expr) typeof(expr) name = expr
// т.е.
DEF_VAR(c,new MyClass(10,20))
// аналогично
typeof(new MyClass(10,20)) c = new MyClass(10,20)
[... skipped ...]
Кё>Согласен, но ты не там копаешь. Лучше так:
Кё>
Кё>var c = new MyClass(10, 20);
Кё>
Кё>Т.е. дать возможность компилятору автоматически определять тип создаваемой переменной по типу (typeof) правой части.
А как же быть, например, с явными реализациями интерфейсов в C#? Т.е. если класс явно реализует несколько интерфейсов с одинаковыми именами членов, например, да вдобавок ещё и имеет собственный член с таким же именем? Или для интерфейсов специально использовать старый синтаксис?
Кё>>Согласен, но ты не там копаешь. Лучше так: Кё>>var c = new MyClass(10, 20); Кё>>Т.е. дать возможность компилятору автоматически определять тип создаваемой переменной по типу (typeof) правой части.
O>А как же быть, например, с явными реализациями интерфейсов в C#? Т.е. если класс явно реализует несколько интерфейсов с одинаковыми именами членов, например, да вдобавок ещё и имеет собственный член с таким же именем? Или для интерфейсов специально использовать старый синтаксис?
С трудом понимаю о чём ты — приведи код Да, старый синтаксис обязательно тоже должен остаться, `var` это просто ещё один синтаксический сахар для удобства, чтобы исключить лишнее имя типа в коде. Он просто как макрос, ничего не меняет.
[... skipped ...]
O>>А как же быть, например, с явными реализациями интерфейсов в C#? Т.е. если класс явно реализует несколько интерфейсов с одинаковыми именами членов, например, да вдобавок ещё и имеет собственный член с таким же именем? Или для интерфейсов специально использовать старый синтаксис?
Кё>С трудом понимаю о чём ты — приведи код Да, старый синтаксис обязательно тоже должен остаться, `var` это просто ещё один синтаксический сахар для удобства, чтобы исключить лишнее имя типа в коде. Он просто как макрос, ничего не меняет.
interface I1
{
string Run();
}
interface I2
{
string Run();
}
class C1 : I1, I2
{
public string Run()
{
return"C1 is running";
}
string I1.Run()
{
return"I1 is running";
}
string I2.Run()
{
return"I2 is running";
}
}
// используемый код
C1 x = new C1();
Console.WriteLine(x.Run()); // C1 is running
Console.WriteLine(((I1)x).Run()); // I1 is running
Console.WriteLine(((I2)x).Run()); // I2 is running
// гипотетический кодvar x2 = new C1();
Console.WriteLine(x2.Run()); // ну и какой же Run() вызывать?
[... skipped ...]
Кё>Согласен, но ты не там копаешь. Лучше так:
Кё>
Кё>var c = new MyClass(10, 20);
Кё>
Кё>Т.е. дать возможность компилятору автоматически определять тип создаваемой переменной по типу (typeof) правой части.
А как это будет вообще работать с наследованием? Вот ещё пример из C#:
public class Base
{
virtual public string Hello()
{
return"Hi from Base";
}
}
public class Derived : Base
{
new public string Hello()
{
return"Hi from Derived";
}
}
// работающий код
Base x = new Derived();
Console.WriteLine(x.Hello()); // Hi from Base
Console.WriteLine(((Derived)x).Hello()); // Hi from Derived
// гипотетический кодvar x2 = new Derived();
Console.WriteLine(x2.Hello()); // опять же, какой Hello вызывать
Эти строки полностью аналогичны
O>C1 x = new C1(); O>var x2 = new C1();
И эти строки, соответственно, тоже полностью аналогичны
O>Console.WriteLine(x.Run()); // C1 is running O>Console.WriteLine(x2.Run()); // ну и какой же Run() вызывать? C1.Run, конечно, как и в предыдущей строке.
O>Console.WriteLine(((I1)x).Run()); // I1 is running O>Console.WriteLine(((I2)x).Run()); // I2 is running
O>В общем-то, не вижу смысла в var.
Я вижу, что ты не видишь смысла Смысл такой, что реальные классы имеют имена куда длиннее, чем `C1`, и к тому же
int[] integers;
foreach (var el in integers) ;
foreach (int el in integers) ;
Ну и тому подобные применения. Всегда, когда тип вновью создаваемой переменной равен типу правой части (т.е. никаких касто вне происходит), можно этот тип не писать. Конечно, если это не приносит ущерба читаемости.
O>// работающий код O>Base x = new Derived(); O>Console.WriteLine(x.Hello()); // Hi from Base O>Console.WriteLine(((Derived)x).Hello()); // Hi from Derived
O>// гипотетический код O>var x2 = new Derived(); O>Console.WriteLine(x2.Hello()); // опять же, какой Hello вызывать
Вот так понятнее?
var Derived = new Derived();
Console.WriteLine(x2.Hello()); // опять же, какой Hello вызывать
Насколько я помню, в C# будет ошибка компиляции во второй строке, и правильно. Но `var` тут ни при чем.
O>IMHO: var в C# не место.
Ты всё еще не понял. Это не сущность, это макрос. typeof(new Derived()) всегда равно `Derived` и никогда не равно `Base`. Тип переменной x2 — `Derived`, независимо от того, сколько каких интерефейсов кто-то где-то реализовал. У typeof по определению только один результат — не может быть никакой неоднозначности.
[... skipped ...]
Кё>Ну и тому подобные применения. Всегда, когда тип вновью создаваемой переменной равен типу правой части (т.е. никаких касто вне происходит), можно этот тип не писать. Конечно, если это не приносит ущерба читаемости.
Экономя на символах, составляющих название класса, мы запутаем сами себя. Например, если в массиве сидят объекты типа Base (отсюда — Re[2]: Синтаксический оверхед в C# / Java
O>>// работающий код O>>Base x = new Derived(); O>>Console.WriteLine(x.Hello()); // Hi from Base O>>Console.WriteLine(((Derived)x).Hello()); // Hi from Derived
O>>// гипотетический код O>>var x2 = new Derived(); O>>Console.WriteLine(x2.Hello()); // опять же, какой Hello вызывать
Кё>Вот так понятнее? Кё>var Derived = new Derived();
Я уже понял, что ты имеешь в виду. Хотел тебе показать, что var принесёт кучу неоднозначности в код.
Кё>Console.WriteLine(x2.Hello()); // опять же, какой Hello вызывать
Кё>Насколько я помню, в C# будет ошибка компиляции во второй строке, и правильно. Но `var` тут ни при чем.
Ошибка компиляции? У меня, видно, компилятор поломался — всё компилится.
O>>IMHO: var в C# не место.
Кё>Ты всё еще не понял. Это не сущность, это макрос. typeof(new Derived()) всегда равно `Derived` и никогда не равно `Base`. Тип переменной x2 — `Derived`, независимо от того, сколько каких интерефейсов кто-то где-то реализовал. У typeof по определению только один результат — не может быть никакой неоднозначности.
Ну а толку-то от такого макроса? Я всё ещё не могу понять — неужели от экономии символов столько пользы, что её можно проделывать засчёт понижения читабельности кода?
O>Base[] array; O>foreach (var x in array) { O> Console.WriteLine(x.Hello()); O>} O>и если хоть один из них на самом деле имеет тип Derived, то поведение будет отличаться от поведения такого кода:
Тип элемента "на самом деле" никак не должен волновать инструкцию var. Если в массиве элементы Base, то var x аналогично Base x. Dervied тут никак не участвует.
O>Base[] array; O>foreach (Base x in array) { O> Console.WriteLine(x.Hello()); O>} O>- согласен?
Не согласен. Не будет отличаться. Ты вкладываешь в `var` какое-то слишком сложное поведение, тогда как его смысл — подсмотреть тип выражения и подставить вместо себя.
Может ты неправильно понимаешь typeof, о котором я говорю? Я не про шарповский, я про гипотетический С++-ный говорил.
class Base {}
class Derived : Base {}
Base ba = new Derived();
typeof(ba) всегда Base и никогда Derived.
[... skipped ...]
Кё>Может ты неправильно понимаешь typeof, о котором я говорю? Я не про шарповский, я про гипотетический С++-ный говорил. Кё>class Base {} Кё>class Derived : Base {}
Кё>Base ba = new Derived(); Кё>typeof(ba) всегда Base и никогда Derived.
Да, тут я тебя недопонял, согласен. Получается, var — действительно только макрос, который обрабатывается на этапе прекомпиляции. И всё-таки Баба Яга против добавления такого сахара. Мой глубочайшее имхо заключается в том, что макросы — зло. Даже в том случае, если они используются крайне редко (как ключевое слово var, например).
O>Ну а толку-то от такого макроса? Я всё ещё не могу понять — неужели от экономии символов столько пользы, что её можно проделывать засчёт понижения читабельности кода?
Я специально оговорил — только если это не понимает читаемость. var применяется, если переменная уничтожается через шесть строк. Определять переменную через var и затем использовать на следующей странице будет очень плохо, я согласен
В качестве компромисса можно сделать его фичей IntelliSense. Т.е. вы пишете var, вместо которого редактор подставляет имя типа.
O>>Ну а толку-то от такого макроса? Я всё ещё не могу понять — неужели от экономии символов столько пользы, что её можно проделывать засчёт понижения читабельности кода?
Кё>Я специально оговорил — только если это не понимает читаемость. var применяется, если переменная уничтожается через шесть строк. Определять переменную через var и затем использовать на следующей странице будет очень плохо, я согласен
В Си тоже макросы добавили во имя благих целей...
Кё>В качестве компромисса можно сделать его фичей IntelliSense. Т.е. вы пишете var, вместо которого редактор подставляет имя типа.
Oyster,
O>Да, тут я тебя недопонял, согласен. Получается, var — действительно только макрос, который обрабатывается на этапе прекомпиляции. И всё-таки Баба Яга против добавления такого сахара. Мой глубочайшее имхо заключается в том, что макросы — зло. Даже в том случае, если они используются крайне редко (как ключевое слово var, например).
Макрос макросу рознь. Если макрос устраняет дублирование, то макрос — хорошо, а дублирование — плохо.
O>Base[] array;
O>foreach (var x in array) {
O> Console.WriteLine(x.Hello());
O>}
O>
O>и если хоть один из них на самом деле имеет тип Derived, то поведение будет отличаться от поведения такого кода:
Нет. Вывод типа происходит статически те тип переменной x будет Base.
Тип можно легко вывести в большинстве мест. По крайней мере у ReSharper'а это очень хорошо получается.
O>В общем, имхо проблем больше, чем преимуществ.
Не согласен.
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, Oyster, Вы писали:
O>>
O>>Base[] array;
O>>foreach (var x in array) {
O>> Console.WriteLine(x.Hello());
O>>}
O>>
O>>и если хоть один из них на самом деле имеет тип Derived, то поведение будет отличаться от поведения такого кода: WH>Нет. Вывод типа происходит статически те тип переменной x будет Base. WH>Тип можно легко вывести в большинстве мест. По крайней мере у ReSharper'а это очень хорошо получается.
Ок, это я уже понял.
O>>В общем, имхо проблем больше, чем преимуществ. WH>Не согласен. WH>
Здравствуйте, Кодёнок, Вы писали:
Кё>В качестве компромисса можно сделать его фичей IntelliSense. Т.е. вы пишете var, вместо которого редактор подставляет имя типа.
Поставь ReSharper
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Oyster, Вы писали:
Кё>>Я специально оговорил — только если это не понимает читаемость. var применяется, если переменная уничтожается через шесть строк. Определять переменную через var и затем использовать на следующей странице будет очень плохо, я согласен O>В Си тоже макросы добавили во имя благих целей...
Так давай отделим мух от катлет и часть языка от макросов. Макросы в С плохи не по тому что они скрывают что-то, а по тому что они не учитывают другие синтаксические конструкции языка и заменяют что попало например макросы min/max из windows.h очень портят нервы когда пытаешься использовать STL и WinAPI совмесно. (особенно пока не знаешь про NOMINMAX)
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
В умных средах это кстати уже есть, только с другой стороны: набираем имя класса, имя переменной, "= new ", Ctrl+Shift+Space и получаем все _совместимые_ типы.
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, Oyster, Вы писали:
Кё>>>Я специально оговорил — только если это не понимает читаемость. var применяется, если переменная уничтожается через шесть строк. Определять переменную через var и затем использовать на следующей странице будет очень плохо, я согласен O>>В Си тоже макросы добавили во имя благих целей... WH>Так давай отделим мух от катлет и часть языка от макросов. Макросы в С плохи не по тому что они скрывают что-то, а по тому что они не учитывают другие синтаксические конструкции языка и заменяют что попало например макросы min/max из windows.h очень портят нервы когда пытаешься использовать STL и WinAPI совмесно. (особенно пока не знаешь про NOMINMAX)
Мух от котлет? Запросто. Строк через 50 кода мы уже забудем, что у нас там в переменной auto x, поэтому можем свято верить, что вызываем один метод, хотя вызовем другой (спасибо программеру Джону, он переопределил значение, возвращаемое методом GetSth() и теперь auto x = GetSth() содержит значение не типа A, а типа B).
Здравствуйте, Кодёнок, Вы писали:
Кё>В качестве компромисса можно сделать его фичей IntelliSense. Т.е. вы пишете var, вместо которого редактор подставляет имя типа.
Лучше наоборот — по левой части предлагать соответствующие подсказки длоя правой. Кстати о new — современные редакторы после new предлагают список конструкторов в соответствии с типом левой части выражения, так что напрактике его (new) отмена приведет только к большей трудоемкости набора кода.
Кё>>В качестве компромисса можно сделать его фичей IntelliSense. Т.е. вы пишете var, вместо которого редактор подставляет имя типа.
AVK>Лучше наоборот — по левой части предлагать соответствующие подсказки длоя правой. Кстати о new — современные редакторы после new предлагают список конструкторов в соответствии с типом левой части выражения, так что напрактике его (new) отмена приведет только к большей трудоемкости набора кода.
Что-то я глубоко сомневаюсь, что IntelliSense когда-нибудь сможет предложить `Some.Namespace.daFunction(new System.Drawing.Point(30,5))` в качестве правой части
Здравствуйте, Oyster, Вы писали:
O>>IMHO: var в C# не место.
O>... и Да здравствует строгая типизация!
Советую обратить внимание на языки с системой типов Хиндлей-Миллнера (с выведением типов, естественно). Сдается мне, это то, что вы тут неявно обсуждаете.
Здравствуйте, WFrag, Вы писали:
O>>... и Да здравствует строгая типизация!
WF>Советую обратить внимание на языки с системой типов Хиндлей-Миллнера (с выведением типов, естественно). Сдается мне, это то, что вы тут неявно обсуждаете.
Не совсем (или совсем не). В C#-то уже другая система типов.
Здравствуйте, Кодёнок, Вы писали:
Кё>Что-то я глубоко сомневаюсь, что IntelliSense когда-нибудь сможет предложить `Some.Namespace.daFunction(new System.Drawing.Point(30,5))` в качестве правой части
Где именно? Если после new, то без проблем, если саму функцию, то тоже проблем особых нет.
Здравствуйте, Кодёнок, Вы писали:
Кё>Что-то я глубоко сомневаюсь, что IntelliSense когда-нибудь сможет предложить `Some.Namespace.daFunction(new System.Drawing.Point(30,5))` в качестве правой части
ReSharper поставь.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Oyster, Вы писали:
WF>>Советую обратить внимание на языки с системой типов Хиндлей-Миллнера (с выведением типов, естественно). Сдается мне, это то, что вы тут неявно обсуждаете.
O>Не совсем (или совсем не). В C#-то уже другая система типов.
Не знаю, не знаю. Очень похоже.
Тоже есть квантор A, также только на самом внешнем уровне (дженерики). Типовые переменные также могут принимать значения только типов без кванторов (т.е параметром дженерика нельзя передать дженерик). Вводится два способа создания подтипов — наследование классов и абстракция.
AndrewVK,
AVK>Лучше наоборот — по левой части предлагать соответствующие подсказки длоя правой. Кстати о new — современные редакторы после new предлагают список конструкторов в соответствии с типом левой части выражения, так что напрактике его (new) отмена приведет только к большей трудоемкости набора кода.
Кстати, эти интеллектуальные подсказчики используют то, что слово new входит в язык. При отсутствии ключевого слова new подсказчикам просто нужно смотреть по-другому, чтобы вывести такие подсказки. Более того, даже не нужно выяснять, можно ли в данном конкретном месте программы создавать экземпляры объектов. Достаточно выяснить, возможен ли идентификатор типа в данном месте, и какие ограничения на этот тип.
Например:
MyClass c = a + <подсказка>;
В месте обозначенном <подсказка> возможен идентификатор типа. Какого типа? Любого типа, который фигурирует в перегруженном операторе "+" для класса объекта a в качестве второго параметра.
Ну или на худой конец, создание объекта повесить на отдельный шорткат.
Здравствуйте, WFrag, Вы писали:
O>>Не совсем (или совсем не). В C#-то уже другая система типов.
WF>Не знаю, не знаю. Очень похоже.
WF>Тоже есть квантор A, также только на самом внешнем уровне (дженерики). Типовые переменные также могут принимать значения только типов без кванторов (т.е параметром дженерика нельзя передать дженерик). Вводится два способа создания подтипов — наследование классов и абстракция.
WF>По-моему, оно. Или нет?
А как быть с интерфейсами? Имхо множественное наследование и явная реализация интерфейсов в C# не дают возможности всегда вывести тип. Та же фигня с ключёвым словом new для члена в наследнике (прерывание наследования).
Здравствуйте, L.C.R., Вы писали:
LCR>Кстати, эти интеллектуальные подсказчики используют то, что слово new входит в язык. При отсутствии ключевого слова new подсказчикам просто нужно смотреть по-другому, чтобы вывести такие подсказки.
Точно такие не получится. К примеру когда я пишу MyClass mc = new и нажимаю пробел, то мне вываливается список всех доступных конструкторов MyClass (если он конечно не абстрактный или не является интерфейсом). А вот в варианте с опущенным new однозначно определить, что речь идет о конструкторе, можно только после того как наберешь MyClass mc = MyClass(, а в таком разе уже и подсказывать нечего. Итого — вариант без new в современном IDE требует больше ручной работы.
LCR> Более того, даже не нужно выяснять, можно ли в данном конкретном месте программы создавать экземпляры объектов. Достаточно выяснить, возможен ли идентификатор типа в данном месте, и какие ограничения на этот тип.
LCR>Например: LCR>
LCR>MyClass c = a + <подсказка>;
LCR>
LCR>В месте обозначенном <подсказка> возможен идентификатор типа. Какого типа? Любого типа, который фигурирует в перегруженном операторе "+" для класса объекта a в качестве второго параметра.
Бесполезная подсказка. Сложение с вызовом конструктора используется довольно редко, чаще это константа или другая переменная.
LCR>Ну или на худой конец, создание объекта повесить на отдельный шорткат.
Здравствуйте, Oyster, Вы писали:
O>А как быть с интерфейсами? Имхо множественное наследование и явная реализация интерфейсов в C# не дают возможности всегда вывести тип.
O>Та же фигня с ключёвым словом new для члена в наследнике (прерывание наследования).
Здравствуйте, Александр Сергеевич, Вы писали:
АС>Этим. Тем что обычная функция(конструктор ведь тоже функция) не может совпадать с именем класса...
Вот полностью рабочий пример:
class Test { }
class Program
{
static Test Test() { return new Test(); }
static void Main(string[] args)
{
Test test = Test();
}
}
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Трурль, Вы писали:
Т>А зачем их различать?
1. Чтобы обеспечить различие между вызовом конструктора и функции.
2. Чтобы сократить количество мест где может возникнуть перегрузка.
Если уж говорить об улучшении синтаксиса... то я бы скорее подумал о том, чтобы заменить С-ишное приведение типов на функциональный вид. Вот тут действительно разница не велика, а функциональный вид удобнее.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Дарней, Вы писали:
Д>нет, несогласны. Что здесь действительно избыточно — так это двойное повторение MyClass
Согласен. Намного было бы удобнее если бы язык сильнее пользовался бы выводом типов. Например, можно было бы ввести конструкцию def. Тогда объявление переменной можно было бы сделать так:
def myVariable = new SomeVeryLongNamespace.SomeVeryBigType();
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Александр Сергеевич, Вы писали:
АС>>Этим. Тем что обычная функция(конструктор ведь тоже функция) не может совпадать с именем класса... VD>Вот полностью рабочий пример: VD>
VD>class Test { }
VD>class Program
VD>{
VD> static Test Test() { return new Test(); }
VD> static void Main(string[] args)
VD> {
VD> Test test = Test();
VD> }
VD>}
VD>
Да... жеска, не думал что так можно
Ну значит запретить такую ситуацию надо при отключении new.
[... skipped ...]
АС>Да... жеска, не думал что так можно АС>Ну значит запретить такую ситуацию надо при отключении new.
И как ты себе это представляешь? Запретить давать мемберу класса такое же имя, как имя любого другого класса из любой сборки в references? Или обязательно обращаться к статическим мемберам класса через имя класса, а к мемберам инстанса — через this (гемморой не меньше)?
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Дарней, Вы писали:
Д>>нет, несогласны. Что здесь действительно избыточно — так это двойное повторение MyClass
VD>Согласен. Намного было бы удобнее если бы язык сильнее пользовался бы выводом типов. Например, можно было бы ввести конструкцию def. Тогда объявление переменной можно было бы сделать так: VD>
VD>def myVariable = new SomeVeryLongNamespace.SomeVeryBigType();
VD>
Тогда лучше если есть дефолтный конструктор, вместо = new SomeVeryLongNamespace.SomeVeryBigType(); писать так:
def myVariable;
myVariable.DoSmth();
Кстати в случае def myVariable = new SomeVeryLongNamespace.SomeVeryBigType(), myVariable будет иметь тип SomeVeryLongNamespace.SomeVeryBigType.
А если надо так:
public class MyClass: BaseClass
{}
BaseClass bc = new MyClass();
Здравствуйте, Oyster, Вы писали:
O>Здравствуйте, Александр Сергеевич, Вы писали:
O>[... skipped ...]
АС>>Да... жеска, не думал что так можно АС>>Ну значит запретить такую ситуацию надо при отключении new.
O>И как ты себе это представляешь? Запретить давать мемберу класса такое же имя, как имя любого другого класса из любой сборки в references?
Угу
Здравствуйте, Александр Сергеевич, Вы писали:
АС>Да... жеска, не думал что так можно АС>Ну значит запретить такую ситуацию надо при отключении new.
Лучше пусть будет new. По жизни он не мешает. Вот что действительно нужно было бы добавить, так это упрощенную инициаилизацию массивов и вывод типо. Это бы действительно сделало бы код короче и проще.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
AndrewVK,
AVK>Точно такие не получится. К примеру когда я пишу MyClass mc = new и нажимаю пробел, то мне вываливается список всех доступных конструкторов MyClass (если он конечно не абстрактный или не является интерфейсом). А вот в варианте с опущенным new однозначно определить, что речь идет о конструкторе, можно только после того как наберешь MyClass mc = MyClass(, а в таком разе уже и подсказывать нечего. Итого — вариант без new в современном IDE требует больше ручной работы.
(По-прежнему в предположении, что отсутствует new). Я набираю =, мне вываливается список типов и объектов, которые подходят сюда. Из типов — это:
1. Тип в левой части или его производный
2. Типы, содержащие статические методы, которые возвращают тип в левой части или его производный.
Второй пункт можно не реализовывать — пользы ноль, а тормоза будут хорошие.
Затем я выбираю нужный тип и подсказчик меня приглашает ввести параметры конструктора.
Что не так?
AVK>Бесполезная подсказка. Сложение с вызовом конструктора используется довольно редко, чаще это константа или другая переменная.
Я этот пример привёл как демонстрацию того, где может появиться идентификатор типа (у нас как бы new уже нет ). То есть я, говоря "возможен", подразумеваю, "да, существующие объекты, константы, но ещё возможен и конструктор подходящего типа".
LCR>>Ну или на худой конец, создание объекта повесить на отдельный шорткат. AVK>Неудобно и нелогично.
Удобство — реальность субъективная, относительная, и неоднородна во времени.
АС>Тогда лучше если есть дефолтный конструктор, вместо = new SomeVeryLongNamespace.SomeVeryBigType(); писать так: АС>
АС>def myVariable;
АС>myVariable.DoSmth();
АС>
Так лучше не писать. Все же намерения лучше выражать явно. У тебя не указан тип переменный. Вывести его в данном случае не откуда. Я же привел пример вывода типа. Когда тип одного выражения выводится из другого. Информации при этом не теряется и язык меняется незначительно.
АС>Кстати в случае def myVariable = new SomeVeryLongNamespace.SomeVeryBigType(), myVariable будет иметь тип SomeVeryLongNamespace.SomeVeryBigType. АС>А если надо так: АС>
АС>public class MyClass: BaseClass
АС>{}
АС>BaseClass bc = new MyClass();
АС>
Если надо так, то так и пиши. def — это возможность не писать информации которая уже есть. Если информации нехватает, то ее нужно задать явно.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, L.C.R., Вы писали:
LCR>(По-прежнему в предположении, что отсутствует new). Я набираю =, мне вываливается список типов и объектов, которые подходят сюда. Из типов — это: LCR>1. Тип в левой части или его производный LCR>2. Типы, содержащие статические методы, которые возвращают тип в левой части или его производный.
Почему статические? instance методы тоже. А еще все поля и локальные переменные того же или совместимого типа. То есть список получается весьма нехилый, в то время как список конструкторов обычно очень небольшой.
AndrewVK,
LCR>>(По-прежнему в предположении, что отсутствует new). Я набираю =, мне вываливается список типов и объектов, которые подходят сюда. Из типов — это: LCR>>1. Тип в левой части или его производный LCR>>2. Типы, содержащие статические методы, которые возвращают тип в левой части или его производный.
AVK>Почему статические? instance методы тоже. А еще все поля и локальные переменные того же или совместимого типа. То есть список получается весьма нехилый, в то время как список конструкторов обычно очень небольшой.
(Ой, про "свои" методы и прочее забыл). Согласен, список будет большой. Поэтому я и подумал, что можно и этот пункт не реализовывать.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>По-моему, обсуждаемое комитетом auto, все-таки, лучше... ПК>
ПК>auto c = new MyClass(10,20);
ПК>
Ага. Вот только ради повторного использования ключевых слов не стоит так уж коверкать язык. auto тут как то совсем не к месту. Лучше было ввести новое ключевое слово.
Я конечно понимаю, что есть проблемы совместимости, но все же какой-нить var или def был бы умеснее.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Кодёнок, Вы писали:
AVK>>Лучше наоборот — по левой части предлагать соответствующие подсказки длоя правой. Кстати о new — современные редакторы после new предлагают список конструкторов в соответствии с типом левой части выражения, так что напрактике его (new) отмена приведет только к большей трудоемкости набора кода.
Кё>Что-то я глубоко сомневаюсь, что IntelliSense когда-нибудь сможет предложить `Some.Namespace.daFunction(new System.Drawing.Point(30,5))` в качестве правой части
А я знаю мегазаклинание introduce variable Оно еще и название для переменной предложит выбрать...
> Ага. Вот только ради повторного использования ключевых слов не стоит так уж коверкать язык. auto тут как то совсем не к месту.
Почему? Автоматический вывод типа — вроде, нормально... В своем первоначальном значении auto уже не используется, соответственно вполне можно использовать его для этой цели
> Я конечно понимаю, что есть проблемы совместимости, но все же какой-нить var или def был бы умеснее.
А var или def чем лучше?
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Почему? Автоматический вывод типа — вроде, нормально...
Не у всех столь богатая фантазия. А почему не автоматически подсчитывать ссылки? В D вроде бы авто именно так используется.
ПК> В своем первоначальном значении auto уже не используется, соответственно вполне можно использовать его для этой цели
Можно. Но все же нужно и о людях подумать. Зачем их удивлять то?
ПК>А var или def чем лучше?
Понятно и привычно. Все же не первый язык их использует.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2,
> ПК> А var или def чем лучше? > > Понятно и привычно. Все же не первый язык их использует.
def в Питоне вообще для других целей используется... var в тех языках, которые пришли мне в голову, тоже не говорит об автоматическом выводе типа из инициализатора, а просто обозначает определение переменной... В общем, пока я не вижу каких-либо серьезных аргументов ни за то, ни за другое...
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Трурль, Вы писали:
Т>>А зачем их различать?
VD>1. Чтобы обеспечить различие между вызовом конструктора и функции.
Хороший ответ на вопрос "зачем различать вызов конструкции и функции". Написал бы проще: "а шоб было".
VD>2. Чтобы сократить количество мест где может возникнуть перегрузка.
Хе-хе. А зачем их сокращать? И на сколько оно сокращается?
Здравствуйте, Andrei N.Sobchuck, Вы писали:
ANS>Хороший ответ на вопрос "зачем различать вызов конструкции и функции". Написал бы проще: "а шоб было". ANS>Хе-хе. А зачем их сокращать? И на сколько оно сокращается?
Ответы на эти вопросы мне кажутся очевидными. Чтобы не было каши вместо кода.
... << RSDN@Home 1.2.0 alpha rev. 516>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>VladD2,
>> ПК> А var или def чем лучше? >> >> Понятно и привычно. Все же не первый язык их использует.
ПК>def в Питоне вообще для других целей используется...
def появился не в питоне и умрет не в нем.
ПК> var в тех языках, которые пришли мне в голову, тоже не говорит об автоматическом выводе типа из инициализатора, а просто обозначает определение переменной...
var — это стандартный префикс описания переменных еще с Паскля (если не раньше).
ПК> В общем, пока я не вижу каких-либо серьезных аргументов ни за то, ни за другое...
В общем, ты никогда ничего не видишь... если очень того не захочешь.
... << RSDN@Home 1.2.0 alpha rev. 516>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Andrei N.Sobchuck, Вы писали:
ANS>>Хороший ответ на вопрос "зачем различать вызов конструкции и функции". Написал бы проще: "а шоб было". ANS>>Хе-хе. А зачем их сокращать? И на сколько оно сокращается?
VD>Ответы на эти вопросы мне кажутся очевидными. Чтобы не было каши вместо кода.
Не увиливай, не в военкомате. (с)
Чтобы сократить количество мест где может возникнуть перегрузка.
Мне достаточно маленького примера каши вместо кода.
Здравствуйте, VladD2, Вы писали:
ПК>> var в тех языках, которые пришли мне в голову, тоже не говорит об автоматическом выводе типа из инициализатора, а просто обозначает определение переменной...
VD> var — это стандартный префикс описания переменных еще с Паскля (если не раньше).
Нужно ключевое слово, обозначающее автоматический вывод типа, а не являющееся признаком объявления переменной. Не вижу, каким образом var справляется с первой задачей лучше, чем auto...
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
VD>И чем это будет отличаться от вызова функции?
Именем. Вряд ли кому-то взбредет в голову называть функцию "MyClass".
К тому же, что касается Джавы, то там есть общепринятая Naming Convention, в сообветствии с которой классы называются в "паскале", а методы в "кемеле".
Здравствуйте, IT, Вы писали:
IT>AVK, не веди себя как беспощадный компилятор. Ну ошибся человек, но из контекста же понятно что имеется ввиду
А честно не понял. По началу тоже подумал про throw, но потом внимательнее поглядел и увидел return, чем весьма удивился, потому что не понял в чем совтсвенно хитрость.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Нужно ключевое слово, обозначающее автоматический вывод типа, а не являющееся признаком объявления переменной. Не вижу, каким образом var справляется с первой задачей лучше, чем auto...
Трурль,
ПК>>Нужно ключевое слово, обозначающее автоматический вывод типа, а не являющееся признаком объявления переменной. Не вижу, каким образом var справляется с первой задачей лучше, чем auto...
Т>Ну, можно попробовать let
Да, type inference by ocaml очень симпатичная вещь. Правда и там есть минусик:
let a = 1.0 +. float_of_int 1;;
Вот эти козявки +. и float_of_int портят всю красоту
Здравствуйте, eugals, Вы писали:
VD>>И чем это будет отличаться от вызова функции? E>Именем. Вряд ли кому-то взбредет в голову называть функцию "MyClass". E>К тому же, что касается Джавы, то там есть общепринятая Naming Convention, в сообветствии с которой классы называются в "паскале", а методы в "кемеле".
1. На яве свет клином не сошелся. В Шарпе конвенции как раз такие что имена методов и классов все пишутся в паскальных соглашениях.
2. Это не застрахует просто не верного названия. Конвенции соблюдают далеко не все.
3. Вместо MyClass в программе может быть Xyz и можно будет долго потом бить себя в грудь и обзывать всех ламерами.
В общем, пустой разговор. Проблем в написании ключевого слова нет. Места оно занимает не много. Это поведение совпадает с С++ и тем самым позволяет проще переходить на Шарп с этого языка. Так что обсуждать особо нечего. Эдак можно до чего хочешь докапаться.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Нужно ключевое слово, обозначающее автоматический вывод типа, а не являющееся признаком объявления переменной. Не вижу, каким образом var справляется с первой задачей лучше, чем auto...
var просто понятно. А auto нет. Только и всего. Конечно зазубрив что auto == объявлению переменной дальше можнобудет жить спокойно. Но интуитивности это не прибавит и язык будет изучать еще сложнее. В прочем это уже капля в море. К тому же не факт что пойдет даже это предложение.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2,
VD>>>И чем это будет отличаться от вызова функции? E>>Именем. Вряд ли кому-то взбредет в голову называть функцию "MyClass".
VD>1. На яве свет клином не сошелся. В Шарпе конвенции как раз такие что имена методов и классов все пишутся в паскальных соглашениях. VD>2. Это не застрахует просто не верного названия. Конвенции соблюдают далеко не все. VD>3. Вместо MyClass в программе может быть Xyz и можно будет долго потом бить себя в грудь и обзывать всех ламерами.
Так то оно так, но конвенции о наименованиях суть следствия синтаксиса языка. Не содержал бы шарп new — конвенции (возможно) были бы другими.
VD>В общем, пустой разговор. Проблем в написании ключевого слова нет. Места оно занимает не много. Это поведение совпадает с С++ и тем самым позволяет проще переходить на Шарп с этого языка. Так что обсуждать особо нечего. Эдак можно до чего хочешь докапаться.
Шарп с Джавой конечно уже не переделаешь, а вот при создании своего языка может пригодиться.
Здравствуйте, L.C.R., Вы писали:
LCR>Так то оно так, но конвенции о наименованиях суть следствия синтаксиса языка. Не содержал бы шарп new — конвенции (возможно) были бы другими.
Возможно. Как и возможно, что были бы такими же. В конце концов Ява тоже new имеет, но конвенции несколько отличаются.
LCR>Шарп с Джавой конечно уже не переделаешь, а вот при создании своего языка может пригодиться.
Языков без new хватет. Та же Дельфи.
Мне другое поражает. Зачем докапываться до невызывающих проблем вещей когда полно действительно неудобных? Например, в классах приходится называть конструтктор именем класса. Проблем от этого море. А ведь можно было бы назвать "Constructor" и проблем бы небыло. Или вот в Шарпе неудобно инициализировать статически инициализируемые массивы если тип элемента не встроенных примитив.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2,
LCR>>Шарп с Джавой конечно уже не переделаешь, а вот при создании своего языка может пригодиться. VD>Языков без new хватет. Та же Дельфи.
Создавать свой язык приходится тогда, когда существующие языки подходят негладко к проблемной области. Дельфи — лишь один из многих "неподходящих гладко".
VD>Мне другое поражает. Зачем докапываться до невызывающих проблем вещей когда полно действительно неудобных? Например, в классах приходится называть конструтктор именем класса. Проблем от этого море. А ведь можно было бы назвать "Constructor" и проблем бы небыло. Или вот в Шарпе неудобно инициализировать статически инициализируемые массивы если тип элемента не встроенных примитив.
Take it easy. Меня только интересовал вопрос, потеряет ли что-нибудь язык, если выкинуть из него new. Этот вопрос пришёл мне в голову, когда я разглядывал результаты эксперимента Nemerle. В этом языке есть любопытные моменты, и в частности есть type inference и при создании объектов не нужен new:
[c#]
new Class (parms) // C#
Class (parms) // Nemerle
[c]
xxx: Пожалуй имеет смысл предупредить о следующем: я не собираюсь развязывать войну Nemerle vs All — это только эксперимент. Могу только сказать, что я планирую пост о возможностях этого языка.
Здравствуйте, L.C.R., Вы писали:
LCR>Создавать свой язык приходится тогда, когда существующие языки подходят негладко к проблемной области. Дельфи — лишь один из многих "неподходящих гладко".
DSL?
LCR>Take it easy. Меня только интересовал вопрос, потеряет ли что-нибудь язык, если выкинуть из него new.
Потеряет. Язык спроектирован в рассчете на использование new. И по-моему ничего ровным счетом не приобретет.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Никогда не использовал. Маленького своего джарчика в каталоге lib хватает за глаза. Но гляну на досуге.
LCR>>Take it easy. Меня только интересовал вопрос, потеряет ли что-нибудь язык, если выкинуть из него new.
VD>Потеряет. Язык спроектирован в рассчете на использование new. И по-моему ничего ровным счетом не приобретет.
Ну в-общем посмотрел я в хистори форума и в сети — понял только, что DSL — это нечто аморфное и неконкретное, вообще непонятно что. Что ты имел ввиду-то, говоря "DSL"?
Здравствуйте, L.C.R., Вы писали:
LCR>Ну в-общем посмотрел я в хистори форума и в сети — понял только, что DSL — это нечто аморфное и неконкретное, вообще непонятно что. Что ты имел ввиду-то, говоря "DSL"?
AndrewVK,
LCR>>Ну в-общем посмотрел я в хистори форума и в сети — понял только, что DSL — это нечто аморфное и неконкретное, вообще непонятно что. Что ты имел ввиду-то, говоря "DSL"?
AVK>http://en.wikipedia.org/wiki/Domain_Specific_Language
Во-во, я и говорю — аморфное. Это не язык вовсе, а видимо некоторое направление в программировании. Кроме того, у меня возникает ощущение, что большинство программистов используют DSL в своей работе, даже не подозревая об этом. Этот "DSL" — это семейство классов, функций и переменных. Domain Specific? Безусловно. Language? Да!
Впрочем, к new это уже имеет отдалённое отношение.
Здравствуйте, L.C.R., Вы писали:
LCR>Во-во, я и говорю — аморфное. Это не язык вовсе, а видимо некоторое направление в программировании.
Язык, язык.
LCR> Кроме того, у меня возникает ощущение, что большинство программистов используют DSL в своей работе, даже не подозревая об этом. Этот "DSL" — это семейство классов, функций и переменных. Domain Specific? Безусловно. Language? Да!
Нет. Классы есть классы. Например, код эффективного парсера — это огромная куча функций (а может и классов) понять которую очень не просто. А вот граматика записанная в EBNF — это очено даже понятная вещь. Так вот EBNF — это и есть DSL. А генератор парсеров — это транслятор переводящий этот DSL в язык общего назначения для последующей компиляции.
В общем, идея простая. Мы создаем очень высокоуровневый язык за счет того, что затачиваем его на решение конкретных проблем. А потом создаем нечто позволяющее выполнять этот язык или преобрзовывать в менее специализированный.
... << RSDN@Home 1.2.0 alpha rev. 591>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, L.C.R., Вы писали:
LCR>xxx: Пожалуй имеет смысл предупредить о следующем: я не собираюсь развязывать войну Nemerle vs All — это только эксперимент. Могу только сказать, что я планирую пост о возможностях этого языка.
И как реализация планов?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, L.C.R., Вы писали:
LCR>Речь пойдет о new.
LCR>Наши любимые C# и Java имеют избыточный синтаксис для создания объекта — оба этих языка используют ключевое слово new для создания объектов в куче. Спрашивается, зачем оно (ключевое слово) нужно, если всё равно создавать на стеке объекты ссылочных типов невозможно, так что приписывание лишнего new не несёт никакого дополнительного смысла.
LCR>Не лучше ли использовать просто: LCR>
LCR>MyClass c = MyClass(10, 20);
LCR>
Это не просто -- это сложно.
Просто -- вот.
MyClass c(10, 20);
LCR>В Джаве new было введено исключительно по политическим причинам, чтобы облегчить переход C++ программистов на Джаве облегчив им узнавание привычных конструкций (создание объектов в куче). В Шарп, вероятно, new было содрано с Джавы, дабы облегчить переход C++ и Джава — программистов на Шарп
LCR>Вопрос: согласны ли вы, что new избыточен? Нет ли каких-нибудь синтаксических косяков (гипотетическое) исключение new из этих языков?
Избыточен. Посто Майкрософт старалась как лучше, а получилось как всегда.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Здравствуйте, Шахтер, Вы писали:
Ш>>Это не просто -- это сложно. Ш>>Просто -- вот. Ш>>
Ш>>MyClass c(10, 20);
Ш>>
СГ>У объектной переменной есть два типа — статический и динамический. СГ>Запись, навроде такой:
СГ>MyAbstractBaseClassOrInterface obj = new MyExtensionConcreteClass(params...);
СГ>позволяет указать сразу два типа.