Re[13]: Может ли в .Net жить язык со структурной типизацией?
От: dotneter  
Дата: 07.03.11 09:40
Оценка:
Здравствуйте, hardcase, Вы писали:

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


D>>Почему нельзя просто обернуть ToString()?


H>А как с GetType быть?

С ним ничего не поделаешь, да и не к чему. Если человеку в данном сценарии понадобилось узнать реальный тип, то скорее всего он занимается созданием костылей.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Talk is cheap. Show me the code.
Re[14]: Может ли в .Net жить язык со структурной типизацией?
От: hardcase Пират http://nemerle.org
Дата: 07.03.11 09:51
Оценка: +1
Здравствуйте, dotneter, Вы писали:

H>>А как с GetType быть?

D>С ним ничего не поделаешь, да и не к чему. Если человеку в данном сценарии понадобилось узнать реальный тип, то скорее всего он занимается созданием костылей.

Фичи в компиляторе должны либо работать везде, либо их не должно быть вообще. Потому поддержка структурной типизации должна быть полностью прозрачной, чтобы программист не задавал себе вопрос "А вот тут мне точно можно вызывать GetType?" (на основании GetType иногда делают реализацию Equals). Кстати, подобные обертки могут работать на уровне методов, но не подходят для хранения в полях классов.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[7]: Может ли в .Net жить язык со структурной типизацией?
От: FR  
Дата: 07.03.11 09:54
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Если ты хочешь что-то контролировать, тебе придется этот контроль явно описать, так? Так это и будет описанием интерфейса.


Не придется, если компилятор сам хорошо умеет это делать.

J>А иначе все сведется к шаблонам С++, где утиная типизация в чистом виде — если и сломается, то только что-то где в глубине, куда без поллитры не проберешься.


Это только проблема C++.
В OCaml нет проблем с инстанцированием шаблонов, да и шаблонов самих нет, есть обычная функция и обычная ошибка компиляции при
попытке вызова с неподходящим типом.

J>Собственно, поэтому и захотели ввести Concepts — утиная типизация в чистом виде неудобна, так как контроль откладывается до места использования, которое может быть очень далеко от кода, с которым взаимодействует юзер. Не говоря уже о том, что юзеру недоступен в простом и понятном виде весь набор требований, которые код предъявляет к его типам. Поэтому такие требования лучше всести воедино, т.е. определить интерфейс.


Ну тот же OCaml если нужно может автоматически создавать интерфейсные файлы (аналог C/C++ .h файлов) в котором будет вся нужная типизация.
Например для функции

let f o = o#put


будет выведено

val f : < put : 'a; .. > -> 'a


и тут без всяких интерфейсов есть вся нужная информация, а именно функция f принимает параметром объекты имеющие метод put,
с обобщенными параметрами. Если же мы перепишем функция например так:

let f o = 1 + o#put 2 2


то получим такую аннотацию:

val f : < put : int -> int -> int; .. > -> int


из которой видно что теперь принимаются только объекты с методом put имеющими два целых параметра и возвращающие целый результат.

J>В том же Go интерфейсы описываются явно:

J>
J>26    type reader interface {
J>27        Read(b []byte) (ret int, err os.Error)
J>28        String() string
J>29    }
J>

J>http://golang.org/doc/go_tutorial.html

OСaml точно также поддерживает и явное описание интерфейсов.
Но как язык с выводом типов если интерфейс не задан явно, выводит самый общий структурно типизированный вариант, это во многих
случаях удобнее и выразительно практически как утиная типизация.

J>Будет такой ad-hoc интерфейс иметь имя или нет — дело десятое. Обычно удобно, чтоб имя было, ибо обычно у тебя есть набор функций/классов, которые предъявляют к входящему типу один и тот же набор требований.


Удобнее не заморачиватся с интерфейсом, и вводить его только когда он необходим.
Re[15]: Может ли в .Net жить язык со структурной типизацией?
От: dotneter  
Дата: 07.03.11 10:22
Оценка:
Здравствуйте, hardcase, Вы писали:

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


H>>>А как с GetType быть?

D>>С ним ничего не поделаешь, да и не к чему. Если человеку в данном сценарии понадобилось узнать реальный тип, то скорее всего он занимается созданием костылей.

H>Фичи в компиляторе должны либо работать везде, либо их не должно быть вообще. Потому поддержка структурной типизации должна быть полностью прозрачной, чтобы программист не задавал себе вопрос "А вот тут мне точно можно вызывать GetType?"

Тоесть, давайте выкинем все движки aop работающие на враперах, из-за того что нельзя вызвать GetType? Да есть такое ограничение, нужно о нем узнать один раз и больше GetType не вызывать.
H>(на основании GetType иногда делают реализацию Equals).
Опять же, Equals можно обернуть.
H>Кстати, подобные обертки могут работать на уровне методов, но не подходят для хранения в полях классов.
Причина?
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Talk is cheap. Show me the code.
Re: Может ли в .Net жить язык со структурной типизацией?
От: Кодёнок  
Дата: 07.03.11 10:41
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Может ли в .Net CLR или JVM (т.е. в рантаймах рассчитанных на номинативную систему типов) жить язык со структурной типизацией?


VD>И если может, насколько при этом такой язык будет "своим" в этих рантаймах? И чем придется платить за совместимость (подозреваю, что производительностью)?


А что подразумевается под “жить в рантаймах”? Можно сделать компилятор, позволяющий приписать новый интерфейс абсолютно любому типу, реализуя это допустим через объект-обертку, форвардящую вызовы, рантайм об этом знать даже не будет. Например создать интерфейс IMyStringInterface и сделать чтобы System.String “реализовал” его, но знать об этом будет только этот самый компилятор, рантайм тут ни при чем.

Или хочется чтобы в метаинформации System.String появилась запись о поддержке IMyStringInterface? Как ты представляешь реализацию этого?
Re[8]: Может ли в .Net жить язык со структурной типизацией?
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.03.11 11:25
Оценка:
Здравствуйте, adontz, Вы писали:

VD>>В том то и дело, что компилятор это разрулить не может.


A>Это почему?


Потому что в дотнете номинативная система типов. Типы идентифицируются по полному имени. И два типа с одинаковой структурой будут считаться разными типами.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Может ли в .Net жить язык со структурной типизацией?
От: adontz Грузия http://adontz.wordpress.com/
Дата: 07.03.11 11:27
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Потому что в дотнете номинативная система типов. Типы идентифицируются по полному имени. И два типа с одинаковой структурой будут считаться разными типами.


Ещё раз перечитай что я тебе написал. Судя по твоему ответу ты вообще не понял что я тебе предлагаю.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[2]: Может ли в .Net жить язык со структурной типизацией?
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.03.11 12:19
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>А что подразумевается под “жить в рантаймах”?


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

Кё>Можно сделать компилятор, позволяющий приписать новый интерфейс абсолютно любому типу, реализуя это допустим через объект-обертку, форвардящую вызовы, рантайм об этом знать даже не будет.


Такое решение имеет ряд проблем. Основная — невозможность обеспечить полноценной передачи по ссылке. Кроме того встает проблема производительности. Особенно производительность просядет в случае вэлью-типов.

Скажем если хочется реализовать универсальную работу с числами, класс-обертка может оказаться слишком большим оверхэдом.

Плюс это уже получается что-то больше похожее на классы типов Хаскеля.

Провел смелый научный эксперимент. Реализовал некий абстрактный обобщенный алгоритм.
using System.Console;
using System.Diagnostics;

interface INumber[T]
{
  Add(a : T, b : T) : T;
  Sub(a : T, b : T) : T;
}

class IntImpl : INumber[int]
{
  public Add(a : int, b : int) : int { a + b }
  public Sub(a : int, b : int) : int { a - b }
}

class DoubleImpl : INumber[double]
{
  public Add(a : double, b : double) : double { a + b }
  public Sub(a : double, b : double) : double { a - b }
}

[Record]
class Algorithms[T]
{
  _helper : INumber[T];
  
  public Alg1(a : T, b : T, c : T) : T
  {
    _helper.Sub(_helper.Add(a, b), c)
  }
}

module Program
{
  Alg1(a : int,    b : int,    c : int)    : int    { a + b - c }
  Alg1(a : double, b : double, c : double) : double { a + b - c }
  
  Main() : void
  {
    def test[T](f : void -> T, msg : string)
    {
      def timer = Stopwatch.StartNew();
      def res = f();
      def spaces = string(' ', 20 - msg.Length);
      WriteLine($"$msg$spaces took: $(timer.Elapsed) res=$res");
    }
    
    def genericInt()
    {
      def algs = Algorithms(IntImpl());
      mutable res = 0L;
      repeat (100_000_000)
        res += algs.Alg1(42, 8, 49);
      res
    }
    def nongenericInt()
    {
      mutable res = 0L;
      repeat (100_000_000)
        res += Alg1(42, 8, 49);
      res
    }
    def genericDouble()
    {
      def algs = Algorithms(DoubleImpl());
      mutable res = 0.0;
      repeat (100_000_000)
        res += algs.Alg1(42.0, 8.0, 49.0);
      res
    }
    def nongenericDouble()
    {
      mutable res = 0.0;
      repeat (100_000_000)
        res += Alg1(42.0, 8.0, 49.0);
      res
    }
    

    test(nongenericInt,    "nongenericInt");
    test(genericInt,       "genericInt");
    test(nongenericDouble, "nongenericDouble");
    test(genericDouble,    "genericDouble");
  }
}

