Примитивы и generic’и в Scala

Когда я только знакомился со Scala, я был впечатлён тем, что ребятки разрешили проблему с поддержкой примитивов в generic’ах, или параметризированных типах, как их здесь называют. Это то, чего в Java очень не хватало. Недавно я заинтересовался деталями реализации, как конкретно это работает. И тут мне открылось страшное.

Оказалось, что по умолчанию компилятор генерирует байт-код только для AnyRef’ов, а примитивы боксятся в Number-объекты, т.е. получается то же, что и в Java. Для того, чтобы сгенерировать байт-код с поддержкой примитивов, надо дополнять сигнатуру аннотацией specialized, и вот тогда при компиляции класса будет сгенерировано несколько версий байт-кода с поддержкой каждого примитива по отдельности. И вот тут кроется чудовищная драма.

Для каждого параметра типа возможно десять различных вариантов байт-кода – для AnyRef (Object), для восьми примитивов и для Unit (void). Если у класса есть два параметра типа, число различных вариантов байт-кода возрастает до ста (10 х 10), и в более общем случае получается, что для класса с N параметрами типа нужно генерировать 10^N версий байт-кода. Мантиссу можно скорректировать, указывая в specialized конкретные примитивы к поддержке, но это делу помогает несильно – объем байт-кода все равно растет экспоненциально.

Из-за этого, чтобы избежать разрастания размеров стандартной библиотеки, аннотацией @specialized отмечены всего несколько классов – Function, Product и Tuple размерностью до двух, а также их Abstract реализации. Получается, что весь collection framework на самом деле не поддерживает специализацию, и в работе с примитивами ничуть не лучше, чем в Java. Поэтому в экосистеме Scala появились отдельные библиотеки со specialized коллекциями типа debox, а также обертки над нижеупомянутыми Java библиотеками. В Java ситуация аналогичная – там есть Trove или Fastutil. Получается, что в работе с примитивами в рантайме «голая» Scala вообще не отошла от Java, хотя изначально унификация системы типов Scala заявлялась её адептами как сокрушительное преимущество.

К счастью, кое-какие подвижки все-таки есть, но о них как-нибудь в следующий раз.

Дополнительное чтение: