cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Antti Koivunen <anryo...@users.sourceforge.net>
Subject Re: [Schecoon] flow control layer
Date Thu, 28 Feb 2002 12:15:32 GMT
See the comments below. I'll try to look at things like an average web 
programmer would, so the results might look more like JavaScript than 
Scheme (but JavaScript is a well known language and does share some of 
the features of real functional languages).

Ovidiu Predescu wrote:
> On Wed, 27 Feb 2002 12:25:30 +0100, Stefano Mazzocchi <stefano@apache.org> 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.

I agree, but would point out that it's possible (to some extent) to have 
variable number of arguments using an implicit argument array (and a 
function that's aware of it), e.g. in JavaScript it's common to have 
functions like:

   function callMethods() {
       var a = arguments, i;
       for (i = 0; i < a.length; i++) {
           this._tmp = a[i];
           this._tmp();
       }
   }

How about setting default values in the function declaration:

   function f1( a, b = 2, c = 3 )
   {
       ...
   }

Should be easy enough to implement?

>>>>>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.

I think it would be good to see at least a minimal example, so it would 
be easier for people to understand and comment on these things.

> 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.

Well, the result will be something that shares the semantics of Scheme, 
but the goal should be to define an easy to use language well suited for 
the task. I mean, we shouldn't just duplicate Scheme using a different 
syntax, and it's okay not to include every single feature.

> 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.

I think people might find identifiers such as 'a-b' confusing (I know 
it's a common naming convention in Scheme), so I would prefer 'a_b' or 'aB'.

> 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.

OK.

> 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;
>  }

OK.

> 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.

OK (also familiar from e.g. JavaScript).

> 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; };
>  }

I wonder if people will find this confusing (especially if dictionaries 
are defined as {"a" = 1, "b" = 2}). Would it be enough to allow the 
following (not as 'Schemy', I know):

   function my_func(a, b)
   {
       var c;
       if (a > b) {
           c = a;
       } else {
           c = 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
>     ...
>  }

Most people might expect an explicit 'return', e.g.

   function f1(a) { return a + 1; };
   function f2(a) { a + 1; };

   f1(2); // 3
   f2(2); // void

> 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};

OK, but the following would be equivalent (and familiar from JavaScript):

   var dict = { a: 1, b: 2 }

   var dict2 = { a: 1, b: { c: 2, d: 3 } }

> 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.

OK, but I'm not sure that it's absolutely necessary. Using eval() is 
generally not seen as the best programming practise.

> 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;

OK, I assume this is legal:

   import org.MyClass;
   {
       var a = new MyClass();  // org.MyClass
       import com.MyClass;
       {
           var b = new MyClass();  // com.MyClass
       }
       var c = new MyClass();  // 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

OK.

> 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.

Looking good :)

(: A ;)




---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


Mime
View raw message