Здравствуйте, Аноним, Вы писали:
А>macro dif(f,x) А> { А> match (f) { А> | <[(a+b)]> => <[dif(a)+dif(b)]> А> | <[x]> => <[1]> А> | _ => <[0]> А>}
А>1. не пойму как отлаживать
поставить вызов макроса assert2(false) — во время компляции можно будет запустить отладчик
А>2. не могу найти ошибку
макрос dif(f, x) принимает два аргумента, а вызывается лишь с одним: dif(a)
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: пытаюсь сделать дифференцирование
От:
Аноним
Дата:
12.04.11 07:52
Оценка:
Здравствуйте, hardcase, Вы писали:
H>Здравствуйте, Аноним, Вы писали:
А>>macro dif(f,x) А>> { А>> match (f) { А>> | <[(a+b)]> => <[dif(a)+dif(b)]> А>> | <[x]> => <[1]> А>> | _ => <[0]> А>>}
А>>1. не пойму как отлаживать
H>поставить вызов макроса assert2(false) — во время компляции можно будет запустить отладчик
А>>2. не могу найти ошибку
H>макрос dif(f, x) принимает два аргумента, а вызывается лишь с одним: dif(a)
Если вы расскажете подробнее, что хотите сделать, то ответы будут точнее
Код, который вы привели — это совсем не дифференцирование. Поясню:
def y = dif(f,x);
Это вызов макроса dif c двумя аргументами — выражением <[ f ]> и выражением <[ x ]>. С точки зрения макроса f — это просто имя (PExpr.Ref), чтобы связать его с функцией f, объявленной выше нужно выполнять типизацию, либо произвести поиск в текущем локальном контексте (ImplicitCTX().LocalContext).
Здравствуйте, Аноним, Вы писали:
А> public macro dif(f,x) А> { А> // assert2(false); А> match (f) { А> | <[{a+b}]> => <[dif(a,x)+dif(b,x)]> А> | <[{x}]> => <[{1}]> А> | _ => <[{0}]> А>}
А> def x=1.0; А> def f(x1:double){x1+x1;}; А> def y=dif(f,x);
А>у Y тип int — почему?
Потому что параметры макроса на генерируемый код не влияют. Макрос всегда возвращает сумму нулей и едениц. И вообще, код этого макроса не имеет смысла. По крайней мере совершенно бессмысленно передавать макросу ссылку на функцию и надеяться на то, что в макросе можно будет получить код этой функции.
Из приведенного кода я не могу понять что же хочет автор. Могу только догадываться, что автор хочет получить частичные вычисления (предварительный расчет формул). Если мои догадки верны, то стоит начать с изучения вот этой странички.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: пытаюсь сделать дифференцирование
От:
Аноним
Дата:
12.04.11 17:33
Оценка:
дифференцирование
передается функция зависящая от одного аргумента. Функция включает в себя этот аргумент, константы, операции сложения и умножения. Преобразование выполняется рекурсивно. Если передается только аргумент то возвращается 1. Если константа то 0. Если dif(a+b) ¤-> dif(a)+dif(b), dif(a*b) ¤-> a*dif(b)+dif(a)*b. Передавая f(x) x*x+x я должен получить функцию от одного аргумента x*1+1*x+1
Влад ваша ссылка была о ином. Эта задача стандартна для лиспа.
Здравствуйте, Аноним, Вы писали:
А>дифференцирование А>передается функция зависящая от одного аргумента. Функция включает в себя этот аргумент, константы, операции сложения и умножения. Преобразование выполняется рекурсивно. Если передается только аргумент то возвращается 1. Если константа то 0. Если dif(a+b) ¤-> dif(a)+dif(b), dif(a*b) ¤-> a*dif(b)+dif(a)*b. Передавая f(x) x*x+x я должен получить функцию от одного аргумента x*1+1*x+1 А>Влад ваша ссылка была о ином.
Пойдем таким путем. Для начала будем работать с выражениями, а функцию будем формировать уже без макроса.
Если я правильно понял вашу задачу, то решение должно быть примерно таким.
Макрос:
Явное указание типов параметра функции нужно так как <[ 1 ]> породит константу типа int. Типизатор обнаружит ее первой и сделает вывод, что выражение оперирует с целыми. Если же указать тип параметра, то типизитор поймет, что константу нужно привести к типу параметра.
Если хочется обойтись без явного указания типов, то можно воспользоваться методом typer.DelayMacro() (я недавно рассказывал об этом методе здесь
Реализация использующая typer.DelayMacro() будет выглядеть так:
using Nemerle;
using Nemerle.Compiler;
using Nemerle.Compiler.Parsetree;
using Nemerle.Utility;
namespace Dif.Macro
{
public macro dif(expr)
{
Impl.Dif(expr, Macros.ImplicitCTX())
}
module Impl
{
public Dif(expr : PExpr, typer : Typer) : PExpr
{
def typedExpr = typer.TypeExpr(expr); // типизируем исходное выражениеdef ty = typedExpr.Type; // получаем его типdef dif(expr : PExpr) : PExpr
{
| <[ $a + $b ]> => <[ $(dif(a)) + $(dif(b)) ]>
| <[ $a * $b ]> => <[ $a * $(dif(b)) + $(dif(a)) * $b ]>
| PExpr.Literal => <[ 0 : $(ty : typed) ]> // задаем литералу тип выражения
| <[ $(_ : name) ]> => <[ 1 : $(ty : typed) ]> // задаем литералу тип выражения
| _ =>
Message.Error(expr.Location, $"Unsupported expression '$expr' ($(expr.GetType()))");
<[ 0 ]>
}
// откладываем раскрытие макроса...
typer.DelayMacro(_ =>
match (ty.Hint)
{ // ... до момента пока не станет известен тип выражения
| Some(FixedType.Class) => Some(dif(expr))
| _ => None()
})
}
}
}
Все нюансы описаны в комментариях.
Вместо выражения можно обрабатывать лямбду. Однако работать с локальными функциями так будет невозможно, так как к моменту передачи имени локальной функции в макрос функция уже будет типизирована и добраться до ее АСТ будет невозможно.
Впрочем, задача не сложная. Ее можно реализовать и на типизированном АСТ.
А>Эта задача стандартна для лиспа.
Которая, эта? Та на которую я дал ссылку?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: пытаюсь сделать дифференцирование
От:
Аноним
Дата:
13.04.11 10:01
Оценка:
Здравствуйте, VladD2, Вы писали:
Удалено излишнее цитирование. Просьба, цитировать только требуемое для понимания своих слов.
VD>Которая, эта? Та на которую я дал ссылку?
Спасибо, я понял... (В лиспе хвалятся тем что можно в отличии от С++ сделать дифференцирование функции)
тогда 2 последних вопроса
как матчить match
т.е. как разбирать match
и как определить что это например переменная x, а не x1 в общем случае в функции может передаваться 5-10-20 параметров, могут участвовать внешние переменные и т д, но dif(x1)=1, а dif(остальных переменных)=0;
Здравствуйте, Аноним, Вы писали:
VD>>Которая, эта? Та на которую я дал ссылку?
А>Спасибо, я понял... (В лиспе хвалятся тем что можно в отличии от С++ сделать дифференцирование функции)
Ну, дык макры немерла во многом взаимсовованы из Лиспа.
А>тогда 2 последних вопроса
А>как матчить match А>т.е. как разбирать match
Точно так же. С помощью квази-цитат.
А>и как определить что это например переменная x, а не x1 в общем случае в функции может передаваться 5-10-20 параметров, могут участвовать внешние переменные и т д, но dif(x1)=1, а dif(остальных переменных)=0;
В макрос dif можно передавать лямбду:
def f = dif((x, y, z) => ...);
Тогда можно будет после типизации расчленить функцию на тело и параметры и потом проверять соответствие параметров.
В общем, можно. Но тут много деталей, так что нужно обсуждать уже конкретные вопросы. Приводите примеры, будем обсуждать.
А вообще, для начала нужно познакомиться с макрос-системой. Почитать статьи. Поделать тесты...
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: пытаюсь сделать дифференцирование
От:
Аноним
Дата:
28.04.11 06:22
Оценка:
понял, спасибо
такой вопрос, как сгенерировать match с зараннее неопределеным количеством выборов?
Здравствуйте, hardcase, Вы писали:
H>Здравствуйте, Аноним, Вы писали:
А>>понял, спасибо
А>>такой вопрос, как сгенерировать match с зараннее неопределеным количеством выборов?
H>Что значит — неопределенным?
Предполагаю интересует синтаксис квзицитаты одного кейса.
mutable cases = [];
cases ||= <[ | 5 => 42 ]>; // я сам так не делал, предполагаю, что синтаксис должен быть такой
cases ||= <[ | 6 => 42*42 ]>;
def match = <[ match (var) { ..$cases } ]>;
Re[13]: пытаюсь сделать дифференцирование
От:
Аноним
Дата:
28.04.11 07:05
Оценка:
Здравствуйте, Ziaw, Вы писали:
Z>Здравствуйте, hardcase, Вы писали:
H>>Здравствуйте, Аноним, Вы писали:
А>>>понял, спасибо
А>>>такой вопрос, как сгенерировать match с зараннее неопределеным количеством выборов?
H>>Что значит — неопределенным?
Z>Предполагаю интересует синтаксис квзицитаты одного кейса.
Z>
Z>mutable cases = [];
Z>cases ||= <[ | 5 => 42 ]>; // я сам так не делал, предполагаю, что синтаксис должен быть такой
Z>cases ||= <[ | 6 => 42*42 ]>;
Z>def match = <[ match (var) { ..$cases } ]>;
Z>