2015-01-26 2 views
0

мне нужно преобразовать арифметическую последовательность, которая использует этот тип:Изменение выражения в строку

type expr = 
     VarX 
    | VarY 
    | Sine of expr 
    | Cosine of expr 
    | Average of expr * expr 
    | Times of expr * expr 
    | Thresh of expr * expr * expr * expr 

здесь определения для всех вещей в нем:

e ::= x | y | sin (pi*e) | cos (pi*e) | ((e + e)/2) | e * e | (e<e ? e : e) 

нужно преобразовать что-то как это:

exprToString (Thresh(VarX,VarY,VarX,(Times(Sine(VarX),Cosine(Average(VarX,VarY))))));; 

к этому:

string = "(x<y?x:sin(pi*x)*cos(pi*((x+y)/2)))" 

Я знаю, что я должен сделать это рекурсивно, сопоставляя каждый expr с соответствующей строкой, но Im не уверен, где функция начнет сопоставляться или как пройти через нее. Любая помощь или подсказки будет оценены

+0

Соответствие может быть неправильным способом думать об этом. Ваш вход уже выложен как дерево с определенной структурой. Вам просто нужно пройти дерево. Модели OCaml - это просто хороший способ описать, что делать для каждого типа компонентов. –

+0

Я понимаю, что вы говорите, я предполагаю, что Varx и Vary - это листья дерева, а функции - узлы, но я не уверен, как синтаксис в Ocaml работает, чтобы пересечь дерево и изменить каждую часть на строки. Можете ли вы привести пример или связать меня с чем-то похожим? –

+0

Опять же, наверное, лучше подумать о вычислении нового значения, а не об изменении чего-либо. Значения, с которыми вы работаете, неизменяемы. Естественная прогрессия может быть такой: как рассчитать длину списка? Как насчет высоты дерева? Как насчет высоты 'expr'? Затем объединяйте строки на каждом уровне (с дополнительным синтаксисом) вместо того, чтобы просто переносить максимальную высоту. –

ответ

1

Вот упрощенная версия того, что вы, вероятно, хотите:

type expr = 
    | VarX 
    | Sine of expr 

let rec exprToString = function 
    | VarX -> "x" 
    | Sine e -> "sin("^exprToString e^")" 

let() = print_endline (exprToString (Sine (Sine (Sine (Sine VarX))))) 

Он рекурсивен над AST узлами и создать строковое представление ввода путем конкатенации строковых представлений узлы.

Этот подход не может работать хорошо для больших примеров реального мира, так как:

  • Объединение строк (^) создает новую строку из двух, это медленнее, чем некоторые более подходящей структуры данных, такие как Buffer.t
  • Too много скобок, например, (2*(2*(2*2))), а не 2*2*2*2. Если вы хотите свести к минимуму количество круглых скобок, ваш алгоритм должен знать о приоритете и возможностях оператора.
Смежные вопросы