migmit: (Default)
[personal profile] migmit

Кто-то (увы, не помню кто - напомните?) не так давно предлагал вопрос для интервью соискателям: где в C++ находится параметрический полиморфизм? Правильный ответ был "в районе шаблонов". Соответственно, я бы предложил следующий вопрос: а почему шаблоны таки не являются параметрическим полиморфизмом? Правильный ответ: потому что это всего лишь макросы на стероидах. Реализация метапрограммирования. А метапрограммирование ничего не может сделать, если под ним находится слишком слабенькая система.

Вот в чём сие выражается. Я запостил на ЛОР задачку (сопроводив её кодом на Хаскеле): подсчитать скалярное произведение двух векторов, статически гарантировав, что они имеют одинаковую длину. Мне не интересно сейчас снова демонстрировать, как это делается на Хаскеле (очень просто), но даже на C# вот такой код вполне работает:


using System;
interface ScalarProduct<A> {
  int scalarProduct(A second);
}
class Nil : ScalarProduct<Nil> {
  public Nil(){}
  public int scalarProduct(Nil second) {
    return 0;
  }
}
class Cons<A> : ScalarProduct<Cons<A>> where A : ScalarProduct<A> {
  public int value;
  public A tail;
  public Cons(int _value, A _tail) {
    value = _value;
    tail = _tail;
  }
  public int scalarProduct(Cons<A> second){
    return value * second.value + tail.scalarProduct(second.tail);
  }
}
class _Test{
  public static int main(int n){
    return _main(n, 0, new Nil(), new Nil());
  }
  public static int _main<A>(int n, int i, A first, A second) where A : ScalarProduct<A> {
    if (n == 0) {
      return first.scalarProduct(second);
    } else {
      return _main(n-1, i+1, new Cons<A>(2*i+1,first), new Cons<A>(i*i, second)); // Works
      //return _main(n-1, i+1, first, new Cons<A>(i*i, second)); // Doesn't work
    }
  }
}
public class Test{
  public static void Main(){
    Console.Write("Enter a number: ");
    int val = Convert.ToInt32(Console.ReadLine());
    Console.WriteLine(_Test.main(val));
  }
}
Однако, переписав этот код почти один в один на C++ (с шаблонами вместо дженериков), получаем... нерабочий код:

#include <iostream>
template <class A> class ScalarProduct {
public:
  virtual int scalarProduct(const A &second) const = 0;
};
class Nil : public ScalarProduct<Nil> {
public:
  Nil(){}
  virtual int scalarProduct(const Nil &second) const {
    return 0;
  }
};
template <class A> class Cons : public ScalarProduct<Cons<A> > {
public:
  int value;
  const A &tail;
  Cons(int _value, const A &_tail) : value(_value), tail(_tail) {}
  virtual int scalarProduct(const Cons<A> &second) const {
    return value * second.value + tail.scalarProduct(second.tail);
  }
};
class _Test {
public:
  static int main(int n){
    return _main<Nil>(n, 0, Nil(), Nil());
  }
  template <class A> static int _main(int n, int i, const A &first, const A &second){
        if (n == 0) {
            return first.scalarProduct(second);
        } else {
          return _main(n-1, i+1, Cons<A>(2*i+1,first), Cons<A>(i*i, second)); // Doesn't work
          //return _main(n-1, i+1, Cons<Nil>(2*i+1, Nil()), Cons<Nil>(i*i, Nil())); // Works, but isn't what we want
        }
    }
};
int main(int argc, char* argv[]){
  std::cout << "Enter a number: ";
  int val;
  std::cin >> val;
  std::cout << _Test::main(val) << std::endl;
  return 0;
}
Бесконечное развёртывание шаблонов.

Джавский вариант тоже, разумеется, работает.

Originally posted on migmit.vox.com

Date: 2009-12-06 01:00 pm (UTC)
From: [identity profile] antilamer.livejournal.com
В Mono, кстати, совсем недавно были баги с инлайнингом полиморфной рекурсии, он тоже пытался все максимально развернуть.

