Gauging Interest: New Functional Library and Programming Language

I have just completed a prototype for a functional programming language called Unimperative, which is also valid C++. This language is implemented in C++ by overloading the comma operator and use of the boost::any library. The language syntax is similar to Scheme but with the significant difference that a Function is called as (MyFxn, x, y). For instance where in Scheme you might write a factorial function as: (define factorial (lambda (n) (if (zero? n) 1 (* n (fact (- n 1)))))) In Unimperative you could write it as: Function Factorial = (If, (Eq, _1, 0), 1, (Mult, _1, (Eval, self, (Dec, _1)))); You can also write procedural code in Unimperative Function F = (Proc, (Output, 1), (Output, 2), (Output, 3), End); I have written a bit more on the language and provided some code examples at http://lambda-the-ultimate.org/node/view/512 . Well anyway, my question to the group, is whether there is some potential interest in this kind of library, and to find out if anyone wants to collaborate. Also, any suggestions on the kinds of features that would make this language/library more interesting to users and/or the boost community? Thanks in advance. Christopher Diggins Object Oriented Template Library (OOTL) http://www.ootl.org

christopher diggins wrote:
I have just completed a prototype for a functional programming language called Unimperative, which is also valid C++. This language is implemented in C++ by overloading the comma operator and use of the boost::any library.
The language syntax is similar to Scheme but with the significant difference that a Function is called as (MyFxn, x, y). For instance where in Scheme you might write a factorial function as:
(define factorial (lambda (n) (if (zero? n) 1 (* n (fact (- n 1))))))
In Unimperative you could write it as:
Function Factorial = (If, (Eq, _1, 0), 1, (Mult, _1, (Eval, self, (Dec, _1))));
Jeez, you and I should really talk. I have a project started 2 years ago called "Rave" which is reminiscent of this. Example: object factorial; factorial = if_(_1 == 0) [ 1 ] .else_ [ _1 * factorial(_1-1) ]; object is a dynamic type (ala scheme/lisp). The difference is that I use a syntax closer to c++. I don't quite like lots of parens and commas. Cheers, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

----- Original Message ----- From: "Joel de Guzman" <joel@boost-consulting.com> To: <boost@lists.boost.org> Sent: Wednesday, February 02, 2005 6:32 AM Subject: [boost] Re: Gauging Interest: New Functional Library and Programming Language
christopher diggins wrote: Jeez, you and I should really talk. I have a project started 2 years ago called "Rave" which is reminiscent of this. Example:
object factorial; factorial = if_(_1 == 0) [ 1 ] .else_ [ _1 * factorial(_1-1) ];
object is a dynamic type (ala scheme/lisp). The difference is that I use a syntax closer to c++. I don't quite like lots of parens and commas.
Hi Joel, That is pretty neat. What status is Rave in? Is there any documentation or code examples I can look at? In Rave, is evaluation lazy? Are there lambda expressions in Rave? In Unimperative a function is unevaluated when not at the beginning of a list. For instance you can write: Function AddOrSub = (If, (Eq, _1, 0), Add, Sub); Function F1 = (Eval, (AddOrSub, 0), 4, 3); Function F2 = (Eval, (AddOrSub, 1), 4, 3); f1.Evaluate(empty); // evaluates to 7 f1.Evaluate(empty); // evaluates to 1 How would this be done in Rave? Christopher Diggins Object Oriented Template Library (OOTL) http://www.ootl.org

christopher diggins wrote:
----- Original Message ----- From: "Joel de Guzman" <joel@boost-consulting.com> To: <boost@lists.boost.org> Sent: Wednesday, February 02, 2005 6:32 AM Subject: [boost] Re: Gauging Interest: New Functional Library and Programming Language
christopher diggins wrote: Jeez, you and I should really talk. I have a project started 2 years ago called "Rave" which is reminiscent of this. Example:
object factorial; factorial = if_(_1 == 0) [ 1 ] .else_ [ _1 * factorial(_1-1) ];
object is a dynamic type (ala scheme/lisp). The difference is that I use a syntax closer to c++. I don't quite like lots of parens and commas.
Hi Joel,
That is pretty neat. What status is Rave in?
Very early alpha prototype. Too much to do to little... ...you know...
Is there any documentation or code examples I can look at?
None yet.
In Rave, is evaluation lazy?
Yes. Are there
lambda expressions in Rave?
Definitely! In Unimperative a function is unevaluated
when not at the beginning of a list. For instance you can write:
Function AddOrSub = (If, (Eq, _1, 0), Add, Sub); Function F1 = (Eval, (AddOrSub, 0), 4, 3); Function F2 = (Eval, (AddOrSub, 1), 4, 3); f1.Evaluate(empty); // evaluates to 7 f1.Evaluate(empty); // evaluates to 1
How would this be done in Rave?
Hmmm. lemme see... object add_or_sub = if_(_1 == 0)[lambda[_1+_2]].else_[lambda[_1-_2]]; object f1 = add_or_sub(0)(4, 3); object f2 = add_or_sub(1)(4, 3); eval(f1); // evaluates to 7 eval(f2); // evaluates to 1 <<< Aside: I'm not quite fond of CamelCase :-) >> If you've seen Phoenix2(http://tinyurl.com/6crgp), Rave is its dynamically-typed counterpart. It's really the same thing. I intend to use it to implement the new AST features of Spirit2 as well as a generic embedded runtime interpreter, say, for parsing c++. Cheers, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

