LINUX.ORG.RU

Зачем нужны динамические языки?


0

0

Собственно не пойму. Вроде обещают более быструю разработку, но за счет чего? За счет того, что не надо писать тип при объявлении переменной? Так это ведь глупость, никакой скорости разработки это не добавит. Естественно, такие языки можно использовать только для прототипирования, но не проще ли сразу использовать язык, который обеспечит и скорость разработки и скорость выполнения, тем более, что динамический язык принципиально нельзя ускорить (имеется ввиду компилятор)? (я имею ввиду современные языки с выводом типов)

Ответ на: комментарий от jtootf

Tcl метаязык? Вот лисп - метаязык. А tcl ни для чего кроме скриптоложества, уж извините, не приспособлен.

Динамика дает динамичность программы в рантайме, и в этом ее главный плюс.

guest-3484-2009
()
Ответ на: комментарий от guest-3484-2009

>Tcl метаязык? Вот лисп - метаязык. А tcl ни для чего кроме скриптоложества, уж извините, не приспособлен

а насколько ты знаешь Tcl чтобы это утверждать?

>Динамика дает динамичность программы в рантайме, и в этом ее главный плюс

на основании этого треда уже можно писать песню. ну или трактат по философии

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

> на основании этого треда уже можно писать песню. ну или трактат по философии

Рано. Мне пока так и не запостили убеждающий пример на хаскеле.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>Конечно НЕ пойдет. Имеется в виду . из с/с++

так на чём написать-то надо? на C++? или на Haskell?

jtootf ★★★★★
()
Ответ на: комментарий от guest-3484-2009

> Tcl метаязык? Вот лисп - метаязык. А tcl ни для чего кроме скриптоложества, уж извините, не приспособлен.

Прослезился. Как это по-лисперски :')
Правильно говорят, что сильнее всех тикль ненавидят лисперы. Столлман тому ярчайшее подтверждение.

> Динамика дает динамичность программы в рантайме, и в этом ее главный плюс.


Простите, я не очень понимаю японскую поэзию. Как это будет по-русски?

gaa ★★
()
Ответ на: комментарий от mv

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

Круто, спасибо.

gaa ★★
()
Ответ на: комментарий от www_linux_org_ru

>Рано. Мне пока так и не запостили убеждающий пример на хаскеле

http://www.cs.uwyo.edu/~skothari/cppvshaskell.pdf

если ещё не читал - делюсь. над примером не было времени подумать, приду домой - буду ваять

jtootf ★★★★★
()
Ответ на: комментарий от gaa

>Сделать с телом функции можно что угодно, это обычный список

в REBOL тоже список, в Tcl это обычная строка; вот интересно, а в Рефал что?

jtootf ★★★★★
()
Ответ на: комментарий от guest-3484-2009

>А еще можно через m4. Даже круче строк и eval получается.

ну и славненько

>Тогда Си вообще самый-пресамый метаязык, выходит.

в связке с m4 - в принципе неплохо, да. а можно определение труЪ-метапрограммирования? а то сложно спорить о сферическом коне в вакууме

jtootf ★★★★★
()
Ответ на: комментарий от guest-3484-2009

> А еще можно через m4. Даже круче строк и eval получается.
> Тогда Си вообще самый-пресамый метаязык, выходит.


Фуфло хоть не компилируется в отличии от :]

sf ★★★
()
Ответ на: комментарий от guest-3484-2009

> А фуфло, это у вас, стало быть, ошибки типов опять?
> Хаскелеводы банальны до невозможности.


Ну почему. Скобки там лишние, запятые, собачки, двоеточия нехватающие ;]

У Вас ошибок вообще не бывает, судя по постам.
Иначе я просто не могу обьяснить тягу сгенерить их всеми доступными способами.
В lisp среде сторонние библиотеки не принято обновлять?

sf ★★★
()
Ответ на: комментарий от sf

>У Вас ошибок вообще не бывает, судя по постам.
Бывает, однако, ошибки они, видите ли, двух видов бывают - аппаратные, логические и опечатки. От первых не спасет ничего, от вторых вас типизация тоже не особо охраняет, от третьих - только от передачи в функцию строки вместо числа(и другого подобного). А вот макросы в лиспе сводят на нет третьи, и в то же время уменьшают вероятность вторых, т.к. выводят абстракцию на качественно новый уровень, позволяя мыслить в терминах решаемой задачи и не отвлекаться на низкоуровневые детали и детали реализации.
>Иначе я просто не могу обьяснить тягу сгенерить их всеми доступными способами.

А я вот не могу понять стремление бегать в стальных валенках.
>В lisp среде сторонние библиотеки не принято обновлять?

