|
Re: The Joy of Joy
|
Posted: Feb 9, 2006 4:38 AM
|
|
> I am doing something similar with the Unimperative. It > uses "," instead of "<<". So the above code would be > writtten:
Yeap, another choice is operator ','. It may feel more natural, especially in the context of a LISP like approach.
> "q" is the quote operator, or "[]" in Joy.
How about using an unary operator? examples:
def dupd = (!dup, dip); def dupd = (~dup, dip); def dup3 = (&(dup, dup), dip);
I think operator '&' would be better as the quote operator, since it there is an analogy of 'address of' to 'value of'.
> > The next step is that I am looking at introducing an > explicitly typed version of Unimperative > > > def<int> square = (dup, multiply); >
I think some type information would definitely help towards less bugs.
> > I have written some code for efficient dynamically typed > variant objects which you might find useful. It's at: > > http://www.codeproject.com/cpp/dynamic_typing.asp
Clever idea to use the pointer itself to store values that their size is <= to sizeof(void *).
A small note though: since a functional approach means 'no assignment', would it be more practical that values are shared between instances of class 'any' (using reference counting)? If I understood your code, each time 'any' is copied, the value is cloned.
> Are you interested in collaborating on the idea of > creating a Joy dialect in pure C++?
Sure!
> > Here is how an Unimperative file might look (it can be > included directly in a C++ project. > > > namespace standard > { > def<any, any> > popd = (q(pop), dip); > > def<any, any> > dupd = (q(dup), dip); > > def<any, any> > swapd = (q(swap), dip); > > def<any, any, any> > rollup = (swap, q(swap), dip); > > def<any, any, any> > rolldown = (q(swap), dip, swap); > > def<any, any, any> > rotate = (swap, q(swap), dip, swap); > > def<any> > unitlist = (emptylist, cons); > > def<list> > unitlistlist = (emptylist, cons); > > def<list, list> > pairlist = (emptylist, cons, cons); > > def<list> > unpair = (uncons, uncons, pop); > > def<list> > second = (rest, first); > > def<list> > third = (rest, rest, first); > > def<list> > uncons2 = (q(uncons), dip, uncons, swapd); > > def<list> > unswons2 = (q(unswons), dip, unswons, swapd); > } >
I think it is the appropriate approach.
Some (maybe silly) notes/questions/ideas:
1) What does 'dip' do? for example, popd would be defined as (pop, pop), wouldn't it?
2) wouldn't 'let' be a more appropriate name instead of 'def' and 'pop_twice' instead of 'popd'? in fact, wouldn't it be better to give better names instead of those cryptic ones? how about 'join' instead of 'cons'? I never agreed with the LISP naming: I find it cryptic and weird and puzzling, especially for newcomers.
3) I think that the reverse polish notation is difficult to stomach, especially if someone is a newbie in this domain (which most certainly it would be the case for most of us!). How about normal left-to-right notation?
For example, instead of adding two numbers like this:
let three = (1, 2, add);
It would be better if it was like this:
let three = (add, 1, 2);
'1' and '2' would still be pushed to the stack, and 'add' would be executed after the push operations, of course.
|
|