----- Original Message ----- From: "Joel de Guzman" <joel@boost-consulting.com>
Hmmm. lemme see...
object add_or_sub = if_(_1 == 0)[lambda[_1+_2]].else_[lambda[_1-_2]]; object f1 = add_or_sub(0)(4, 3); object f2 = add_or_sub(1)(4, 3); eval(f1); // evaluates to 7 eval(f2); // evaluates to 1
<<< Aside: I'm not quite fond of CamelCase :-) >>
The reason for the syntax of Unimperative is that I wanted to provide syntax which makes sense as a programming language independant of C++. The goal for Unimperative is to be both a subset of C++ and also an easily scripted language (ala Guile). I plan on writing a run-time interpreter for Unimperative as well. This will mean that I can both write a single Unimperative file: // factorial.uni Function Factorial = (If, (Eq, _1, 0), 1, (Mult, _1, (Eval, self, (Dec, _1)))); I can use this in a C++ program as follows: #include <unimperative> #include <iostreams> #include "factorial.uni" int main() { std::cout << any_cast<int>(eval(Factorial)) << endl; } But then I want to also be able to write: #include <unimperative> #include <fstreams> int main() { fstream("factorial.uni") > UnimperativeInterpreter; // the greater than operator is a stream redirect operator, which I was proposing earlier for boost::iostreams } Of course there is nothing preventing this possibility for Rave as well, it is just a little trickier. At this point it seems we have nearly identical tools, with different syntax. Unimperative syntax is quite deliberate, since I wanted it to be recognizable to programmers from backgrounds like Haskell, Lisp, Scheme, etc. It sounds like you are pleased with the Rave syntax as well, and won't be changing it anytime soon neither. It seems silly that we would be working on two tools with so much similarity. Can you think of any way we can help each other out, and perhaps reach some common ground?
If you've seen Phoenix2(http://tinyurl.com/6crgp), Rave is its dynamically-typed counterpart. It's really the same thing. I intend to use it to implement the new AST features of Spirit2 as well as a generic embedded runtime interpreter, say, for parsing c++.
That is quite impressive. I have to say Joel, I think your work is excellent and I love that you have been pushing the C++ envelope so much. CD

christopher diggins wrote:
----- Original Message ----- From: "Joel de Guzman"
At this point it seems we have nearly identical tools, with different syntax. Unimperative syntax is quite deliberate, since I wanted it to be recognizable to programmers from backgrounds like Haskell, Lisp, Scheme, etc. It sounds like you are pleased with the Rave syntax as well, and won't be changing it anytime soon neither. It seems silly that we would be working on two tools with so much similarity. Can you think of any way we can help each other out, and perhaps reach some common ground?
I'll try to resurrect Rave and polish it. It's been ehm, almost 2 years ago. It was a fun-only project, but I got too carried away (e.g. it even had big-nums and the whole numeric tower!), alas it never got finished. I'm quite sure that the common ground is the low level (dynamic) 'object' mechanism. There's fine detail going on here such as dealing with type promotion (e.g. int to real), multiple dispatch (e.g. how to deal with, say int+real, bignum+int), etc. I even went as far as providing XDR binary serialization of objects, so, you can send objects over the net or save as a file. The idea is that since a function is merely an object that you can save to file, the scheme can be an alternative to the usual bytecode. A function saved to a file can be loaded and executed. Pretty cool, IMO. Whether it's compiled by the c++ compiler, or compiled by a script parser (using Spirit of course), we don't really care. Cheers, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Joel de Guzman wrote:
I'm quite sure that the common ground is the low level (dynamic) 'object' mechanism. There's fine detail going on here such as dealing with type promotion (e.g. int to real), multiple dispatch (e.g. how to deal with, say int+real, bignum+int), etc.
When I finish implementing overloads library, I'm going to add multimethods to dynamic_any. My current vision of it is below: struct plus : operation<plus, anyT(anyT const&, anyT const&)> { template<class OperationList> struct definition { definition(plus) {} int operator()(id<1>, int a, int b) const { return a + b; } float operator()(id<2>, int a, float b) const { return a + b; } // ... any<OperationList> operator()(id<100>, any<OperationList> const& a, any<OperationList> const& b) const { // Default case. Use other dispatch mechanisms or throw exception. // ... } }; }; // Other operations // ... typedef any<vector<plus,minus,integral_promotion,/*...*/> > object; -- Alexander Nasonov

christopher diggins wrote:
I have just completed a prototype for a functional programming language called Unimperative, which is also valid C++. This language is implemented in C++ by overloading the comma operator and use of the boost::any library.
The language syntax is similar to Scheme but with the significant difference that a Function is called as (MyFxn, x, y). For instance where in Scheme you might write a factorial function as:
How do you find time to do so many things at once ?!? ;-) Jonathan

From: "Jonathan Turkanis" <technews@kangaroologic.com> To: <boost@lists.boost.org> Sent: Wednesday, February 02, 2005 4:24 PM Subject: [boost] Re: Gauging Interest: New Functional Library andProgrammingLanguage
christopher diggins wrote:
I have just completed a prototype for a functional programming language called Unimperative, which is also valid C++. This language is implemented in C++ by overloading the comma operator and use of the boost::any library.
The language syntax is similar to Scheme but with the significant difference that a Function is called as (MyFxn, x, y). For instance where in Scheme you might write a factorial function as:
How do you find time to do so many things at once ?!? ;-)
Easy, I'm unemployed ... and crazy. ;-) -- Christopher Diggins Currently seeking employment, http://www.cdiggins.com/cv.html
participants (4)
-
Alexander Nasonov
-
christopher diggins
-
Joel de Guzman
-
Jonathan Turkanis