Re[2]: Lisp
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.07.05 02:51
Оценка:
Здравствуйте, andyJB, Вы писали:

JB>Здравствуйте, fionbio, Вы писали:

F>>[skip]
JB>Появился вопрос. Чем возможности CL как "метаязыка" лучше CamlP4?

Хороший вопрос. Я про не го много слышал. Да и Ocaml мне лично больше нравится чем Илсп.

Покажи как будет выглядить пример с генерацией свойсатв на CamlP4 и Ocaml-е. Думаю, тут всем будет интересно.
... << RSDN@Home 1.2.0 alpha rev. 575>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Lisp
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.07.05 02:51
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Не для этого xslt создавался. Он создавался прежде всего для генерации html и xsl:fo по xml-файлам с данными. Вобщем понятно — эффективно предложенную задачу на лиспе не решить. И, заметь, совсем не потому что он универсальный. На универсальном O'Caml задачка решается не сильно хуже XSLT.


А где решение? Ссылочку можно?
... << RSDN@Home 1.2.0 alpha rev. 575>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: Lisp
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.07.05 02:51
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Ок. благодарю. просто, вроде бы, видел упоминание, что решение на OCaml лучше чем на LISP.


Да, я тоже. Но найти не смог.

Если тко видел, дайте ссылку, плиз.
... << RSDN@Home 1.2.0 alpha rev. 575>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Lisp
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.07.05 02:51
Оценка: 10 (1) +1
Здравствуйте, eao197, Вы писали:

Я вот тоже решил попробовать решить задачку импиративно на Шарпе. Причем в отличии от твоего примера я все же создал декларативное описание шаблона. Выносить шаблоны и модель в файл было влом, так что в целях сравнения мысленно отбрасывай их .

using System;
using System.Text;
using System.Xml;

class Program
{
    // Модель для преобразования.
    const string _model =
@"<objects>
    <object name='Obj1'>
        <property name='prop1' type='int'/>
        <property name='prop2' type='string'/>
    </object>
    <object name='AnotherObject'>
    </object>
    <object name='YetAnotherObject'>
        <property name='a' type='int'/>
        <property name='b' type='string'/>
        <property name='c' type='AnotherObject'/>
    </object>
</objects>";

    const string _templates =
@"<Templates>
    <Class>
public class #ClassName#
{
    public Obj1(#CtorParams#)
    {
        #CtorInits#
    }

#Properties#
}
    </Class>

    <Properties>
    private #type#  _#fieldName#;
    
