# comments - 6

## phimvt@lurac.latrobe.edu.au — 2000-07-27 09:28:00

    NOTE: I am calling this "Comments - 6" because my posting

    "Comments - 4" from 20-JULY should have been called "Comments - 5".

    I have apologised already.

    Some time ago I read a book in which the author moaned in

    the preface "it was like a practical demonstration of Zeno's paradox".

    That's what I feel like trying to catch up with the "concatenative"

    mail.

    "Digest 28"

        This was slow reading because much of the material was very thought

    provoking to me.

    1.    "Type checking written in its own language". In some languages

    (Lisp, Joy, ..?) there are type predicates that can be used to ensure

    that appropriate actions are taken depending on the type of the actual

    parameters of a function. If the wrong type is given, a suitable error

    message can be given. If no such checking is written by the programmer,

    then the canned error message from the interpreter will be given. If

    the interpreter doesn't do its checking, the operating system will

    (typically) come up with a cryptic error message. Of these three possi-

    bilities only the first is of interest here. At best it gives dynamic,

    run-time checking - even if the checking could have been done at compile

    time.

        If the implementation is by a compiler, then that compiler can be

    written in its own language. For example, at least the early Pascal

    compilers were all written in their own language, and they already did

    all the required type checking. However, it would be possible to write

    the first few generations of bootstrapping compilers in such a way that

    a) they are written in a type-correct way, but b) do not do any type

    checking. Then one of them adds type checking, and that is retained

    henceforth. This now is static, compile time checking.

        The drift of the discussion seemed to be a desire for a methodology

    that straddles the two extremes in the two paragraphs above. It would

    be for a way of writing, in the language, a collection of type checking

    routines and then using them from then on in the same program. That

    of course should be without going through a bootstrapping of a new

    compiler.

        I suspect it cannot be done in the weakly typed languages such

    as Lisp, Scheme (and probably Erlang). I know it cannot be done in Joy.

    I do not know enough about Forth to say whether it might be done there.

    In an "extended Joy" a type checked definition of list reversal might

    look like this:

        DEF  reverse  ==

                 |:|top of stack is a list|:|

                 here usual definition.

    The idea is that the test inside |:| is to be applied at compile time

    whenever reverse is called:

        DEF  foo  ==  [1 2 3]  reverse   (is OK)

        DEF  bar  ==   1 2 3   reverse   (type error detected at compile time)

    The error is detected by using the |:| test at compile time.

    There is no way in which this sort of thing can be implemented in

    Joy as she is now. Now doubt one could extend Joy in some appropriate way.

        Question to the Forth wizards: can you do it? How in detail?

    Is this what IMMED (or something) is used for? Clarification

    would be most useful.

    2.  There was also some good discussion about GC (for a high level

    part of a language), how to implement it (in a low level part of the

    same(?) language), and how to break the GC (by using the low level part

    maliciously).

        I don't think there is a way out of that. You can certainly write

    a GC in, say, Pascal or C or any other procedural language (you do need

    mutable arrays - assignment etc). You then need the _discipline_ to

    stick to exactly the memory management functions that you have implemented.

    One bad move ruins the lot. I've done mark-sweep GC once in a Pascal

    program, and stop-copy GC in a C program. (Both happen to be Joy interpreters.)

    Its an experience rather different from the sort of programming

    I had done before.

        As far as I can see there is _no way_ that one could implement

    any kind of GC in a purely functional language. So if GC is to be

    written in the language itself, then there needs to be assignment.

        Do we now have a low level language, without GC but with assignment,

    and also a high level language with GC (maybe purely declarative,

    but maybe with assignment)? Or do we have just one language with two

    individually useful sublanguages? I don't know how to jump here.

    But unless there is a way to prevent the high level language from

    using the low level part to ruin the GC, the GC will not be safe

    from malice or mistakes. It should be quite easy to have two brackets

          BEGIN-GC-SAFE

          ...

          END-GC-SAFE

    such that anything in the ... part is checked by the compiler,

    and the programmer can treat is as being written in the high level

    portion of the language.

    3.  There was a short discussion on what to do after e.g

                [dup 3 +]  first

    which leaves  dup  on top of the stack. What can one do with it?

    You cannot execute it with _any_ of the Joy combinators, of course,

    but you can do this:

              [] cons   ...   i

    this first turns the  dup  into  [dup]  which is a quotation that can

    be executed any time by, say,  i.  If that sort of thing is needed

    often, one might define "interpret just one":

            i1  ==  [] cons i

    But I have not seen much use for it, except for the Joy-in-Joy

    interpreter.

    4.  There seems to be some demand for being able to manipulate

    lists ins very general way. In Joy there is the  infra  combinator:

        [..somelist..]   [..someprog..]   infra

    will temporarily take ..somelist.. to become the stack, execute

    ..someprog.. to yield a different stack, and finally push  that

    as a list onto the previous stack:

        10  11  12  [13 14]  [dup dup]  infra    ==

        10  11  12  [13 13 13 14]

    This happens at run time, of course. In the discussion there

    seemed to be a demand for doing this at compilee time, so that

    the declaration

        mylist  ==  !! [13 14]  [dup dup]  infra !!

    would be the same as

        mylist  ==  [13 13 14]

    because the !! part was executed at compile time (when storing

    the definition).

        It would be possible to add such a feature, essentially making

    Joy its own macro expansion language. The early IBM language PL1

    did that sort of thing. But I remain to be convinced about the

    usefulness of such a facility. I prefer not to add more and more

    features and make Joy bloated for the sake of making it bigger.

    But it might be persuaded that such compile time macros are a good idea.

    Try me.

        Manfred