А это тут причем?

guest-3484-2009
()
Ответ на: комментарий от sf

> В lisp среде сторонние библиотеки не принято обновлять?

Принято. Более того, обновленная библиотека может поломать функциональность старой (поищи посты den73 со словом weblock)

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> Ну так где твой суперпример на хаскеле? Аналог моего на плюсах, но с const T* ?

А можно точную постановку задачи? Я в какой-то момент потерял эту нить разговора, а теперь не понимаю, о чём речь идёт.

Miguel ★★★★★
()
Ответ на: комментарий от Miguel

> А можно точную постановку задачи? Я в какой-то момент потерял эту нить разговора, а теперь не понимаю, о чём речь идёт.

Вот там sf поставил (мне кажется, в плюсах без лишнего параметра не обойтись, интересно как в хаскеле)

http://www.linux.org.ru/jump-message.jsp?msgid=3594542&cid=3600072

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от guest-3484-2009

> >У Вас ошибок вообще не бывает, судя по постам. > Бывает, однако, ошибки они, видите ли, двух видов бывают - аппаратные, логические и > опечатки. От первых не спасет ничего, от вторых вас типизация тоже не особо охраняет, от

Не согласен :] Гораздо проще ошибиться, когда в языке всего то 2 базовых типа - и те нельзя проверить на правильность употребления до запуска программы без самописных средств(даже если этого кода очень мало). А их для lisp особо не напишешь в свете eval и перегрузки reader-macro (или я не прав?).

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

Классный пример автоматического тестирования функции в haskell - либа QuickCheck. Основываясь на _типе_ инварианта генерирует произвольные входные данные и проверяет его. Как в lisp сделать что-то подобное я не знаю.

Видать, это больше идеологический вопрос :]

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

Звучит как назначение языка программирования как такового. Я с этим тоже не согласен(про всемогущесть макросов, но я верю в их удобство! :]) - надо ж лупасить скобки и функции/макросы с параметрами, нет? Или обычно дело влепить какие-нить reader macros?

От языка не так много надо, чтобы на нем можно было реализовавыть собственные fool-proof абстракции. Всё равно полностью абстрагироваться не получается (если только полностью не разделять язык реализации и пользовательский DSL). Влазят какие-то константы, числа, строки, предикаты, функции высшего порядка и в чистом виде присутствуют в свежеслепленном DSL и вытаскивают наружу (ну или между внутренностями, но я хочу проверить хотя-бы часть исходника) эти гадкие базовые типы.

Последний написанный мной классификатор на ruby (:p) предоставлял вообще отдельный микроязык именно для того, чтобы увеличить информативность об ошибках и проверять типы и вычислять простейшие выражения.

> >Иначе я просто не могу обьяснить тягу сгенерить их всеми доступными способами. > А я вот не могу понять стремление бегать в стальных валенках. Мне не нравится эта аналогия. Она не отражает сути.

> >В lisp среде сторонние библиотеки не принято обновлять? > А это тут причем? Просто интересно как происходит процесс познания (например, случайно) немного изменившегося API модуля. Функции с &rest аргументами совсем не радуют :[

sf ★★★
()
Ответ на: комментарий от www_linux_org_ru

> > Фуфло хоть не компилируется в отличии от :]

> Ну так где твой суперпример на хаскеле? Аналог моего на плюсах, но с const T* ?

Не могу заставить компилироваться :] (шутка) Как только осилю - сразу запощу.

sf ★★★
()
Ответ на: комментарий от www_linux_org_ru

> Ну пролог такой мелкий язычишко, который стыдно не знать.

судя по всему пролог в умелых руках огого :)

http://gazeta.ru/science/2009/04/03_a_2969757.shtml

правда все могучие книги по нему после рассмотрения библейской базы имен в начале плавно переходят к --- "а вот так мы получаем списки (ет цетера) и теперь все и начинается по настоящему..." :)

psv1967 ★★★★★
()
Ответ на: комментарий от jtootf

листинг на 156 странице... это просто открыл вот прямо "не листая".

кроме того все буквы во "фразе" в книге встречаются :)

psv1967 ★★★★★
()
Ответ на: комментарий от psv1967

>в общем пролог кончается к 94 странице (там же начинаются "списки" :)

насколько я помню, там во второй части идёт описание eDSL для решения шахматного эндшпиля. впрочем, уточню :)

jtootf ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>> А если писать селектор типа такого: a get -dir "inbox" -account "vasya_pupkin@test.ru", то такую ошибку совершить невозможно. Отсюда хороший дизайнерский хинт: если ключей больше двух, их стоит подписать.

