M>>Приведенный вариант просто вернет true или false. Мой вариант вернет список не прошедших валидацию полей и всех ошибок, которые с ними связаны (правила валидации могут передаваться списком). SR>А, ну надо было тогда в условие задачи, добавить, что правила проверки должны задаваться более-менее декларативно.
Ну, во многом в этом и состоит смысл ПМа — описывать ребуемое декларативно
M>>При этом функция остается общей и может использоваться для любых полей любой веб-формы. Без ПМа здесь только один выход — создание некоего движка правил. Но это — совсем неудобно SR>А у вас стало быть не движок правил?
Да, действительно, я неправильно выразился. Он у меня тоже есть Но описывается он гораздо понятнее
SR>
SR> public void main() {
SR> Form form = new Form();
SR> form.put("login", "name");
SR> form.put("password", "123");
SR> form.put("password_repeated", "123");
SR> form.put("email", "name@domain.com");
SR> form.put("born_year", "1980");
SR> Object[] rules = new Object[] {
SR> "login", "length", parameters(4, 16),
SR> "password", "length", parameters(4, 16),
SR> "password", "=", parameters("password_repeated"),
SR> "email", "email", parameters(),
SR> "born_year", "<", parameters("1990")
SR> };
SR> check(form, rules);
SR> }
SR> // О боже мой, кажется, я реализовал сопоставление с образцом для списка в Java!
SR> // Этого не может быть, наверное я сплю.
SR> private void check(Form form, Object[] rules) {
SR> for (int index = 0; index < rules.length; index += 3) {
SR> String field = rules[index].toString();
SR> String rule = rules[index+1].toString();
SR> Object[] parameters = (Object[])rules[index+2];
SR> check(form, field, rule, parameters);
SR> }
SR> }
SR> private void check(Form form, String field, String rule, Object[] parameters) {
SR> if (rule.equals("length")) {
SR> int min = (Integer)parameters[0];
SR> int max = (Integer)parameters[1];
SR> checkLength(form.get(field), min, max);
SR> }
SR> ...
SR> // остальной код в той же мере тривиален
SR> }
SR>
Правильно. И такой код придется писать каждый раз заново для любой более-менее тривиальной смены структуры передаваемых данных.
придется реализовывать метод equals для term, для моего примера — целую отдельную функцию, эмулирующую сопоставление с образом, для менее тривиального примера
придется еще как-нибудь изворачиваться. А ПМ позвлит все задачи решить декларативно. Это не магическая пуля, конечно, писать все равно придется Но каждый раз это будет легко и — главное! — одинаково.
Просто if поможет только сравнить значения. ПМ позволит наглядно сравнить и структуру и значения.
Здравствуйте, Mamut, Вы писали:
M>Правильно. И такой код придется писать каждый раз заново для любой более-менее тривиальной смены структуры передаваемых данных.
Какой такой? Цикл по списку? Так это аналог рекурсии по списку, которую тоже придется писать каждый раз.
M>То есть. Для исхдного примера
придется реализовывать метод equals для term,
Метод equals легко автоматизируется, также как создание getter, setter и конструктора по полям в eclipse.
Я уж молчу про поддержку со стороны компилятора.
M>для моего примера — целую отдельную функцию, эмулирующую сопоставление с образом,
Странно, стороннику ФП не нравятся отдельные функции. Ну раз не нравятся объедините в одну большую.
M>для менее тривиального примера
придется еще как-нибудь изворачиваться.
Пример не более тривиален чем исходный.
M>А ПМ позвлит все задачи решить декларативно. Это не магическая пуля, конечно, писать все равно придется Но каждый раз это будет легко и — главное! — одинаково.
Так все задачи или не магическая пуля?
M>Просто if поможет только сравнить значения. ПМ позволит наглядно сравнить и структуру и значения.
Какая структура в вашем-то примере?
Re[13]: Действительно ли ML языки хороши в компиляторописани
M>>Правильно. И такой код придется писать каждый раз заново для любой более-менее тривиальной смены структуры передаваемых данных. SR>Какой такой? Цикл по списку? Так это аналог рекурсии по списку, которую тоже придется писать каждый раз.
придется реализовывать метод equals для term, SR>Метод equals легко автоматизируется, также как создание getter, setter и конструктора по полям в eclipse.
Какой-какой автоматизированый equals мне поможет это написать?
SR>Я уж молчу про поддержку со стороны компилятора.
Я тоже умолчу
M>>для моего примера — целую отдельную функцию, эмулирующую сопоставление с образом, SR>Странно, стороннику ФП не нравятся отдельные функции. Ну раз не нравятся объедините в одну большую.
?
M>>А ПМ позвлит все задачи решить декларативно. Это не магическая пуля, конечно, писать все равно придется Но каждый раз это будет легко и — главное! — одинаково. SR>Так все задачи или не магическая пуля?
Любая, где требуется разбор структур (данных). Сопоставление с образцом — это унифицированый подход к разбору произвольных структур(данных)
M>>Просто if поможет только сравнить значения. ПМ позволит наглядно сравнить и структуру и значения. SR>Какая структура в вашем-то примере?
M>Какой-какой автоматизированый equals мне поможет это написать?
Как-то определили, что мне знаком erlang?
Потом, предлагаю, не отвлекаться каждый раз на свои структуры.
Как повелось сторонниками ФП демонстрировать преимущества сопоставления с образцом на основе структур для условного калькулятора так предлагаю и продолжать.
Нет, если конечно считаете, что у вас какая-то принципиально иная структура, которая в калькулятор не укладывается.
SR>>Странно, стороннику ФП не нравятся отдельные функции. Ну раз не нравятся объедините в одну большую.
M>В какую ону большую? В Tom что ли?
Гм, по вашему одна большая функция не разбитая на малые превращается сразу в язык программирования Tom. Интересная способ рассуждений.
SR>>Пример не более тривиален чем исходный.
M>
M> | {i,FLT,{'Break',s}} :: z -> return best(emit(sb,s),n,k+#s,z)
M> | {i,BRK,{'Break',_}} :: z -> return best(nl(sb,i),i,i,z)
M> | {i,FLT,{'Group',x}} :: z -> return best(sb,w,k,{i,FLT,x}::z)
M>
M>это, я так понимаю, предлагается переписать в виде M>
M>?
Нет. Вспомните, я и код такого вида не приводил.
M>Любая, где требуется разбор структур (данных). Сопоставление с образцом — это унифицированый подход к разбору произвольных структур(данных)
Это вы хватили, насчет произвольных структур. Вот например разработчики Tom'а заявляли, что в Tom возможно сопоставлять с образцом более сложные структуры чем в Scala, но все равно не произвольные.
M>>>Просто if поможет только сравнить значения. ПМ позволит наглядно сравнить и структуру и значения. SR>>Какая структура в вашем-то примере?
M>
M>Как придумал, так и записал.
M>Более того, реализация сильно похожа на то же самое
В реализации многовато дублирования образцов. Практически каждый по два раза.
M>Но у меня, безусловно, простой пример. А есть посложнее. Типа того, что я привел в самом начале.
Про посложнее это понятно. Однако считается, что преимущество сопоставления с образцом видно уже на простых иерархиях.
А у вас странно звучит — да на простой иерархии особой разницы не видно, но если ее навернуть на порядок, тогда преимущество будет очевидно.
Re[15]: Действительно ли ML языки хороши в компиляторописани
M>>Какой-какой автоматизированый equals мне поможет это написать? SR>Как-то определили, что мне знаком erlang?
Ну, мы ж про паттерн-матчинг говорим? А тут вполне себе паттерн-матчинг. Вполне понятный даже незнакомому с Эрлангом
SR>Потом, предлагаю, не отвлекаться каждый раз на свои структуры. SR>Как повелось сторонниками ФП демонстрировать преимущества сопоставления с образцом на основе структур для условного калькулятора так предлагаю и продолжать. SR>Нет, если конечно считаете, что у вас какая-то принципиально иная структура, которая в калькулятор не укладывается.
сообщении был приведен и пример кода их компилятора
Вообще-то на одном только изолированом примере показать/доказать что-то сложно.
Надо привести два-три примера, где ПМ позволяет использовать одинаковый подход к решению проблемы, а язык без ПМа требует каждый раз нового подхода (здесь
— функции с применением if-ов). А ПМ в итоге позволяет читать код, как книгу, без необходимости пробираться сквозь дебри if-ов и попыток понять, что же автор хотел сказать тем или иным циклом
SR>>>Странно, стороннику ФП не нравятся отдельные функции. Ну раз не нравятся объедините в одну большую.
M>>В какую ону большую? В Tom что ли? SR>Гм, по вашему одна большая функция не разбитая на малые превращается сразу в язык программирования Tom. Интересная способ рассуждений.
Или в нечто ему подобное. Потому что мы же хотим некую общую функцию, которая поможет разбирать образцы не только на одном примере разбора веб-форм
SR>>>Пример не более тривиален чем исходный.
M>>
M>> | {i,FLT,{'Break',s}} :: z -> return best(emit(sb,s),n,k+#s,z)
M>> | {i,BRK,{'Break',_}} :: z -> return best(nl(sb,i),i,i,z)
M>> | {i,FLT,{'Group',x}} :: z -> return best(sb,w,k,{i,FLT,x}::z)
M>>
M>>это, я так понимаю, предлагается переписать в виде M>>
M>>? SR>Нет. Вспомните, я и код такого вида не приводил.
Ну, для калькулятора был код с term.equals, для проверки веб-=форм был код с if'ами. Для этого конкретного примера term.equals не подойдет, потому что нам не всегда все значения нужны. Так что if-ы
M>>Любая, где требуется разбор структур (данных). Сопоставление с образцом — это унифицированый подход к разбору произвольных структур(данных) SR>Это вы хватили, насчет произвольных структур. Вот например разработчики Tom'а заявляли, что в Tom возможно сопоставлять с образцом более сложные структуры чем в Scala, но все равно не произвольные.
Это, возможно, ограничения языков и/или JVM.
M>>Более того, реализация сильно похожа на то же самое SR>В реализации многовато дублирования образцов. Практически каждый по два раза.
Это мои кривые руки.
M>>Но у меня, безусловно, простой пример. А есть посложнее. Типа того, что я привел в самом начале. SR>Про посложнее это понятно. Однако считается, что преимущество сопоставления с образцом видно уже на простых иерархиях. SR>А у вас странно звучит — да на простой иерархии особой разницы не видно, но если ее навернуть на порядок, тогда преимущество будет очевидно.
На простых просто как раз и начинается- а вот тут я могу if'ом, а вот тут — функцией...
Хотя... Опять же. ПМ предлагает одинаковый подход к решению всех приведенных здесь примеров. Который еще и очень легко читается.
SmbdRsdn,
LCR>>А решать вопрос "сбрасывать или нет" каждый раз должен программист? SR>Нет. Сбрасывать не зачем.
Тогда приведи наконец этот мега-equals (или matches, неважно). Хотя бы его poc.
SR>Я, конечно, понимаю, отчего возникло непонимание. SR>Мне было лень писать что-то вроде: SR>
SR>abstract class Term {};
SR>class Num extends Term {};
SR>class Var extends Term {}
SR>@Exhaustive
SR>Term simplify(Term term) {
SR> if (term instanceof Num)
SR> return ...;
SR> if (term instanceof Var)
SR> return ...;
SR> // отсутствует "This method must return a result of type Term."
SR>}
SR>
SR>для показа как может выглядеть проверка на полноту при сопоставлении с образцом в Java.
Это очень хорошо, что ты снизошёл до более предметного разговора, только вот здесь ничего проверить невозможно, потому что у компилятора нет доказательства того, что у Term только 2 потомка. Ведь действительно, мы при запуске можем добавить ещё пару джарок, в которых может определено ещё сколько угодно подклассов Term. В Скале такой проблемы нет, потому что класс помечен sealed.
Попытка номер два?
LCR>>Специально помеченные if-ы SR>Не отдельные if, а отдельный метод. Помеченный аннотацией. Что является законным способом добавления мета-данных в Java.
Как ты собираешься отделять "паттерн-матчинговские" if-ы от обычных, в которых объекты просто сравниваются между собой?
LCR>>(которые, заметим, работают совсем не так как выглядят!) SR>Работают так же как и выглядят. То есть делают тоже, что и написано. Просто быстрее.
Да вот оказывается нет, не так.
_Term x = new _Term();
if (term.equals(new Mul(new Num(1), x))) return x.value;
Я ожидаю здесь создания композиции из трёх объектов и сравнения (по-видимому глубокого) с объектом term. А оказывается:
1. никакого создания объектов не происходит
2. equals вовсе никакое не сравнение, он не симметричен (уж не знаю, что там с транзитивностью), возвращает значения через параметры (то есть метод имеет побочные эффекты!), и вообще это не метод, а просто символическое имя, которое этот препроцессор понимает по-своему.
3. класс _Term вообще какой-то волшебный. Он одновременно является подклассом всех классов входящих в юнион-тип, потому что класс может принимать в качестве параметра не абстрактный Term, а какие-то конкретные термы, и вайлдкард может матчить как раз конкретный терм:
...
case class Yo(n: Add) extends Term
def simplify(term: Term) = term match {
...
case Yo(x) => x
case _ => term
}
4. код неявно предполагает, что объекты типов Term, Num, Mul, Add и т.п. иммутабельны, а конструкторы не имеют побочных эффектов. Но это полная туфта, в яве ты нигде не можешь потребовать того, чтобы объект был иммутабельным, и задача определения наличия значимых побочных эффектов в общем случае неразрешима.
Короче, ты просто пытаешься старым именем назвать новую сущность. Код стал более понятным? Щаз. Лично меня ты ввёл в конкретное заблуждение. Я сначала так и подумал: товарищ создаёт дерево на трёх элементах, заводит локальную переменную, передаёт в функцию equals — фигня какая-то. Зачем это делать, если можно этого не делать?
SR>К тому же в Java сообществе имеется много материалов, о том как написать свой equals и для каких целей это может потребоваться.
Да, я всё жду от тебя твоего мега-equals. Не забудь про рефлексивность, симметричность, транзитивность и неналичие побочных эффектов (это чтобы порядок вызова нескольких equals не имел значения).
SR>Готового производительного решения и нет. А преимущества в отсутствии необходимости перехода на другой язык с сильно измененным синтаксисом только для возможности сопоставления с образцом.
Ничего хорошего в этом я не вижу в упор. Синтаксис должен подчёркивать главное и всячески помогать в программировании, а не смешивать разные сущности в одной ступе а потом тщательно толочь чтобы у программиста сформировалась равномерно распределённая каша в голове... Syntax does matter.
Здравствуйте, Mamut, Вы писали:
M>>>При этом с ПМ рекрсия по списку тривиальна SR>>Неужели считаете, что цикл нетривиален?
M>Он менее "читаем", чем ПМ
Цикл это цикл, причем тут сопоставление с образцом? Сопоставление происходит уже внутри цикла.
M>>>
M>>>Какой-какой автоматизированый equals мне поможет это написать? SR>>Как-то определили, что мне знаком erlang?
M>Ну, мы ж про паттерн-матчинг говорим? А тут вполне себе паттерн-матчинг. Вполне понятный даже незнакомому с Эрлангом
Ладно попробую, хотя смысл ok слабо понятен. Какое-то ключевое слово в erlang, видимо. Так что пока без ok.
private Response getResponse() {
return new Response(list (
list ( "HTTP/1.1", 200, "OK" ),
list (
"Content-Type: text/html; charset=UTF-8",
"Content-Length: 0" ),
list ( "" )
));
}
public void parse() {
Response response = getResponse();
Any _ = new Any();
Match version = new Match(), responsePhrase = new Match(), headers = new Match(), body = new Match();
if (response.matches( list ( list (version, 200, responsePhrase), headers, body ))) {
System.out.println(responsePhrase.value);
}
if (response.matches( list (_, _, body))) {
System.out.println(body.value);
}
if (response.matches( list ( list (_, 200, _), headers, body))) {
System.out.println(headers.value);
}
}
сообщении был приведен и пример кода их компилятора
Какого компилятора? Была приведена только функция упрощения выражения. Потому что Одерски показывал только сопоставление с образцом.
Я уже приводил ссылку на полную версию программы на Scala.
Кстати код на Java, который был приведен в исходном сообщении, вроде бы тоже не руками написан, а с применением спец-компилятора Java
M>Вообще-то на одном только изолированом примере показать/доказать что-то сложно. M>Надо привести два-три примера, где ПМ позволяет использовать одинаковый подход к решению проблемы, а язык без ПМа требует каждый раз нового подхода (здесь
— функции с применением if-ов).
M>А ПМ в итоге позволяет читать код, как книгу, без необходимости пробираться сквозь дебри if-ов и попыток понять, что же автор хотел сказать тем или иным циклом
Какие дебри? Даже if'а в if'e нет. Замените if на case и вот практически код на erlang. Или там дебри case'ов?
SR>>Гм, по вашему одна большая функция не разбитая на малые превращается сразу в язык программирования Tom. Интересная способ рассуждений. M>Или в нечто ему подобное. Потому что мы же хотим некую общую функцию, которая поможет разбирать образцы не только на одном примере разбора веб-форм
Списки — простой случай, повторяю в который раз. Неужели сомневаетесь, что можно написать обобщенную функцию разбора?
SR>>Нет. Вспомните, я и код такого вида не приводил.
M>Ну, для калькулятора был код с term.equals, для проверки веб-=форм был код с if'ами. Для этого конкретного примера term.equals не подойдет, потому что нам не всегда все значения нужны. Так что if-ы
Если бы вы внимательно посмотрели на код с equals то увидели бы, что там далеко не все значения используются в дальнейшем.
M>Это, возможно, ограничения языков и/или JVM.
В Nemerle тоже сопоставляются только варианты.
M>На простых просто как раз и начинается- а вот тут я могу if'ом, а вот тут — функцией... M>Хотя... Опять же. ПМ предлагает одинаковый подход к решению всех приведенных здесь примеров. Который еще и очень легко читается.
не вижу различий, еще раз считайте что if это case.
Re[8]: Действительно ли ML языки хороши в компиляторописани
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>SmbdRsdn,
LCR>Тогда приведи наконец этот мега-equals (или matches, неважно). Хотя бы его poc.
Это в почти стандартный equals для сравнения не по ссылке а по содержанию.
class A {
public Class1 field1;
public Class2 field2;
public boolean equals(Object object) {
return object instanceof A && equals((A)object);
}
private boolean equals(A a) {
return field1.equals(a.field1) && field2.equals(a.field2);
}
}
Конечно реальный equals отличается еще поддержкой связывания.
LCR>Это очень хорошо, что ты снизошёл до более предметного разговора, только вот здесь ничего проверить невозможно, потому что у компилятора нет доказательства того, что у Term только 2 потомка. Ведь действительно, мы при запуске можем добавить ещё пару джарок, в которых может определено ещё сколько угодно подклассов Term. В Скале такой проблемы нет, потому что класс помечен sealed.
Не забывайте, что Скала не может выйти за пределы JVM. LCR>Попытка номер два?
Надуманная проблема, тем не менее хорошо, что она была озвучена. Решение — конструктор базового класса видимый только из пакета, потомки sealed.
LCR>>>Специально помеченные if-ы SR>>Не отдельные if, а отдельный метод. Помеченный аннотацией. Что является законным способом добавления мета-данных в Java. LCR>Как ты собираешься отделять "паттерн-матчинговские" if-ы от обычных, в которых объекты просто сравниваются между собой?
Зачем? Вполне разумно вынести сопоставление с образцом в отдельный метод, в котором не будет if'ов вида (if (object.equals(new Object()))) не представляющих сопоставление с образцом.
SR>>Работают так же как и выглядят. То есть делают тоже, что и написано. Просто быстрее. LCR>Да вот оказывается нет, не так. LCR>
LCR> _Term x = new _Term();
LCR> if (term.equals(new Mul(new Num(1), x))) return x.value;
LCR>
LCR>Я ожидаю здесь создания композиции из трёх объектов и сравнения (по-видимому глубокого) с объектом term. А оказывается: LCR>1. никакого создания объектов не происходит
А что тут удивительного? В Java для повышения производительности во время выполнения объект может и не создаваться каждый раз, а браться из пула уже созданных объектов. Даже проще во время компиляции преобразовать образец не в набор if'ов, а в обращение к некоторому пулу образцов, который будет создавать объекты по требованию. LCR>2. equals вовсе никакое не сравнение, он не симметричен (уж не знаю, что там с транзитивностью),
Симметричность, специально не проверял, но кажется будет симметричен и транзитивен. LCR>возвращает значения через параметры (то есть метод имеет побочные эффекты!),
Не забывайте, это же Java!
Что еще за требование, что метод не может иметь побочных эффектов?
Может и от оператора присваивания отказаться? LCR>и вообще это не метод, а просто символическое имя, которое этот препроцессор понимает по-своему.
В каком-то смысле любой метод это символическое имя которое компилятор понимает по своему. LCR>3. класс _Term вообще какой-то волшебный. Он одновременно является подклассом всех классов входящих в юнион-тип, потому что класс может принимать в качестве параметра не абстрактный Term, а какие-то конкретные термы, и вайлдкард может матчить как раз конкретный терм:
Класс _Term очень простой, его даже можно вывести из его применения.
public class _Term extends Term {
public Term value;
}
LCR>4. код неявно предполагает, что объекты типов Term, Num, Mul, Add и т.п. иммутабельны, а конструкторы не имеют побочных эффектов.
Из кода не видно, зачем ему это предположение, видимо очень не явно. На Java с Yo можно сопоставлять аналогично предыдущим классам.
LCR>Короче, ты просто пытаешься старым именем назвать новую сущность.
Скорее новым (для Java) именем старую. Equals можно было переопределять давным давно.
LCR>Код стал более понятным? Щаз. Лично меня ты ввёл в конкретное заблуждение.
Ну если так легко ввести в заблуждением кодом вида if (object.equals(new Object())), тогда не знаю.
Видимо надо начинать спрашивать про опыт программирования на Java.
SR>>К тому же в Java сообществе имеется много материалов, о том как написать свой equals и для каких целей это может потребоваться. LCR>Да, я всё жду от тебя твоего мега-equals. Не забудь про рефлексивность, симметричность, транзитивность и неналичие побочных эффектов (это чтобы порядок вызова нескольких equals не имел значения).
LCR>Ничего хорошего в этом я не вижу в упор. Синтаксис должен подчёркивать главное и всячески помогать в программировании, а не смешивать разные сущности в одной ступе а потом тщательно толочь чтобы у программиста сформировалась равномерно распределённая каша в голове... Syntax does matter.
Ну это поэзия, которая может быть и красивой, но часто неправой. А в реальности имеем синтаксис отличающийся словом new.
Re[17]: Действительно ли ML языки хороши в компиляторописани
M>>>>При этом с ПМ рекрсия по списку тривиальна SR>>>Неужели считаете, что цикл нетривиален?
M>>Он менее "читаем", чем ПМ SR>Цикл это цикл, причем тут сопоставление с образцом? Сопоставление происходит уже внутри цикла.
match([]) ->
not_ok.
match([H|T]) ->
ok.
намного понятнее. Тем более, что мы сразу на месте можем указать, что нам нужно:
match([{ok, Value}|T]) ->
ok.
match([что_то_там|T]) ->
ok.
match([{ok, {{Version, 200, ReasonPhrase}, Headers, Body}}|T]) ->
%% здесь мы сразу получаем доступ ко всем переменным
ok.
M>>>>Какой-какой автоматизированый equals мне поможет это написать? SR>>>Как-то определили, что мне знаком erlang?
M>>Ну, мы ж про паттерн-матчинг говорим? А тут вполне себе паттерн-матчинг. Вполне понятный даже незнакомому с Эрлангом SR>Ладно попробую, хотя смысл ok слабо понятен. Какое-то ключевое слово в erlang, видимо. Так что пока без ok. SR>
SR> private Response getResponse() {
SR> return new Response(list (
SR> list ( "HTTP/1.1", 200, "OK" ),
SR> list (
SR> "Content-Type: text/html; charset=UTF-8",
SR> "Content-Length: 0" ),
SR> list ( "" )
SR> ));
SR> }
SR> public void parse() {
SR> Response response = getResponse();
SR> Any _ = new Any();
SR> Match version = new Match(), responsePhrase = new Match(), headers = new Match(), body = new Match();
SR> if (response.matches( list ( list (version, 200, responsePhrase), headers, body ))) {
SR> System.out.println(responsePhrase.value);
SR> }
SR> if (response.matches( list (_, _, body))) {
SR> System.out.println(body.value);
SR> }
SR> if (response.matches( list ( list (_, 200, _), headers, body))) {
SR> System.out.println(headers.value);
SR> }
SR> }
SR>
И это называется удобным??? На каждый случай писать свою, отдельную, специализированную функцию, заточенную под разбор только данного конкретного случая?
На четырех простейших примерах — это уже четвертая такая функция. Это как раз то, о чем я говорю. ПМ позволяет использовать унифицированый подход к разбору как структуры так и значений:
%% Первый пример, http://rsdn.ru/Forum/Message.aspx?mid=2766871&only=1
%% намеренно сокращен :)
match({0, x}) ->
0;
match({1, x}) ->
x;
match({a, b}) ->
a*b;
%% Второй пример, с правилами валидации
%% http://rsdn.ru/Forum/Message.aspx?mid=2927907&only=1
%% Слегка сокращен
match({Field, Rule}) ->
match_rule(Field, Rule);
match(Field) when is_atom(Field) ->
field_exists(Field);
match_rule(Field, {Func, Value}) ->
Func(Field, Value);
%% третий пример, http://rsdn.ru/Forum/Message.aspx?mid=2927730&only=1
match([]) ->
ok;
match({i, _, empty}) ->
ok;
match({i, m, {'Cons', x, y}}) ->
ok;
%% и так далее
%% четвертый пример, http://rsdn.ru/Forum/Message.aspx?mid=2929226&only=1
match({ok, {{Version, 200, ReasonPhrase}, Headers, Body}}) ->
ok;
match({ok, {{_, 404, ReasonPhrase}, _, _}}) ->
ok;
Я с удовольствием посмотрю на общую функцию match, которая разберется со всеми этими примерами одним махом.
SR>>>Гм, по вашему одна большая функция не разбитая на малые превращается сразу в язык программирования Tom. Интересная способ рассуждений. M>>Или в нечто ему подобное. Потому что мы же хотим некую общую функцию, которая поможет разбирать образцы не только на одном примере разбора веб-форм SR>Списки — простой случай, повторяю в который раз. Неужели сомневаетесь, что можно написать обобщенную функцию разбора?
Сомневаюсь. Выше приведено четыре примера, на каждый из которых с нашей стороны был приведен простейший декларативный код с ПМом, а с вашей — четыре разные функции, которые еще и накладывают ограничения на реализацию (например, необходимость реализации метода equals в первом примере)
SR>>>Нет. Вспомните, я и код такого вида не приводил.
M>>Ну, для калькулятора был код с term.equals, для проверки веб-=форм был код с if'ами. Для этого конкретного примера term.equals не подойдет, потому что нам не всегда все значения нужны. Так что if-ы SR>Если бы вы внимательно посмотрели на код с equals то увидели бы, что там далеко не все значения используются в дальнейшем.
Зачем их тогда упоминать?
M>>Это, возможно, ограничения языков и/или JVM. SR>В Nemerle тоже сопоставляются только варианты.
M>>На простых просто как раз и начинается- а вот тут я могу if'ом, а вот тут — функцией... M>>Хотя... Опять же. ПМ предлагает одинаковый подход к решению всех приведенных здесь примеров. Который еще и очень легко читается. SR>не вижу различий, еще раз считайте что if это case.
и if и case могут проверять только значения. ПМ позвляет проверять и структуру и значения сразу, без какойлибо дополнительной работы со сторноы программиста. В этом — главное и основное отличие
Здравствуйте, Mamut, Вы писали:
M>>>>>При этом с ПМ рекрсия по списку тривиальна SR>>>>Неужели считаете, что цикл нетривиален?
M>>>Он менее "читаем", чем ПМ SR>>Цикл это цикл, причем тут сопоставление с образцом? Сопоставление происходит уже внутри цикла.
M>
M>match([]) ->
M> not_ok.
M>match([H|T]) ->
M> ok.
M>
M>намного понятнее. Тем более, что мы сразу на месте можем указать, что нам нужно:
Вы не поняли изначально. В вашем коде и моем нет сопоставления цикл — pattern matching. А есть сопоставление цикл — рекурсия.
А нужна она для того, чтобы после разбора начала списка, разобрать хвост списка. Это же стандартная тема сопоставления ФП и ИП.
M>И это называется удобным???
M>На каждый случай писать свою, отдельную, специализированную функцию, заточенную под разбор только данного конкретного случая?
Гм, у вас какое-то преувеличение насчет списков. Эта структура данных известна давным давно, все с ней более менее ясно.
С чего вы взяли, что там отдельная специализированная функция? Там обобщенная. А класс Response всего лишь обертка, которую можно и не заводить.
Я же его завел, потому что мне хотелось иметь инфиксную форму вызова matches.
А так было бы,
И сопоставлять она будет списки с произвольной структурой.
В который уже раз повторяю — обратите внимание, практически всегда, когда идет нахваливание сопоставления с образцом речь идет о вариантах, а не о просто списках.
M>На четырех простейших примерах — это уже четвертая такая функция.
Не четыре, а два и приводилась декларативная форма представления. А как это реализовано внутри не важно, главное, что можно сделать это обобщенно.
Неужели считаете, что в Scala сопоставление со списком и с вариантами это одна функция? Конечно, это может быть и так, но скорее всего их тоже две.
M>ПМ позволяет использовать унифицированый подход к разбору как структуры так и значений:
Сопоставление с образцом в Java позволяет ровно тоже самое.
M>Я с удовольствием посмотрю на общую функцию match, которая разберется со всеми этими примерами одним махом. M>
Match x = new Match();
if (list.matches(0, x))
return 0;
if (list.matches(1, x))
return x.value;
Match a = new Match, b = new Match();
if (list.matches(a, b))
return a.value * b.value;
Match field = new Match(), rule = new Match();
if (list.matches(field, rule)) {
Match func = new Match(), value = new Match();
if (rule.value.matches(func, value))
return func.value(field.value, value.value);
}
if (list.matches(field))
return fieldExists(field.value);
if (list.matches())
return ok;
Match i = new Match(), empty = new Match();
if (list.matches(i, _, empty))
return ok;
Match m = new Match(), x = new Match(), y = new Match();
if (list.matches(i, m, list("Cons", x, y)))
return ok;
Match ok = new Match(), version = new Match(), reasonPhrase = new Match(), headers = new Match(), body = new Match();
if (list.matches(ok, list (version, 200, reasonPhrase), headers, body)
return ok;
if (list.matches(ok, list (_, 404, reasonPhrase), _, _)
return ok;
M>Сомневаюсь. Выше приведено четыре примера, на каждый из которых с нашей стороны был приведен простейший декларативный код с ПМом, а с вашей — четыре разные функции, которые еще и накладывают ограничения на реализацию (например, необходимость реализации метода equals в первом примере)
С моей стороны функции, не приводились, а приводился лишь образец для сопоставления.
И случаев относящихся к сопоставление с образцом не четыре, а два. Сопоставление со списком, и сопоставление с вариантами.
Остальные два варианта с функцией validate и c циклом приводились, для уточнения условий задачи и там, действительно или не использовалось или не было ярко выражено сопоставление с образцом.
SR>>Если бы вы внимательно посмотрели на код с equals то увидели бы, что там далеко не все значения используются в дальнейшем. M>Зачем их тогда упоминать?
Как раз, чтобы показать, что сопоставлять можно со структурой, отдельные элементы которой, могут быть не важны.
M>и if и case могут проверять только значения. ПМ позвляет проверять и структуру и значения сразу, без какойлибо дополнительной работы со сторноы программиста. В этом — главное и основное отличие
Так же и при сопоставлении с образцом в Java.
Re[19]: Действительно ли ML языки хороши в компиляторописани
Здравствуйте, FR, Вы писали:
FR>Вообще классно пишешь, и главное так хитро и тонко, я вот почитал и практическм перестал сомневатся в преимуществах ML образных
Спасибо, за похвалу.
Re[20]: Действительно ли ML языки хороши в компиляторописани
Здравствуйте, FR, Вы писали:
FR>Вообще классно пишешь, и главное так хитро и тонко, я вот почитал и практическм перестал сомневатся в преимуществах ML образных
Давай-давай.
У нас конкурентов меньше будет.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[19]: Действительно ли ML языки хороши в компиляторописани
Здравствуйте, SmbdRsdn, Вы писали:
SR>Гм, у вас какое-то преувеличение насчет списков. Эта структура данных известна давным давно, все с ней более менее ясно.
А причем тут вобще списки?
SR>В который уже раз повторяю — обратите внимание, практически всегда, когда идет нахваливание сопоставления с образцом речь идет о вариантах, а не о просто списках.
Вобще говоря списки это частный случай вариантов.
Не знал?
А алгоритм генерации сопоставления с образцом уже не различает списки там или нет.
M>>ПМ позволяет использовать унифицированый подход к разбору как структуры так и значений: SR>Сопоставление с образцом в Java позволяет ровно тоже самое.
Реализацию такую чтобы я ее не разломал в пыль с первой же попытки в студию.
Про то чтобы оно еще и работало хотябы со скоростью аналога на скале я думаю можно вобще не заикаться.
M>>Я с удовольствием посмотрю на общую функцию match, которая разберется со всеми этими примерами одним махом.
У этой горы кода есть 2 проблемы:
1)Куча грязи.
2)Он не работает.
А так да. Написать кучу неработающего псевдокода с кучей грязи может любой.
SR>Так же и при сопоставлении с образцом в Java.
А его нет.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[20]: Действительно ли ML языки хороши в компиляторописани
Гм, а раньше только улыбались в оценках...
WH>А причем тут вобще списки?
Если {0, {1, 2}} не список, тогда действительно не причем.
SR>>В который уже раз повторяю — обратите внимание, практически всегда, когда идет нахваливание сопоставления с образцом речь идет о вариантах, а не о просто списках. WH>Вобще говоря списки это частный случай вариантов. WH>Не знал? WH>
WH>А компилятор их просто слегка подсахаривает.
А можно в этот вариант вложить {0, {1, 2}}? Или только {0, 1, 2}?
WH>А алгоритм генерации сопоставления с образцом уже не различает списки там или нет.
Тем лучше, значит и в java можно сделать единую функцию сопоставления с образцом
WH>Реализацию такую чтобы я ее не разломал в пыль с первой же попытки в студию.
Ожидаете устойчивый к разламыванию в пыль код сопоставления с образцом?
Что вы кстати вкладываете в понятие разламывание в пыль?
До получения ответа, не рискну выкладывать код, так как не знаю требований.
Впрочем, куски кода мною уже выкладывались, в них не хватает буквально по строчке кода в паре мест.
Убежден, что из этих кусков решение можно восстановить целиком.
WH>Про то чтобы оно еще и работало хотябы со скоростью аналога на скале я думаю можно вобще не заикаться.
Скорость сопоставления с образцом уже обсуждалась. Могу лишь вновь повторить свои доводы.
WH>У этой горы кода есть 2 проблемы: WH>1)Куча грязи.
"Грязь" — там только в необходимости заранее объявлять переменные.
Грязь в кавычках, потому что существует много доводов как за, так и против использования переменных без их объявления.
Сами же образцы для сопоставления отличаются несущественно. WH>2)Он не работает.
Он не не работает, он не приведен целиком.
Впрочем с учетом того, что код проделывающий сопоставление с образцом является в достаточной мере обобщенным и может быть вынесен в библиотеку. WH>А так да. Написать кучу неработающего псевдокода с кучей грязи может любой.
Псевдокод это, обычно, код, для которого пока не существует компилятора.
Мой же код с успехом компилируется существующими компиляторами Java.
WH>А его нет.
А она есть. Замечу, правда, что в эту игру — есть/нет — можно играть долго.
Re[19]: Действительно ли ML языки хороши в компиляторописани
SR>Вы не поняли изначально. В вашем коде и моем нет сопоставления цикл — pattern matching. А есть сопоставление цикл — рекурсия. SR>А нужна она для того, чтобы после разбора начала списка, разобрать хвост списка. Это же стандартная тема сопоставления ФП и ИП.
Ничего не понял
M>>И это называется удобным???
M>>На каждый случай писать свою, отдельную, специализированную функцию, заточенную под разбор только данного конкретного случая? SR>Гм, у вас какое-то преувеличение насчет списков. Эта структура данных известна давным давно, все с ней более менее ясно.
Причем тут списки? Идет речь не о списках, а о произвольных структурах.
SR>С чего вы взяли, что там отдельная специализированная функция? Там обобщенная. А класс Response всего лишь обертка, которую можно и не заводить. SR>Я же его завел, потому что мне хотелось иметь инфиксную форму вызова matches. SR>А так было бы, SR>
SR>И сопоставлять она будет списки с произвольной структурой. SR>В который уже раз повторяю — обратите внимание, практически всегда, когда идет нахваливание сопоставления с образцом речь идет о вариантах, а не о просто списках.
Так никто про списки изначально и не говорил
M>>На четырех простейших примерах — это уже четвертая такая функция. SR>Не четыре, а два и приводилась декларативная форма представления. А как это реализовано внутри не важно, главное, что можно сделать это обобщенно.
Как это реализовано внутри — это очень важно. Во всех примерах на Яве приходилось задвигать передаваемые данные в прокрустово ложе if'а (case'а), потому что ни if ни case не разбирают структуру разбираемых данных.
SR>Неужели считаете, что в Scala сопоставление со списком и с вариантами это одна функция? Конечно, это может быть и так, но скорее всего их тоже две.
Да, но прогарммисту, это использующему — абсолютно все равно:
case input_data of
[{elem1, elem2}|T] -> сделаем что-то одно
[[L]|T] -> разбираем вложенный список
{a, b} -> а ждесь вообще не список, оппаньки
{[H|T], [H2|T2]} -> и здесь не список передали. но внутри список
{a, {b, {c, d}}} -> здесь списком даже и не пахнет, но все разобрали
{_, _, _, _, x} -> нам важен только 5-й параметр, хотя струкутра может быть такой:
{{a, b, c}, [H|T], {[H2|T2]}, d, e} -> и все равно мы ее сможем разобрать
end
M>>ПМ позволяет использовать унифицированый подход к разбору как структуры так и значений: SR>Сопоставление с образцом в Java позволяет ровно тоже самое.
Не позволяет. Его в Яве нет. Все, что есть — это if/case, которые структуру разобрать не позволяют.
M>>Я с удовольствием посмотрю на общую функцию match, которая разберется со всеми этими примерами одним махом.
SR>[поскипаны примеры псевдокода]
что за list.match()? кто его написал? откуда он взялся? он будет работать для произвольных данных?
M>>Сомневаюсь. Выше приведено четыре примера, на каждый из которых с нашей стороны был приведен простейший декларативный код с ПМом, а с вашей — четыре разные функции, которые еще и накладывают ограничения на реализацию (например, необходимость реализации метода equals в первом примере)
SR>С моей стороны функции, не приводились, а приводился лишь образец для сопоставления. SR>И случаев относящихся к сопоставление с образцом не четыре, а два. Сопоставление со списком, и сопоставление с вариантами.
И для каждого случая пришлось писать отдельную функцию, разбирающую отдельную структуру только в данном конкретном случае для того, чтобы вернуть true/false, чтобы это можно было проверить if/case'ом
M>>и if и case могут проверять только значения. ПМ позвляет проверять и структуру и значения сразу, без какойлибо дополнительной работы со сторноы программиста. В этом — главное и основное отличие SR>Так же и при сопоставлении с образцом в Java.
Как общим кодом на Яве узнать, что:
— в первом случае у нас объект с тремя целочисленными полями
— во втором — с тремя текстовыми полями
— в третьем — вообще списко/массив
?
Более того, если нас не интересует тимп полей, а только их структура? Сколько перегруженых операторов equals придется писать для каждого отдельного случая?
Здравствуйте, Mamut, Вы писали:
M>Ничего не понял
Сочувствую.
M>Причем тут списки? M>Так никто про списки изначально и не говорил
Притом, что в ваших образцах в большинстве случаев приводятся списки.
То есть, что-то типа {obj1, obj2, _, {obj3, _ }, _}.
Я же вам в который раз отвечаю, что такие образцы легко релизуются в java. Легко по сравнению со вторым типом.
А вот более интересные типа Obj1(Obj2(_, Obj3())) у вас встречаются значительно реже.
M>Как это реализовано внутри — это очень важно. Во всех примерах на Яве приходилось задвигать передаваемые данные в прокрустово ложе if'а (case'а), потому что ни if ни case не разбирают структуру разбираемых данных.
Конечно не разбирают. Разбирает метод matches. А if в зависимости от успешности разбора передает управление.
Кстати, когда я говорил вам обратить внимание, что if это case, я имел ввиду, case из erlang, а не из java.
M>Да, но прогарммисту, это использующему — абсолютно все равно: M>
M>case input_data of
M> [{elem1, elem2}|T] -> сделаем что-то одно
M> [[L]|T] -> разбираем вложенный список
M> {a, b} -> а ждесь вообще не список, оппаньки
M> {[H|T], [H2|T2]} -> и здесь не список передали. но внутри список
M> {a, {b, {c, d}}} -> здесь списком даже и не пахнет, но все разобрали
M> {_, _, _, _, x} -> нам важен только 5-й параметр, хотя струкутра может быть такой:
M> {{a, b, c}, [H|T], {[H2|T2]}, d, e} -> и все равно мы ее сможем разобрать
M>end
M>
if (data.matches(list(elem1, elem2), T))
if (data.matches(list(L), T))
if (data.matches(a, b)
if (data.matches(list(H, T), list(H2, T2))
if (data.matches(a, list(b, list(c, d)))
if (data.matches(_, _, _, _, x))
if (data.matches(list(a, b, c), list(H, T), list(list(H2, T2), d, e)))
M>Не позволяет. Его в Яве нет. Все, что есть — это if/case, которые структуру разобрать не позволяют.
Позволяют. Играть, в эту игру можно долго.
SR>>[поскипаны примеры псевдокода]
Какой же это псевдокод? Вполне себе успешно компилируется Java.
M>что за list.match()? кто его написал? откуда он взялся? он будет работать для произвольных данных?
Его написал я. Я. Я его написал. Да.
M>И для каждого случая пришлось писать отдельную функцию, разбирающую отдельную структуру только в данном конкретном случае для того, чтобы вернуть true/false, чтобы это можно было проверить if/case'ом
Нет код обобщенный, пишу уже в который раз.
M>Еще раз — Java такого не позволяет:
Позволяет. Играть в эту игру можно долго.
M>ПМ: M>
M>Как общим кодом на Яве узнать, что: M>- в первом случае у нас объект с тремя целочисленными полями
if (list.matches(1, 2, 3))
return ok;
M>- во втором — с тремя текстовыми полями
if (list.matches("a", "b", "c")
return ok;
M>- в третьем — вообще списко/массив
Match h = new Match(); Tail t = new Tail();
if (list.matches(h, t))
return ok;
M>?
M>Более того, если нас не интересует тимп полей, а только их структура?
Что же не привели образец для сопоставления? Уверен я легко мог бы сделать такой и на Java. M>Сколько перегруженых операторов equals придется писать для каждого отдельного случая?
0. equals пишется для вариантов, но при поддержке компилятора и среды его можно и не писать.
Re[21]: Действительно ли ML языки хороши в компиляторописани
Здравствуйте, SmbdRsdn, Вы писали:
M>>Более того, если нас не интересует тимп полей, а только их структура? SR>Что же не привели образец для сопоставления? Уверен я легко мог бы сделать такой и на Java.
Нельзя. Точнее, можно, но совершенно непрактично.
M>>Сколько перегруженых операторов equals придется писать для каждого отдельного случая? SR>0. equals пишется для вариантов, но при поддержке компилятора и среды его можно и не писать.
?? equals можно автоматически сгенерировать с помощью IDE.
Sapienti sat!
Re[21]: Действительно ли ML языки хороши в компиляторописани
Здравствуйте, SmbdRsdn, Вы писали:
WH>>А причем тут вобще списки? SR>Если {0, {1, 2}} не список, тогда действительно не причем.
Это вобще туплы.
SR>А можно в этот вариант вложить {0, {1, 2}}? Или только {0, 1, 2}?
В этот нельзя.
Язык статически типизированный.
В динамически типизированных языках таких как erlang можно.
SR>Тем лучше, значит и в java можно сделать единую функцию сопоставления с образцом
Теоритически все можно сделать... особенно на словах...
WH>>Реализацию такую чтобы я ее не разломал в пыль с первой же попытки в студию. SR>Ожидаете устойчивый к разламыванию в пыль код сопоставления с образцом?
Да.
SR>Что вы кстати вкладываете в понятие разламывание в пыль?
Покажи код увидишь.
SR>До получения ответа, не рискну выкладывать код, так как не знаю требований.
Устойчивость к дуракам типа меня.
Ну и чтобы лишних проверок не делал.
SR>Впрочем, куски кода мною уже выкладывались, в них не хватает буквально по строчке кода в паре мест. SR>Убежден, что из этих кусков решение можно восстановить целиком.
Вот еще за тебя делать твою работу.
WH>>Про то чтобы оно еще и работало хотябы со скоростью аналога на скале я думаю можно вобще не заикаться. SR>Скорость сопоставления с образцом уже обсуждалась. Могу лишь вновь повторить свои доводы.
Ты где настолько умные компиляторы видел?
Я покачто видел только компиляторы которые генерили оптимальный код только если точно знали что происходит.
SR>"Грязь" — там только в необходимости заранее объявлять переменные.
Там ее еще много.
SR>Грязь в кавычках, потому что существует много доводов как за,
Аргументов за нет и быть не может.
Ибо невозможно обосновать наличие текста который совершенно ничего не дает.
SR>так и против использования переменных без их объявления.
А это вобще бред.
Переменные объявляются в коде паттерна.
SR>Сами же образцы для сопоставления отличаются несущественно.
На игрушечных примерах.
SR>Псевдокод это, обычно, код, для которого пока не существует компилятора. SR>Мой же код с успехом компилируется существующими компиляторами Java.
Полный код в студию.
В чем проблема?
Ведь ты же его вроде как уже написал.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн