Dear Tonglet,

Sorry for the late replay. I am most happy that there are macro facilities underway for Oz!!

On 29.05.2006, at 17:57, tooli wrote:
nb1 : if you are interested in using/testing the pre-processor, or reading the complete report, I can send it to you, as well as the source code.

I would like to have a look at that.

Here are some thoughts on your proposal.

I am very much looking forward to define and use macros in my Oz applications. When reading my comments, please bear in mind that I am looking at your proposal mainly from a users perspective, and users can be very demanding...

To be specific from the beginning, here are two macros I miss all the time in Oz:

* I would like to redefine Oz' function definition syntax to allow for functions with optional arguments and (optional) keyword arguments.

* I would like to define a class definition macro which beefs up classes by reflective capabilities. For example, the macro should implicitly define methods which return the attributes defined for a class instance (attributes directly defined by the class or inherited attributes). Also, the macro should implicitly define a method which returns the init method record which would create a given object instance (this requires analysing the init method definition, e.g., to collect the default values for optional init method arguments).

These two cases can not be defined as procedures, because they extend the syntax of Oz and therefore call for macro facilities. The first macro would change/extend the syntax of procedure (and function) definitions (which would also be reflected by procedure/function application). The second macro would analyse the special syntax of class definitions (or some equivalent).

So, I looked at your proposal and then tried to realise the first macro, namely the definition (and application) of functions with optional and keyword arguments. I am now presenting some of my tries and ask you and the rest of the community whether there are perhaps more suitable ways to address these requirements. I will even use your macro facilities in a way which they do not support -- please let me know about more suitable ways in these cases.

        --------

I do understand that the syntax defined by your macros must consist in literal Oz value (i.e. values with a textual representation such as atoms or records). This implies, that macros can not use characters like '{' or '}' (nor '[]', or all the infix operators defined by Oz). Side note: having the full macro facilities of Lisp within Oz would perhaps allow to turn these characters into macro characters (http://www.lisp.org/HyperSpec/Body/sec_2-1-4-4.html) such that their meaning can be programmed.

Consequently, {<something>} is no data structure which can be processed somehow as macro argument. Besides, all function arguments are mandatory in Oz: Oz' function application can not handle optional/keyword arguments. Therefore, I surround all my function arguments with a record (quasi my lambda list in Oz). So, my first alternative syntax attempt for function definition looks like this:

%% The macro defun defines the function Foo with the mandatory argument X, %% the optional argument Y (defaults to 42) and the keyword argument z (defaults to bla).
defun '{'Foo args(X Y#42 z:Z#bla)'}'
  [X Y Z]
end

Here are some example calls for Foo

{Foo args(hi)} % -> [hi 42 bla]

{Foo args(hi there)} % -> [hi there bla]

{Foo args(hi z:there)} % -> [hi 42 there]

{Foo args(z:bar)} % Exception: no Args.1 given


Here comes some template how the macro defun could be defined (the functions MakeDefaultVals and MakeAllVarDecls are not defined here, but I hope the example is readable anyway).

pmacro defun '{' Name Args '}' Body end
  Defaults = {MakeDefaultVals Args}
in
  (| fun {Name MyArgs}
       ','{MakeAllVarDecls Defaults MyArgs}
     in
       Body
     end |)
end

The comma is not part of your proposal and obviously inspired by Lisp. I just did not find something in your proposal which does allow me to process Args without evaluating it first: I want to process the _code_ bound to Args _before_ evaluating it later when the macro is called (e.g. the variables in Args are not defined at all at the time when MakeAllVarDecls is called). BTW: I did not find something like Lisps ,@<val> in your proposal either.

The function definition

defun '{'Foo args(X Y#42 z:Z#bla)'}'
  [X Y Z]
end

is now macroexpands into this code

local
  Defaults = args(2:24 z:bla)
in
  fun {Foo MyArgs}
    X = MyArgs.1
    Y = {SelectArg 2 MyArgs Defaults}
    Z = {SelectArg z MyArgs Defaults}
  in
    [X Y Z]
  end
end
%% I use this function in the macro expansion
fun {SelectArg Feature Spec Defaults}
   if {HasFeature Spec Feature}
   then Spec.Feature
   else Defaults.Feature
   end
end


The syntax of my function definition and application is rather bulky. Here are some alternative attempts (only the syntax, no macro def nor expansion). The problem here is still that { <something> } can not be processed as data in the macro. So I try to do without it (i.e. replace it by my own lambda list). Now, this becomes eerily Lisp-like...


defun [Foo X optional Y#42 key z#Z#bla]
  [X Y Z]
end

This function definition requires also function application to become a macro

apply [Foo hi z#there] end %% -> [hi 42 there]


Next try:

defun f(Foo X Y#42 z:Z#bla)
  [X Y Z]
end

apply f(Foo hi z:there) end %% -> [hi 42 there]


My favorite syntax would be the following. Yet, this is no legal Oz record syntax: a record label can not be a function (yet?).

defun Foo(X Y#42 z:Z#bla)
  [X Y Z]
end

apply Foo(hi z:there) end %% -> [hi 42 there]


        ----------------------

OK, to conclude here are a few further thoughts.

* According to your specification, macro must terminate with the keyword 'end'. Most existing Oz keyword constructs do indeed have this form. Still, there also exist predefined oz constructs which are not terminated by 'end' (e.g. andthen, orelse). Should the macro facility perhaps also allow for such constructs?

* Besides, could there perhaps be some alternative values allowed for macro termination (i.e. instead of 'end'). My function application macro 'apply <..> end' (see above) is af course a bit too verbose. For example, I envy the SmallTalk guys for their concise way to define blocks by [<some code>]. This syntax makes macros almost unnecessary -- just use first class functions for stuff like your macro unlike ;-) But that would definitely be no Oz anymore ;-)

* You propose macros as a pre-processor facility. This pre-processing is not specified in the program itself. I would prefer that a program somehow imports its macros explicitly, so that the meaning of a program is defined fully by the program itself.

* Are the keywords pmacro and fmacro the best choice? I agree that keywords must be short, but these keywords are hard to pronounce (e.g. all existing alphabetic Oz keywords can be pronounced, cf. http://www.mozart-oz.org/documentation/notation/ node2.html#chapter.lexical).

This mail become rather lengthy, sorry.

Best,
Torsten

--
Torsten Anders
Sonic Arts Research Centre • Queen's University Belfast
Frankstr. 49 • D-50996 Köln
Tel: +49-221-3980750
www.torsten-anders.de
strasheela.sourceforge.net


_________________________________________________________________________________
mozart-users mailing list                               
[email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-users

Reply via email to