On Wed, 27 Feb 2002 12:25:30 +0100, Stefano Mazzocchi <[EMAIL PROTECTED]> wrote:
> > > why isn't simple and friendly positional syntax good enough? (remember: > > > I'm going to ask you to remove half of the things, and then half again, > > > until everything that's there *has* to be there, I'll be your anti-FS > > > nightmare :) > > > > Fair enough ;-) > > > > I guess I'm a little bit biased by languages like Python and Common > > Lisp, where you can actually do this. It's a very nice feature and > > very easy to implement. It also opens the road to functions with > > variable number of arguments, something which I badly miss in Java. > > Ok, you changed my mind. I've always missed the ability to have a > variable collection of parameters to pass and I think it could be way > cool to add it. > > So, go on. ;-) That's good. > > > > The above things are working fine right now, although I don't have a > > > > good example to demonstrate it. Since the flow would be written in > > > > Scheme, I figured not many people would be interested in it. But > > > > please let me know if there's interest to see a complete example using > > > > the flow layer written in Scheme. > > > > > > Yes, I am. Definately. In order to provide a syntax, one has to > > > understand the semantics. Without a detailed example, I think I might > > > not be able to grasp the entire concepts that the syntax should > > > describe. > > > > The more I think about it, the more I realize that writing a complete > > sample in Scheme will scare the people away. So I think I'll postpone > > this little exercise until I have some rudimentary implementation of > > the flow language. I just hope to find the time to write the > > translator... > > Please, consider giving us more info so that you don't have to write a > translator, we reject the syntax and you have to write another one. > > Trust the power of open development and trust the open-mindness of the > cocoon community. I do trust the model, but sometime is hard to formulate what you want to accomplish. What I've been thinking about is a syntax which emulates the semantic of the Scheme language as close as possible, yet provide a syntax, and a tight integration with Java. In Scheme there is no notion of statement, everything is an expression. This makes possible all sorts of things, so I'm going to follow this approach. Scheme defines nested functions and lexical scoping. A free variable in an inner function (aka a variable not declared in that function) is bound in the lexical scope in which it appears, e.g. its definition is looked up in the outer scopes. This mechanism is called closure, and is a requirement for continuations as first class objects. In Scheme identifiers can contain any symbol you like, except spaces, because operators, which are really functions, always appear in the first position in a list. So identifiers like call/cc, send-page, clear+add are perfectly valid. To be able to call normal Scheme functions from the flow language, we need to have the same ability. However because operators in jWebFlow are going to be infix, we need to require a space before them (see further why a space is not required after it). Characters like '(' ')' ',' are not allowed in identifiers. Special characters like '+' '-' '"' and ' are not allowed at the beginning or end of an identifier. This allows for things like '-a' 'a - b' 'a++', 'f(1)' to really mean what you intend. However 'a-b' is an identifier. As I mentioned earlier functions also associate arguments by name. You can call a function either by enumerating the expressions, or by associating them with names. In the later case, you can pass fewer or more arguments than are actually declared by the function: function my_func(a, b, c) { ... } // positional invocation: my_func(1, 2, 3); // by name invocation: my_func(a = 1, b = 2, c = 3); my_func(c = 3, a = 1, b = 2); my_func(a = 1); my_func(d = 4, c = 3, a = 1, b = 2); By name invocation will allow invocation from the XML sitemap without having to remember what is the order in which the arguments have been declared in the function: <map:call function="my_func"> <map:parameter name="c" value="2"/> <map:parameter name="a" value="1"/> <map:parameter name="b" value="3"/> </map:call> The actual values of the arguments in my_func are associated using their actual name. Any additional arguments which are not declared by the function, will be simply ignored. Like in Lisp, Scheme, JavaScript, Smalltalk, Python, etc. variables don't have types associated with them, only values have. Variables are declared using 'var': function my_func(a, b, c) { var d = 1; } Functions are first class objects, you can assign functions to variables. There is the notion of anonymous function, a function without a name: var f = function(a, b) { a + b; }; f(1, 2); The above declares f as a variable that holds a function which takes two arguments. The function returns the sum of the two arguments. Anonymous functions are the equivalent of lambda functions in Scheme. Blocks of code are declared with curly braces ('{' and '}'). A block is really an sequential list of expressions. The value returned by the block is the last expression in the block: function my_func(a, b) { var c = { if (a > b) a; else b; }; } The 'return' special form, takes an optional expression as argument, and terminates the execution of the current block. The value of the block becomes the value of the 'return' expression, if any, otherwise void is returned (see below for an explanation of void). function my_func(a, b) { if (a == 0) return b; // Some lengthy computation here ... } As Scheme the language has proper tail recursion. This means the following code consumes no stack at runtime: function f (i, acc) { if (i == 0) acc; else f (i - 1, acc + i); } f (100000); Built-in datatypes are numbers, arrays, dictionaries and function objects. There is a special type 'void', that has a single possible value named 'void'. With numbers there is no distinction between int, float etc. as in Java. Instead, as in Scheme, the language supports a tower of numeric subtypes, which allows arbitrarily large numbers, either exact or inexact, in a transparent manner. An array is declared using square brackets ('[' and ']'): var array = [1, 2, "abc"]; A dictionary is defined using comma in an expression context: var dict = {"a" = 1, "b" = 2}; As in Scheme and JavaScript, dynamic code can be created and executed at runtime using the 'eval' function: eval("1 + 2"); parses and evaluates the "1 + 2" expression. Eval makes the parser and evaluator available in the language. The interface with Java is straightforward. You can write: import java.io.*; var a = new InputStream(new File("/tmp/a")); The 'import' statement is a special expression which defines, in the current scope, a set of variables with the same name as the imported classes. E.g. this means that the scope of an imported class name is valid only in the scope in which it was defined: { import org.MyClass; var a = new MyClass(); // refers to org.MyClass } new MyClass(); => illegal, MyClass not defined import com.MyClass; var b = new MyClass; // refers to com.MyClass; Handling Java exceptions is similar with Java: try { a.write("abc"); } catch(IOException e) { System.out.println("exception caught: " + e); throw new RuntimeException(e); } The lexical scoping, of which I've talked about earlier, allows things like this: function my_func(a, b) { function(c) { return a + b + c; } } var f1 = my_func(1, 2); var f2 = my_func(2, 3); f1(3); // returns 6 f2(4); // returns 9 my_func is a function which returns a function object. Inside the returned function object, the values of a and b are bound to the ones at the time of my_func invocation. For example in the f1 case, the a and b values are bound to 1 and 2 respectively. This is what is called 'closure' in functional languages. I guess I can go on and on, but I'll stop here. Please let me know if I forgot to mention something which you consider is important. Right now I'm trying to decide on a way to implement the translator, which also allows me to introduce support for macros at a later point. Macros would be an advanced feature of the language, which allows one to introduce new syntaces for the language, essentially extending the language syntax at runtime. This is one of the very powerful features of Scheme and Lisp languages in general. Particularly Scheme has a very powerful way of defining macros, and I'd like to have this in the language as well. In fact, if you look at Scheme, the core language has very few built-in constructs, and everything else is defined in terms of these using macros. While programming in Python some years ago, I always missed the ability to define my own syntax. The Python parser is implemented very nicely, which makes you think you can extend the syntax, or define new mini-languages by using Python's parser. Unfortunately this is not possible, as Python doesn't expose the parser at the language level. OK, I'm not going to talk more about this feature, as I think Stefano will quickly categorize it in the "flexibility syndrom" category ;-) I'll see instead if I can implement the translator in a way which leaves the doors open. Greetings, -- Ovidiu Predescu <[EMAIL PROTECTED]> http://www.geocities.com/SiliconValley/Monitor/7464/ (GNU, Emacs, other stuff) --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]