Date: 2009-12-06 02:38 pm (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
Как раз на mono и проверял, ессна.

Date: 2009-12-06 02:40 pm (UTC)
From: [identity profile] antilamer.livejournal.com
Давно ставил? Проверь вот на этом http://bugzilla.novell.com/show_bug.cgi?id=557606 ?

Date: 2009-12-06 02:43 pm (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
Cегодня.

Проверил. Зависло. Damn.

Date: 2009-12-06 03:26 pm (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
У меня mono из портов, версия 2.4.2.3

Date: 2009-12-06 01:57 pm (UTC)
From: [identity profile] mr-aleph.livejournal.com
тут задача с "потенциально бесконечным" числом типов, чего же ты хотел от языка, в котором любая программа должна порождать конечное число типов?

в Java работает, потому что там один тип на самом деле остаётся, случай тут простой и чекер его осиливает...

в C# я думаю типы-инстансы плодяться во время исполнения --- потому и работает...

у С++ нету VM поэтому и беда-беда...

Date: 2009-12-06 02:10 pm (UTC)
From: [identity profile] antilamer.livejournal.com
Кстати давно хотел померить, тормозит ли в C# полиморфная рекурсия из-за проверки "есть ли уже такой инстанс метода" в рантайме.

Date: 2009-12-06 02:40 pm (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
> чего же ты хотел от языка, в котором любая программа должна порождать конечное число типов?

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

> в C# я думаю типы-инстансы плодяться во время исполнения --- потому и работает...

А там не как в жабе сделано? Я о внутренностях шарпа вообще нифига не знаю.

> у С++ нету VM поэтому и беда-беда...

У GHC тоже нет, но повторить там подобную штуку - нет проблем. И да, там тоже один тип остаётся.

Date: 2009-12-06 02:55 pm (UTC)
From: [identity profile] mr-aleph.livejournal.com
> шаблоны таки дают параметрический полиморфизм

Ну, а они его и дают. Просто не надо хотеть всяких извращений =)

Ну не умеют С++-компиляторы просекать типы с одинаковым "представлением" и использовать для них один и тот же шаблон...

Что ж поделать...

> А там не как в жабе сделано?

Вроде там честное инстанциирование и можно делать new T(), чего в Java делать нельзя. Могу наврать впрочем...


Date: 2009-12-06 03:01 pm (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
> Ну, а они его и дают.

Если бы давали - оно бы работало. Они дают иллюзию параметрического полиморфизма.

> Ну не умеют С++-компиляторы просекать типы с одинаковым "представлением"

Если бы был параметрический полиморфизм, то был бы одни тип.

> Вроде там честное инстанциирование и можно делать new T(), чего в Java делать нельзя. Могу наврать впрочем...

А можно чуть подробнее? А то я в жабе ламер...

(no subject)

From: [identity profile] mr-aleph.livejournal.com - Date: 2009-12-06 03:03 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2009-12-06 03:17 pm (UTC) - Expand

(no subject)

From: [identity profile] mr-aleph.livejournal.com - Date: 2009-12-06 03:12 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2009-12-06 03:22 pm (UTC) - Expand

(no subject)

From: [identity profile] mr-aleph.livejournal.com - Date: 2009-12-06 03:24 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2009-12-06 03:29 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2009-12-06 03:32 pm (UTC) - Expand

(no subject)

From: [identity profile] mr-aleph.livejournal.com - Date: 2009-12-06 03:13 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2009-12-06 03:22 pm (UTC) - Expand

Date: 2009-12-06 08:19 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
Вы, надеюсь, понимаете, что ввиду отсутствия определения параметрического полиморфизма ваш пост - просто фантазия. Вы написали какой-то код, который якобы, как подсказывает вам ваше образное мышление на основании туманных эмоциональных образов, использует параметрический полиморфизм, а затем переписали этот код на другой язык, где он не заработал. И на этом основании заявляете, что в С++ нету параметрического полиморфизма, а в Java он есть. Как можно обсуждать то, что невозможно точно определить?

Date: 2009-12-06 11:42 pm (UTC)
From: [identity profile] udpn.livejournal.com
Даже несмотря на то, что я полностью согласен с вами... Должен реквестировать доказательство, что параметрический полиморфизм невозможно точно определить.

Похоже, очень даже можно, причем несколькими методами. Каждый из них вполне точный и дает свой особый ППМ.

Date: 2009-12-07 06:05 am (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
Во-1, порядок был обратный (сначала была написана плюсовая версия, потом жабская, потом шарповая).

Во-2, да, пост рассчитан на то, что понимание понятия "параметрический полиморфизм" у читателей совпадает с моим. Если ваше - не совпадает, то предьявить собственное определение должны ВЫ.

В-3, покажите мне хоть один ЖЖ-пост, где определены все используемые понятия.

Date: 2009-12-07 06:10 am (UTC)
From: [identity profile] nponeccop.livejournal.com
> В-3, покажите мне хоть один ЖЖ-пост, где определены все используемые понятия.

Это ж мой главный аргумент - что все эти тёрки в ЖЖ о том, чей полиморфизм круче, не имеют научного смысла, т.к. за неимением общепринятого определения отсутствует предмет обсуждения.

Date: 2009-12-07 06:27 am (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
И только-то? Вы могли не трудиться, излагая подобный трюизм. Я не считаю ЖЖ научным журналом и не считаю себя обязанным соблюдать научную строгость при публикации.

(no subject)

From: [identity profile] nponeccop.livejournal.com - Date: 2009-12-07 06:44 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2009-12-07 06:53 am (UTC) - Expand

(no subject)

From: [identity profile] nponeccop.livejournal.com - Date: 2009-12-07 02:44 pm (UTC) - Expand

Date: 2009-12-07 06:41 am (UTC)
From: [identity profile] nponeccop.livejournal.com
> Если ваше - не совпадает, то предьявить собственное определение должны ВЫ.

Вообще-то никто никому ничего не должен. Я не говорил, что вы мне что-то должны.

Во-первых, как я могу понять, что моё определение не совпадает с вашим? Хорошо, если размышляя, используя свое определение, я приду к противоречию, и пойму, что что-то не так. А если не приду? Тогда возникнет тихое недопонимание, и я, возможно, заражусь от вас ложными убеждениями.

Соответственно, упоминание используемых определений полезно скажется на качестве вашего ЖЖ. Разумеется, по умолчанию подразумевается, что вы используете общепринятые термины, и ничего пояснять не надо. Но в данном конкретном случае общепринятого определения нет, и пояснения были бы полезны.

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

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

Date: 2009-12-07 06:52 am (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
> Хорошо, если размышляя, используя свое определение, я приду к противоречию, и пойму, что что-то не так. А если не приду? Тогда возникнет тихое недопонимание, и я, возможно, заражусь от вас ложными убеждениями.

В математике, например, это происходит сплошь и рядом, если речь идёт о таких областях, где понятия ещё не до конца устаканились. Да и в основах тоже: в одних статьях, например, ноль считают натуральным числом, в других нет. И как-то все понимают.

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

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

> мне было интересно вас подколоть, такой микротроллизм

Рискуете. Я умею обращаться с банхаммером.

(no subject)

From: [identity profile] nponeccop.livejournal.com - Date: 2009-12-07 02:44 pm (UTC) - Expand

(no subject)

From: [identity profile] nponeccop.livejournal.com - Date: 2009-12-07 02:58 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2009-12-07 03:13 pm (UTC) - Expand

(no subject)

From: [identity profile] nponeccop.livejournal.com - Date: 2009-12-07 03:52 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2009-12-07 06:04 pm (UTC) - Expand

(no subject)

From: [identity profile] nponeccop.livejournal.com - Date: 2009-12-07 03:58 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2009-12-07 03:59 pm (UTC) - Expand

Date: 2010-02-11 02:24 pm (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
Отвечаю на вопрос из другого топика:

> Ну и почему же Sun тогда не ввели новые, полностью безопасные generic классы?

Недостаток времени/лень/память подвела/не сообразили - спросите у фирмы Sun.

> Нет, и что? Это возмножно и в языке, в котором типов нет ВООБЩЕ.

Отмотать для вас тред?

>>>>Ага, только в результате не получается вводить полиморфные типы, аргументы которых заранее неизвестны.
>>>Для этого вполне подходит ООП (фабрики классов и т.п.), да и в простом Си это тоже возможно.
>>Нет. Система типов C тем более полиморфных типов не содержит (вообще). И даже имитации нет.
>Нет, и что? Это возмножно и в языке, в котором типов нет ВООБЩЕ.

Может быть, вы мне объясните, с помощью какой магии можно вводить полиморфные типы, если типов нет?

>>Но вы порывались утверждать, что возможности дженериков меньше, чем возможности темплейтов C++.
>"Хозяин" C# -- Микрософт в лице MSDN со мной согласна.

Что вы говорите! А я-то думал, что по приведённой вами ссылке указаны НЕКОТОРЫЕ (но не все) отличия темплейтов от дженериков. Видимо, я где-то не заметил фразу "дженерики имеют меньше возможностей, чем C++".

В любом случае, это неправда - пример приведён.

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

Вы спросили про продакшен. Мне лично представляется, что продакшен-код в подавляющем большинстве случаев содержит ОЧЕНЬ много строк.

> А я называл?

Вы писали: "а оказывается лучше дженерики C#/Java (которые на самом деле были введены для того, чтобы убрать приведение типов при доступе к контейнеру)." Поскольку статья, собственно, рассматривает именно вопрос о полиморфизме, то вариантов два: либо вы согласны с тем, что темплейты не дают параметрического полиморфизма (и, значит, фраза из статьи в этом контексте верна), либо нет - тогда вы в очередной раз не видите очевидного.

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

Неверно. Можно реализовать любой алгоритм; это не значит, что можно реализовать любую ИДЕЮ.

> для решения простой задачи понапихали тайпкастов и рефлексий.

Я не понял задачу. Если она имеет отношение к дискуссии, то расшифруйте. Если нет - не надо.

> Вы умнее меня, поэтому уж расскажите, как в Java сделать так, чтобы можно было обощенно использовать complex, complex, а еще complex и complex, и (о ужас, basic_string) -- все это помогает создавать легко читаемый код.

Более подробно можно? Что вы хотите получить в итоге? В чём у вас проблема?

Date: 2010-02-12 07:10 am (UTC)
From: [identity profile] secondary-tea.livejournal.com
>Поскольку статья, собственно, рассматривает именно вопрос о полиморфизме, то вариантов два: либо вы согласны с тем, что темплейты не дают параметрического полиморфизма (и, значит, фраза из статьи в этом контексте верна),
Трудно с чем-то согласиться или не согласиться в статье, которая написана так, что и человеку, который "в теме", трудно ее читать. Может быть в книге, на которую автор ссылается, есть внятное определение параметрического полиморфизма, но я ее не читал. В статье написано, что параметрический полимофизм не имеет ограничений, а ad-hoc имеет. Типобезопасные генерики в Java должны иметь ограничение -- от чего-то там унаследоваться и т.п. , то есть по приведенному автором признаку это больше похоже на ad-hoc полиморфизм (я не утверждаю, что это так, просто как пример, что изложение очень невразумительное).

>либо нет - тогда вы в очередной раз не видите очевидного.
По опредлению очевидного, то, на что Вы сослались -- не очевидно.

>Вы писали: "а оказывается лучше дженерики C#/Java (которые на самом деле были введены для того, чтобы убрать приведение типов при доступе к контейнеру)."
Я это писал в контексте кода, реализованного на Си++, приведенного непосредственного выше по тексту. Насколько я знаю C# и Java, на них аналог кода, написанного в статье на C++ можно сделать только при помощи рефлексий, там кстати ошибка int result=0; вместо T result; . Примеров кода на Java автор почему-то не дает и хочет, чтобы их написали читатели.

И вообще, судя по тому, что участник топкодера Haskell-master (http://www.topcoder.com/tc?module=MemberProfile&cr=22627322) пишет на С++, Haskell идеологически ближе C++, нежели чем C# или Java. Топкодер, кстати, Java-центричен - эталонные решения задач пишутся на Java, возможность решения на C++/C# не гарантируется.

>Неверно. Можно реализовать любой алгоритм; это не значит, что можно реализовать любую ИДЕЮ.
Может быть и так. Только термин "ИДЕЯ" не является научным даже отдаленно, а ненаучное я рассматривать не буду.

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

Date: 2010-02-12 08:49 am (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
> Трудно с чем-то согласиться или не согласиться в статье, которая написана так, что и человеку, который "в теме", трудно ее читать.

Но у вас получилось:

> Откровенное вранье там присутствует, еще как

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

Полиморфизм: разные типы, один интерфейс.

Ad-hoc-полиморфизм: разные типы, один интерфейс, разные реализации.

Параметрический полиморфизм: разные типы, один интерфейс, одна реализация.

> изложение очень невразумительное

Естественно, это же Душкин.

> Насколько я знаю C# и Java, на них аналог кода, написанного в статье на C++ можно сделать только при помощи рефлексий, там кстати ошибка int result=0; вместо T result; .

Вы про это?
template<class T> T sum (std::list<T> iList) {
  int result = 0;
  for (std::list<T>::iterator i = iList.begin (); i != iList.end (); ++i) {
    result += *i;
  }
  return result;
}

На Java это делается примерно так:
interface Plus<A> {
  void plus(A arg);
}
class Sum<A extends Plus<A>> {
  A sum(A[] list){
    A result = new A();
    for (int i = 0; i < list.size(); i++){
      result.plus(list[i]);
    }
    return result;
  }
}


При мне сейчас нет жабакомпилятора, так что не гарантирую синтаксическую корректность. Ключевое место - это class Sum<A extends Plus<A>>.

> Haskell идеологически ближе C++, нежели чем C# или Java.

Если смотреть из того места, где находится Haskell, то C++, Java и C# почти неразличимы.

> Только термин "ИДЕЯ" не является научным даже отдаленно, а ненаучное я рассматривать не буду.

Ваши проблемы.

Date: 2010-02-12 11:27 am (UTC)
From: [identity profile] secondary-tea.livejournal.com
>На Java это делается примерно так:
Код не компилируется: видны плюсистские привычки. В жабе нужно писать не .size(), а .length; и Вам уже как минимум 2 (два) человека (я и Алеф) сказали, что в жабе нельзя инстанцировать параметризованный тип, а Вы пытаетесь это сделать. К тому же Вы зачем-то заменили связанный список на массив (вероятно, это хаскельные привычки).
После устранения этих ошибок код все равно получается практически бесполезный. Во-первых, вместо 1 сишной функции объявлены 2 класса и 2 функции. Во-вторых, складывать он может только те элементы, которые унаследованы от Plus. То есть с "примитивными" типами он не работает. Надо для каждого примитивного типа и любого другого, который нам понадобится складывать, завести класс-оболочку. То есть количество копипасты получается одинаковым: вместо нескольких функций Sum программист будет копипастить оболочки. В ряде случаев можно унаследоваться от целевого класса, а если он объявлен final (как например string?) -- то придется делать аггрегацию и копипастить объявления конструкторов и прочих методов. И полученный класс нельзя будет передавать в методы, которые требуют string.

>Если смотреть из того места, где находится Haskell, то C++, Java и C# почти неразличимы.
Что думает сам Haskell-master, лучше спросить у него самого. Общее между Haskell и C++, например, то, что есть полиморфизм времени компиляции и нет принудительного ООП.

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-12 11:35 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-12 11:58 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-12 12:04 pm (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-12 12:11 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-12 12:15 pm (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-14 03:44 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-14 09:23 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-16 05:54 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-16 07:35 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-18 10:13 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-18 10:49 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-20 05:02 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-20 09:14 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-22 07:52 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-22 08:38 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-22 10:19 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-22 10:22 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-22 10:33 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-22 11:57 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-22 12:11 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-22 12:23 pm (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-25 04:48 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-25 05:36 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-25 06:42 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-25 06:50 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-26 04:51 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-26 05:36 pm (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-03-01 06:34 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-03-01 09:02 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-03-01 12:02 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-25 06:56 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-14 03:48 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-14 09:13 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-16 05:47 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-16 07:31 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-18 10:15 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-14 09:51 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-16 05:56 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-16 07:30 am (UTC) - Expand

Date: 2010-02-12 07:09 am (UTC)
From: [identity profile] secondary-tea.livejournal.com
>Что вы говорите! А я-то думал, что по приведённой вами ссылке указаны НЕКОТОРЫЕ (но не все) отличия темплейтов от дженериков. Видимо, я где-то не заметил фразу "дженерики имеют меньше возможностей, чем C++".
http://msdn.microsoft.com/en-us/library/c6cyy67b(VS.80).aspx
Ну давайте почитаем различия между ними. Первое:
C# generics do not provide the same amount of flexibility as C++ templates.
Дальше идут пять (5) пунктов, начинающихся с C# does not
И еще
At the implementation level, the primary difference is that C# generic type substitutions are performed at runtime
У темплэйтов C++ есть куча недостатков, только они не оказались достаточно значимыми, чтобы быть упомянутыми в статье из MSDN. То, что генерики C# интстанцируются в рантайме -- это круто, но mixed blessing... Это значит, что на очень большом числе архитектур генерики C# работать не будут вообще.

>Может быть, вы мне объясните, с помощью какой магии можно вводить полиморфные типы, если типов нет?
Если типов нет в языке, это не значит, что их нет вообще. Главное, чтобы функция имела общий интерфейс к полиморфному типу, с которым она работает, -- если интерфейса нет, то действительно необходима магия, или хотя бы ЛИСП. Интерфейс может быть любым. Например, qsort из Си может сортировать данные любых типов благодаря указателю на функцию.

В Java генерики не работают с "примитивными" типами. Все остальные типы в Java -- это всегда указатель на объект, в терминах Си -- void * (реже void **). В каждом объекте по фиксированному смещению лежит указатель на дескриптор класса. В дескрипторе класса по фиксированному смещению лежит указатель на таблицу виртуальных функций реализаций (с интерфейсами сложнее, т.к. для них есть множественное наследование). Кстати, конструкторов в этой таблице нет и поэтому нельзя вызвать конструктор для параметризованного типа. Поскольку JIT'ы никогда не хранят скомпилированный код на диске, а только статистики выполнения, проблемы бинарной несовместимости не возникает. Таким образом, генерик-функция работает фактически с одним типом -- void * с пришпиленными таблицами , по которым процессор может найти нужные ООП функции. Это в первом приближении, а во втором JIT-компилятор может создать сколько угодно экземпляров генерик-функции с заинлайненными вызовами и это поведение контролировать на уровне исходного кода нельзя. Следствие -- что генерики в Java бесполезны без ООП. Другое следствие -- если бы не было общего предка (Object), то ситуация была гораздо хуже. В C# "примитивные" типы при подстановке в генерик подвергаются автобоксингу -- и дальше действует схема, похожая на вышеописанную, но с существенными отличиями. Инстанцирование в C# необходимо, т.к. там могут быть значимые типы (которые не являются void*) и таким образом, функция действительно должна работать с другими объектами.

>В любом случае, это неправда - пример приведён.
Имеющий практического смысла меньше, чем ray-tracer в compile-time.
>Вы спросили про продакшен. Мне лично представляется, что продакшен-код в подавляющем большинстве случаев содержит ОЧЕНЬ много строк.
Особенно если это индусский или китайский код.

Как надо: запускаем Maple или если ее нет, идем на http://www.wolframalpha.com/input/
вбиваем sum(i=0..n-1,(2*i+1)*i*i)
После чего пишем в код обширный комментарий, проверку и строку, которая вычисляет нужное за O(1)
if(n<0) throw чего-то там;
return (n-1)*n*(3*n*n-n-1)/6;
если не будет хватать диапазона значений, легко будет изменить одну строку, а не раскиданные по всему коду.

Date: 2010-02-12 08:57 am (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
> Ну давайте почитаем различия между ними.

Ещё раз:

>> по приведённой вами ссылке указаны НЕКОТОРЫЕ (но не все) отличия темплейтов от дженериков.

Поэтому этой статьёй можете хоть обчитаться.

> Это значит, что на очень большом числе архитектур генерики C# работать не будут вообще.

Гм. Учитывая, что C# работает на, по сути, ОДНОЙ архитектуре (.NET)...

> Если типов нет в языке, это не значит, что их нет вообще.

И откуда тогда В ЯЗЫКЕ возьмутся полиморфные типы?

> Кстати, конструкторов в этой таблице нет и поэтому нельзя вызвать конструктор для параметризованного типа.

В шарпе можно.

> Таким образом, генерик-функция работает фактически с одним типом -- void * с пришпиленными таблицами , по которым процессор может найти нужные ООП функции.

Это всё - исключительно детали реализации, которые никого не ебут. Вопрос не в том, что там происходит в бинарнике, вопрос в том, какие возможности у ЯЗЫКА.

> Следствие -- что генерики в Java бесполезны без ООП.

Что вы разумеете под "ООП", в данном случае? На самом деле, я полагаю, что жаба без наследования (но с реализацией интерфейсов) и с дженериками была бы весьма полезной штукой.

> Имеющий практического смысла меньше, чем ray-tracer в compile-time.

А вы что хотели от примера?

>> Вы спросили про продакшен. Мне лично представляется, что продакшен-код в подавляющем большинстве случаев содержит ОЧЕНЬ много строк.
> Особенно если это индусский или китайский код.

Может быть, покажете продакшен-код, умещающийся в один ЖЖ-шный постинг?

> вбиваем sum(i=0..n-1,(2*i+1)*i*i)
> После чего пишем в код обширный комментарий, проверку и строку, которая вычисляет нужное за O(1)
> if(n<0) throw чего-то там;
> return (n-1)*n*(3*n*n-n-1)/6;

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

Date: 2010-02-12 11:46 am (UTC)
From: [identity profile] secondary-tea.livejournal.com
>>> по приведённой вами ссылке указаны НЕКОТОРЫЕ (но не все) отличия темплейтов от дженериков.
Ссылку в MSDN, где приведены ВСЕ различия, не подскажете?

>Гм. Учитывая, что C# работает на, по сути, ОДНОЙ архитектуре (.NET)...
Вы правы.

>И откуда тогда В ЯЗЫКЕ возьмутся полиморфные типы?
Вам шашечки или ехать? Меня больше интересуют ПРОГРАММЫ, а не языки.

>Это всё - исключительно детали реализации, которые никого не ебут.
Тем не менее Душкина и Вас почему-то занимает вопрос, как обрататывает исходный код компилятор C++. Про кодогенератор GHC почему-то ни слова, Алеф негодует.

>Может быть, покажете продакшен-код, умещающийся в один ЖЖ-шный постинг?
На коммент ограничение 4 тысячи символов, на пост еще больше. Вы хотите сказать что в продашкн коде не бывает модулей менее 4 кб ?

>Что вы разумеете под "ООП", в данном случае? На самом деле, я полагаю, что жаба без наследования (но с реализацией интерфейсов) и с дженериками была бы весьма полезной штукой.
Я читал интервью одного из разработчиков Java, что он так бы и сделал (ссылку, к сожалению, не могу найти). Только вот, между наследованием от интерфейса и наследованием от абстрактного класса семантически нет никакой разницы. ООП = все, что использует виртуальные функции или эквивалент. Страуструп сказал в 80-х: "вам не нужен С++, если вы не используете виртуальные функции". К настоящим объектным языкам я этот критерий не отношу.

>Вы, надеюсь, понимаете, что мне не составит абсолютно никакого труда заполнять массив не заранее известными числами,
Вот ТАМ у Вас как раз не массив, а связный список. Опять путаете.
>а вводимыми пользователем? И будет при этом то же самое.
На хаскеле, с инкапсуляцией ввода в монады?

Date: 2010-02-12 11:55 am (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
> Ссылку в MSDN, где приведены ВСЕ различия, не подскажете?

Нет, не подскажу.

> Вам шашечки или ехать? Меня больше интересуют ПРОГРАММЫ, а не языки.

Тогда какого хрена вы разговариваете о возможностях ЯЗЫКОВ?

> Тем не менее Душкина и Вас почему-то занимает вопрос, как обрататывает исходный код компилятор C++.

Не занимало бы, если бы не отражалось на возможностях языка.

> На коммент ограничение 4 тысячи символов, на пост еще больше. Вы хотите сказать что в продашкн коде не бывает модулей менее 4 кб ?

Бывают, конечно. Так почему вы так испугались, когда я сказал, что продакшен-код будет больше?

> Я читал интервью одного из разработчиков Java, что он так бы и сделал (ссылку, к сожалению, не могу найти).

Интересно, не знал.

> Только вот, между наследованием от интерфейса и наследованием от абстрактного класса семантически нет никакой разницы.

Да. Если хотите, чтобы я сказал "оставьте наследование только от (полностью) абстрактных классов" - пожалуйста. Правда, тогда проще будет, если обозвать их "интерфейсами".

> Вот ТАМ у Вас как раз не массив, а связный список.

Глубоко по барабану.

> На хаскеле, с инкапсуляцией ввода в монады?

Могу и на хаскеле, да. Так уж получилось, знаете, что интерфейс ввода-вывода в хаскеле монадический.

А могу на жабе, или на шарпе.

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-12 12:07 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-12 12:10 pm (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-14 03:44 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-14 09:17 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-16 05:50 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.vox.com - Date: 2010-02-16 07:29 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2010-02-18 10:21 am (UTC) - Expand