    public #type# #PropName#
    {
        get { return _#fieldName#; }
    }
    </Properties>

    <CtorParams>#type# #fieldName#</CtorParams>
    <CtorInits>_#fieldName# = #fieldName#;</CtorInits>
</Templates>";

    static void Main()
    {
        Console.WriteLine(MakeCode());
    }

    static XmlDocument _pemplateDoc = new XmlDocument();

    static string MakeCode()
    {
        _pemplateDoc.LoadXml(_templates);
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(_model);
        string res = "";
        // Перебираем описание класов из файла модели...
        foreach (XmlNode @class in doc.SelectNodes(@"//object"))
        {
            // Заменяем паттерны на шаблоны попутно раскрывая их.
            string str = GetTemplate("#Class#").Replace("#ClassName#", @class.Attributes["name"].Value);
            ReplacePatterns(ref str, "#CtorParams#", @class, ", ");
            ReplacePatterns(ref str, "#CtorInits#", @class, ";\r\n        ");
            ReplacePatterns(ref str, "#Properties#", @class, "\r\n");
            res += str;
        }

        return res;
    }

    // Загружает шаблон и раскрвает его для каждого описания свойства.
    private static void ReplacePatterns(ref string source,
        string templateName, XmlNode @class, string separator)
    {
        StringBuilder str = new StringBuilder();
        string template = GetTemplate(templateName);

        foreach (XmlNode prop in @class.SelectNodes("property"))
        {
            str.Append(separator);
            str.Append(template.Replace("#type#", prop.Attributes["type"].Value)
                .Replace("#fieldName#", prop.Attributes["name"].Value)
                .Replace("#PropName#", Capitalize(prop.Attributes["name"].Value)));
        }

        if (str.Length > 0)
            str.Remove(0, separator.Length);
        source = source.Replace(templateName, str.ToString());
    }

    // Загружает шаблон кода по его имени. Если шаблона нет кидает исключение.
    static string GetTemplate(string templateName)
    {
        templateName = "//" + templateName.Replace("#", "");
        string template = _pemplateDoc.SelectSingleNode(templateName).InnerText;
        if (template == null)
            throw new Exception("The template '" + templateName + "' not exists.");
        return template;
    }

    // Переводит первую букву в строке в верхний регистр.
    static string Capitalize(string text)
    {
        char[] array = text.ToCharArray();
        array[0] = char.ToUpper(array[0]);
        return new String(array);
    }
}


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

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

В общем, если еще часа два подумать, то может получиться вполне себе работоспособное решение с очень простым декларативным синтаксисом.

Например в качестве имен паттернов можно попробовать использовать XPath. Однако это все ближе и ближе к XSLT.
... << RSDN@Home 1.2.0 alpha rev. 575>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Lisp
От: Cyberax Марс  
Дата: 17.07.05 05:58
Оценка:
fionbio wrote:

>>> VD>А зачем тогда Lisp? XSLT и конечное решение в две строчки пишется.

>>> Но лисп то появился до XSLT . Почему ж изобрели лисапед вместо того,
>>> чтобы лисп или ту же схему
>>> подлатать? .
> C>А можно парсер Лиспа в 12 килобайт кода?
> Не знаю, как у остальных, а у меня оно живёт вот тут:
> C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Tool
> Developers Guide\Samples\clisp\

И это _полноценный_ Лисп?

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[11]: Lisp
От: Cyberax Марс  
Дата: 17.07.05 06:02
Оценка:
aka50 wrote:

> C>Не простенький, а полноценный. Этот даже строковые литералы не парсит.

> К стати, тут собственно не лисп нужен а sexpr интерпретатор .
> Дык вот он есть: http://sexpr.sourceforge.net/ правда либа весит 30к,
> но думаю это не сильно важно .

Называется: "XML — вид в профиль". Вдобавок потоковый процессинг не
поддерживается.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[11]: Lisp
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 17.07.05 06:55
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А где решение? Ссылочку можно?


Нельзя. Под рукой нету, а вспоминать влом. Но в принципе очень похоже на то, что приводил Гапертон для Erlang.
... << RSDN@Home 1.2.0 alpha rev. 573>>
AVK Blog
Re[2]: Lisp
От: ON  
Дата: 17.07.05 10:21
Оценка:
> А можно увидеть на лиспе решение следующей задачи

На Лиспе все должно быть совсем по другому. Это же язык ИИ.
Без шаблонов и парсеров. Программа сама вполне в состоянии их сделать.

Человек дает два файла — XML с описанием и соответствующий "примерно такой вид" на С#. Программа их сопоставляет — находит лексику, поля подстановок и грамматику. Потом человек дает другой XML и программа уже сама выдает соответствующий код на C#. Если возникает неоднозначность человек просто выбирает тот вариант, который ему больше нравится.

Тут несколько человек смогут такое написать. Не важно на каком языке, но в таком вот мета- духе.
Posted via RSDN NNTP Server 1.9
Re[3]: Lisp
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 17.07.05 10:35
Оценка: +1
Здравствуйте, ON, Вы писали:

ON>Человек дает два файла — XML с описанием и соответствующий "примерно такой вид" на С#. Программа их сопоставляет — находит лексику, поля подстановок и грамматику. Потом человек дает другой XML и программа уже сама выдает соответствующий код на C#. Если возникает неоднозначность человек просто выбирает тот вариант, который ему больше нравится.


А зачем? Алгоритмы, которые требуются в данном конкретном случае, просты и детерминированны. Вносить неопределенность здесь не имеет никакого смысла.
... << RSDN@Home 1.2.0 alpha rev. 573>>
AVK Blog
Re[4]: Lisp
От: ON  
Дата: 17.07.05 11:46
Оценка:
> А зачем? Алгоритмы, которые требуются в данном конкретном случае, просты и детерминированны. Вносить неопределенность здесь не имеет никакого смысла.

Можно из такой программы выдернуть парсер+генератор и в явном виде. Но раз они просты и детерминированы, компьютер с ними как раз лучше справится.
Posted via RSDN NNTP Server 1.9
Re[5]: Lisp
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 17.07.05 13:53
Оценка:
Здравствуйте, ON, Вы писали:

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


Он с ними лучше справится, если ему точно объяснить что нужно. А в этом как раз и закавыка.
... << RSDN@Home 1.2.0 alpha rev. 573>>
AVK Blog
Re[8]: Lisp
От: Andre Украина  
Дата: 17.07.05 15:26
Оценка: 26 (1)
VD>

VD>    // Переводит первую букву в строке в верхний регистр.
VD>    static string Capitalize(string text)
VD>    {
VD>        char[] array = text.ToCharArray();
VD>        array[0] = char.ToUpper(array[0]);
VD>        return new String(array);
VD>    }
VD>


Это в принципе можно сократить до:
CultureInfo.CurrentCulture.TextInfo.ToTitleCase(string text)
... << RSDN@Home 1.1.4 beta 7 rev. 467>> :: silent
Я бы изменил мир — но Бог не даёт исходников...
Re[6]: Lisp
От: ON  
Дата: 17.07.05 16:20
Оценка:
> Он с ними лучше справится, если ему точно объяснить что нужно. А в этом как раз и закавыка.

Лучше один раз показать, чем сто раз объяснить
Posted via RSDN NNTP Server 1.9
Re[9]: Lisp
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.07.05 18:33
Оценка: :)
Здравствуйте, Andre, Вы писали:

A>Это в принципе можно сократить до:

A>
A>CultureInfo.CurrentCulture.TextInfo.ToTitleCase(string text)
A>


Сенкс. Однако хорошо они эту функцию припрятали.
... << RSDN@Home 1.2.0 alpha rev. 577>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Lisp
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.07.05 18:40
Оценка:
Здравствуйте, Andre, Вы писали:

A>Это в принципе можно сократить до:

A>
A>CultureInfo.CurrentCulture.TextInfo.ToTitleCase(string text)
A>


Глянул ее реализацию... и понял, что в МС платят за объем кода :
public unsafe string ToTitleCase(string str)
{
      if (str == null)
      {
            throw new ArgumentNullException("str");
      }
      if (this.m_cultureTableRecord.IsSynthetic)
      {
            if (this.ANSICodePage == 0x4e6)
            {
                  return CultureInfo.GetCultureInfo("tr-TR").TextInfo.ToTitleCase(str);
            }
            return CultureInfo.GetCultureInfo("en-US").TextInfo.ToTitleCase(str);
      }
      int num1 = str.Length;
      if (num1 == 0)
      {
            return str;
      }
      StringBuilder builder1 = new StringBuilder();
      string text1 = null;
      for (int num2 = 0; num2 < num1; num2++)
      {
            int num3;
            UnicodeCategory category1 = CharUnicodeInfo.InternalGetUnicodeCategory(str, num2, out num3);
            if (char.CheckLetter(category1))
            {
                  if (num3 == 1)
                  {
                        builder1.Append(TextInfo.nativeGetTitleCaseChar(this.m_pNativeTextInfo, str[num2]));
                  }
                  else
                  {
                        char ch1;
                        char ch2;
                        this.ChangeCaseSurrogate(str[num2], str[num2 + 1], out ch1, out ch2, true);
                        builder1.Append(ch1);
                        builder1.Append(ch2);
                  }
                  num2 += num3;
                  int num4 = num2;
                  bool flag1 = category1 == UnicodeCategory.LowercaseLetter;
                  while (num2 < num1)
                  {
                        category1 = CharUnicodeInfo.InternalGetUnicodeCategory(str, num2, out num3);
                        if (this.IsLetterCategory(category1))
                        {
                              if (category1 == UnicodeCategory.LowercaseLetter)
                              {
                                    flag1 = true;
                              }
                              num2 += num3;
                              continue;
                        }
                        if (str[num2] == '\'')
                        {
                              num2++;
                              if (flag1)
                              {
                                    if (text1 == null)
                                    {
                                          text1 = this.ToLower(str);
                                    }
                                    builder1.Append(text1, num4, (int) (num2 - num4));
                              }
                              else
                              {
                                    builder1.Append(str, num4, (int) (num2 - num4));
                              }
                              num4 = num2;
                              flag1 = true;
                              continue;
                        }
                        if (this.IsWordSeparator(category1))
                        {
                              break;
                        }
                        num2 += num3;
                  }
                  int num5 = num2 - num4;
                  if (num5 > 0)
                  {
                        if (flag1)
                        {
                              if (text1 == null)
                              {
                                    text1 = this.ToLower(str);
                              }
                              builder1.Append(text1, num4, num5);
                        }
                        else
                        {
                              builder1.Append(str, num4, num5);
                        }
                  }
                  if (num2 < num1)
                  {
                        if (num3 == 1)
                        {
                              builder1.Append(str[num2]);
                        }
                        else
                        {
                              builder1.Append(str[num2++]);
                              builder1.Append(str[num2]);
                        }
                  }
            }
            else if (num3 == 1)
            {
                  builder1.Append(str[num2]);
            }
            else
            {
                  builder1.Append(str[num2++]);
                  builder1.Append(str[num2]);
            }
      }
      return builder1.ToString();
}


Да и это немного не то. Это подем регистра у первых букв каждого слова.
... << RSDN@Home 1.2.0 alpha rev. 577>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Lisp
От: Andre Украина  
Дата: 17.07.05 18:54
Оценка:
VD>Глянул ее реализацию... и понял, что в МС платят за объем кода
Мне как то лень было Мда... Лучше действительно тогда твою оставить
... << RSDN@Home 1.1.4 beta 7 rev. 467>> :: silent
Я бы изменил мир — но Бог не даёт исходников...
Re[13]: Lisp
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 18.07.05 12:05
Оценка: 72 (8)
ANS>Здравствуйте, AndrewVK, Вы писали:

AVK>>Вопросы:

AVK>>1) Валидация исходной схемы?
AVK>>2) Собственно генерирующий код?
AVK>>3) Возможность генерации нескольких разных исходников по одной модели?

