# Re: [stack] On comments 1..6

## Louis Madon — 2000-09-05 07:41:50

    phimvt@... wrote:

     > Comments - 6

    >     I had considered a certain extension of Joy, something like

    > a macro preprocessor. Louis said it would not be necessary because

    > "Joy is its own macro language". While it is true that Joy can

    > manipulate its own programs, that isn't quite the same as being

    > its own macro language. In a later message I suggested looking at

    > M4 as a suitable testbed. (Whether M4 is the best is debateable,

    > but if it was good enough for Ratfor, then it is good enough for

    > some experiments here).

    >     For ease of reading, I'll define macro names with a capital

    > letter. Then the joy definition of square and the M4 definition

    > of Square look like this:

    >     square  ==  dup *

    >     define(Square, dup *)

    > Both can be used in  the same way:

    >     3 square  ==  9

    >     3 Square  ==  9

    > But Square is an in-line version of square. For example

    >     [square] size  ==  1

    >     [Square] size  ==  [dup *] size  == 2

    > Some people want inline definitions for efficiency, since it saves

    > a call. I am not all that keen on it.

    >     But there may be other uses of M4 style macros, especially

    > for definitions. Consider

    >     n1  ==  ...x1...

    >     n2  ==  ...x2...

    > where the dots represent some fairly complicated stuff. With M4

    > definitions that use parameters ($1, $2 and so on), such definitions

    > look like this

    >     define(N, ...$1...)

    >     n1  ==  N(x1)

    >     n2  ==  N(x2)

    > The alternative in "pure" Joy is to have

    >     n  ==  shuffle x into the right position inside ...x...

    >     n1  ==  x1 n

    >     n2  ==  x2 n

    > All the shuffling has to take place at run time, for every call.

    > (Some of my own programs do this - e.g. mk_qsort in STDLIB.JOY.)

    > It may be possible to enter things into the symbol table after

    > some preliminary (="compile time") processing, but I do not yet

    > see through all this too clearly. Maybe somebody will want to

    > have a look at using M4 in detail. _If_ it turns out useful,

    > one should investigate a taylor-made preprocessor for Joy.

     So if I understand, your key point is that macros are needed for

    efficiency reasons (you do not seem to be claiming that macros increase

    expressiveness for example). Specifically, macros would be useful in

    non-optimising compilers as a way of minimising runtime overhead.

    Conversely, in an optimising Joy compiler that finds and evaluates

    invariants at compile time they would serve no useful purpose. Does this

    seem right, or did I miss something?

    --

    Louis.

