Здравствуйте, mkizub, Вы писали:
M>Посмотри на код, генерируемый Scala и ужаснись.
Покажи... вот честно, интересно... а то пока только пугаешь (есть там конечно кривости, но как это сделать иначе я тоже не сильно представляю)
M>Или вот, пусть мне нужны параметры типов в рантайме. Чтоб я мог написать M>List<String> ls = ...; M>String[] arr = ls.toArray(); M>а не M>String[] arr = ls.toArray(new String[ls.size()]);
Вообще-то разработчику vm должно быть стыдно, если он не знает почему именно требуется объект массива
на scala это решается безо всяких прыжков:
scala> val ls = 1 :: 2 :: Nil
ls: List[Int] = List(1, 2)
scala> ls.toArray
unnamed1: Array[Int] = [I@4854f6 << обрати внимание, что тут именно нейтив массив, а не boxed
Код в самой скала самый обычный:
override def toArray[B >: A]: Array[B] = {
val result = new Array[B](size)
copyToArray(result, 0)
result
}
Другой вопрос, когда мы хотим что-то такое, но это уже спасибо блин erasure...
Здравствуйте, mkizub, Вы писали:
M>Здравствуйте, deniok, Вы писали:
D>>Э, а примерчик можно? Например, я знаю, как записать алгоритм быстрой сортировки на нескольких языках. Как его записать в виде семантического дерева?
M>Да так-же. Как во всех тех языках. Компилятор всё равно парсит текст в дерево. Вот так и записывать.
Я думаю, что в случае Хаскелля и C это будут разные деревья. В Хаскелле это как раз декларативное описание того, что нужно получить, а в C — полновесный набор инструкций, что откуда брать и что куда записывать. И, кстати, компиляторы чистых функциональных и императивных языков работают сильно различным образом.
Здравствуйте, Курилка, Вы писали:
M>>http://www.rsdn.ru/Forum/message/2520182.aspx К>Прикольно — рсдн противится, ссылка не работает, выдаёт форму логина в обоих фреймах, причём логин/пароль не срабатывает, хотя на др. сообщениях рсдн всё корректно
Все верно. Ссылка ведет в приватный форум.
Туда есть доступ только у команды.
У mkizub есть доступ только к этой теме в форуме.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, Курилка, Вы писали:
M>>>http://www.rsdn.ru/Forum/message/2520182.aspx К>>Прикольно — рсдн противится, ссылка не работает, выдаёт форму логина в обоих фреймах, причём логин/пароль не срабатывает, хотя на др. сообщениях рсдн всё корректно WH>Все верно. Ссылка ведет в приватный форум. WH>Туда есть доступ только у команды. WH>У mkizub есть доступ только к этой теме в форуме.
Здравствуйте, aka50, Вы писали:
A>Как видишь, довольно глубоко, но если начинать складывать в кучку все эти объекты, то получим некую величину которую человек осознать не в силах, вот собственно и есть предел сложности. При этом работая с бд мы и так работаем практически с объектами предметной области (счет, платеж, клиент) т.е. выше собственно абстрагироваться некуда (ну если только сделать одну большую кнопку "шоб работало" и оно само догадалось что мы хотим).
Совершенно верно. Каждый следующий уровень абстракции отрезает у нас возможность полного, оптимального использования системы.
Это один из постулатов кибернетики — для эффективного управления системой, управляющая система должна быть сложнее управляемой, чтоб иметь возможность постоить полную модель и выбрать оптимальный способ изменения управляемой системы. А если управляющая система будет более сложной, чем управляемая — то как управлять управителем? Только бесконечно сложная система может эффективно управлять своими под-системами. Грубо говоря — Бог. А мы вынуждены каждый раз уменьшать сложность управляющей системы, чтоб в результате просто иметь возможность управлять, пусть и не максимально эффективно.
Именно в этом месте SOP предлагает — нет, не сделать нас богами и дать возможность максимально эффективно управлять ресурсами — он предлагает убрать (насколько возможно) узкие места между уровнями, переходами верхних абстракций на нижние. Раньше было одно такое узкое место, сейчас их уже два — текстовый код программы и байткод. Неформально изложенное пожелание "отобразить список книг" должно быть переведено на язык программирования в синтаксических терминах конкретного языка. А теперь уже скомпилированный в байткод код программы надо перевести в нэйтивный код процессора. Пример с JIT компилятором в яве ты же читал в статье? Большая часть его сложности — в попытке угадать из байткода — что же на самом деле писал программист. Чтоб хоть как-то облегчить ему задачу — в явовском компиляторе напроч вырубили оптимизацию.
SOP предлагает всю информацию сверху (от архитектора проекта) донизу (скомпилированного кода) передавать в едином формате с минимумом потери информации. В виде дерева.
Конечно, это не решает проблему полностью, полностью её решает лишь Бог. Но просто за счёт убирания узких мест мы получаем возможность программировать настолько хорошо, насколько это позволяет сложность системы, а не настолько, насколько пропустит байткод или фиксированный синтаксис.
Здравствуйте, aka50, Вы писали:
M>>Первое, что сделаю, когда редактор стрелки научится рисовать — перепишу все эти control flow M>>красиво.
A>нуну... текст тем и отличается, что позволяет разобраться, а вот визуальное представление A>во первых элементарно менее компактно (т.к. требует разместить все в одном месте, иначе ты либо потеряешь конкретику, либо стрелки будут уезжать за экран что не способствуем лучшему пониманию кода) A>во вторых требует дополнительного кодирования (например цветами и формой) чтобы можно было ориентироваться
A>Как пример для анализа: http://kernelmapper.osdn.com/map.php Мне лично удобнее использовать grep + ide, чем пытатся в этой куче что-то найти
Ты хочешь привести всё к одному знаменателю. Либо только текст, либо только диаграмы.
Не надо этого. Можно и то и другое. Рисовать flow control удобнее стрелками. Да, с цветами — типа чёрным безусловные переходы, красным — если выражение true и синим — если false.
А другие вещи лучше выразить текстом. Желательно тоже расцвеченым. Ты же не возражаешь против colorer-ов? А некоторые вещи удобнее как математика, формулами рисовать.
Здравствуйте, aka50, Вы писали:
A>Здравствуйте, mkizub, Вы писали:
M>>Посмотри на код, генерируемый Scala и ужаснись. A>Покажи... вот честно, интересно... а то пока только пугаешь (есть там конечно кривости, но как это сделать иначе я тоже не сильно представляю)
M>>Или вот, пусть мне нужны параметры типов в рантайме. Чтоб я мог написать M>>List<String> ls = ...; M>>String[] arr = ls.toArray(); M>>а не M>>String[] arr = ls.toArray(new String[ls.size()]);
A>Вообще-то разработчику vm должно быть стыдно, если он не знает почему именно требуется объект массива
Устыди. Я не понял где мне стыдится. Я знаю, что он требуется в яве. А в моем комплиторе он не требуется.
A>на scala это решается безо всяких прыжков:
A>
scala>> val ls = 1 :: 2 :: Nil
A>ls: List[Int] = List(1, 2)
scala>> ls.toArray
A>unnamed1: Array[Int] = [I@4854f6 << обрати внимание, что тут именно нейтив массив, а не boxed
A>
A>Код в самой скала самый обычный: A>
A>override def toArray[B >: A]: Array[B] = {
A> val result = new Array[B](size)
A> copyToArray(result, 0)
A> result
A>}
A>
A>Другой вопрос, когда мы хотим что-то такое, но это уже спасибо блин erasure... A>
A>class MyType[T] {
A> def oops = new T()
A>}
A>
Я же сказал — в рантайме. А рантайме типы нужны. А ты опять про erasure.
Я не знаю, как в Scala сделан List[Int].toArray, но он не может этого делать
без инлайнинга или передачи спрятанных параметров в метод. Чудес не бывает.
Откуда-то метод toArray должен узнать тип массива. И поскольку в Scala эти
типы отрезаются компилятором — то только один из предложенных вариантов — хранить
в самом List (передача параметра во время создания списка) и передавать
параметр во время вызова toArray. Других вариантов просто нет.
Здравствуйте, deniok, Вы писали:
D>>>Э, а примерчик можно? Например, я знаю, как записать алгоритм быстрой сортировки на нескольких языках. Как его записать в виде семантического дерева?
M>>Да так-же. Как во всех тех языках. Компилятор всё равно парсит текст в дерево. Вот так и записывать.
D>Я думаю, что в случае Хаскелля и C это будут разные деревья. В Хаскелле это как раз декларативное описание того, что нужно получить, а в C — полновесный набор инструкций, что откуда брать и что куда записывать. И, кстати, компиляторы чистых функциональных и императивных языков работают сильно различным образом.
Совершенно верно. Это будут две разные семантически программы. Поэтому и в виде дерева семантических узлов этот алгоритм сортировки будет записан по разному для разных языков
(наборов семантики, онтологии).
Но плюс к тому, его ещё можно просто записать новое семантическое понятие для сортировки как
node Sort {
attribute Expr container;
}
и рисовать это как
sort list
а в виде дерева (приведу в виде XML дампа)
<node type="Sort">
<container>
<node type="VarRef">
<name>list</name>
</node>
</container>
</node>
А при трансляции это будет разворачиваться плагином в дерево узлов соответствующее хаскелевской семантике, или С-шной семантике, в зависимости от наших пожеланий.
Разумеется, вводить новый узел только для сортировки будет не очень умно в обычной ситуации, но если вдруг надо будет написать проект, который будет сортировать
списки в каждой строчке программы — то почему нет?
Здравствуйте, mkizub, Вы писали:
M>Но плюс к тому, его ещё можно просто записать новое семантическое понятие для сортировки как M>node Sort { M> attribute Expr container; M>} M>и рисовать это как M>sort list M>а в виде дерева (приведу в виде XML дампа) M><node type="Sort"> M> <container> M> <node type="VarRef"> M> <name>list</name> M> </node> M> </container> M></node>
M>А при трансляции это будет разворачиваться плагином в дерево узлов соответствующее хаскелевской семантике, или С-шной семантике, в зависимости от наших пожеланий.
Вот тут начинаю не понимать. Это какой-то очень-очень умный плагин. Который, получив только что введённое семантическое понятие Sort, описанное к тому же далеко не исчерпывающей семантикой (тут же нет формально описанного требования, что мы хотим получить отсортированный контейнер), разворачивается, по твоим словам, в дерево узлов, соответствующих семантике сортировки. В такой записи, ИМХО, это не что иное, как указание программисту на конкретном языке написать (или использовать существующий) код сортировки, и не более того.
Здравствуйте, deniok, Вы писали:
D>Вот тут начинаю не понимать. Это какой-то очень-очень умный плагин. Который, получив только что введённое семантическое понятие Sort, описанное к тому же далеко не исчерпывающей семантикой (тут же нет формально описанного требования, что мы хотим получить отсортированный контейнер), разворачивается, по твоим словам, в дерево узлов, соответствующих семантике сортировки. В такой записи, ИМХО, это не что иное, как указание программисту на конкретном языке написать (или использовать существующий) код сортировки, и не более того.
Мы вводим в SOP семантический узел. Как он реализован — это другой вопрос. В этом одно из преимуществ SOP.
Если у нас операция сортировки прямо поддерживатся виртуальной машиной — то на этом практически всё. Если нет — надо определять Sort через другие семантические узлы, в конечном итоге пока не дойдём до "нэйтивных" операций.
Конечно, Sort мало кто поддерживает. А вот операция rotate bits некоторыми процессорами поддерживается напрямую. Или операция с deciaml числами. Или векторные инструкции. Или строковые операции на x86 и т.д.
Вот пишет программист на Java 3D игрушку. А в байткоде операции для векторных вычислений нет. Компилятор должен развернуть операцию по сложению двух векторов в последовательность скалярных операций. А потом JIT компилятор должен догадаться, что это на самом деле векторное сложение, и задействовать SIMD инструкции. Байткод — это тоже текст. Это бутылочное горлышко. И точно такое-же бутылочное горлышко — это текстовое представление языка программирования, фиксированный синтаксис.
Сейчас эта проблема ещё не очень остро стоит. Лет через 10 она будет стоять во весь рост, потому как тупо наращивать количество транзисторов в CPU уже нельзя будет. Надо будет делать сложные процессоры. В том числе перепрограммируемые, с изменяемыми коммандами, распределением вычислений по ядрам и многое другое. Представляешь, насколько узким местом станет фиксированный байткод, если программист уже пишет на Scala или Nemerle, и процессор адаптируемый — а байткод фиксированный.
Здравствуйте, mkizub, Вы писали:
M>Сейчас эта проблема ещё не очень остро стоит. Лет через 10 она будет стоять во весь рост, потому как тупо наращивать количество транзисторов в CPU уже нельзя будет. Надо будет делать сложные процессоры. В том числе перепрограммируемые, с изменяемыми коммандами, распределением вычислений по ядрам и многое другое. Представляешь, насколько узким местом станет фиксированный байткод, если программист уже пишет на Scala или Nemerle, и процессор адаптируемый — а байткод фиксированный.
Так ведь VM тоже эволюционируют. Как можно наращивать мощу сохраняя при этом обратную совместимость видно на примере семейства x86, а ведь та же JVM это по сути программный (не железный) процессор, который к тому же добавляет еще один уровень автоматизации под конкретное железо на этапе JIT'a.
Другое дело что байт код по определению не должен зависить от железа (на одном проце какая-то инструкция есть, а на другом нет), поэтому тупо добавлять новомодные фичи наверное не стоит.
Поразмышляв немного над SOP пришел к следующему выводу: по сути предлагается поднять уровень абстракции самого байт кода (в роли байт кода семнатические приблуды SOP, которые потом преобразуются во что угодно (как в JIT)). В приницпе звучит интересно, но вот проблемы там будут те же самые + добавяться некоторые другие:
— кто будет определять как какой узел семантического дерева во что преобразовать?
— а если у меня собственное дерево, мне что самому надо будет делать маппинг подо все платформы?
— а как на счет переносимости по бинарникам? (не придется ли каждый раз запускать всю цепочку преобразования сампольного DSL в машинный код?)
И кто-то еще говорит что Scala тормозит...
Кастати никаких проблем с интеропом коллекций между жабой и встроеной скалой нет, в случае если это коллекции жабы (разве что не получится пользоваться ФП-фичами).
У Interpeter есть замечательный метод bind, типа:
i.bind("list",list.getClassName(),list);
И можно пользоваться list'ом как уже готовой переменной, одно огорчает Interpreter выполняет код только по одной строке, в ближайшее время планирую помучится с ScritpRunner'ом (или как он там называется). С груви вообще никаких проблем.
Кроме того из встроенной скалы замечательно видны все внешние классы жабы, так можно наладить взаимодействие через static, типа
public class Main
{
public static LinkedList<String> list = new LinkedList<String>();
....
public static void main(String[] _args)
{
....
list.add("Hello world!!");
i.interpet("Console.println(embededscala.Main.list.get(0))");
....
}
}
P.S. Единственное что удручает так это тормоза, поэтому возможно проще будет компилить все
заранее (при запуске), а потом дергать уже готовые классы, реализующие некий заранее известный жаба-интерфейс. Как сделать пока не знаю...
Здравствуйте, mini_root_2, Вы писали:
__>Здравствуйте, mkizub, Вы писали:
M>>Сейчас эта проблема ещё не очень остро стоит. Лет через 10 она будет стоять во весь рост, потому как тупо наращивать количество транзисторов в CPU уже нельзя будет. Надо будет делать сложные процессоры. В том числе перепрограммируемые, с изменяемыми коммандами, распределением вычислений по ядрам и многое другое. Представляешь, насколько узким местом станет фиксированный байткод, если программист уже пишет на Scala или Nemerle, и процессор адаптируемый — а байткод фиксированный.
__>Так ведь VM тоже эволюционируют. Как можно наращивать мощу сохраняя при этом обратную совместимость видно на примере семейства x86, а ведь та же JVM это по сути программный (не железный) процессор, который к тому же добавляет еще один уровень автоматизации под конкретное железо на этапе JIT'a. __>Другое дело что байт код по определению не должен зависить от железа (на одном проце какая-то инструкция есть, а на другом нет), поэтому тупо добавлять новомодные фичи наверное не стоит. __>Поразмышляв немного над SOP пришел к следующему выводу: по сути предлагается поднять уровень абстракции самого байт кода (в роли байт кода семнатические приблуды SOP, которые потом преобразуются во что угодно (как в JIT)). В приницпе звучит интересно, но вот проблемы там будут те же самые + добавяться некоторые другие: __> — кто будет определять как какой узел семантического дерева во что преобразовать?
Нэйтивный компилятор.
Каждый нэйтивный компилятор будет иметь свой набор семантических узлов, непосредственно им поддерживаемых.
Плюс каждый семантческий узел может иметь в своём описании fallback преобразование (не обязательно одно). Если нэйтивный компилятор не поддерживает данную семантику напрямую — он может использовать fallback правила преобразования для узла. Чаще всего такими fallback преобразованиями будут, конечно, библиотечные методы. То есть нэйтивный компилятор будет ещё и знать, что для запуска данного приложения нужна такая-то библиотека.
Как пример — J2ME CLDC 1.0, в котором нет float переменных, а в CLDC 1.1 они есть.
При SOP подходе программа бы просто содержала операции над float значениями, и они либо выполнялись непосредственно на CLDC 1.1, либо при установке мидлета телефон автоматически ещё бы устанавливал библиотеку эмуляции плавающей точки, либо говорил — "данная операция на этом устройстве невозможна".
Кроме того, программисты для телефонов могли бы себе определить новый тип данных, который бы имел fallback сратегии для платформ с float (где этот код исполнялся бы более эффективно) и для платформ только с int (где часть битов в int была-бы зарезервирована для небольшой дробной части).
Сам нэйтивный процессор не должен быть монолитным. Скажем, для мобилок — он частично может исполнятся на сервере и передавать пред-компилированные данные (то есть байткод+информация по оптимизации) в телефон, где простой bytecode-to-native транслятор преобразовывал программу уже непосредственно в нэйтивный код ARM, x86, C166 и прочих процессоров мобильного зоопарка.
__> — а если у меня собственное дерево, мне что самому надо будет делать маппинг подо все платформы?
Да, для всех платформ, где ты его хочешь исполнять. Но если у тебя своё дерево — зачем-то же ты его сделал? Скажем, ты сделал дерево для аппаратных lisp машин. Ты его только на этом target и собирался ведь исполнять, да? Тебе его совсем нет необходимости маппировать на x86 набор инструкций.
__> — а как на счет переносимости по бинарникам? (не придется ли каждый раз запускать всю цепочку преобразования сампольного DSL в машинный код?)
Как хочешь. Можешь запускать эту цепочку каждый раз. Можешь пред-компилировать в native код при инсталляции, можешь предкомпилировать в промежуточный код, который каждый раз компилировать в нэйтивный JIT компилятором.
__>И кто-то еще говорит что Scala тормозит... __>Кастати никаких проблем с интеропом коллекций между жабой и встроеной скалой нет, в случае если это коллекции жабы (разве что не получится пользоваться ФП-фичами).
Здравствуйте, mkizub, Вы писали:
M>Вся фишка в том, что предлагается так и писать M>trace WARNING "Message" M>и отдельно написать плагин к компилятору (точнее — среде разработки), который будет это пожелание trace трансформировать M>в понятия более низкого уровня, вроде "вызвать функцию такую-то с такими-то аргументами".
А как программа узнает, что trace значит "оттрэйсит в лог" и в какой лог, BAR или FOO, а не "вывести фигуру на экран"?
M>Программист не будет переводить задачу не с человеческого описания на конкретный язык с конкретными библиотеками. M>Один будет формировать понятия предметной области и либо расширять существующий язык, либо писать отдельный язык. M>А другой будет обеспечивать работу первого — заниматься низкоуровневыми деталями. M>Это разделение позволит ещё больше структурировать программу. Как сейчас одни пишут библиотеки, а другие их M>пользуют, так и предлагается делать, только библиотеки эти будут библиотеками значений, концепций.
Так ведь по сути есть уже похожий язык. SQL. Попробуйте переведите на русский SELECT users FROM U_Table. Пользователи могут так и писать "ВЫБЕРИ МНЕ Пользователь ИЗ U_Table У КОТОРЫХ число_сообщений>100". Чем не устраивает?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, mkizub, Вы писали:
M>>Вся фишка в том, что предлагается так и писать M>>trace WARNING "Message" M>>и отдельно написать плагин к компилятору (точнее — среде разработки), который будет это пожелание trace трансформировать M>>в понятия более низкого уровня, вроде "вызвать функцию такую-то с такими-то аргументами".
А>А как программа узнает, что trace значит "оттрэйсит в лог" и в какой лог, BAR или FOO, а не "вывести фигуру на экран"?
Видимо, из настроек проекта, больше неоткуда.
M>>Программист не будет переводить задачу не с человеческого описания на конкретный язык с конкретными библиотеками. M>>Один будет формировать понятия предметной области и либо расширять существующий язык, либо писать отдельный язык. M>>А другой будет обеспечивать работу первого — заниматься низкоуровневыми деталями. M>>Это разделение позволит ещё больше структурировать программу. Как сейчас одни пишут библиотеки, а другие их M>>пользуют, так и предлагается делать, только библиотеки эти будут библиотеками значений, концепций.
А>Так ведь по сути есть уже похожий язык. SQL. Попробуйте переведите на русский SELECT users FROM U_Table. Пользователи могут так и писать "ВЫБЕРИ МНЕ Пользователь ИЗ U_Table У КОТОРЫХ число_сообщений>100". Чем не устраивает?
Меня SQL вполне устраивает. Хороший язык для своих целей. Вот давайте в этом направлении и двигать
Здравствуйте, mkizub, Вы писали:
VD>>Мнея интересует сравнение с Явой. Потому на этом форуме и задал ворос. Понятно, что Ява в следствии дизайна имеет некоторый оверхэд по сравнению с С/С++, но все же он приемлем для многих применений. Скала вроде бы не сильно его увеличивает. Или я ошибаюсь?
M>Я не сравниваю Scala с С++. M>Я пишу о том, что разработчик языка делает выбор, исходя из своих собственных представлений о том, как правильно, хорошо, как надо. M>И потом про это книжки пишет, почему я выбрал так, а не иначе. M>А загогулина в том, что автор другого языка сделал прямо противоположный выбор, и тоже правильный, тоже обоснованный. M>Тоже книжки пишет, почему его выбор правильный.
M>Это трудно понять с первого раза, но решение проблемы "какой язык лучше" не в спорах о том, чей выбор правильней. M>Решение в том, чтоб вообще отказаться от принятия выборов за программистов, пишущих на этом языке.
Извини, ты сказал много слов, но закоченного смысла я в них уловить не смог.
Я увидил в твоей критике немой вопрос "почему Скала не С++". Ответ очевиден, потому что это развите Явы.
Я не заметил ни одного дизайнерского выбора авторов Скалы которое шло бы в разрез путем Явы. Да, это не С++-путь, но ведь этого никто и не ждет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
A>Haskell: [ (x, y) | x<-[0,1,2,3], y <- [0,1,2,3], x < y]
A>Python: [(x, y) for x in [0,1,2,3] for y in [0,1,2,3] if x < y]
A>Scala: for( x <- 0::1::2::3::Nil; y <- 0::1::2::3::Nil if x < y) yield (x,y)
A>Lisp: (comprehension (cons x y)
A> ((x '(0 1 2 3)) (y '(0 1 2 3)))
A> ((< x y)))
A>
A>А теперь вопрос: где гибче синтаксис и язык и где лучше понимаемость кода? И самое интересное: почему в самом гибком языке нужно явно указывать, что это у нас comprehension?
Все же не совсем соглашусь с тобой. Если взять только твои примеры, то кажется, что ты прав. Ведь действительно во всех перечисленных примерах на разных языках кроме Лиспа comprehension встроен в язык и имеет более краткий и внятный синтаксис. Лисп же реализует компрешеншон макросом и начинают вылезать неприятности. К тому же приходится использовать цитирование, что так же ухудшает восприятие. Последнем гвоздем в крышку (как сказал твой аппонент) яляются скобки, коих явно многовато (от них рябит в глазах). Несомненно и то, что возможность создать подобные кострукции средствами самого языка — это просто супер-мега-возможность!
Но! Ниже я приведу пример который полностью разваливает твою позицию:
$[(x, y) | x in [0,1,2,3], y in [0,1,2,3], x < y]
(эх, жаль Явщики нихрена не поймут ни в твоих, ни в моих примерах )
Что это за язык? Думаю все догадались . Это конечно же Немреле.
Лучше чем в Лиспе? По-моему, несомненно. Хуже чем в Хаскеле? Ни чуть! (опять же, по-моему).
Гибче ли Лисп? А вот ни чуть. Приведенный пример — это использование макроса. List comprehensions в Nemerle реализован, как и в Лиспе, макросом. Только при этом Nemerle не отказыается от полноценного синтаксиса и имеет большую базу (основной язык который по стути похож на Яву и Шарп).
Какой вывод можно сделать из моих слов?
Дело все же не в гибкости. Просто раньше добиться гибкости Лиспа в других языках было невозможно.
Так что проблемы Лиспа все же в очень большой степени упираются в его убогий синтаксис и в некоторые другие дизайнерские решения. Ну, и конечно в хреновый маркетинг и никудышное обучение.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Книга { название, аннотация }
[SQLTable: ТаблицаКниг]
class Book {
[SQLField: индекс, primary key] id : int
[SQLField: название, not null, 80 chars] title : string
[SQLField: аннотация, maybe null, long varchar] annotation : long string
private dirty : bool
}
Я мог реализовать в C# (с чуть более строгим синтаксисом) уще несколько лет назад BLToolkit сделаный IT именно это и делал. Единственное, что такая реализация требует много услий. Но потом ее использование уже будет простым.
На Немерле я могу реализовать подобную ведь макросом, так что никакой рантайм-поддержки и моря кода не потребуется.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, mkizub, Вы писали:
M>Вот и должен один программист работать в понятиях, где неважна конкретная реализация, конкретный рубильник. M>А другой программист должен это понятие реализовать, выразить в низкоуровневых операциях. И первый не должен беспокоиться как сделать работу за второго.
Замечательно, но Лисп и Немерле как раз предоставлюят такие возможности в виде макроподсистемы. А что же предлагаешь ты?
Чем твой СОМ (или как там его?) отличается от тех же маросов?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>Книга { название, аннотация }
VD>[SQLTable: ТаблицаКниг]
VD>class Book {
VD> [SQLField: индекс, primary key] id : int
VD> [SQLField: название, not null, 80 chars] title : string
VD> [SQLField: аннотация, maybe null, long varchar] annotation : long string
VD> private dirty : bool
VD> }
VD>
Там в другом фишка — это не генерация кода, это его изображение, одно для дазайнера и другое для программиста.
Ты можешь один и тот-же код отображать в редакторе программы по разному. В Nemerle ты этого принципиально не можешь — он в себе подобный рендерер кода не имеет.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, mkizub, Вы писали:
M>>Вот и должен один программист работать в понятиях, где неважна конкретная реализация, конкретный рубильник. M>>А другой программист должен это понятие реализовать, выразить в низкоуровневых операциях. И первый не должен беспокоиться как сделать работу за второго.
VD>Замечательно, но Лисп и Немерле как раз предоставлюят такие возможности в виде макроподсистемы. А что же предлагаешь ты? VD>Чем твой СОМ (или как там его?) отличается от тех же маросов?
Влад, остановись и подумай. Ещё раз. Внимательней.
Код
[SQLTable: ТаблицаКниг]
class Book {
[SQLField: индекс, primary key] id : int
[SQLField: название, not null, 80 chars] title : string
[SQLField: аннотация, maybe null, long varchar] annotation : long string
private dirty : bool
}
не сгенерирован автоматически из кода
Книга { название, аннотация }
Это никакого отношения к макросам не имеет. Это больше похоже на folding в редакторе, когда блок кода сворачивается в {...}
Только тут не просто сворачивание кода, а отображение самой существенной его части, так как хочет видеть архитектор программы.