Результаты оказались следующими (Release Core 2 2.4 Ghz):
nongenericInt        took: 00:00:00.1687145 res=100000000
genericInt           took: 00:00:00.7156627 res=100000000
nongenericDouble     took: 00:00:00.1261819 res=100000000
genericDouble        took: 00:00:00.7166952 res=100000000

То есть разница составляет 4-6 раз. И это при оптимальном стечении обстоятельств.

Кё>Например создать интерфейс IMyStringInterface и сделать чтобы System.String “реализовал” его, но знать об этом будет только этот самый компилятор, рантайм тут ни при чем.


И на каждую строку держать по два объекта? Или, как в моем тесте, использовать некий общий объект без состояния?

Кё>Или хочется чтобы в метаинформации System.String появилась запись о поддержке IMyStringInterface? Как ты представляешь реализацию этого?


Нет. Метаинформация это лишнее.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Может ли в .Net жить язык со структурной типизацией?
От: jazzer Россия Skype: enerjazzer
Дата: 07.03.11 13:24
Оценка:
Здравствуйте, FR, Вы писали:

FR>В OCaml нет проблем с инстанцированием шаблонов, да и шаблонов самих нет, есть обычная функция и обычная ошибка компиляции при

FR>попытке вызова с неподходящим типом.

Написал большой ответ, но браузер съел, переписывать лень.
В С++ тоже будет обычная ошибка компиляции, тут без разницы.
Речь не об одной функции и с одним параметром, тут все понятно, что в OCaml, что в С++.
А вот когда у тебя условия начнут разножаться, причем их еще и придется копи-пейстом по разным функциям разносить, тогда жизнь перестает быть прекрасной. Но если что-то нужно один раз, тогда конечно, нет проблем забзать условие прямо в объявлении функции безо всяких явных интерфейсов, хоть в плюсах, хоть в окамле.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[9]: Может ли в .Net жить язык со структурной типизацией?
От: FR  
Дата: 07.03.11 14:03
Оценка:
Здравствуйте, jazzer, Вы писали:

J>В С++ тоже будет обычная ошибка компиляции, тут без разницы.


Разница есть, что-то типа

template <typename T>
void dummy(T t)
{
not_exist_func();
}

int main()
{
}


просто не скомпилируется, ну и другие подобные шаблонные ошибки невозможны.

J>Речь не об одной функции и с одним параметром, тут все понятно, что в OCaml, что в С++.

J>А вот когда у тебя условия начнут разножаться, причем их еще и придется копи-пейстом по разным функциям разносить, тогда жизнь перестает быть прекрасной. Но если что-то нужно один раз, тогда конечно, нет проблем забзать условие прямо в объявлении функции безо всяких явных интерфейсов, хоть в плюсах, хоть в окамле.

В окамле вообще не надо бацать, само выведется, так что копипаста никакого не будет.
Но это ты уже совсем о другом. Я не против интерфейсов, они вполне полезны когда нужно жестко все ограничить.
Re[4]: Может ли в .Net жить язык со структурной типизацией?
От: hi_octane Беларусь  
Дата: 07.03.11 14:23
Оценка:
_>Как альтернатива — компилятор может смотреть в какие dynamic<> функции пихаются типы для которых мы подразумеваем структурную эквивалентность, и добавлять в них автоматом интерфейсы, для того чтобы типы сходились. Ну и соответственно ругаться на этапе компиляции если добавляемый интерфейс структурой или классом не поддерживается.

Это предложение в игнор Попытался сделать алгоритм вывода наибольшего общего интерфейса и понял что ошибся. Можно написать такой метод в котором компилятор выведет автоматом интерфейсы, которые не сможет поддержать ни один класс, при этом метод будет корректным.
Re[5]: Может ли в .Net жить язык со структурной типизацией?
От: hi_octane Беларусь  
Дата: 07.03.11 14:23
Оценка:
J>Главное отличие (если, конечно, я правильно понимаю, как работают интерфейсы в .NET) — интерфейсы нужно описывать и объявлять до объявления класса, который этот интерфейс реализует (явно). Т.е. разработчик класса до того, как он напишет свой класс, должен 1) знать, что такой интерфейс существует, и 2) явно от него отнаследоваться.

