Информация об изменениях

Сообщение Re[12]: Что должен возвращать if? от 22.10.2014 18:30

Изменено 22.10.2014 18:32 Evgeny.Panasyuk

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

EP>>Явно или автоматически: Variant<Variant<T, void>, void> -> Variant<T, void>

G>А явно это как? Особенно интересно, как это "явно" будет выглядеть в обобщенном коде.

Например simplify(v) или какой-нибудь унарный оператор ^^ v

G>А если автоматически, то получается тип Variant<Variant<T, void>, void> существовать не может? Я вас правильно понимаю?


Хм, наверное да. Точнее существовать может, но до первого использования.

G>>>Почему только при присвоении?! Везде, где "по смыслу" должно быть T.

EP>>Вот тут:
EP>>
EP>>auto foo()
EP>>{
EP>>    return (if(c) T{1} else T{2});
EP>>}
EP>>

EP>>какой должен быть тип результата у foo?
G>Очевидно — variant.

Variant[T]? А как же:

G>>>Почему только при присвоении?! Везде, где "по смыслу" должно быть T.

Что имелось в виду? Протягивать Variant[T] до T? А если пользователь просто захочет позвать метод T?

G>Хотите работать с res как c variant'ом — ктож вам запретит Но если у вас есть, например, какая-нибудь ф-ция от X, то, согласитесь, удобней "уметь" в неё передавать variant[X] "as is", а не дергать какие-то unbox'ы.


Можно и так — автоматически/неявно.

G>>>В нашем случае использовать if не получится...

EP>>Почему?
G>?! Очевидно, потому что if вернет нам новый variant. С которым "нужно что-то делать"

Когда из if возвращается указатель на какую-нибудь абстрактную базу, при работе с ней придётся точно также выяснять — что же там внутри, и какой именно метод вызывать. Выбор-то никуда не исчезает

G>>>конечно, если вы не предлагаете "нафантазировать" для этого случая еще один — специальный — "if". Ну, который не будет вычисляться в variant .

EP>>Зачем?
G>?! Вы серьезно не понимаете? ?! Очевидно, потому что "нормальный" if вернет нам новый variant. С которым "нужно что-то делать"

А сейчас возвращается общая база, с которой тоже "нужно что-то делать".

G>Это пример из boost, в который вы мне тыкали, как в пример. И таки да... это называется, двойная диспетчеризация.


Там одинарная диспетчеризация, а не двойная

G>>>?! Вы вообще о чем? Как определить этот "метод"? Смысл использования variant'а — по вашей же логике — "впихнуть невпихуемое". Если мы подразумеваем общий интерфейс, то зачем variant-то?!

EP>>Я уже приводил пример, придётся скопировать:
EP>>
EP>>...
EP>>

EP>>Здесь нет общего предка у Widget и Gadget (да и вообще у них нет ни одного метода), а интерфейс использования в данном случае у них одинаковый
G>Я где-то говорил за "общего предка"?! Процитирую себя

Если мы подразумеваем общий интерфейс, то зачем variant-то?!


Тогда покажите как этот пример (где у разных типов общий интерфейс) переделать без variant'а и без общего предка.

G>Что мешает-то на лету "собрать" нужный тип (в вашем примере, это агрегат Widget и Gadget), реализующий _нужный_ интерфейс?!


Пример сборки нужного типа в студию. Мне кажется это будет сложнее чем variant.

G>>>Проблему можно выразить так: Если результат if можно обработать только через PM, то зачем нам использовать if? Почему сразу не использовать PM?!

EP>>Во-первых, не только через PM.
G>Возвращаемся к нашим баранам. Таки через visitor'ы предлагаете? :-
Один из вариантов. Вот только visitor может иметь один полиморфный метод, а может много перегрузок — а-ля PM.

G>Повторюсь — обработка через if даст вам на выходе опять variant. Т.е. получаем "один раз variant — всегда variant". Оно действительно надо?


С общим предком тоже самое. Если же обработать всё что относится к этой ветки, внутри неё, и наружу никогда не выдавать полиморфный тип (будь то variant или абстрактная база), то мы очень быстро получим комбинаторный взрыв.


G>>>Напоминаю, в сабже if — это "сахар" для PM.

EP>>И что? Это мешает построить if возвращающий variant?
G>Да ничего не мешает. Вопрос не в этом. Вопрос в том, чего вы этим хотите добиться? Пресловутой "симметрии" с if-без-else, как вроде бы выяснили, добиться таким образом не получится. Так в чем смысл-то?

Как это не получится, если выяснили что как раз получается

EP>>Чем код выше, принципиально отличается от следующего:

EP>>
EP>>MATCH( IF(x>0) { return getA(); } ELSE { return getB(); } )
EP>>    CASE(y IS A) { handleA(y.PropertyOfA); }
EP>>    CASE(y IS B) { handleB(y.MethodOfB()); }
EP>>;
EP>>

EP>>
G>Принципиально — ничем. Только какое он имеет отношение к?

