Здравствуйте, Oyster, Вы писали:
O>На самом деле, можно и сейчас писать Si.Mass(10), как и раньше, конечно.
Думаю, что Адонц просто не понимает, что kg — это такой забавный оператор явного приведения типов, или даже фунция "int -> Si.Mass".
O>Вообще идею с "физическими литералами" придумал я но вот очень-очень её захотел видеть vdimas.
Думаю, что это та мысль которая что называется витает в воздухе и она приходит в голову всем людям с развитым воображеним и чувством гормонии.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Oyster, Вы писали:
O>В общем, опять началась охота на ведьм
Точно!
O>Советую снова — попробуй Nemerle и мою библиотеку в действии, прежде чем критиковать их.
Можешь создать некий пакет чтобы его можно было загрузить из Интернета или взять с диска и одним запуском батника попробовать? Ну, и инструкцию к нему, что можно менять...
Думаю, это простило бы ситуацию и убрало бы барьер восприятия. Ведь попробовав на практике многие вопросы бы отпали сами собой.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, WolfHound, Вы писали:
WH>Нет. И не надо. Учи матчасть. Посмотри как это реализовано и не говори глупостей.
С таким уровнем аргументации далеко не уедешь. Nemrle не распространён, у него даже официальной документации нет. Если знаешь что-то важное — говори, а RTFM неуместен.
VD>"x" будет иметь тип int независимо от того, что за тип выводится из "любое_выражение". Если тип несовместим или требует рантайм-приведения, то компилятор просто откажется компилитовать код. VD>Надесь, на этом данная дискусиия будет закрыта.
Влад, это понятно, это ты вопроса не понял. Вопрос такой
Здравствуйте, VladD2, Вы писали:
A>> А ведь это более естественно Да и где гарантия, что никто не забудет это самое k. Ошибка в 1000 раз на пустом месте. VD>Нда. Тяжолый случай. Рассуждения без малейшено понимания о предмете рассуждения. Еше раж. "10" и "10 kg" разные типы данных для языка. "10" — это int, а "10 kg" это 10 килограм, то есть другой тип данных. Так как нет неявного приведения, то они несовместимы и компилятор выдаст ошибку.
Влад, ты невнимательно читаешь. Ещё раз — "Да и где гарантия, что никто не забудет это самое k"?
То есть вместо 10 kg мы получим 10 g. Между ними как раз очень даже есть преобразование.
A>>Мне подход с явным указанием типов, а не суффиксов, нравиться больше. VD>Используй его. Ты единственный кому это нравится, но это не проблема.
Влад, давай не будем говорить за всех, ОК?
A>>И, учитывая, что Nemerle язык новый, а Си++ старый, я бы это рассматривал как большой плюс Си++. Хотя конечно на Nemerle всё удобнее. VD>Логика изумительная. Нет слов! Тогда давай PL1 рассматр как идеальный язык. Оно ведь куда старше.
Влад, ты читаешь, то что я пишу? Я сказал — достоинством Си++ является то, что на нём можно реализовать довольно новые идеи, пусть и не очень удобно. Причём тут идеальный язык?
VD>Короче, мне все меньше и меньеш интересен этот разговр.
Ну если ты просто придумываешь мои слова, вместо того чтобы их читать, тогда и правда не интересно.
VD>"value_t<1, 1, -2>"- это бред сивой кобылы. Эта строчка только в очень багатом воображении может оказаться осмысленной. Между тем имея полноценный ДСЛ описывающий взамиоотношения типов ты в силах описать любую комбинацию очень кратко и понятно.
Нет value_t<1, 1, -2> это величина с разверностью
м*кг
-----
с^2
Здравствуйте, VladD2, Вы писали:
VD>В общем, я просто не хочу вести разговор с теми кто даже не пробовл но хит. Попробуй, выяви проблемы, тогда их и обсудим. А пока это только твои фобии.
А ты пробовал? Я просил привести пример, но так и не увидел его. Почему мои фобии менее убедительны, нежели твой патриотизм?
VD>
VD>Думаю, что ты поймешь ее даже незня, что такое match и т.п. Изменение каких приоритетов может нарушить логику этой конструкции?
ОК, очень просто. Насколько я понял тут выполняется одно из нескольких условий (| я воспринял как оператор OR, Если это не так — интуитивная понятность отметается). Пусть str подходит под несколько (why собственно not?). Просто поменяй условия местами — вот и всё.
VD>Если в ДСЛ появляются приоритеты — это это уже путь в неверном направлении. ДЧЛ должен максимально декларативно описывать суть задачи, а макросы превращать это описание в реальный код отрабатывающий ее решение.
Декларативные языки удобнее в использовании, но вот создавать их эффективные реализации труднее. Не говоря уже о хоть каких-то реализациях.
VD>Так что ошибиться в описании ДСЛ-я куад сложенее чем при проектировании библиотеки.
Это ты как великий теоритик говоришь или я всё таки увижу созданный тобой и используемый где либо кроме лаборатории DSL? Подмножества универсальных языков типа XML конфига или кода Designer.cs не в счёт.
VD>Нда. И где я уже видил эту аргументацию? А, у АВК. Когда аргументы по делу кончаются, то почему-то сразу начинаются "аргументы" вроде "Это что серебрянная пуля? Их не быват... Не пудрите мне мозги...".
Ну так покажи пример. Где он? Нету, одни обещания всех шапками закидать. Я бы и рад поверить тебе, но моим аргументам ты можешь только противопоставить свои, а где факты? А факты удачного использования куда-то спешно удалились.
VD>Это следующий шаг в развитии индустрии программировния. Сама по себе концпция ДСЛ-ей не избавит от решения задач. Но во многих случаях она позволит решать задачи более просто, а значит решать более сложные задачи и решать их быстрее. Как ООП, ФП и другие парадигмы эта позволяет увеличить сложность решаемых задач впихнув их в довольно скудные возможности мозга человека.
Заканчивал курсы маркетологов? Почём брали за месяц?
Здравствуйте, VladD2, Вы писали:
VD>КОП и МП могут прекрасно существовать вместе и дополнять друг-друга. КОП больше ориентируется на рантайм, а МП на реализацию. Но они имеют общую задачу. Обе парадигмы призваны упростатить разработку сложных систем путем выделения в программах отдельных частей которыми можно оперировать как высокоуровневыми сущьностями.
Здравствуйте, Oyster, Вы писали:
O>Кстати, ты всерьёз считаешь, что value_t<1, 1, -2> удобнее хоть в каком-то случае?
Конечно нет. Конечно же для всех базовых величин надо сделать typedef. НО! Если я захочу производную размерность, причём не важно какую, она у меня есть. Причём именно в том виде в котором я её записываю — единицы измерения со степенями, ибо названия нет.
, всё не можешь понять, что я на Nemerle решил точно ту же задачу, но без скалярных параметров шаблонов, и что скалярные параметры шаблонов для решения этой задачи совсем не нужны. vdimas-а я смог переубедить
Здравствуйте, VladD2, Вы писали:
VD>Можешь создать некий пакет чтобы его можно было загрузить из Интернета или взять с диска и одним запуском батника попробовать? Ну, и инструкцию к нему, что можно менять... VD>Думаю, это простило бы ситуацию и убрало бы барьер восприятия. Ведь попробовав на практике многие вопросы бы отпали сами собой.
Влад, давай хоть что-то конструктивное сделаем, может интегрировать Nemerle в студию? Чтобы был нормальный проект типа file\new\project\nemerle console application? Дело-то не хитрое, ну на недельку от силы. Ниже этого барьер не опустить. Но с тебя иконки
Здравствуйте, adontz, Вы писали:
A>Влад, ты невнимательно читаешь. Ещё раз — "Да и где гарантия, что никто не забудет это самое k"?
Гарантия может быть только одна. Разрешено ли неявное преобразование между килограммами и граммами. Если боишся ошибиться, не вводи преобрзование.
Надо все же понимать, что имешь дело с полноценной настраиваемой системой типов. И что ты можешь настроить ее как тебе нужно.
A>То есть вместо 10 kg мы получим 10 g. Между ними как раз очень даже есть преобразование.
Тебу тут уже радом объясняли, что с тем же успехом ты можешь перепутать "+" и "*". Это докапывание не по существу.
Боишся опечаток, строй дизайн так чтобы они приводили к ошибкам. Допускай меньше неявных преобрзований типов.
В общем, это не проблема языка.
Лично я вижу что ты пыташся найти проблему там где ее нет. Ну, да ты тут не первый. Я уже привык к пдобному поведению. Оно возникает от нежелания принять новое. Вместо понимания начинаются поиски ведьм.
A>>>Мне подход с явным указанием типов, а не суффиксов, нравиться больше. VD>>Используй его. Ты единственный кому это нравится, но это не проблема.
A>Влад, давай не будем говорить за всех, ОК?
Я констатирую факты. Ты единственный из тех кто высказался по этому поводу и кому не понравилась идея физических литералов. Если найдешь второго такого кто высказался до тебя, то я возьму свои слова обратно. А пока, изини, но говорю, то что есть.
A>>>И, учитывая, что Nemerle язык новый, а Си++ старый, я бы это рассматривал как большой плюс Си++. Хотя конечно на Nemerle всё удобнее. VD>>Логика изумительная. Нет слов! Тогда давай PL1 рассматр как идеальный язык. Оно ведь куда старше.
A>Влад, ты читаешь, то что я пишу? Я сказал — достоинством Си++ является то, что на нём можно реализовать довольно новые идеи, пусть и не очень удобно. Причём тут идеальный язык?
Я не вижу в твоих словах рассуждений о реализации. Я вижу утверждение "С++ старый и это плюс".
VD>>"value_t<1, 1, -2>"- это бред сивой кобылы. Эта строчка только в очень багатом воображении может оказаться осмысленной. Между тем имея полноценный ДСЛ описывающий взамиоотношения типов ты в силах описать любую комбинацию очень кратко и понятно.
A>Нет value_t<1, 1, -2> это величина с разверностью A>м*кг A>----- A>с^2
Это домыслы. На самом деле это какие-то цифирьки дающие весма неинтуитивные побочные эффекты.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
A>>Влад, ты читаешь, то что я пишу? Я сказал — достоинством Си++ является то, что на нём можно реализовать довольно новые идеи, пусть и не очень удобно. Причём тут идеальный язык?
VD>Я не вижу в твоих словах рассуждений о реализации. Я вижу утверждение "С++ старый и это плюс".
Влад, в первом классе есть урок — чтение. Не прогуливал?
"С++ это старый язык, позволяющий, пусть и не оптимально, реализовывать новые идеи и это плюс".
VD>>>"value_t<1, 1, -2>"- это бред сивой кобылы. Эта строчка только в очень багатом воображении может оказаться осмысленной. Между тем имея полноценный ДСЛ описывающий взамиоотношения типов ты в силах описать любую комбинацию очень кратко и понятно.
A>>Нет value_t<1, 1, -2> это величина с разверностью A>>м*кг A>>----- A>>с^2
VD>Это домыслы.
Нажимаем Ctrl+Space.
Здравствуйте, adontz, Вы писали:
A>Влад, давай хоть что-то конструктивное сделаем, может интегрировать Nemerle в студию? Чтобы был нормальный проект типа file\new\project\nemerle console application?
Да, на уровне редактирование, подсветка, отладка. К сожалению комлита нет. А отладка кривовата. Но хоть что-то.
Ссылки можно найти здесь: Re: Микро-аддин для VS 2005
Естественно, да.
A> Я просил привести пример, но так и не увидел его.
Пример чего? ДСЛ-я? Я тебе их несколько привел.
A>ОК, очень просто. Насколько я понял тут выполняется одно из нескольких условий (| я воспринял как оператор OR, Если это не так — интуитивная понятность отметается).
Почти. Смысл очень похож. Хотя я бы сказал, что "|" используется как некая префиксная запятая.
A> Пусть str подходит под несколько (why собственно not?). Просто поменяй условия местами — вот и всё.
А зачем менять местами? Если ты ифы местами поменяшь, тоже смысл изменится.
К моту же я уже говорил, что если компилятор или макрос может вычислить, что условия идущие после недоступны, то выдается ошибка. С регепсами конечно не просто, но в принципе такую проверку сделать можно.
A>Декларативные языки удобнее в использовании, но вот создавать их эффективные реализации труднее. Не говоря уже о хоть каких-то реализациях.
На то в Немерле и встроена мощьнейшая система макросов. Она является результатом акумуляции опыта большого числа языков имеющих встроенные системы метапрограммирования. С ее помощью создание эффективных алгоритмов реализции резко упрощается. Хотя несомненно, работа есть работа. Но эту работу все равно прийдетя делать.
VD>>Так что ошибиться в описании ДСЛ-я куад сложенее чем при проектировании библиотеки.
A>Это ты как великий теоритик говоришь или я всё таки увижу созданный тобой и используемый где либо кроме лаборатории DSL? Подмножества универсальных языков типа XML конфига или кода Designer.cs не в счёт.
Хм. А почему собственно не в счет? То что я создавал на Немерле пока что пробы пера. Хотя одна из них мне самоу понравилась. Я написал забавный макрос автоматизирующий перевод программ на другие языки. В программе ты используешь строки вида %%"ля-ля-ля $(выражение) тополя", а макрос при компиляции сам их разбирает и генерирует файл заготовку для перевода (в формате ХМЛ). Далее когда программа запускается она читает этот файл и формирует строки. При чтении она проверяет не содержит ли файл строк для текущего языка процесса и если содержит выбирает его. Так что можно изменить этот файл введя текс на других языках и получить переведенную программу. Сама же программа при этом пишется как будто ее не требуется переводить. Более того любая имеющаяса Немерловая программа может быть простой контекстной заменой превращена в переводимую на другие языки.
Вот как выглядит программа с использованием этого макроса:
using Localization;
[assembly: LocalizationFile("Strings.xml")]
using System.Console;
def nums = array[1, 2, 3];
def x = 5;
WriteLine(%%"a=$(nums[1]) x = $x");
def F(y : int){ y * y }
WriteLine(%%"F(3)=$(F(3))");
Вот что формируется в результате компиляции этой программы файл перевода:
<strings>
<ID_0>
<en-US>a={0} x = {1}</en-US>
</ID_0>
<ID_1>
<en-US>F(3)={0}</en-US>
<ru-RU>Функция F(3) вернуло значение {0}.</ru-RU>
</ID_1>
</strings>
а вот как выглядит макрос:
using System;
using System.Console;
using Nemerle.Compiler;
using Nemerle.Collections;
using Nemerle.Macros;
using PT = Nemerle.Compiler.Parsetree;
using System.Text;
using System.IO;
using System.Xml.XPath;
namespace Localization
{
// Meta-attribut which call when assembly loading.
// It's receive name of localization file nale.
// The LocalizationString macro write into this file
// localization information. Папа мама я.
[Nemerle.MacroUsage(Nemerle.MacroPhase.BeforeInheritance,
Nemerle.MacroTargets.Assembly)
]
macro LocalizationFile(fileName : string)
{
Helper._fileName = fileName;
_ = Helper._builder.AppendLine("<strings>");
// _holder save _builder content to a file when ncc closing.
Helper._holder = Helper.Holder();
}
macro LocalizationString(str : string)
syntax ("%%", str)
{
def exprs = Helper.make_splice_distribution (
str, ImplicitCTX().Env);
// Формируем строку формата "str" и список аргуменов (выражений в них подсавляемых).
def (str, args, _) = exprs.FoldRight(("", [], 0), fun(expr, accumulator)
{
// Выделяем из кортежа отдельные значения
// str - формируемая строка форамата.
def (str, args, i) = accumulator;
def x = expr.ToString(); // Преобразуем текущее выражение в строку.
// Функция Unquot(s) убирает обрамляющие ковычки из строки.
def Unquot(s) { s.Substring(1).Substring(0, s.Length - 2) }
// AddTwiceBraces(s) удваиват знаки "{" и "}".
def AddTwiceBraces(s) { s.Replace("{", "{{").Replace("}", "}}") }
if (x.Length > 0)
{
// Если стока начинается с ", то это просто подстрока которую нужно
// обработать и добавить в строку формата.if (x[0] == '"')
(str + AddTwiceBraces(Unquot(x)), args, i)
// иначе это "встроеное" подвыражение выделенное из строки.
// Для каждого такого подвыражения нужно добавить с форматную строку
// тег вида {x} где x - это номер подвыражения, а так же добавить выражение
// в список выражений которые в посделствии будут формировать параметры.else
(str + "{" + i.ToString() + "}", expr :: args, i + 1)
}
else// Если строка пуста, то ничего не делаем.
accumulator
});
// Добавляем в начала списока параметров парамер содержащий строку формата.
// сам список параметров при этом разворачиваем, так как формировался он в обратном порядке.
def args = <[ $(Helper.GenerateId() : string) ]> :: args.Reverse();
// Добавляем тег в файл локализации.
Helper.AddString(str);
// Формируем выражение форматированного вывода и возвращаем его как результат работы макроса.
// Этот код заместит вызов макроса. Консрукция ( .. $args) сформирует кортэж с параметрами.
// В Nemerle кортежи и списки параметров функций равнозначны. Так что можно считать, что
// сформирован список парамтеров!
<[ Localiser._instace.Format( .. $args) ]>
}
internal module Helper
{
public mutable _cointer : int = 0;
public mutable _fileName : string;
public _builder : StringBuilder = StringBuilder();
public mutable _holder : Holder;
public GenerateId() : string
{
"ID_" + _cointer.ToString()
}
public AddString(str : string) : void
{
_ = _builder.AppendFormat(" <ID_{0}>", _cointer);
_ = _builder.AppendLine();
_ = _builder.AppendLine( " <en-US>" + str + "</en-US>");
_ = _builder.AppendFormat(" </ID_{0}>", _cointer);
_cointer++;
_ = _builder.AppendLine();
}
// Holder save the _builder content to file (with name contain in _fileName)
// when ncc closing.
[Record]
internal class Holder
{
protected override Finalize() : void
{
_ = Helper._builder.AppendLine("</strings>");
File.WriteAllText(Helper._fileName, Helper._builder.ToString());
}
}
/** for $(..) expressions:
- first evaluate expressions
- store intermediate results in variables
- return list of evaluators and reference variables in reverse order
*/public make_splice_distribution (str : string, _env : GlobalEnv)
: list [PT.PExpr]
{
mutable seen_non_alnum = false;
def find_end (balance, idx) {
when (idx >= str.Length)
Message.FatalError ("runaway $(...) in format string");
def ch = str[idx];
seen_non_alnum = seen_non_alnum || !(System.Char.IsLetterOrDigit (ch) || ch == '_');
match (ch) {
| ')' when balance == 1 => idx
| ')' => find_end (balance - 1, idx + 1)
| '(' => find_end (balance + 1, idx + 1)
| _ => find_end (balance, idx + 1)
}
}
def find_end_normal (idx) {
if (idx >= str.Length) idx
else
match (str[idx]) {
| '_'
| ch when System.Char.IsLetterOrDigit (ch) => find_end_normal (idx + 1)
| _ => idx
}
}
def loop (res, idx) {
if (idx < 0 || idx >= str.Length)
res
else if (str[idx] == '$') {
when (idx + 1 >= str.Length)
Message.FatalError ("lone `$' at the end of the format string");
if (str[idx + 1] == '(') {
def end = find_end (1, idx + 2);
def expr = str.Substring (idx + 2, end - idx - 2);
def expr =
if (expr == "" || expr == "_" ||
seen_non_alnum ||
System.Char.IsDigit (expr [0])) {
MacroColorizer.PushUseSiteColor ();
def expr = MainParser.ParseExpr (_env, expr);
MacroColorizer.PopColor ();
expr
} else if (expr == "this")
<[ this ]>
else
<[ $(expr : usesite) ]>;
loop (expr :: res, end + 1)
}
else if (str[idx + 1] == '$')
loop (<[$("$" : string)]> :: res, idx + 2)
else {
def end = find_end_normal (idx + 1);
def variable_name = str.Substring (idx + 1, end - idx - 1);
if (variable_name == "") {
Message.Warning ("expected variable name or expression enclosed with (..) after $ in splice string");
loop (<[$("$" : string)]> :: res, idx + 1)
}
else {
def expr =
if (variable_name == "this") <[ this ]>
else <[ $(variable_name : usesite) ]>;
loop (expr :: res, end)
}
}
} else {
def next_idx = str.IndexOf ('$', idx);
def next_str =
if (next_idx == -1) str.Substring (idx)
else str.Substring (idx, next_idx - idx);
loop (<[ $(next_str : string) ]> :: res, next_idx)
}
}
loop ([], 0)
}
}
public class Localiser
{
public static _instace : Localiser = Localiser();
public this()
{
def lang = System.Threading.Thread.CurrentThread.CurrentCulture.Name;
def defLang = "en-US";
def doc = XPathDocument("Strings.xml");
def iter = doc.CreateNavigator().Select("/strings/*");
foreach (vlue :> XPathNavigator in iter)
{
mutable langIter = vlue.Select(lang);
when (!langIter.MoveNext()) // Нет строк для этого языка!
{
langIter = vlue.Select(defLang);
when (!langIter.MoveNext())
throw ApplicationException("No string for ID={0} found.");
}
_msgMap.Add(vlue.Name, langIter.Current.Value);
}
}
private _msgMap : Hashtable.[string, string] = Hashtable.[string, string]();
public Format(msgId : string, params args : array[object]) : string
{
string.Format(_msgMap[msgId], args);
}
}
}
ДСЛ прост как три копйки хотя и позволяет в выражениях использовать любые конструкции Немерла. Контроль выражений осуществляется самим компилятором. А моя забота только грамотно отработать семантику.
A>Ну так покажи пример. Где он?
Пример чего? Тебе же дали ссылку на огромый ДСЛ описания физ.велечин. Что тебе еще надо? Что за дурацкая привычка делать вид, что ничего не видешь?
A> Нету, одни обещания всех шапками закидать. Я бы и рад поверить тебе, но моим аргументам ты можешь только противопоставить свои, а где факты? А факты удачного использования куда-то спешно удалились.
Есть пустопорожний треп. Но мне кажется он исходит не от меня.
Какие на фиг нружны еще факты? Прочитай о языке. Поробуй написать пару строк. А потом уже поговорим. А то у нас получается разговор Бабл-программиста. Ты не представляешь возможности другого языка и смотришь на него с точки зрения более низкоуровневых языков. В результате ты просто не всилах понять все его мощи, но тебе кажется, что ты видишь набор закорючек и что все тебя обманывают.
VD>>Это следующий шаг в развитии индустрии программировния. Сама по себе концпция ДСЛ-ей не избавит от решения задач. Но во многих случаях она позволит решать задачи более просто, а значит решать более сложные задачи и решать их быстрее. Как ООП, ФП и другие парадигмы эта позволяет увеличить сложность решаемых задач впихнув их в довольно скудные возможности мозга человека.
A>Заканчивал курсы маркетологов? Почём брали за месяц?
Дорого. Тебе не понятуть.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>А зачем менять местами?
Чтобы добавить номер версии. вообще я просто привёл пример смены приоритетов. придумывать для такой замены смысл я не буду — это всего лишь пример.
A>>Это ты как великий теоритик говоришь или я всё таки увижу созданный тобой и используемый где либо кроме лаборатории DSL? Подмножества универсальных языков типа XML конфига или кода Designer.cs не в счёт.
VD>Хм. А почему собственно не в счет?
Потому что в когда Си++ придумывали никто грабли не проектировал, однако он есть Пока не начнёшь использовать что-то каждый день — недостатков не увидишь.
VD>Вот как выглядит программа с использованием этого макроса: VD>[пример поцокан]
Вааа наконецто! Уже лучше! Да, признаю, некоторая ощютимая польза от макросов Nemеrle есть при сохранении условия простоты использования.
//
//
// ПИШЕМ СУПЕР ВЕЩЬ!
//
//#include <Math.h>
//template <
int length_power, int weight_power, int time_power,
typename value_type = double,
int length_coef_numerator = 1, int length_coef_denominator = 1,
int weight_coef_numerator = 1, int weight_coef_denominator = 1,
int time_coef_numerator = 1, int time_coef_denominator = 1>
class physical_value_t
{
private:
value_type _value;
private:
static const value_type length_coefficient;
static const value_type weight_coefficient;
static const value_type time_coefficient;
private:
void assign(const physical_value_t & value)
{
_value = value._value;
}
void assign(const value_type & value)
{
_value = value;
}
template <
typename vt,
int lcn, int lcd,
int wcn, int wcd,
int tcn, int tcd>
void assign(const physical_value_t<length_power, weight_power, time_power, vt, lcn, lcd, wcn, wcd, tcn, tcd> & value)
{
_value = value.dangerous_dimensionless() *
pow((((value_type)lcn)/((value_type)lcd))/length_coefficient, length_power) *
pow((((value_type)wcn)/((value_type)wcd))/weight_coefficient, weight_power) *
pow((((value_type)tcn)/((value_type)tcd))/time_coefficient, time_power);
}
public:
physical_value_t() : _value(0)
{
}
physical_value_t(const physical_value_t & value)
{
assign(value);
}
physical_value_t(const value_type & value)
{
assign(value);
}
template <
typename vt,
int lcn, int lcd,
int wcn, int wcd,
int tcn, int tcd>
physical_value_t(const physical_value_t<length_power, weight_power, time_power, vt, lcn, lcd, wcn, wcd, tcn, tcd> & value)
{
assign<vt, lcn, lcd, wcn, wcd, tcn, tcd>(value);
}
physical_value_t & operator = (const physical_value_t & value)
{
assign(value);
return *this;
}
physical_value_t & operator = (const value_type & value)
{
assign(value);
return *this;
}
template <
typename vt,
int lcn, int lcd,
int wcn, int wcd,
int tcn, int tcd>
physical_value_t & operator = (const physical_value_t<length_power, weight_power, time_power, vt, lcn, lcd, wcn, wcd, tcn, tcd> & value)
{
assign<vt, lcn, lcd, wcn, wcd, tcn, tcd>(value);
return *this;
}
value_type dangerous_dimensionless() const
{
return _value;
}
physical_value_t operator + (const physical_value_t & right)
{
return physical_value_t (_value + right._value);
}
physical_value_t operator - (const physical_value_t & right)
{
return physical_value_t (_value - right._value);
}
physical_value_t operator * (const value_type & right)
{
return physical_value_t(_value * right);
}
physical_value_t<
2*length_power, 2*weight_power, 2*time_power,
value_type,
length_coef_numerator*length_coef_numerator, length_coef_denominator*length_coef_denominator,
weight_coef_numerator*weight_coef_numerator, weight_coef_denominator*weight_coef_denominator,
time_coef_numerator*time_coef_numerator, time_coef_denominator*time_coef_denominator>
operator * (const physical_value_t & right)
{
return physical_value_t<
2*length_power, 2*weight_power, 2*time_power,
value_type,
length_coef_numerator*length_coef_numerator, length_coef_denominator*length_coef_denominator,
weight_coef_numerator*weight_coef_numerator, weight_coef_denominator*weight_coef_denominator,
time_coef_numerator*time_coef_numerator, time_coef_denominator*time_coef_denominator>(
_value * right._value);
}
physical_value_t operator / (const value_type & right)
{
return physical_value_t(_value / right);
}
physical_value_t<
0, 0, 0,
value_type,
1, 1,
1, 1,
1, 1>
operator / (const physical_value_t & right)
{
return physical_value_t<
0, 0, 0,
value_type,
1, 1,
1, 1,
1, 1>(
_value / right._value);
}
physical_value_t & operator += (const physical_value_t & right)
{
_value += right._value;
return *this;
}
physical_value_t & operator -= (const physical_value_t & right)
{
_value -= right._value;
return *this;
}
physical_value_t & operator *= (const value_type & right)
{
_value += right;
return *this;
}
physical_value_t & operator /= (const value_type & right)
{
_value -= right;
return *this;
}
template <
typename vt,
int lcn, int lcd,
int wcn, int wcd,
int tcn, int tcd>
physical_value_t operator + (const physical_value_t & right)
{
return physical_value_t(_value + physical_value_t(right).dangerous_dimensionless());
}
template <
typename vt,
int lcn, int lcd,
int wcn, int wcd,
int tcn, int tcd>
physical_value_t operator - (const physical_value_t & right)
{
return physical_value_t(_value - physical_value_t(right).dangerous_dimensionless());
}
template <
int lp, int wp, int tp,
typename vt,
int lcn, int lcd,
int wcn, int wcd,
int tcn, int tcd>
physical_value_t<
length_power + lp,
weight_power + wp,
time_power + tp,
value_type,
length_coef_numerator, length_coef_denominator,
weight_coef_numerator, weight_coef_denominator,
time_coef_numerator, time_coef_denominator>
operator * (const physical_value_t<lp, wp, tp, vt, lcn, lcd, wcn, wcd, tcn, tcd> & right)
{
return physical_value_t<
length_power + lp,
weight_power + wp,
time_power + tp,
value_type,
length_coef_numerator, length_coef_denominator,
weight_coef_numerator, weight_coef_denominator,
time_coef_numerator, time_coef_denominator>(
_value * right.dangerous_dimensionless() *
pow((((value_type)lcn)/((value_type)lcd))/length_coefficient, lp) *
pow((((value_type)wcn)/((value_type)wcd))/weight_coefficient, wp) *
pow((((value_type)tcn)/((value_type)tcd))/time_coefficient, tp));
}
template <
int lp, int wp, int tp,
typename vt,
int lcn, int lcd,
int wcn, int wcd,
int tcn, int tcd>
physical_value_t<
length_power - lp,
weight_power - wp,
time_power - tp,
value_type,
length_coef_numerator, length_coef_denominator,
weight_coef_numerator, weight_coef_denominator,
time_coef_numerator, time_coef_denominator>
operator / (const physical_value_t<lp, wp, tp, vt, lcn, lcd, wcn, wcd, tcn, tcd> & right)
{
return physical_value_t<
length_power - lp,
weight_power - wp,
time_power - tp,
value_type,
length_coef_numerator, length_coef_denominator,
weight_coef_numerator, weight_coef_denominator,
time_coef_numerator, time_coef_denominator>(
(_value / right.dangerous_dimensionless()) *
pow((((value_type)lcn)/((value_type)lcd))/length_coefficient, -lp) *
pow((((value_type)wcn)/((value_type)wcd))/weight_coefficient, -wp) *
pow((((value_type)tcn)/((value_type)tcd))/time_coefficient, -tp));
}
template <
typename vt,
int lcn, int lcd,
int wcn, int wcd,
int tcn, int tcd>
physical_value_t & operator += (const physical_value_t & right)
{
_value += physical_value_t(right).dangerous_dimensionless();
return *this;
}
template <
typename vt,
int lcn, int lcd,
int wcn, int wcd,
int tcn, int tcd>
physical_value_t & operator -= (const physical_value_t & right)
{
_value -= physical_value_t(right).dangerous_dimensionless();
return *this;
}
};
//template <
int length_power, int weight_power, int time_power,
typename value_type,
int length_coef_numerator, int length_coef_denominator,
int weight_coef_numerator, int weight_coef_denominator,
int time_coef_numerator, int time_coef_denominator>
const value_type physical_value_t<
length_power, weight_power, time_power,
value_type,
length_coef_numerator, length_coef_denominator,
weight_coef_numerator, weight_coef_denominator,
time_coef_numerator, time_coef_denominator>::length_coefficient = ((value_type)length_coef_numerator)/((value_type)length_coef_denominator);
//template <
int length_power, int weight_power, int time_power,
typename value_type,
int length_coef_numerator, int length_coef_denominator,
int weight_coef_numerator, int weight_coef_denominator,
int time_coef_numerator, int time_coef_denominator>
const value_type physical_value_t<
length_power, weight_power, time_power,
value_type,
length_coef_numerator, length_coef_denominator,
weight_coef_numerator, weight_coef_denominator,
time_coef_numerator, time_coef_denominator>::weight_coefficient = ((value_type)weight_coef_numerator)/((value_type)weight_coef_denominator);
//template <
int length_power, int weight_power, int time_power,
typename value_type,
int length_coef_numerator, int length_coef_denominator,
int weight_coef_numerator, int weight_coef_denominator,
int time_coef_numerator, int time_coef_denominator>
const value_type physical_value_t<
length_power, weight_power, time_power,
value_type,
length_coef_numerator, length_coef_denominator,
weight_coef_numerator, weight_coef_denominator,
time_coef_numerator, time_coef_denominator>::time_coefficient = ((value_type)time_coef_numerator)/((value_type)time_coef_denominator);
//
//
// УСЁ, ТЕПЕРЬ ИСПОЛЬЗУЕМ
//
//typedef physical_value_t<1, 0, 0> phys_meter_t;
typedef physical_value_t<0, 1, 0> phys_kilogramm_t;
typedef physical_value_t<0, 0, 1> phys_second_t;
//typedef physical_value_t<1, 0, 0, double, 1, 100, 1, 1, 1, 1> phys_centimeter_t;
typedef physical_value_t<0, 1, 0, double, 1, 1, 1, 1000, 1, 1> phys_gramm_t;
typedef physical_value_t<0, 0, 1, double, 1, 1, 1, 1, 60, 1> phys_minute_t;
typedef physical_value_t<1, 0, -1> phys_mps_t;
typedef physical_value_t<2, 0, 0> phys_m2_t;
//int _tmain(int argc, _TCHAR* argv[])
{
// some tests
phys_meter_t m = 2;
phys_centimeter_t cm = m;//must be 200
phys_kilogramm_t kg = 3;
phys_gramm_t g = kg;// must be 3000
phys_second_t s = 5;
phys_minute_t min = s;// must be 0.8333
phys_mps_t mps = m / s;// must be 0.4
mps = m / min;//must be still 0.4
phys_m2_t m2 = m * m;//must be 4
m2 = m * cm;//must be still 4
m += cm * 5;// must be 12return 0;
}
//
//
// КОНЧАЕМ ИСПОЛЬЗОВАТЬ - ПЕРЕКУР. И ВООБЩЕ ПОРА ЖРАТЬ.
//
//
Я был бы очень признателен если бы ты привёл объективные недостатки использования данного решения и преимущества использования решения на Nemerle.
Заметь, что мой код гораздо меньше при приблизительно одинаковой функциональности — контроль размерностей.
Правда суффиксов нет . Хотя, так на вскидку.
#define kg() * phys_kilogramm_t(1)
Наверное не лучший вариант, просто первое, что в голову пришло. Без operator value_type нормально работать вряд ли будет, но я его специально не сделал.
Здравствуйте, VladD2, Вы писали:
A>>Влад, создаётся впечатление, что DSL это панацея от всех бед. Я не видел ещё ни одного простого и в тоже время эффективного промышленного языка, даже в пределах предметной области. A>>А наколеночные поделки не интересны — их и так плодят пачками.
VD>Нда. И где я уже видил эту аргументацию? А, у АВК. Когда аргументы по делу кончаются, то почему-то сразу начинаются "аргументы" вроде "Это что серебрянная пуля? Их не быват... Не пудрите мне мозги...". VD>Это следующий шаг в развитии индустрии программировния. Сама по себе концпция ДСЛ-ей не избавит от решения задач. Но во многих случаях она позволит решать задачи более просто, а значит решать более сложные задачи и решать их быстрее.
Вот сказать по-нормальному: "создание DSL в ряде случае вопозволяет решить задачу быстрее и проще" и никакой революции не нужно. Все и так давно об этом знали и не кипятились. Иначе бы не было языков управления пакетной обработкой.
Это сама пе себе "парадигма DSL" появилась благодаря тому, что для разных задач удобны разные языки, а не наоборот. Наоборот была бы каша. Что лишний раз подтверждает собирательный (а не сущностный) характер понятия "парадигма".
VD>Как ООП, ФП и другие парадигмы эта позволяет увеличить сложность решаемых задач впихнув их в довольно скудные возможности мозга человека.
О! Ссылка на "парадигму", как некую самостоятельную сущность.
PS.: В одном ты прав. Действительно, когда мы пишем библиотеку, то по сути, создаём свой DSL.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, adontz, Вы писали:
A>Я был бы очень признателен если бы ты привёл объективные недостатки использования данного решения и преимущества использования решения на Nemerle.
Давай хотя бы сравним вот эту строку из твоего примера:
Мне понадобилось секунды три чтобы понять, что происходит в первом случае(да, я настолько тупой ). И ~0.0 секунд чтобы разобраться во втором.
A>Заметь, что мой код гораздо меньше при приблизительно одинаковой функциональности — контроль размерностей.
Очень смешно. Во-первых не увидел одинаковой функциональности. У тебя предусмотрены только три вида базовых единиц — масса, длина и время. В решении на Nemerle произвольное количество и причем любых(хоть сам придумывай). Обрати внимание в примере описания вот на это:
В решении на Nemerle практически нет хардкодинга и в этом его главное преимущество. Мне честно-говоря даже страшно представить во что превратится твое решение на C++ если скажем понадобится десятка два таких базовых единиц.