> В том, что ключевые (а не позиционные) параметры нужны, ты прав. Но ты возможно забываешь о том, что у нас имеется куча функций, принимающих на вход данные с интерфейсом "массив" (или в языках со статикой -- коллекция, forward_iterator, ...). И вот твое изделие нужно будет адаптировать под это дело. В языках со статикой и мощной системой типов такую адаптацию можно написать раз и навсегда, причем надежно. Делать это будет компилятор во время компиляции.

> В динамическом языке -- вероятно придется патчить интерфейс коллекции, ну или сразу его писать таким, чтобы он выполнял ту работу, которую выполняет компилятор. Нет? 

В динамических языках всё делается совсем по другому. Если кто-то в Ruby хочет добавить метод sum ко ВСЕМ контейнерам (колекциям), то он пишет

  class Enumerable
    def sum
      inject{|a,b| a+b}
    end
  end

Примесь Enumerable примешена к Array, String, Set, Range, Map ...
И если ты написал свой новый контейнер с методом each для итерирование элементов контейнера -- будь добр, примешай к своему классу Enumerable.
В общем, возникают совсем другие паттерны программирования. И они реально ускоряют разработку. Вот уж не думал, что у кого то есть еще сомнения, что на Python или Ruby прогается также как и на C++.




Greck
()
Ответ на: комментарий от www_linux_org_ru

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

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

> Например:

> $a=array(
> "vasya_pupkin@example.com"=>array( "inbox"=>array(....), "sent  items"=>array(....) ),
> "vasya_pupkin@test.ru"=>array( "inbox"=>array(....), "sent items"=>array(....) )
> )

> Никто не помешает мне перепутать и написать $a["inbox"]["vasya_pupkin@test.ru"].


Ничто не мешает в C++ напороться на тот же баг:

 map< string, map<string, mailbox> > a;
 ...
 a["inbox"]["vasya_pupkin@test.ru"] = ...
 ...
 ...
 s = a["vasya_pupkin@test.ru"]["inbox"]

И при чём тут статическая/динамическая типизация типизация?
-- типичный, кстати, пример того, что статическая типизация совсем не спасает.

Зато её отсутствие дает гибкость + заставляет писать юнит-тесты, и это оказывается концептуально правильнее -- крайне важно иметь возможность запустить тест и проверить, что твое малое изменение не поломало код в первом приближении (не только ожидания о "способностях" (см. duck typing) аргументов в разных функциях выполнены, но и всё по прежнему работает в простейших случаях). А тесты В ЛЮБОМ СЛУЧАЕ писать нужно. 

Статическая типизация позволяет повысить производительность кода. Это да.

Agile Development она не помогает, а мешает.
Такие вот простые истины :)





Greck
()
Ответ на: комментарий от Greck

> Статическая типизация позволяет повысить производительность кода. Это да.

>Agile Development она не помогает, а мешает.

> Такие вот простые истины :)

"Каждая сложная задача имеет простое, ясное для понимания неправильное решение" (c). Динамическая типизация - как раз такое решение.

tailgunner ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>> Можно сделать почти десятичную систему - D1(D2(D3())) вместо 123.

>Ты еще попробуй напиши со своим D1(D2(D3())) аналог

>template<int a, int b> T<a*b> operator* (T<a>, T<b>) {.....} 

Не поверите, но что бы не скрывалось за этими {.....}, на динамическом языке программирования это будет так:

class T
  def *(a)
    ..
  end
end

( точек в 2.5 раза меньше, кто не заметил :) )
Делайте выводы о читаемости и скорости разработки.

Greck
()
Ответ на: комментарий от Greck

А вот мне чисто в теории интересно, можно ли в Хаскеле сделать так, чтобы во время компиляции открывался какой-то сторонний файл и что-нибудь в него можно было записать/прочитать.

Или (самое тупое), чтобы посреди файла возникал на консоли запрос к пользователю "введите следующий оператор, который мы вкомпилируем в наш файл"

В лиспе и m4 это возможно. Кто скажет, что это не нужно - тот лох.

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

void bar() {
int foo;
exec sql
select foo from bar into :foo
end sql
return foo;
}

Препроцессоры для embedded sql, встраивающие sql в С и другие языки работают так, наверное, уже лет 30. Я правда, ими не пользовался, но они дают самый быстрый и самый надёжный код для доступа к СУБД. Создатели Nemerle писали кипятком от радости, когда им удалось это реализовать.

И ещё два вопроса по Хаскелю.