Тем что такой синтаксис можно получить на базе boost::variant
Здравствуйте, gbear, Вы писали:

EP>>Явно или автоматически: Variant<Variant<T, void>, void> -> Variant<T, void>

G>А явно это как? Особенно интересно, как это "явно" будет выглядеть в обобщенном коде.

Например simplify(v) или какой-нибудь унарный оператор ^^ v

G>А если автоматически, то получается тип Variant<Variant<T, void>, void> существовать не может? Я вас правильно понимаю?


Хм, наверное да. Точнее существовать может, но до первого использования.

G>>>Почему только при присвоении?! Везде, где "по смыслу" должно быть T.

EP>>Вот тут:
EP>>
EP>>auto foo()
EP>>{
EP>>    return (if(c) T{1} else T{2});
EP>>}
EP>>

EP>>какой должен быть тип результата у foo?
G>Очевидно — variant.

Variant[T]? А как же:

G>>>Почему только при присвоении?! Везде, где "по смыслу" должно быть T.

Что имелось в виду? Протягивать Variant[T] до T? А если пользователь просто захочет позвать метод T?

G>Хотите работать с res как c variant'ом — ктож вам запретит Но если у вас есть, например, какая-нибудь ф-ция от X, то, согласитесь, удобней "уметь" в неё передавать variant[X] "as is", а не дергать какие-то unbox'ы.


Можно и так — автоматически/неявно.

G>>>В нашем случае использовать if не получится...

EP>>Почему?
G>?! Очевидно, потому что if вернет нам новый variant. С которым "нужно что-то делать"

Когда из if возвращается указатель на какую-нибудь абстрактную базу, при работе с ней придётся точно также выяснять — что же там внутри, и какой именно метод вызывать. Выбор-то никуда не исчезает

G>>>конечно, если вы не предлагаете "нафантазировать" для этого случая еще один — специальный — "if". Ну, который не будет вычисляться в variant .

EP>>Зачем?
G>?! Вы серьезно не понимаете? ?! Очевидно, потому что "нормальный" if вернет нам новый variant. С которым "нужно что-то делать"

А сейчас возвращается общая база, с которой тоже "нужно что-то делать".

G>Это пример из boost, в который вы мне тыкали, как в пример. И таки да... это называется, двойная диспетчеризация.


Там одинарная диспетчеризация, а не двойная

G>>>?! Вы вообще о чем? Как определить этот "метод"? Смысл использования variant'а — по вашей же логике — "впихнуть невпихуемое". Если мы подразумеваем общий интерфейс, то зачем variant-то?!

EP>>Я уже приводил пример, придётся скопировать:
EP>>
EP>>...
EP>>

EP>>Здесь нет общего предка у Widget и Gadget (да и вообще у них нет ни одного метода), а интерфейс использования в данном случае у них одинаковый
G>Я где-то говорил за "общего предка"?! Процитирую себя

Если мы подразумеваем общий интерфейс, то зачем variant-то?!


Тогда покажите как этот пример (где у разных типов общий интерфейс) переделать без variant'а и без общего предка.

G>Что мешает-то на лету "собрать" нужный тип (в вашем примере, это агрегат Widget и Gadget), реализующий _нужный_ интерфейс?!


Пример сборки нужного типа в студию. Мне кажется это будет сложнее чем variant.

G>>>Проблему можно выразить так: Если результат if можно обработать только через PM, то зачем нам использовать if? Почему сразу не использовать PM?!

EP>>Во-первых, не только через PM.
G>Возвращаемся к нашим баранам. Таки через visitor'ы предлагаете? :-
Один из вариантов. Вот только visitor может иметь один полиморфный метод, а может много перегрузок — а-ля PM, а может и то и то.

G>Повторюсь — обработка через if даст вам на выходе опять variant. Т.е. получаем "один раз variant — всегда variant". Оно действительно надо?


С общим предком тоже самое. Если же обработать всё что относится к этой ветки, внутри неё, и наружу никогда не выдавать полиморфный тип (будь то variant или абстрактная база), то мы очень быстро получим комбинаторный взрыв.


G>>>Напоминаю, в сабже if — это "сахар" для PM.

EP>>И что? Это мешает построить if возвращающий variant?
G>Да ничего не мешает. Вопрос не в этом. Вопрос в том, чего вы этим хотите добиться? Пресловутой "симметрии" с if-без-else, как вроде бы выяснили, добиться таким образом не получится. Так в чем смысл-то?

Как это не получится, если выяснили что как раз получается

EP>>Чем код выше, принципиально отличается от следующего:

EP>>
EP>>MATCH( IF(x>0) { return getA(); } ELSE { return getB(); } )
EP>>    CASE(y IS A) { handleA(y.PropertyOfA); }
EP>>    CASE(y IS B) { handleB(y.MethodOfB()); }
EP>>;
EP>>

EP>>
G>Принципиально — ничем. Только какое он имеет отношение к?

Тем что такой синтаксис можно получить на базе boost::variant