Re[10]: IIFE
От: Sinix  
Дата: 14.05.15 16:27
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>В expression bodied methods уже можно запихнуть statement'ы, завернув их в immediately-invoked function expression.


Что-то типа
int Do(int x) => DoAnything(()=>
{
  // any code
});

?

Ну да, но это именно из серии "надо намеренно извратиться"
Re[11]: IIFE
От: Qbit86 Кипр
Дата: 14.05.15 22:58
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Что-то типа

S>
int Do(int x) => DoAnything(() => {...});

S>?

Можно анонимно, как в исходной JavaScript-идиоме:
int Do(int x) => new Func<int, int>(y => {...}).Invoke(x);


S>Ну да, но это именно из серии "надо намеренно извратиться":)


А хотелось бы не извращаться, а чтобы компилятор просто поддерживал желаемый синтаксис.
Скажем, было:
private int Foo => ThirdPartyApi.ComputeValue();

И samius решил обмазаться using-expression'ом (в примере я его назвал with):
private int Foo => with (var sw = new StopwatchLogger()) ThirdPartyApi.ComputeValue();

Компилятор пусть просто генерит «IIFE-извращение»:
private int Foo => new Func<int>(() => { using (var sw = new StopwatchLogger()) return ThirdPartyApi.ComputeValue(); })();

или просто классический метод/свойство (не expression bodied).

S>Получаем правку expression trees, костыли ко всем linq-провайдерам и невозможность компиляции кода под младшие версии фреймворка.


Не получаем. Просто в expression tree вместо нашего выражения будет непрозрачный вызов метода.
Глаза у меня добрые, но рубашка — смирительная!
Re[12]: IIFE
От: Sinix  
Дата: 15.05.15 08:05
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Компилятор пусть просто генерит «IIFE-извращение»:


Ну... всё замечательно, но меня по-прежнему не отпускает мысль "но зачем???"
Что от такого изврата мы проигрываем — уже очевидно. Выигрыша нет вообще, если не считать двух сэкономленных скобок. Да и то они меняются на =>.

Не, серьёзно, это стоит того чтоб быть добавленным в язык вместо других нужных и действительно полезных вещей? Compiler team не резиновый, если они делают хотелку A, то в релиз автоматом не попадают B,C и D. Просто потому, что вместо полезной работы они искали обходы для всех дурацких последствий от A. Для всех желающих это в прямом эфире показывают. Что там с приятными мелочами типа params IEnumerable в шестом шаре?


S>>Получаем правку expression trees, костыли ко всем linq-провайдерам и невозможность компиляции кода под младшие версии фреймворка.

