Friday, May 04, 2007

Динамические языки внутри .net и JVM

В продолжение к предыдущему посту — а собственно почему столько шума? Зачем столько пафоса при релизе DLR?

А дело все в том, что и sun и microsoft последние несколько лет внимательно смотрят в сторону динамических языков. Потому как различные php, python'ы и ruby играют нынче мощную роль на рынке — и на этот рынок, конечно, хочется влиять.

Когда создавались .net и JVM основной их задачей было соответственно выполнение C# и Java программ, об остальном их создатели думали не столь внимательно. Как заметил автор этой презентации, по аналогии с известным высказыванием Г. Форда, "вы можете запустить на .net любой язык, если это C#".

Однако вскоре стало понятно что одной явой и C# при написании веб-приложений сыт не будешь, тут-то собственно языки тоже заинтересовали и sun, и ms — последняя наняла Jim Huguin'а, автора JPython, а sun прошлым летом наняла авторов JRuby.

Проблемы реализации прежде всего вырастают из того факта, что и CLI, и JVM прежде всего ориентированы на языки со статической типизацией — у них даже байт-код строго статически типизированный. А динамическому языку нужно позднее связывание (оно же динамическая диспетчеризация) — при вызове a.someMethod() какой именно метод вызывать выясняется во время выполнения, основываясь на динамическом типе значения a. Причем a вообще может не иметь такого метода — это заранее неизвестно.

А при вызове call, callvirt в .net мы должны заранее, статически, знать класс объекта (как и при вызове метода — обычном или виртуальном — в C++).

Конечно, проблема решается довольно-таки очевидным способом — в CLR и java все классы наследуются от корневого Object — соответственно процедуры в динамическом языке получают тип Object someMethod(Object[] args), и в местах вызова вставляется код который ищет в словаре соответствующий метод у объекта. С одной стороны тут возникает некоторое количество сложностей, с другой — благодаря развитому reflection'у и генерации кода на лету — все проблемы решаются, и даже получается оптимизировать такие вызовы — если в o.someMethod() значение переменной o имеет всегда один и тот же тип, каждый раз тратить O(logN) времени на поиск по словарю не надо, и т.п.

Эффективные, обкатанные на IronPython решения для этой и других (динамическая типизация, изменение классов на лету, closures...) проблем как раз и предоставляет DLR. Для JVM кстати что-то похожее уже создавалось — однако то ли эту библиотеку вообще не релизили, то ли я плохо искал. А вообще уже несколько лет тянется процесс добавления в яву байт-кода invokedynamic — который будет как раз реализовывать позднее связывание на уровне виртуальной машины.

Теперь интересные линки:
Итого, что мы имеем из динамических языков, компилируемых в байт-код:
на JVM: JPython, JRuby, Groovy на CLI: IronPython, JScript.Net, VB.NET, PHP (На самом деле динамических языков намного больше, но остальные вроде как в байт-код напрямую не компилируются).

JVM:



.NET:

1 comment:

Alex Ott said...

из динамических для JVM еще можно упомянуть реализации Scheme - Kawa & Bigloo