пытаюсь сделать дифференцирование
От: Аноним  
Дата: 12.04.11 06:47
Оценка:
macro dif(f,x)
{
match (f) {
| <[(a+b)]> => <[dif(a)+dif(b)]>
| <[x]> => <[1]>
| _ => <[0]>
}

1. не пойму как отлаживать
2. не могу найти ошибку
Re: пытаюсь сделать дифференцирование
От: hardcase Пират http://nemerle.org
Дата: 12.04.11 07:15
Оценка:
Здравствуйте, Аноним, Вы писали:

А>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)



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[3]: пытаюсь сделать дифференцирование
От: hardcase Пират http://nemerle.org
Дата: 12.04.11 08:36
Оценка:
Здравствуйте, Аноним, Вы писали:


А>у Y тип int — почему?


Потому что:
А> | <[{x}]> => <[{1}]>
А> | _ => <[{0}]>


Если вы расскажете подробнее, что хотите сделать, то ответы будут точнее

Код, который вы привели — это совсем не дифференцирование. Поясню:
def y = dif(f,x);

Это вызов макроса dif c двумя аргументами — выражением <[ f ]> и выражением <[ x ]>. С точки зрения макроса f — это просто имя (PExpr.Ref), чтобы связать его с функцией f, объявленной выше нужно выполнять типизацию, либо произвести поиск в текущем локальном контексте (ImplicitCTX().LocalContext).
/* иЗвиНите зА неРовнЫй поЧерК */
Re[3]: пытаюсь сделать дифференцирование
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.04.11 14:17
Оценка:
Здравствуйте, Аноним, Вы писали:

А> 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
Влад ваша ссылка была о ином. Эта задача стандартна для лиспа.
Re[5]: пытаюсь сделать дифференцирование
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.04.11 18:50
Оценка:
Здравствуйте, Аноним, Вы писали:

А>дифференцирование

А>передается функция зависящая от одного аргумента. Функция включает в себя этот аргумент, константы, операции сложения и умножения. Преобразование выполняется рекурсивно. Если передается только аргумент то возвращается 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
А>Влад ваша ссылка была о ином.

Пойдем таким путем. Для начала будем работать с выражениями, а функцию будем формировать уже без макроса.

Если я правильно понял вашу задачу, то решение должно быть примерно таким.
Макрос:
using Nemerle.Compiler;
using Nemerle.Compiler.Parsetree;

namespace Dif.Macro
{
  public macro dif(expr)
  {
    Impl.dif(expr)
  }
  
  module Impl
  {
    public dif(expr : PExpr) : PExpr
    {
      | <[ $a + $b ]>       => <[ $(dif(a)) + $(dif(b)) ]>
      | <[ $a * $b ]>       => <[ $a * $(dif(b)) + $(dif(a)) * $b ]>
      | <[ $(_ : name) ]>   => <[ 1 ]>
      | <[ $(_ : uint) ]>   => <[ 0 : uint ]>
      | <[ $(_ : ulong) ]>  => <[ 0 : ulong ]>
      | <[ $(_ : int) ]>    => <[ 0 : int ]>
      | <[ $(_ : long) ]>   => <[ 0 : long ]>
      | <[ $(_ : float) ]>  => <[ 0 : float ]>
      | <[ $(_ : double) ]> => <[ 0 : double ]>
      | _                   => 
        Message.Error(expr.Location, $"Unsupported expression '$expr' ($(expr.GetType()))");
        <[ 0 ]>
    }
  }
}

Его использование:
def f(x : double) { dif(x * x + x) }
    
WriteLine(f(8.0));


Явное указание типов параметра функции нужно так как <[ 1 ]> породит константу типа int. Типизатор обнаружит ее первой и сделает вывод, что выражение оперирует с целыми. Если же указать тип параметра, то типизитор поймет, что константу нужно привести к типу параметра.

Если хочется обойтись без явного указания типов, то можно воспользоваться методом typer.DelayMacro() (я недавно рассказывал об этом методе здесь
Автор: VladD2
Дата: 11.04.11
).

Реализация использующая 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;
Re[7]: пытаюсь сделать дифференцирование
От: hardcase Пират http://nemerle.org
Дата: 13.04.11 10:45
Оценка:
Здравствуйте, Аноним, Вы писали:

А>как матчить match

А>т.е. как разбирать match

match(code)
{
  | <[ match($expr) { $..cases } ]> =>
    // expr : PExpr
    // cases : list[MatchCase]

}
/* иЗвиНите зА неРовнЫй поЧерК */
Re[8]: пытаюсь сделать дифференцирование
От: hardcase Пират http://nemerle.org
Дата: 13.04.11 10:46
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Здравствуйте, Аноним, Вы писали:


А>>как матчить match

А>>т.е. как разбирать match

H>
H>match(code)
H>{
H>  | <[ match($expr) { $..cases } ]> =>
H>    // expr : PExpr
H>    // cases : list[MatchCase]

H>}
H>


Упс, опечатка: ..$cases
/* иЗвиНите зА неРовнЫй поЧерК */
Re[9]: пытаюсь сделать дифференцирование
От: _nn_ www.nemerleweb.com
Дата: 13.04.11 12:13
Оценка: 7 (1)
Здравствуйте, hardcase, Вы писали:

Добавлю.
Есть еще Implicit match.
Используется в локальных функциях и в некоторых макросах:
#pragma indent

def f(x)
  | 1 => "a"
  | _ => "b"

foreach (n in [1..10])
  | 4 => ()
  | _ => ()


разбирается так:
#pragma indent

match (code)
  | <[ match ($(null)) { ..$cases } ]> => ...
  ...
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[7]: пытаюсь сделать дифференцирование
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.04.11 14:27
Оценка:
Здравствуйте, Аноним, Вы писали:

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 с зараннее неопределеным количеством выборов?
Re[11]: пытаюсь сделать дифференцирование
От: hardcase Пират http://nemerle.org
Дата: 28.04.11 06:39
Оценка:
Здравствуйте, Аноним, Вы писали:

А>понял, спасибо


А>такой вопрос, как сгенерировать match с зараннее неопределеным количеством выборов?


Что значит — неопределенным?
/* иЗвиНите зА неРовнЫй поЧерК */
Re[12]: пытаюсь сделать дифференцирование
От: Ziaw Россия  
Дата: 28.04.11 07:00
Оценка:
Здравствуйте, 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>


понял, сейчас попробую
Re[14]: пытаюсь сделать дифференцирование
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.04.11 19:52
Оценка: 11 (2)
Здравствуйте, Аноним, Вы писали:

Z>>Предполагаю интересует синтаксис квзицитаты одного кейса.


Возможно. Но тогда правильный вариант:
<[ case: | _ => null ]>

т.е. с модификатором "case:". Иначе компилятор не поймет, что ты не просто выражение хочешь распарсить, а именно вхождение матч.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.