Да но это же и хорошая гарантия надёжности. Т.е. если разработчик захочет класс изменить до полной несовместимости с интерфейсом — ему компилятор этого сделать не даст. Или интерфейс меняй, или методы поддержи, или отказывайся от поддержки интерфейса вообще.

J>А структурная типизация позволяет описывать индерфейсы уже имеющихся классов имено в том месте, в котором они используются, и сами классы и их разработчики ничего о них знать не будут.


Получается разработчик может класс отрефакторить и при этом не узнать что он ломает публичный контракт на который кто-то завязан? Как-то чем больше об этом думаю, тем больше нравится идея extension interfaces, которую я выше уже описывал.
Re[10]: Может ли в .Net жить язык со структурной типизацией?
От: jazzer Россия Skype: enerjazzer
Дата: 07.03.11 15:02
Оценка:
Здравствуйте, FR, Вы писали:

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


J>>В С++ тоже будет обычная ошибка компиляции, тут без разницы.


FR>Разница есть, что-то типа


FR>
FR>template <typename T>
FR>void dummy(T t)
FR>{
FR>not_exist_func();
FR>}

FR>int main()
FR>{
FR>}
FR>


FR>просто не скомпилируется, ну и другие подобные шаблонные ошибки невозможны.

ну, вообще-то, в С++ этот код тоже не скомпилируется
причем именно потому что функция not_exist_func неизвестна

J>>Речь не об одной функции и с одним параметром, тут все понятно, что в OCaml, что в С++.

J>>А вот когда у тебя условия начнут разножаться, причем их еще и придется копи-пейстом по разным функциям разносить, тогда жизнь перестает быть прекрасной. Но если что-то нужно один раз, тогда конечно, нет проблем забзать условие прямо в объявлении функции безо всяких явных интерфейсов, хоть в плюсах, хоть в окамле.

FR>В окамле вообще не надо бацать, само выведется, так что копипаста никакого не будет.

оно выведется если функции зовут друг друга, а если функции просто логически связаны между собой, типа sin, cos, tan — откуда тут что выведется?

FR>Но это ты уже совсем о другом. Я не против интерфейсов, они вполне полезны когда нужно жестко все ограничить.

Да я с самого начала об этом, просто не удалось выразить мысль по-человечески — сказывается бессонная ночь
В общем и целом, конечно же, лучше иметь несколько возможностей, чем только одну или вообще ни одной.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: Может ли в .Net жить язык со структурной типизацией?
От: jazzer Россия Skype: enerjazzer
Дата: 07.03.11 15:28
Оценка: 9 (1)
Здравствуйте, hi_octane, Вы писали:

J>>Главное отличие (если, конечно, я правильно понимаю, как работают интерфейсы в .NET) — интерфейсы нужно описывать и объявлять до объявления класса, который этот интерфейс реализует (явно). Т.е. разработчик класса до того, как он напишет свой класс, должен 1) знать, что такой интерфейс существует, и 2) явно от него отнаследоваться.


_>Да но это же и хорошая гарантия надёжности. Т.е. если разработчик захочет класс изменить до полной несовместимости с интерфейсом — ему компилятор этого сделать не даст. Или интерфейс меняй, или методы поддержи, или отказывайся от поддержки интерфейса вообще.

С одной стороны оно, конечно, да.
С другой стороны... вот представь, написал ты интерфейс I5 с 5-ю функциями f1-f5, и свой класс реализовал.
А другой(!) человек пишет свою функцию, которая может работать с любыми объектами, у которых есть функции f1-f4, а f5 ей до лампочки.
Он, конечно, мог бы реализовать свою функцию в терминах твоего интерфейса, тогда она будет бесшовно работать с твоими объектами, но перестанет работать с его, у которых нету никакой f5. И какой же у него выбор? Если доступны исходники — сделать интерфейс I4 из функций f1-f4, а I5 отнаследовать от I4 с добавлением f5. Если недоступны — придется писать две версии: для твоего I5 и для его I4, так как они между собой никак не связаны. Ну и дальше по индукции, сам посчитай, сколько всего комбинаций есть из этих 5 функций, и сколько придется рожать интерфейсов. Либо свести все к абсурду — все интерфейсы состоят ровно из одной функции. Тогда можно почти все, что угодно, сделать. Только вот в резульате код "другого человека" превратится как раз в проверку наличия индивидуальных функций

