Tree Manipulation Language

Started by
24 comments, last by choffstein 17 years, 7 months ago
Quote:Original post by Andrew Russell
Quote:Original post by Anonymous Poster
And I feel very flattered at being called legendary, but I'm actually a beginner at lisp

Woah.

Well, it seems like I'm going to need to learn Lisp anyway - just to fully appreciate that code.

If no one can point me in an even better direction, I'm going to go for Lisp on this project. Cheers [smile]


wtf, taking the meaning of the word beginner to another level.

Anyways as the L AP stated, the pattern matching syntax of the ML languages are far superior to Lisp's and will certainly make your task easier and more mentally palapable. However, the meta capabilities of Lisp will make it trivial to create a special syntax most suited for your problem domain. You might want to take a view at Nemerle which strikes a balance between the two and is also a member of the curly brace (or optionally, indentation) family of syntax.
Advertisement
Different non-Godlike ap here:

nemerle is dead sexy. Plus P. Grahams is free now:

http://www.paulgraham.com/onlisptext.html
Quote:Original post by Daerax
[...]There is a way that is many, many orders of magnitudes better than this. The method you are espousing would quickly get bogged down in semantics and become impossible to work with least of all verify, as it would become more and more specific and hardcoded. As well it would be exponentially difficult to extend. You know of metamath. that way is one way, another way is to do it constructively in a strongly typed lambda calculus whose termination assures that the proof is correct.
MetaMath is not a tree manipulation language. It does nothing more replace identifiers with strings to build new strings. I'm 99% certain that it isn't turing complete, since it does not provide a method to replace strings (so strings can be expanded, but not contracted).
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Quote:Original post by Extrarius
Quote:Original post by Daerax
[...]There is a way that is many, many orders of magnitudes better than this. The method you are espousing would quickly get bogged down in semantics and become impossible to work with least of all verify, as it would become more and more specific and hardcoded. As well it would be exponentially difficult to extend. You know of metamath. that way is one way, another way is to do it constructively in a strongly typed lambda calculus whose termination assures that the proof is correct.
MetaMath is not a tree manipulation language. It does nothing more replace identifiers with strings to build new strings. I'm 99% certain that it isn't turing complete, since it does not provide a method to replace strings (so strings can be expanded, but not contracted).


Oh right, I know that but your post was confusing since it didnt read, to me, like it had much to do with tree manipulation. You said:
Quote:You might want to look into buying "ANSI Common Lisp"(ISBN: 0133708756) as it includes as an example a pretty complex pattern matching system. It uses it to provide a relational logic language ("M is-mother-of C" implies "C is-child-of M" type of stuff), but the way it handles things (IIRC) should make it fairly easy to build up a formalization of mathematics on top (math formalization does start with basic logic, after all =-)

And I was simply noting that such a method is not that most fruitful of ways to approach the formailization of mathematics which has nothing to do with the original tree manipulation post. As well the pattern matching of MLs, orginally created for proof theoretic reasons is much more powerful (do not overestimate succintity).

Yeah, Metamath is not turing complete since it does no computations (that is its beauty) but can easily be extended so.

---

but to remain ontopic I will resuggest Nemerle which has the pattern matching capabilities of an ML but also the metabilities of a Lisp.
Quote:Original post by Daerax
[...]And I was simply noting that such a method is not that most fruitful of ways to approach the formailization of mathematics which has nothing to do with the original tree manipulation post. As well the pattern matching of MLs, orginally created for proof theoretic reasons is much more powerful (do not overestimate succintity).

Yeah, Metamath is not turing complete since it does no computations (that is its beauty) but can easily be extended so.

---

but to remain ontopic I will resuggest Nemerle which has the pattern matching capabilities of an ML but also the metabilities of a Lisp.
The part of importance was the pattern matching, which is exactly what is needed to tree manipulation. I just mentioned that it wasn't designed for the purpose of direct tree manipulation, but even without modification, it could be used as such in a contrived kind of way (inference engines are far stronger than 'metamath's language, and perform tree manipulation as a main function)
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
The pattern matching of ML would make this a piece of cake.
I will use SML/NJ for my example.

datatype expr = Const of real | Var of string | Plus of expr*expr | Minus of expr*expr | Times of expr*expr | Div of expr*expr | Collection of expr list; fun eval1(e:expr) : expr =    case e of        Div(Times(a,b),c) => Times(a, Times(b, Div(Const(1.0), c)))      |_ => efun eval2(e:expr) : expr =     case e of       Div(Times(a,b),c) => Times(Div(a, c), Div(b,c))      |_ => efun eval3(e:expr) : expr =    case e of       Div(Plus(a,b),c) => Plus(Div(a, b), Div(b,c))      |_ => e fun eval4(e:expr) : expr =   case e of      Div(Times(a,b),Const(n)) => Times(a, Times(b, Const(1.0/n)))     |_ => efun eval5(e:expr) : expr =   let       fun evalHelper(l: expr list, b:expr) : expr =         case l of            h::[] => Div(h,b)           |h::t => Times(Div(h,b), evalHelper(t, b))           |_ => raise Fail "Should never occur"               in       case e of          Div(Collection(a), b) => evalHelper(a,b)         |_ => e   end 


I think that should work. Those are some pretty specific rules. You can add a more general eval function that will actually parse it out and evaluate it for you. Something like:

fun eval(e:expr) : real =    case e of      Const(a) => a     |Plus(a,b) => eval(a) + eval(b)     |Minus(a,b) => eval(a) - eval(b)     |Div(a,b) => eval(a) / eval(b)     |Times(a,b) => eval(a) * eval(b)     |_ => raise Fail "Cannot parse type."


To do variables, you could have assocation list such as:

type association = string*realfun lookup(a:string, l:association list) : real =   case l of      [] => raise Fail "not in list"     |(x,y)::t => if a = x then y else lookup(a,t)


Then, in you eval function, just change the code to pass in an association list and when it is of type Variable(a), simply put "=> lookup(a, l)", where l is the association list.


Anyway, I hope that is what you were looking for. Your rules were rather specific -- but it can definitely easily be done using SML.

Here is some usage of the code from the SML interpreter

- Div(Times(Const(2.0), Const(4.0)), Const(12.0));val it = Div (Times (Const #,Const #),Const 12.0) : expr- eval1(it);val it = Times (Const 2.0,Times (Const #,Div #)) : expr- eval(it);val it = 0.666666666667 : real


With some extra "to string" code...

fun toString(e:expr) : string =   case e of      Const(a) => Real.toString(a)      |Plus(a,b) => toString(a) ^ "+" ^ toString(b)      |Minus(a,b) => toString(a) ^ "-" ^ toString(b)      |Div(a,b) => toString(a) ^ "/" ^ toString(b)      |Times(a,b) => toString(a) ^ "*" ^ toString(b)


With interpreter...

- Div(Times(Const(2.0), Const(4.0)), Const(12.0));val it = Div (Times (Const #,Const #),Const 12.0) : expr- eval1(it);val it = Times (Const 2.0,Times (Const #,Div #)) : expr- toString(it);val it = "2.0*4.0*1.0/12.0" : string


[Edited by - visage on September 21, 2006 5:01:55 PM]

This topic is closed to new replies.

Advertisement