Q>Не получаем. Просто в expression tree вместо нашего выражения будет непрозрачный вызов метода.
Тоже вариант, но это классический пример leaked abstraction: вместо относительно понятной ошибки компиляции или рантайма пользователь сообщает ошибку от провайдера "неподдерживаемый метод". Ну, или невалидный expression tree, как повезёт.
Re[9]: [C# 7] Design notes, Mar 18
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.05.15 16:04
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>Expression Bodied Functions уже наступили на все грабли. И не я их предложил. То есть скобки и грабли с гайдлайнами не аргумент в случае Expression Bodied Functions, но почему-то аргумент в случае using...


S>Потому что exp bodied хороши для существующих выражений. А вот попытка добавить impure-выражения испортит и expression bodied тоже. Потому что смысл в них окончательно потеряется.

Не догоняю. Разве exp bodies запрещают impure-выражения? нет ведь. Все impure благополучно вставляются в exp bodies и ничего не портится. Или все что может быть испорчено, уже испорчено.


S>>Ненене, Дэвид Блейн! Не все что можно засунуть легально в expression проглотят linq-провайдеры и это не приводит к костылям. Поэтому не аргумент.

S>А, ну т.е. ешё хуже решение. Теперь у нас есть выражения для expression-tree и выражения, которые не подходят для expression-tree и всё это ещё и различается для разных версий фреймворка. Как человек, писавший хоть и наколенный, но linq-провайдер — поверьте, там и без этого геммороя хватает
Наколенный и я писал. Выражения, которые не подходят для expression-tree linq-провайдера и без того есть.
Но я всеже не о выражениях ExpressionTree, а об выражениях, которые отличаются от стейтментов. Вот есть у нас стейтмент try/finally, и он ничего не ломает, ни в какие деревья выражений его совать не надо. Этот using стейтмент умеет возвращать результат. И это опять ничего не ломает (ведь существует, и никто не жалуется на это). И о ужас! Мы даже можем вставлять try/finally в лямбду!
Так вот, единственное, что сейчас отличает try/finally (using, lock) от выражения — это фактически пара внешних скобочек {}, которая придает стейтменту форму функции.
Очередное обновление языка нам позволяет записывать функции-мемберы без скобочек, но с =>, как у лямбд. Но вот то что в лямбды мы стейтменты вставлять можем, но если мы стейтменты вставим в функции-мемберы без скобочек, то сразу добавим геморроя — вот это я не понимаю.

S>>Expression Bodied Functions потребуют утверждения стандартов кодирования. На том же ровном месте.

S>На сегодня нет. Т.к. ничего сложнее одного "?:" или linq-запроса туда не влазит. Т.е. правил достаточно тех же, что для любой одиночной строчки кода.
Туда не влазит, как я понимаю, ровно из-за того, что у стейтмента нет типа результата. Поправьте, если ошибаюсь.

S>>Работал на проектах и побольше. И мне не очевидно, почему такие проекты придется закапывать из-за using-expression.

S>Не только из-за него. Когда у тебя на руках регулярно оказывается код, который надо поддерживать, но

S>1. Единственное, что с ним можно сделать — это сжечь и засыпать солью.

S>2. Код даже трогать нельзя, т.к. он стоил несколько человеколет разработки, а код, который от него зависит — стоит эдак на порядок больше.
S>3. Исправление нужно прямсейчасиписецкаксрочно

S>решения из разряда "лишь бы не как в гадлайнах" начинаешь очень не любить

Разве я предложил что-то ломать?

S>>Вопрос был изначально не в том, что бы на кого-то повесить головную боль, а в том, не приходило ли кому в голову, не обсуждалось ли? И только лишь.

S>Обсуждалось конечно, ссылки на обсужденее более общей проблемы я в первом ответе и привёл. Вы там ещё написали "Я знаю, чем отличается выражение от стейтмента"

S>>pure и impure отлично смешиваются и без using-ов. да и никто не озаботился явной документацией pure и impure.

S>Тем не менее на сегодняшний момент в шарпе надо специально постараться, чтоб запихнуть impure-код в выражения.
MethodCallExpression не отличит pure от impure.

S>>F# как раз заточен на работу в том же рантайме и том же фреймворке, что и C#. Кейворд use в частности заточен на работу с IDisposable, сценарии использования которого в точности совпадают со сценариями его использования на C#.

S>Ну так и немерль и iron python заточены. Языками со своей концепцией и сценариями использования они от этого быть не перестали
Конечно нет, но работают они с тем же фреймворком и библиотеками, что и C#.
Re[10]: IIFE
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.05.15 16:07
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, Sinix:


Q>В expression bodied methods уже можно запихнуть statement'ы, завернув их в immediately-invoked function expression. Я так понимаю, samius'у будет достаточно сахара, не нужны хитрые expression trees.

Верно. Мне кажется что вообще у деревьев выражений и exp bodies ничего общего кроме набора букв "expression" нет. Т.е. body expression-ы мемберов никто в linq-провайдеры совать не собирается. Могу ошибаться, конечно.
Re[13]: IIFE
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.05.15 16:09
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Qbit86, Вы писали:


Q>>Компилятор пусть просто генерит «IIFE-извращение»:


S>Ну... всё замечательно, но меня по-прежнему не отпускает мысль "но зачем???"

S>Что от такого изврата мы проигрываем — уже очевидно. Выигрыша нет вообще, если не считать двух сэкономленных скобок. Да и то они меняются на =>.

А какой выигрыш от exp bodies, кроме двух сэкономленных скобок, которые заменились на => ???
Re[10]: [C# 7] Design notes, Mar 18
От: Sinix  
Дата: 15.05.15 19:36
Оценка:
Здравствуйте, samius, Вы писали:

S>Не догоняю. Разве exp bodies запрещают impure-выражения? нет ведь. Все impure благополучно вставляются в exp bodies и ничего не портится. Или все что может быть испорчено, уже испорчено.

Не запрещает конечно. Но impure-выражений на сегодня как таковых нет. Разве что спрятанные в методы, инкремент и присваивания. Но последние два сразу видно. А от первого в принципе не защитишься без отсечения части сценариев типа кэширования.

Добавление using expression будет провоцировать написание кода с побочными эффектами (потому что коду без побочных эффектов юзинг по определению не нужен). Т.е. размывать и без того нечёткую разницу между выражениями и стейтментами


S>Вот есть у нас стейтмент try/finally, и он ничего не ломает, ни в какие деревья выражений его совать не надо. Этот using стейтмент умеет возвращать результат. И это опять ничего не ломает (ведь существует, и никто не жалуется на это). И о ужас! Мы даже можем вставлять try/finally в лямбду!


Неа, это уже будет не expression-лямбда, а сокращённая запись для анонимного делегата. Потому что будет содержать statement block. Ну и соответственно, не может быть сконвертирована в expression, по крайней мере для текущей версии шарпа.

Т.е. синтаксис для юзинга добавить можно, но мы получим парадоксальную ситуацию: код
int Do() => using (SomeScope()) SomeValue();

выглядит как expression lambda но ей не является т.к. его нельзя сконвертить в expression tree.

Т.е. это statement lambda, но тогда её надо записать как
int Do() => { using (SomeScope()) return SomeValue(); }

что ещё длиннее, чем оригинальный
int Do() { using (SomeScope()) return SomeValue(); }

В общем, борьба с синтаксическим оверхедом не задалась
Сорри, что сразу не привёл это объяснение, неправильно понял твой вопрос


S>Очередное обновление языка нам позволяет записывать функции-мемберы без скобочек, но с =>, как у лямбд. Но вот то что в лямбды мы стейтменты вставлять можем, но если мы стейтменты вставим в функции-мемберы без скобочек, то сразу добавим геморроя — вот это я не понимаю.

Потому что мы запутаем клиента: выглядит как expression lambda, но на самом деле это statement lambda.

Хотя, на самом деле мы тут страдаем фигнёй. Нужен коммент от ув. Никова.


S>Конечно нет, но работают они с тем же фреймворком и библиотеками, что и C#.

Фигово работают, надо признать. Ибо привычное API для этих языков плохо укладывается в рамки CLS.
Re[14]: IIFE
От: Sinix  
Дата: 15.05.15 19:42
Оценка:
Здравствуйте, samius, Вы писали:

S>А какой выигрыш от exp bodies, кроме двух сэкономленных скобок, которые заменились на => ???


Если выйти за пределы сценария "сахар для геттеров/простых методов" — никакого. Если не выходить, то поддержка statement as expression как раз не нужна. Почему — смотрим всё обсуждение, уже раза три наверно писал
Re[13]: IIFE
От: Qbit86 Кипр
Дата: 15.05.15 19:45
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Что от такого изврата мы проигрываем — уже очевидно.


От изврата, конечно, проигрываем. И выигрываем от небольшой поддержки компилятора, которая избавит от необходимости городить изврат.

S>Выигрыша нет вообще, если не считать двух сэкономленных скобок. Да и то они меняются на =>.


Ещё и «return ...»; выражению он не нужен. Но просто взять фигурные скобки можно только в expression-bodied-методах, заменив их на обычные. Есть и другие контексты, где может встретиться выражение. Например,
var foo = Foo(...);
var bar = ThirdPartyApi.ComputeBar(foo);
var qux = Qux(bar);

Скажем, хотим померять и залогировать время вызова сторонней функции:
var foo = Foo(...);
var bar = with (new StopwatchLogger()) ThirdPartyApi.ComputeBar(foo);
var qux = Qux(bar);

Тут уже добавление фигурных скобок будет ломать scope'ы.

S>Тоже вариант, но это классический пример leaked abstraction: вместо относительно понятной ошибки компиляции или рантайма пользователь сообщает ошибку от провайдера "неподдерживаемый метод". Ну, или невалидный expression tree, как повезёт.

Ещё раз: предложенный мной подход не порождает невалидных expression trees или новых недостижимых ранее ошибок linq-провайдеров. Есть понятная семантика, которая может быть достигнута существующими средствами языка и фреймворка; то есть не требуется ничего революционного кроме ложечки сахара.

Я не говорю, что жить не могу без using-выражений; эту ветку начал samius. Эти выражения я применял бы не каждый день, наверное; но значительно чаще, чем те linq-провайдеры, которыми не пользовался уже года три.
Глаза у меня добрые, но рубашка — смирительная!
Re[11]: [C# 7] Design notes, Mar 18
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.05.15 20:09
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>Не догоняю. Разве exp bodies запрещают impure-выражения? нет ведь. Все impure благополучно вставляются в exp bodies и ничего не портится. Или все что может быть испорчено, уже испорчено.

S>Не запрещает конечно. Но impure-выражений на сегодня как таковых нет. Разве что спрятанные в методы, инкремент и присваивания. Но последние два сразу видно. А от первого в принципе не защитишься без отсечения части сценариев типа кэширования.
+1

S>Добавление using expression будет провоцировать написание кода с побочными эффектами (потому что коду без побочных эффектов юзинг по определению не нужен). Т.е. размывать и без того нечёткую разницу между выражениями и стейтментами

Здесь по поводу побочных эффектов согласен. Но! Тот C# в отличие от F# провоцирует на побочные эффекты практически все. Точнее, в F# есть хотя бы инфраструктура, которая может позволить в некоторых сценариях обходиться без них, а в C# у нас нет даже коллекций без побочных эффектов. Тем не менее, в F# try/finally — выражение, хотя для функционального языка такая провокация как серпом по яйцам. Но она есть.

S>>Вот есть у нас стейтмент try/finally, и он ничего не ломает, ни в какие деревья выражений его совать не надо. Этот using стейтмент умеет возвращать результат. И это опять ничего не ломает (ведь существует, и никто не жалуется на это). И о ужас! Мы даже можем вставлять try/finally в лямбду!


S>Неа, это уже будет не expression-лямбда, а сокращённая запись для анонимного делегата. Потому что будет содержать statement block. Ну и соответственно, не может быть сконвертирована в expression, по крайней мере для текущей версии шарпа.


S>Т.е. синтаксис для юзинга добавить можно, но мы получим парадоксальную ситуацию: код

S>
S>int Do() => using (SomeScope()) SomeValue();
S>

S>выглядит как expression lambda но ей не является т.к. его нельзя сконвертить в expression tree.
Как же? можно. Речь таки о наличии лишней пары скобочек и оператора return. Т.е. мы говорим не о семантических отличиях, а о синтаксических и только лишь.

S>Т.е. это statement lambda, но тогда её надо записать как

S>
S>int Do() => { using (SomeScope()) return SomeValue(); }
S>

S>что ещё длиннее, чем оригинальный
Это длинее чем оригинальный потому как using приходится оборачивать в скобки из-за того, что он стейтмент. Был бы он експрешном — не пришлось бы вставлять скобки.
S>
S>int Do() { using (SomeScope()) return SomeValue(); }
S>

S>В общем, борьба с синтаксическим оверхедом не задалась
Конечно не задалась. Она не задалась еще с саамого expr bodies, т.к. вместо скобок пришлось писать =>.
S>Сорри, что сразу не привёл это объяснение, неправильно понял твой вопрос
Не страшно.

S>>Очередное обновление языка нам позволяет записывать функции-мемберы без скобочек, но с =>, как у лямбд. Но вот то что в лямбды мы стейтменты вставлять можем, но если мы стейтменты вставим в функции-мемберы без скобочек, то сразу добавим геморроя — вот это я не понимаю.

S>Потому что мы запутаем клиента: выглядит как expression lambda, но на самом деле это statement lambda.
И statement оно лишь потому что using не експрешн.

S>Хотя, на самом деле мы тут страдаем фигнёй. Нужен коммент от ув. Никова.

согласен, что фигней. Тем более, что в данном случае аргументы "почему нет" интересуют меня немного более самой фичи. Ведь речь всего лишь о скобочках, а не о просовывании чего-то нового в linq-провайдеры.

S>>Конечно нет, но работают они с тем же фреймворком и библиотеками, что и C#.

S>Фигово работают, надо признать. Ибо привычное API для этих языков плохо укладывается в рамки CLS.
Есть предложения, как сделать лучше?
Re[2]: [C# 7] Design notes, Mar 18
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 19.05.15 13:15
Оценка:
Здравствуйте, samius, Вы писали:

S>Интересно, никому не приходило в голову что Expression Bodied Functions and Properties хорошо бы дополнить возможностью использовать using statement в качестве expression?


static TReturn Using<TValue, TReturn>(TValue val, Func<TValue, TReturn>) {...}


Не?
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[3]: [C# 7] Design notes, Mar 18
От: Sinix  
Дата: 19.05.15 14:05
Оценка: +1
Здравствуйте, AndrewVK, Вы писали:

AVK>Не?

static TReturn Using<TValue, TReturn>(Func<TValue> val, Func<TValue, TReturn> callback) {...}

тогда уж.

Иначе первый же залетевший дятел одно исключение — и утёкший ресурс

UPD.
P.S. Кто сказал future монада?
    public static Func<TReturn> Then<TValue, TReturn>(this Func<TValue> val, Func<TValue, TReturn> callback) { return () => callback(val()); }
...
        Func<string> a = () => Console.ReadLine();
        var b = a
            .Then(_ => int.Parse(_))
            .Then(_ => Math.Sqrt(_))
            .Then(_ => { Console.WriteLine(_); return _; });
        var c = b();


P.P.S. Все вопросы "НО ЗАЧЕМ???" — к топикстартеру. Это ему нужны были юзинги в выражениях
Отредактировано 19.05.2015 14:46 Sinix . Предыдущая версия .
Re[3]: [C# 7] Design notes, Mar 18
От: samius Япония http://sams-tricks.blogspot.com
Дата: 19.05.15 17:59
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, samius, Вы писали:


AVK>
AVK>static TReturn Using<TValue, TReturn>(TValue val, Func<TValue, TReturn>) {...}
AVK>


AVK>Не?

Да, с учетом поправки Sinix, оно самое.
Re[4]: [C# 7] Design notes, Mar 18
От: samius Япония http://sams-tricks.blogspot.com
Дата: 19.05.15 18:05
Оценка: 34 (1) +1
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, AndrewVK, Вы писали:


AVK>>Не?

S>
S>static TReturn Using<TValue, TReturn>(Func<TValue> val, Func<TValue, TReturn> callback) {...}
S>

S>тогда уж.

S>Иначе первый же залетевший дятел одно исключение — и утёкший ресурс


S>UPD.

S>P.S. Кто сказал future монада?
S>
S>    public static Func<TReturn> Then<TValue, TReturn>(this Func<TValue> val, Func<TValue, TReturn> callback) { return () => callback(val()); }
S>...
S>        Func<string> a = () => Console.ReadLine();
S>        var b = a
S>            .Then(_ => int.Parse(_))
S>            .Then(_ => Math.Sqrt(_))
S>            .Then(_ => { Console.WriteLine(_); return _; });
S>        var c = b();
S>

Давно это было, вряд ли кто уж вспомнит.
Из F# спеки

Member Description
member Using : 'a * ('a -> M<'b>) -> M<'b> when 'a :> IDisposable Optional member. Used to de-sugar use bindings within computation expressions.
Construct De-sugared Form
use pat = expr in cexpr b.Using(expr, (fun pat -> cexpr))
use! pat = expr in cexpr b.Bind(expr, (fun x -> b.Using(x, fun pat -> cexpr))

S>P.P.S. Все вопросы "НО ЗАЧЕМ???" — к топикстартеру. Это ему нужны были юзинги в выражениях

Я такого не утверждал (что нужны). Я поинтересовался, была ли такая идея?
Re[4]: [C# 7] Design notes, Mar 18
От: IT Россия linq2db.com
Дата: 19.05.15 18:07
Оценка:
Здравствуйте, samius, Вы писали:

AVK>>Не?

S>Да, с учетом поправки Sinix, оно самое.

Про where TValue : class, IDisposable не забудте. А то надиспозите.
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: [C# 7] Design notes, Mar 18
От: samius Япония http://sams-tricks.blogspot.com
Дата: 19.05.15 18:11
Оценка:
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, samius, Вы писали:


AVK>>>Не?

S>>Да, с учетом поправки Sinix, оно самое.

IT>Про where TValue : class, IDisposable не забудте. А то надиспозите.

Возражаю, не нужен такой констрейнт. Контракт на IDisposable предполагает возможность многократного вызова метода Dispose() и только. А флаги об успешном освобождении ресурса вовсе не обязательно держать в теле структуры.
Re[4]: [C# 7] Design notes, Mar 18
От: Jack128  
Дата: 19.05.15 18:36
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, AndrewVK, Вы писали:


AVK>>Не?

S>
S>static TReturn Using<TValue, TReturn>(Func<TValue> val, Func<TValue, TReturn> callback) {...}
S>

S>тогда уж.

S>Иначе первый же залетевший дятел одно исключение — и утёкший ресурс

А можно пояснить ??
Вот есть метод
static TReturn Using<TValue, TReturn>(this TValue val, Func<TValue, TReturn> callback) where TValue: IDisposable
{
   using(val) { return callback(val); }
}

типичное использование, ну например так:
var fileSize = new FileStream(...).Using(stream => stream.Length);


как тут возможна утечка ?
Отредактировано 19.05.2015 18:37 Jack128 . Предыдущая версия .
Re[5]: [C# 7] Design notes, Mar 18
От: Sinix  
Дата: 19.05.15 18:49
Оценка: 3 (1)
Здравствуйте, Jack128, Вы писали:

J>как тут возможна утечка ?

Thread.Abort(), и, опционально, corrupted state exceptions, например out of memory при попытке выделить память под лямбду. Тут конечно ситуация из разряда "поздно пить боржоми", но мы ж инфраструктурный код обсуждаем, а не одноразовый хелпер.
Re[6]: [C# 7] Design notes, Mar 18
От: Jack128  
Дата: 19.05.15 18:58
Оценка: +1 :))
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Jack128, Вы писали:


J>>как тут возможна утечка ?

S>Thread.Abort(), и, опционально, corrupted state exceptions, например out of memory при попытке выделить память под лямбду. Тут конечно ситуация из разряда "поздно пить боржоми", но мы ж инфраструктурный код обсуждаем, а не одноразовый хелпер.
Как страшно жить :-D
Re[5]: [C# 7] Design notes, Mar 18
От: IT Россия linq2db.com
Дата: 19.05.15 19:10
Оценка: +2
Здравствуйте, Jack128, Вы писали:

J>типичное использование, ну например так:

J>
var fileSize = new FileStream(...).Using(stream => stream.Length);


Такой метод нужно называть не Using, а что-то вроде DisposeAfter.
Если нам не помогут, то мы тоже никого не пощадим.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.