Ну и есть фича, как в хаскелевких Type Classes, так и в плюсовых Concepts — если у какого-то типа нет нужной функции, но ее можно соорудить, чтобы удовлетворить такому вот ad hoc интерфейсу, то это можно сделать, причем это будет локально (т.е. только тот код, который определен в терминах данного ad hoc интерфейса, увидит этот замещающий код). Не уверен, что extension interfaces позволяют делать такие локализованные маппинги.

В принципе, классические интерфейсы ad hoc интерфейсам не мешают, они ортогональны и говорят несколько о разном. И классические интерфейсы — это, скорее, деталь архитектуры, в отличие от ad hoc интерфейсов, которые деталь реализации.

J>>А структурная типизация позволяет описывать индерфейсы уже имеющихся классов имено в том месте, в котором они используются, и сами классы и их разработчики ничего о них знать не будут.


_>Получается разработчик может класс отрефакторить и при этом не узнать что он ломает публичный контракт на который кто-то завязан?

Например? Ну и не забывай про сoncept map (внешнее добавление недостающих функций в определенном контексте — оно решает проблему поломанной завязанности, если, конечно, я правильно тебя понял).

_>Как-то чем больше об этом думаю, тем больше нравится идея extension interfaces, которую я выше уже описывал.

см. выше.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[11]: Может ли в .Net жить язык со структурной типизацией?
От: FR  
Дата: 07.03.11 15:42
Оценка:
Здравствуйте, jazzer, Вы писали:

FR>>просто не скомпилируется, ну и другие подобные шаблонные ошибки невозможны.

J>ну, вообще-то, в С++ этот код тоже не скомпилируется

В сферическом С++ возможно, но VC 2010 и мой "любимый" bcc без писка кушают

J>причем именно потому что функция not_exist_func неизвестна


Да gcc так и говорит.
Но все-таки шаблонная и обычная функция в C++ вещи разные, в отличии от окамла.

FR>>В окамле вообще не надо бацать, само выведется, так что копипаста никакого не будет.

J>оно выведется если функции зовут друг друга, а если функции просто логически связаны между собой, типа sin, cos, tan — откуда тут что выведется?

Тут не понял, если они у нас используются будет вывод типов тут никакой завязки на вызов друг друга нет.

FR>>Но это ты уже совсем о другом. Я не против интерфейсов, они вполне полезны когда нужно жестко все ограничить.

J>Да я с самого начала об этом, просто не удалось выразить мысль по-человечески — сказывается бессонная ночь
J>В общем и целом, конечно же, лучше иметь несколько возможностей, чем только одну или вообще ни одной.

Re[10]: Может ли в .Net жить язык со структурной типизацией?
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.03.11 17:42
Оценка:
Здравствуйте, adontz, Вы писали:

A>Судя по твоему ответу ты вообще не понял что я тебе предлагаю.


Ага. Видимо плохо объясняешь.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Может ли в .Net жить язык со структурной типизацией?
От: adontz Грузия http://adontz.wordpress.com/
Дата: 07.03.11 18:25
Оценка:
Здравствуйте, VladD2, Вы писали:

A>>Судя по твоему ответу ты вообще не понял что я тебе предлагаю.

VD>Ага. Видимо плохо объясняешь.

Да что же сложного-то Имя типа зависит только от его содержимого.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[9]: Может ли в .Net жить язык со структурной типизацией?
От: dotneter  
Дата: 07.03.11 18:31
Оценка:
Здравствуйте, VladD2, Вы писали:

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


VD>>>В том то и дело, что компилятор это разрулить не может.


A>>Это почему?


VD>Потому что в дотнете номинативная система типов. Типы идентифицируются по полному имени. И два типа с одинаковой структурой будут считаться разными типами.

adontz вроде предлагает не делать два типа, компилятор смотрит есть ли структурный интерфейс IPropertyBarMethodFoo, если есть использует, если нет генерит.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Talk is cheap. Show me the code.
Re[10]: Может ли в .Net жить язык со структурной типизацией?
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.03.11 21:46
Оценка:
Здравствуйте, dotneter, Вы писали:

D>adontz вроде предлагает не делать два типа, компилятор смотрит есть ли структурный интерфейс IPropertyBarMethodFoo, если есть использует, если нет генерит.


Подумайте на досуге что делать при наличии двух сборок в которых уже сгенерированны и использованы разные типы.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Может ли в .Net жить язык со структурной типизацией?
От: adontz Грузия http://adontz.wordpress.com/
Дата: 07.03.11 21:52
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Подумайте на досуге что делать при наличии двух сборок в которых уже сгенерированны и использованы разные типы.


У меня вызывает большие сомнения принципиальная возможность в рамках CLR структурной типизации, модульности и компилируемости одновременно.
A journey of a thousand miles must begin with a single step © Lau Tsu
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.