Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, agat50, Вы писали:
A>>http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/6504697-block-code-as-value-another-syntax-for-semicolon A>>Ага, хорошо бы. S>А нафига? Ну, кроме как "в других языках есть"?
S>Не, серьёзно, зачем портить язык, добавляя 100500й способ сделать то же самое, только на пару символов короче? Не, для write-only кода, который никогда читать не будут, а сразу выбросят и перепишут, оно может и удобно.
S>Для нормального человека в чём кайф ловить разницу между S>
S>public int F(int a) =>
S>(
S> Console.WriteLine(a);
S> a + 1
S>)
S>// и
S>public int F(int a)
S>{
S> Console.WriteLine(a);
S> return a + 1;
S>}
S>
Нафиг, согласен.
S>?
A>> Ну возвращать последнее выражение видимо уже невозможно, поведение сильно поменяет. А так конечно локальных функций нормальных не хватает иногда. S>
S>Func<int, int> x = i => { ... };
S>
S>?
И это писать в каждом таком применении (а там может быть совсем не инт а что-то монстрообразное). Ну если пример с if чисто чтобы был для описания, то ситуация вида создал переменную, создал ресурс, записал в переменную, закрыл ресурс, работаешь с переменной дальше — ну просто на каждом шагу. Приходится постоянно писать отдельно объявление и присвоение из-за областей видимости. В объявлении соотвественно хрен напишеш var. Хорошо ещё решарпеп помогает быстро var менять на точный класс.
int a =
lock(dataInstance)
{
return dataInstance.Member1;
};
vs
int a = (Func<int>)(
() => {
lock(dataInstance)
{
return dataInstance.Member1;
};
})();
Мне очевидно что первое короче не на "два символа".
Здравствуйте, agat50, Вы писали:
A>И это писать в каждом таком применении (а там может быть совсем не инт а что-то монстрообразное). Ну если пример с if чисто чтобы был для описания, то ситуация вида создал переменную, создал ресурс, записал в переменную, закрыл ресурс, работаешь с переменной дальше — ну просто на каждом шагу.
Не, с lock тут пример абсолютно бесполезен, что с ним, что без него — одинаково. С "using что-нибудь" лучше смотреться будет.
Угу, проблема. Причём в общем случае: код в using большой, или надо вернуть больше одной переменной — красиво не решается. Я на практике с такой необходимостью не сталкивался, поэтому ничего предложить не могу. Ну, кроме метода Eval. Вместе с using static будет примерно так:
var a = Eval(() => { using (var x = GetX()) return x.y; });
Для любителей извращений — заменить на
var a = λ(() => { using (var x = GetX()) return x.y; });
и пойдёт.
A>Мне очевидно что первое короче не на "два символа".
Ну а
int a;
lock(dataInstance)
{
a = dataInstance.Member1;
};
S>var a = Eval(() => { using (var x = GetX()) return x.y; });
S>
Ну в целом да Обойти понятно можно. Просто выглядит чуть искусственно.
Про возврат нескольких переменных, так всеми желаемый PM и т.п. — имхо нужна просто возможность тонкой настройки области видимости переменной, очень много решит. https://roslyn.codeplex.com/discussions/552375 вариант с out, хотя сейчас я мб уже к какой-нибудь нормальной директиве типа using в объявлении.
object x = Foo();
if(
x is A
&&
{
//Компилятор сам переносит объявление куда нужно
#using(var a, SCOPES_OUTER) = 5;
return true;
}
)
{
Console.WriteLine("{0}", a);
}
Определять тип в var из первого присваивания.
#using(var a, INFERENCE_LAZY);
a = 5;
склоняюсь для разнообразия. Не то чтобы оно было часто надо, но имхо одной фичей бы убили много зайцев. И в IDE анализировать возможные not initialized проще имхо.
Здравствуйте, agat50, Вы писали:
A>И это писать в каждом таком применении (а там может быть совсем не инт а что-то монстрообразное). Ну если пример с if чисто чтобы был для описания, то ситуация вида создал переменную, создал ресурс, записал в переменную, закрыл ресурс, работаешь с переменной дальше — ну просто на каждом шагу. Приходится постоянно писать отдельно объявление и присвоение из-за областей видимости. В объявлении соотвественно хрен напишеш var. Хорошо ещё решарпеп помогает быстро var менять на точный класс.\
A>vs A>
A>int a = (Func<int>)(
A> () => {
A> lock(dataInstance)
A> {
A> return dataInstance.Member1;
A> };
A> })();
A>
A>Мне очевидно что первое короче не на "два символа".
Тут проблема другого рода, а именно слабый вывод типов.
Зато компилятор быстро работает
C# не позволяет выводить тип из использования, т.е.:
var a = x => x + 1;
var b = a(1); // выводит Func<int, int> a
Здравствуйте, _NN_, Вы писали:
_NN>Тут проблема другого рода, а именно слабый вывод типов. _NN>Зато компилятор быстро работает _NN>C# не позволяет выводить тип из использования, т.е.:
_NN>
_NN>var a = x => x + 1;
_NN>var b = a(1); // выводит Func<int, int> a
_NN>
Ну вывести тип для Func<TRes> (Ну и Func<Task<TRes>> в свете асинков) без единого параметра вроде не представляет никакой сложности, просто синтаксис добавить. Мне больше и не надо. Тут в общем речь и не о лямбдах\делагатах, скорее просто чуть другая запись кода.
Здравствуйте, VladD2, Вы писали: X>>В нашем вот проекте (как и во многих проектах на прошлых работах) будет очень полезна, и вот почему — архитектура у нас такая многослойная, как лук и на границе между слоями как правило имеются методы
X>>try {
X>> // Что-то делаем на более низком уровне
X>>} catch(Exception ex) {
X>> Log(ex);
X>> throw;
X>>}
VD>И причем тут фильтры?
Выставите отладчику вываливаться на любое брошенное исключение и запустите этот код
Здравствуйте, xy012111, Вы писали:
X>В первом методе вас будет выбрасывать в отладчик на каждый throw, а во-втором — только на первый в Do. Отлаживать сильно удобнее.
То есть вместо того чтобы чуть-чуть доработать отладчик лучше тратить уйму сил на изменение языка?
ЗЫ
Возникает еще один вопрос, зачем перехватывать исключения где попало? Их же можно перехватить ближе к корню колстека. Тогда и проблемы такой не возникнет. У меня вот за 12 лет использования дотнета таких проблем не возникло.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
More libraries. Consider the subset we have today a down-payment on what is to come. Our goal is to open source the entire .NET Core library stack by Build 2015.
Собственно в этом вся интрига.
Оптимистичный вариант: на build "перережут ленточку" и заопенсорсят одновременно вместе с релизом.
Реалистичный: на build — исходники в опенсорс + очередное preview, релиз — осенью.
UPD: то, что скорее всего перейдёт в .net core, можно посмотреть тут.
Здравствуйте, Sinix, Вы писали:
S>Оптимистичный вариант: на build "перережут ленточку" и заопенсорсят одновременно вместе с релизом. S>Реалистичный: на build — исходники в опенсорс + очередное preview, релиз — осенью.
Я этого не говорил, но на билде будет первый превью .NET Core, в том числе и работающий на Х-платформах.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
Здравствуйте, VladD2, Вы писали:
VD>В отличии от Nemerle и F#, в C# не поддерживается концепция "все является выражением", по этому везде приходится пихать return. Фигурные скобки и return вкупе дают довольно значительный синтаксический шум. Вот авторы C# и решили подсакратить таковой позволим записывать мелкие методы в одну строку.
Когда необходимо документироавть каждый метод (описание метода, его параметров, возвращаемого значения), жертвовать единообразием кода для его сокращения на 2-3 строки — сомнительное дело.
Здравствуйте, Tesh, Вы писали:
T>Когда необходимо документироавть каждый метод (описание метода, его параметров, возвращаемого значения), жертвовать единообразием кода для его сокращения на 2-3 строки — сомнительное дело.
Зачем чего-то документировать? Чем жертвовать?
Какой-то набор предрассудков.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Зачем чего-то документировать? Чем жертвовать?
VD>Какой-то набор предрассудков.
Если код в будущем требуется поддерживать, то документация весьма полезна для того, чтобы понять что метод делает, что принимает на вход и какие ограничения имеет.
Единообразие кода также помогает в дальнейшей его поддержке и развитии. Когда ты смотришь в любую часть проекта, которая не важно кем была написана, и видишь код, написанный в одном стиле, то и поддержка сильно облегчается, как и уменьшается вероятность ошибок.
Никаких предрассудков, исключительно жизненный опыт.
Здравствуйте, Tesh, Вы писали:
T>Если код в будущем требуется поддерживать, то документация весьма полезна для того, чтобы понять что метод делает, что принимает на вход и какие ограничения имеет.
Документация полезна только для публичного API. Для понимания кода полезно внятные имена методам давать. Зачем документировать приватные методы, я не очень понимаю. Тем более, что проекты разные бывают. Когда я пишу прототип, то последнее о чем я думаю — это о документировании методов.
T>Единообразие кода также помогает в дальнейшей его поддержке и развитии.
Или замедляет процесс разработки, если в документации банальные вещи. Их нужно написать и поддерживать. А у меня метод может жить пару дней до следующего рефакторинга.
T>Когда ты смотришь в любую часть проекта, которая не важно кем была написана, и видишь код, написанный в одном стиле, то и поддержка сильно облегчается, как и уменьшается вероятность ошибок. T>Никаких предрассудков, исключительно жизненный опыт.
Однобокий опыт и рождает предрассудки. Зачем мне документировать, например, методы в прарсере? Они все отражают какие-то правила. Какие — ясно из имени метода. Все их параметры одинаковые. Причем метод может быть ровно однострочным.
В Шарпе нет локальных фукнций (как в Пасклале, Nemerle или F#) и многие используют методы просто для декомпозиции и того самого повышения читабельности кода. Именованная функция намного лучше чем комментарий в море кода. Документировать такие функции нет ни времени, ни желания, ни смысла (изменяются слишком часто, на правки документации всю жизнь убьешь).
Чем больше ты используешь функциональный стиль, тем больше у тебя методов. Тем мельче они. В итоге большая часть кода у тебя будет заниматься скобками. Ты уже не можешь взглянуть на код всего класса одним взглядом. Это понижает производительность.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Sinix, Вы писали:
S>UPD: то, что скорее всего перейдёт в .net core, можно посмотреть тут.
В репозитории corefx не могу найти определения классов Task и TaskCompletionSource. Хотя в некоторых других классах таски используются. Кто-нибудь собирал corefx? Где можно почитать реализацию этих классов? Вообще в идеале хотелось бы найти простую и переносимую реализацию Futures/Promises без всего этого многопоточного гудрона.
Здравствуйте, Qbit86, Вы писали:
Q>В репозитории corefx не могу найти определения классов Task и TaskCompletionSource. Хотя в некоторых других классах таски используются. Кто-нибудь собирал corefx? Где можно почитать реализацию этих классов? Вообще в идеале хотелось бы найти простую и переносимую реализацию Futures/Promises без всего этого многопоточного гудрона.
Здравствуйте, Qbit86, Вы писали:
Q>В репозитории corefx не могу найти определения классов Task и TaskCompletionSource.
В CoreClr надо смотреть.
Q>Вообще в идеале хотелось бы найти простую и переносимую реализацию Futures/Promises без всего этого многопоточного гудрона.
Предположим, вы её нашли. Что вы с ней собираетесь делать, особенно с учётом "без многопоточного гудрона"?
И с учётом того, что таски — это вообще-то _не_ future/promise? Это кирпичики, на которых можно построить почти любой async pattern — промайзы, пайплайн, cps, акторы, воркфлоу etc. Но не сами паттерны. Ваш кэп
Здравствуйте, Sinix, Вы писали:
Q>>Вообще в идеале хотелось бы найти простую и переносимую реализацию Futures/Promises без всего этого многопоточного гудрона. S>Предположим, вы её нашли. Что вы с ней собираетесь делать, особенно с учётом "без многопоточного гудрона"?:)
Использовать в игре на движке Unity. В геймдеве обычно игровой цикл торчит наружу, поэтому вместо push-модели событий/асинхронности часто удобно применять poll-модель (опрос результата, корутины).
S>И с учётом того, что таски — это вообще-то _не_ future/promise?
https://en.wikipedia.org/wiki/Futures_and_promises
«...A future is a read-only placeholder view of a variable, while a promise is a writable, single assignment container which sets the value of the future... In .NET 4.0 System.Threading.Tasks.Task<T> represents a read-only view [future]. Resolving the value can be done through System.Threading.Tasks.TaskCompletionSource<T> [promise].»
S>Это кирпичики, на которых можно построить почти любой async pattern — промайзы, пайплайн, cps, акторы, воркфлоу etc. Но не сами паттерны. Ваш кэп:)
А так да, для фьючерок Task'и сильно перегружены. Не говоря уже о том, что, почему-то, входят в пространство имён Threading, хотя призваны абстрагировать асинхронность от таких примитивов ОС как потоки.
Здравствуйте, Qbit86, Вы писали:
S>>И с учётом того, что таски — это вообще-то _не_ future/promise? Q>https://en.wikipedia.org/wiki/Futures_and_promises
Ну блин... грубо говоря, таски — это конструктор. Await/tpl/dataflow/orleans/etc — реализация определённых паттернов поверх этого конструктора. Не сами паттерны.
Это важно, поскольку в реализации скрывается тонна мелочей, от шедулинга и обработки исключений и до передачи контекста выполнения. Так вот, когда код описывается как "используем taskCompletionSource" — это даёт на порядок больше информации, чем "у нас тут промайзы". Особенно если человек про промайзы/таски слышит в первый раз (так хоть понятно, что искать), или если видел десятки реализаций промайзов разнообразной степени корявости.
Ну и кроме того, Task<T> — это _не_ future. На этиграбли уже пробовали наступить, по итогам отказались.
В общем, лучше не использовать в обсуждении паттерны, если не уверены, что понимание собеседника целиком и полностью совпадает с вашим пониманием. Ну, или если детали реализации в обсуждении не имеют никакого значения, что ещё реже встречается.
Q>А так да, для фьючерок Task'и сильно перегружены. Не говоря уже о том, что, почему-то, входят в пространство имён Threading, хотя призваны абстрагировать асинхронность от таких примитивов ОС как потоки.
Ну да, для велосипеда седельный тягач сильно перегружен
Таски и не заточены под "абстрагировать асинхронность", для этого IAsyncResult есть.
Здравствуйте, Sinix, Вы писали:
S>Ну блин... грубо говоря, таски — это конструктор. Await/tpl/dataflow/orleans/etc — реализация определённых паттернов поверх этого конструктора. Не сами паттерны.
Дотнетовские Таски жЫрноваты для примитивов.
S>Это важно, поскольку в реализации скрывается тонна мелочей, от шедулинга и обработки исключений и до передачи контекста выполнения.
Мне не нужны шедулинг и передача контекста выполнения.
S>Так вот, когда код описывается как "используем taskCompletionSource" — это даёт на порядок больше информации, чем "у нас тут промайзы".
Я настаиваю на транскрипции «промиcы».
S>Особенно если человек про промайзы/таски слышит в первый раз (так хоть понятно, что искать)
Промисы/фьючерки — это внеязыковые понятия. С гораздо большей вероятностью программист (даже пришедший со Scala или C++11) будет знаком с этими понятиями, чем с сишарповским TaskCompletionSource.
S>Ну и кроме того, Task<T> — это _не_ future.
Task<T> — это future на стероидах.
S>На этиграбли уже пробовали наступить, по итогам отказались.
Я и пишу: «Вообще в идеале хотелось бы найти простую и переносимую реализацию Futures/Promises без всего этого многопоточного гудрона.»