1. Можно ли определить в Хаскеле тип "строка или чётное число"?
2. Если там есть классы, то можно ли изменить класс сущности? Т.е., вчера объект был класса "куколка", а с сегодняшнего дня пусть у него будет класс "бабочка". При этом, чтобы он сохранил свою идентичность.

den73 ★★★★★
()
Ответ на: комментарий от Miguel

>>>> В плюсах с замыканиями вроде как проблем нет.
>>> Ы?

>>> Или ты хочешь сказать "как и замыканий"?

>> В с++0х уже есть.

>А. Я уж испугался было.


Это не замыкания. Слово clousure в новом стандарте с++0х употреблено для красного словца:

"If a closure object containing references to local variables is invoked after the innermost block scope of its creation, the behaviour is undefined." (http://en.wikipedia.org/wiki/C++0x#Lambda_functions_and_expressions)

Настоящими замыканиями называется то, что не ведёт себя неопределенным образом при выходе из блока, в котором были определены локальные переменные, которое лямбда использует. Это правильнее назвать анонимными функциями -- функциями без имени, которые можно создавать на лету. Это неплохая фича, но это не замыкание. Лямбда должна уметь возвращаться как результат выполнения функции и не разваливаться при этом. Настоящее замыкание - это когда в лямбде замкнут "вид на окружающий мир" из той точки, где лябмда была создана. Если язык позволяет иметь доступ к стеку вызовов (как, например, в динамических языках), то и в лямде этот стек должен храниться и не исчезать, даже если выполнение функции, в которой лямда была создана, давно закончилась, и стек вызовов уже другой. Если бы ламбда была создана внутри объекта, и возвращена как результат одной из его функций и сохранена во внешней переменной, а потом этот объект был бы удалён - что бы тогда делал C++? Видна концептуальная несвовместимость. Весь этот флуд, что вот мол, давайте к "объективщине" и "императивщине" С++ добавим "функциональщину" и получим нечто объемлющее Хаскел и Лисп никуда не годится.

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

Кстати, по сабжу.
Динамические языки отчасти и возникли оттого, что захотелось делать мультипарадигменные языки ("императивщину" смешать с "функциональщиной"). Как только мы делаем это смешение, сразу получаем необходимость сборщика мусора. Осталось пожелать
1) ООП,
2) рефлексии + открытости классов,
3) отсутствия типов в сигнатурах функций и объявлениях переменных -- сразу получите Ruby/Python/Lua ...
по каждому из четырех типов я могу ответить, почему (по моему мнению) был сделан такой выбор.
Когда я сам, изучая Tcl, Perl, Ruby, Python, Haskel, пытался эксперименировать с придумыванием новых удобных мне языков программирования (не с целью создать реальный язык, а чтобы лучше понять выбор других разработчиков языков), обнаруживал, что вопросов, где можно повыбирать не так много.

Greck
()
Ответ на: комментарий от Greck

> Ничто не мешает в C++ напороться на тот же баг:

Ты кривые приемы из динамических языков переносишь в плюсы. Как я уже писал, можно либо в плюсах юзать ключевые параметры, либо, что более стандартно, юзать разные типы:

в худшем случае будет a[box("inbox")][user("vasya_pupkin@test.ru")]

а скорее всего будет так:

Box b="inbox";
User u="vasya_pupkin@test.ru";

... a[b][u] ... причем на a[u][b] компилятор ругнется.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от den73

> Или (самое тупое), чтобы посреди файла возникал на консоли запрос к пользователю "введите следующий оператор, который мы вкомпилируем в наш файл"

Кстати, есть такая задачка на сообразительность по си: написать программу, которая во время компиляции считывает с stdin код другой программы, и потом при исполнении исполняет считанную программу :)

gaa ★★
()
Ответ на: комментарий от Greck

> Это не замыкания. Слово clousure в новом стандарте с++0х употреблено для красного словца: "If a closure object containing references to local variables is invoked after the innermost block scope of its creation, the behaviour is undefined."

Гы-гы-гы. Там же совсем рядом написано:

If [=] is used instead of [&], all referenced variables will be copied, allowing the lambda function to be used after the end of the lifetime of the original variables.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>> А можно точную постановку задачи? Я в какой-то момент потерял эту нить разговора, а теперь не понимаю, о чём речь идёт.

> Вот там sf поставил (мне кажется, в плюсах без лишнего параметра не обойтись, интересно как в хаскеле)

> http://www.linux.org.ru/jump-message.jsp?msgid=3594542&cid=3600072

[пытаясь не уходить от сабжа] программист при работе с динамическими языками не тратит свое время думание и на обсуждение того, как (красиво) реализовать max_bound. Его больше интересуют другие вещи. Это называется абстракцией от ненужных на выбранном уровне деталей.