## phimvt@lurac.latrobe.edu.au — 2000-09-07 03:02:48

    On Date: Tue, 05 Sep 2000 17:41:50 +1000

    Louis Madon <madonl@...> wrote

     >> It may be possible to enter things into the symbol table after

    >> some preliminary (="compile time") processing, but I do not yet

    >> see through all this too clearly. Maybe somebody will want to

    >> have a look at using M4 in detail. _If_ it turns out useful,

    >> one should investigate a taylor-made preprocessor for Joy.

    >

    >So if I understand, your key point is that macros are needed for

    >efficiency reasons (you do not seem to be claiming that macros increase

    >expressiveness for example). Specifically, macros would be useful in

    >non-optimising compilers as a way of minimising runtime overhead.

    >Conversely, in an optimising Joy compiler that finds and evaluates

    >invariants at compile time they would serve no useful purpose. Does this

    >seem right, or did I miss something?

    >

     Generally my concern is not  all that much about machine efficiency,

    but of course I grant that some people emphasise it for good reasons

    in their applications. Inlining is just one instance, and a preprocessor

    would save some run time. In my prototype the Joy version square would

    need 3 calls (square, dup, *), and the M4 version Square would need

    2 calls (dup *). That may be a worthwhile saving.

    But macros can be used for many other things. I see Joy syntax as

    an essential part of the language (more than in most other languages),

    so I do not want to use M4 macros to change the syntax. But one

    could use it for many other purposes which deserve investigation.

    One of them is for packages. Suppose you need almost identical

    sets of definitions for handling strings and list (which collectively

    I call sequences. But for strings and lists you would need to use

    the empty string and the empty list in the two sets of definitions.

    Most other things are the same because things like cons, first,

    rest, concat .. are sufficiently polymorphic. Consider the M4 macro

    defined by

        define(Sequence-package,

            $1-foo   ==   ... $2 ...

            $1-bar   ==   ... $2 ... )

    Now the call

            Sequence-package(list,[])

    produces the Joy definitions

            list-foo   ==   ... [] ...

            list-bar   ==   ... [] ...

    and the call

            Sequence-package(string,"")

    produces the Joy definitions

            string-foo   ==   ... "" ...

            string-bar   ==   ... "" ...

    This is worth it only there are more than just two, foo and bar,

    and only if they are sufficiently large. Of course one can have

    more than two parameters in packages, and M4 would allow one macro

    to call others in its body, and even have macros as parameters.

    That is where the fun starts. I do not know of a really good

    book that deals with the theory of macro expansion. But this

    might give you an idea of the sort of things that may be worth

    exploring for Joy.

    I'll also use this opportunity to answer a question that arose

    earlier. Somebody asked about the difference between text macros

    and syntax macros. A text macro preprocessor can be used for any

    text - letters to mum, Fortran, Joy, ... M4 and the C preprocessor

    fall into this class. The result of a call will be some text,

    and if that happens to be an illegal program, the compiler will

    complain. On the other hand a syntax macro preprocessor would

    check the syntax of a macro at the point of definition of the macro.

    So such a preprocessor is specific to a particular programming

    language. For example M4 will accept the definition

        define(echochar, BEGIM reed(ch], wryte(ch) EMMD )

    but a Pascal preprocessor would complain angrily.

    For the time being I would be content with M4 style text macro

    preprocessing - mainly to investigate whether a Joy-specific

    syntax macro preprocessor would be worth having.

        Hope this helps

            Manfred

## Louis Madon — 2000-09-07 05:48:36

    phimvt@... wrote:

     > On Date: Tue, 05 Sep 2000 17:41:50 +1000

    > Louis Madon <madonl@...> wrote

    >

    > >> It may be possible to enter things into the symbol table after

    > >> some preliminary (="compile time") processing, but I do not yet

    > >> see through all this too clearly. Maybe somebody will want to

    > >> have a look at using M4 in detail. _If_ it turns out useful,

    > >> one should investigate a taylor-made preprocessor for Joy.

    > >

    > >So if I understand, your key point is that macros are needed for

    > >efficiency reasons (you do not seem to be claiming that macros

    > increase

    > >expressiveness for example). Specifically, macros would be useful in

    > >non-optimising compilers as a way of minimising runtime overhead.

    > >Conversely, in an optimising Joy compiler that finds and evaluates

    > >invariants at compile time they would serve no useful purpose. Does

    > this

    > >seem right, or did I miss something?

    > >

    > Generally my concern is not  all that much about machine efficiency,

    > but of course I grant that some people emphasise it for good reasons

    > in their applications. Inlining is just one instance, and a

    > preprocessor

    > would save some run time. In my prototype the Joy version square would

    > need 3 calls (square, dup, *), and the M4 version Square would need

    > 2 calls (dup *). That may be a worthwhile saving.

     I agree that the reference implementation of Joy could benefit,

    efficiency-wise, from something like m4. In the presence of an optimiser

    (esp. partial evaluation) I don't see such benefits, so I was wondering

    what else macros in Joy may be good for ...

     > But macros can be used for many other things. I see Joy syntax as

    > an essential part of the language (more than in most other languages),

    > so I do not want to use M4 macros to change the syntax. But one

    > could use it for many other purposes which deserve investigation.

    > One of them is for packages. Suppose you need almost identical

    > sets of definitions for handling strings and list (which collectively

    > I call sequences. But for strings and lists you would need to use

    > the empty string and the empty list in the two sets of definitions.

    > Most other things are the same because things like cons, first,

    > rest, concat .. are sufficiently polymorphic. Consider the M4 macro

    > defined by

    >

    >     define(Sequence-package,

    >         $1-foo   ==   ... $2 ...

    >         $1-bar   ==   ... $2 ... )

    >

    > Now the call

    >         Sequence-package(list,[])

    > produces the Joy definitions

    >         list-foo   ==   ... [] ...

    >         list-bar   ==   ... [] ...

    >

    > and the call

    >         Sequence-package(string,"")

    > produces the Joy definitions

    >         string-foo   ==   ... "" ...

    >         string-bar   ==   ... "" ...

     Ah yes, generating new top-level definitions programatically.  However,

    if the language has a type system that supports overloading you

    shouldn't need to do that.  Actually, the specific example above doesn't

    even need a type system:

    foo == ... [] ...

    bar == ... [] ...

    [] is the empty list as usual.  This works if strings are treated as

    lists of chars and therefore "" and [] are the same thing.  More

    generally though, I see your point as:

    foo == ... newOfTypeA ...

    foo == ... newOfTypeB ...

    ie. identical code except that we need to create instances of different

    types within the function body depending on the context.  All you need

    then is polymorphism on return type:

    new (TypeA) == ... create a new instance of type A

    new (TypeB) == ... create a new instance of type B

    and then do

    foo == ... new ...

    Moreover, we can add additional overloads on 'new' at any time and foo

    will automatically handle them without any changes to itself.

    (BTW, Haskell also treats strings as lists of char and it also has

    polymorphism on return type).

     > This is worth it only there are more than just two, foo and bar,

    > and only if they are sufficiently large. Of course one can have

    > more than two parameters in packages, and M4 would allow one macro

    > to call others in its body, and even have macros as parameters.

    > That is where the fun starts. I do not know of a really good

    > book that deals with the theory of macro expansion. But this

    > might give you an idea of the sort of things that may be worth

    > exploring for Joy.

     Maybe I'm just being too closed-minded but I still feel macros are an

    unnneccesary complication. I'll summarise as follows:

    Points for (so far):

    1 - They improve runtime efficiency (eg. by inlining)

    2 - They let you create top-level definitions programmatically

    My counterpoints:

    1 - A good optimiser can do better without requiring language extensions

    2 - A type system can eliminate the need for (2) above

    I'm not 100% sure about the validity of my counterpoint 2, but certainly

    your example above doesn't present a problem.

    Can you think of any other reasons for having macros?

    --

    Louis.