Всё дело проверялось на LispWorks 4.4 Personal Ed. for Win.

Перед кодом краткое пояснение:
(format t "..." ...) — выводит строку в поток (t — на стандартный вывод). Формат "~&" — новая строка; "~t" — табуляция; "~A" подставляет значение соответсвующего параметра.

(defun gen-constructor (name proplist)
  (format t "~&~tpublic ~A " name)
  ;вывод через з.п.т параметров конструктора
  ;может его можно записать короче, но я не знаю как ;)
  (format t "(~A)" (reduce #'(lambda (a b) (concatenate 'string a ", " b))
      (loop for e in proplist 
           if e collect (concatenate 'string (first e) " " (second e)))
        )
  )
  (format t "~&~t{")
  ;вывод инициализации переменных
  (dolist (i proplist) (format t "~&~t~t_~A = ~A;" (second i) (second i)))
  (format t "~&~t}")
)

(defmacro object (name &body body)
 `(progn 
      (format t "~&class ~A {" ,name)
      ;(eval e) выполняет все вложенные определения свойств
      ;и собирает список пар (тип имя-свойства) по которым и генерируется конструктор
            ;если тут будет не только property, а, например, еще и constant
            ;то тот метод должен вернуть пустой список.
            ;при генерации конструктора эти пустые значения будут отброшены
      (gen-constructor ,name (loop for e in '(,@body) collect (eval e)))
      (format t "~&}~%")
  )
)

(defmacro property (&key name type)
 `(progn
    (format t "~&~tprivate ~A _~A;" ,type ,name)
    (format t "~&~tpublic ~A ~A {" ,type (string-capitalize ,name) )
    (format t "~&~t~tget { return _~A; }" ,name)
    (format t "~&~t}")
        ;выводит в поток определения свойств, и возвращает пару (тип имя-свойства)
    ;для генерации конструктора
    (list ,type ,name)
  )
)


Итого:
Самая сложная часть — вывод параметров конструктора через з.п.т. Меняя эти три функции получаем возможность генерировать разные исходники.

В качестве исходного дерева возьмём:

(object "Test" 
    (property :name "prop1" :type "int")
    (property :name "prop2" :type "string")
)


Результат:
class Test {
 private int _prop1;
 public int Prop1 {
  get { return _prop1; }
 }
 private string _prop2;
 public string Prop2 {
  get { return _prop2; }
 }
 public Test (int prop1, string prop2)
 {
  _prop1 = prop1;
  _prop2 = prop2;
 }
}


Так же, если, постоянно заглядывая в доку, я и смог написать этот фрагмент, то на валидацию
меня уже не хватает. Идея, как реализовать валидацию, у меня такая: завести динамическую переменную, в которой будет хранится список допустимых "тегов". Методы object, property проверяют валидность своих параметров, и, заглядывая в переменную определяют, могут ли они находится на этом уровне вложенности. Это должно получится еще короче, чем методы генерирующие код.
Интересный вопрос: нафига тут валидация вообще? Всё равно, истина в последней
инстанции — это компилятор. С валидацией у тебя есть куча мест, где можно ошибится:
код генерирующий исходный описатель это раз, схема данных это два, генератор это три.
Какой прок от валидации в данном случае?


А теперь пару критических слов о Common Lisp после написания на нём этой программки.

Во-первых, если вас спросят, есть ли что-то общее между Perl и CL, смело отвечайте — есть. "Птичий" язык в CL не уступает перловому: В вышеприведённом коде употребляются модификаторы из прямого апострофа, диеза-и-апострофа, обратного апострофа, запятой, запятой-и-собаки, двоеточия, амперсанда. Есть еще правила их использования внутри "квоченного" текста.

Именование и количество методов — это песня. Если CONS, CAR, CDR — еще запоминается без проблем, то, например, MAP, MAPC, MAPCAR, MAPCAN, MAPL, MAPLIST, MAPCON — и каждая со своими вариантами поведения — это уже перебор. Вот набор повеселее: CAR, CDR, CAAR, CADR, CDAR, CDDR, CAAAR, CAADR, CADAR, CADDR, CDAAR, CDADR, CDDAR, CDDDR, CAAAAR, CAAADR, CAADAR, CAADDR, CADAAR, CADADR, CADDAR, CADDDR, CDAAAR, CDAADR, CDADAR, CDADDR, CDDAAR, CDDADR, CDDDAR, CDDDDR. Разбираться с этим в программе? Я пас.

Неконсистентность. Например:
EVERY — первый параметр это предикат, второй — список.
APPLY — первый параметр — функция, второй — неограниченной число аргументов. (Внутри функции — и то и то — список, а вот с вызывающей стороны выглядит по другому. После smalltalk-овского единообразия это удивляет.)
MAP — первый параметр — тип результата, второй — функция, третий — неограниченное число списков.
DOLIST — первый параметр — пара(!) из имени переменной и обрабатываемого списка, потом тело метода.
DO — первый параметр — список типа (имя-переменной инициализатор-переменной имя-пер...).
LOOP — это вообще не LISP (это демонстрация использования не-лиспа в лиспе)! Пример:
(loop for i in '(1 324 2345 323 2 4 235 252)
when (oddp i)
do (print i)
and collect i into odd-numbers
and do (terpri)
else
collect i into even-numbers
finally
(return (values odd-numbers even-numbers)))
Там к LOOP идёт нехилое руководство.
и еще под конец — PROGV — первый параметр — список имён локальных переменных (может вычислятся в ран-тайме), второй — список начальных значений для переменных. Сравните это с "DO"
Короче, пилите, Шура, они зол... Э... В смысле, это не возможно понять это нужно запомнить!

По непонятной мне причине функции map, concatenate, merge требуют задать тип результата. Например: (concatenate 'string a ", " b)

Дальше: логика, по которой (lambda (x) (* x x)) — это не замыкание а _имя_ замыкания мне кажется несколько инородной Само замыкание достаётся по '#(lambda (x) (* x x))

Ну, и на последок: лисповая подсветка в фаре глючит

В защиту нужно сказать, что в CL есть вроде все(!) возможности из других языков. Лексические, динамические переменный, продолжаемые исключения, возвращение множества результатов с удобным доступом к ним, ключевые параметры, необязательные параметры, неограниченное число параметров, макры, поддержка ООП, мультиметоды, всякие :before, :after и пр. хуки, поддержка функционального программирования, патерн-матчинг, продолжения, замыкания, поддержка GOTO (через tagbody и go), бактрекинг. Что я забыл?
И в конце концов, как по мне, то грехемовская "On Lisp" — неплохая книга.
... << RSDN@Home 1.1.4 stable rev. 510>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[11]: Lisp
От: Cyberax Марс  
Дата: 18.07.05 12:40
Оценка:
Здравствуйте, Andre, Вы писали:

VD>>Глянул ее реализацию... и понял, что в МС платят за объем кода

A>Мне как то лень было Мда... Лучше действительно тогда твою оставить

Для какого-нибудь арабского работать не будет. Юникод — дело тонкое...
Sapienti sat!
Re[14]: Lisp
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 18.07.05 12:50
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Интересный вопрос: нафига тут валидация вообще? Всё равно, истина в последней

ANS>инстанции — это компилятор. С валидацией у тебя есть куча мест, где можно ошибится:
ANS>код генерирующий исходный описатель это раз, схема данных это два, генератор это три.
ANS>Какой прок от валидации в данном случае?

Очень простой. В случае xml я просто описываю схему, а в кодогенераторе даже не забочусь о том, что в исходных данных будет некорректная синтаксическая структура.
... << RSDN@Home 1.2.0 alpha rev. 580>>
AVK Blog
Re[15]: Lisp
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 18.07.05 13:41
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, Andrei N.Sobchuck, Вы писали:


ANS>>Интересный вопрос: нафига тут валидация вообще? Всё равно, истина в последней

ANS>>инстанции — это компилятор. С валидацией у тебя есть куча мест, где можно ошибится:
ANS>>код генерирующий исходный описатель это раз, схема данных это два, генератор это три.
ANS>>Какой прок от валидации в данном случае?

AVK>Очень простой. В случае xml я просто описываю схему, а в кодогенераторе даже не забочусь о том, что в исходных данных будет некорректная синтаксическая структура.


Я не совсем идею понял. Почему тебя не волнует правильность исходных данных? И всё таки, если прохождение валидации не гарантирует правильность целевого кода, то зачем она нужна?

Если речь идёт о внутрипрограмной генерации, то не проще ли создать генератор с неким API. Который, можно протестировать. У тебя будет одна точка, где может возникнуть ошибка, а не три.
... << RSDN@Home 1.1.4 stable rev. 510>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.