"Чуешь?" (c)

см. http://www.ruby-doc.org/core/classes/Fixnum.html : "if any operation on a Fixnum exceeds this range, the value is automatically converted to a Bignum."

Greck
()
Ответ на: комментарий от gaa

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

Под виндой ведь не заработает, да? Но идея здравая (для костыля).

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от Greck

> [пытаясь не уходить от сабжа]

Там у нас были междусобойные разборки по системе типов, и людям из динамических языков они будут видимо совсем не понятны.

З.Ы. у нас тоже есть числа произвольной точности c +-/*

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> Гы-гы-гы. Там же совсем рядом написано: > If [=] is used instead of [&], all referenced variables will be copied, allowing the lambda function to be used after the end of the lifetime of the original variables.

А вот и не ГЫ-ГЫ-ГЫ. Одно дело copied, и совсем другое дело, когда две разные лямбда реально шарят одну и туже локальную x переменную после того, как вычисление функции вообще закончилось. И еще, представьте разные ситуации с несколькими лямбдами и несколькими тредами. Выберем средней сложности -- создана лямбда A типа [=x] и сохранена в глобальную переменную, которой паралельно воспользовался другой тред, выполнил, и в результате выполнения эта переменная x была изменена. Но наш исходный тред завел еще обыкновенную лямбду B типа [&x] и тоже её выполнил, и эта лямбда тоже меняет переменную x. ... развейте тему дальше сами, оцените то количество глюков и непоняток, которые придется разрулить всем компиляторам этого нового стандарта. Кстати, зашаривание локальных переменных между двумя замыканиями с целью зашаривания и обмена данными - это классика в динамическом программировании.

Greck
()
Ответ на: комментарий от www_linux_org_ru

> Ты кривые приемы из динамических языков переносишь в плюсы.

Да нет, иногда реально нужно создать хеш хешей типа string->string->value

С техникой насильного введения новых ненужных (дублирующих уже существующие, но "другие") типов специально для отлавливания ошибок типизации я знаком.

Букв приходится писать больше. Ошибки такого сорта предпочитаю находить другими способами.

Greck
()
Ответ на: комментарий от Greck

> А вот и не ГЫ-ГЫ-ГЫ ... зашаривание локальных переменных между двумя замыканиями с целью зашаривания и обмена данными - это классика в динамическом программировании.

гы-гы-гы

boost::shared_ptr<Foo> ptr = new Foo(.....); и дальше спокойно шаришь ptr между двумя замыканиями после выхода из функции

идея сохранять стэковый фрейм -- это spagetty stack и неэффективно

З.Ы. жаль в жцц 4.4 еще замыканий нет, а то бы дал рабочий пример в 10 строк.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> Там у нас были междусобойные разборки по системе типов, и людям из динамических языков они будут видимо совсем не понятны.

Да понимаю я ваши разборки, понимаю. И они на меня тоску наводят. Сам устраивал такие разборки.

> З.Ы. у нас тоже есть числа произвольной точности c ++

Я в курсе. А теперь внимание вопрос: чего тогда не используете, а флудите? Отвечу сам: полюбили всей душой машиный уровень. Вы и машина -- одной крови. Есть ли Bignum, который используют _БОЛЬШИНСТВО_ пакетов в дистрибутиве Linux? Нету. И как же после этого вам абстрагироваться от конечности типа int, если вы используете сторонние библиотеки, где этот тип используется? Хрен абстрагируешься. Так и будете всю жизнь об этом помнить, учитывать разные разрядности архитектур и т.д. и т.п. Собственно, помнить об размере int - это нормально для kernel и огромного класса задач. Мне просто давно уже такие задачи не попадались. Признаюсь, область моих интересов довольно специфическая.

Greck
()
Ответ на: комментарий от Greck

> Букв приходится писать больше. Ошибки такого сорта предпочитаю находить другими способами.

Все же выяснилось, что плюсы эту ошибку ловят... это уже хорошо.

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

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от Greck

> Я в курсе. А теперь внимание вопрос: чего тогда не используете, а флудите?

что и доказывает, что разборки ты наши не понял, елки палки.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>> Кстати, есть такая задачка на сообразительность по си: написать программу, которая во время компиляции считывает с stdin код другой программы, и потом при исполнении исполняет считанную программу
> Под виндой ведь не заработает, да? Но идея здравая (для костыля).


Достаточно вспомнить шутку про то, что Биллгейца в детстве дразнили ботаником, как и на винду спортировать получится. Во всяком случае, с mingw работало.

gaa ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.