# ANNOUNCE: Joy-in-Scheme version 0.80 (no Scheme required; please test!)

## John Cowan — 2006-05-29 16:43:49

    I'm announcing version 0.80 of Joy-in-Scheme, eventually to become Joy2.

    You do not need a Scheme system to run this version; it should work

    anywhere that there is a C compiler.  I'd like as many different people

    to test it as possible.

    Download it, say "touch joy80.c", and then "make".  You may need to

    fiddle with the Makefile a bit, but it should be simple.

    It implements about 80% of the Joy primitives.  However, the input

    routine is very limited compared to standard Joy; in particular:

    	To evaluate Joy code, type the words followed by "!" by itself

    	("."  will not work, nor will "!" attached to the end of a word)

    	To define a Joy word, use "DEFINE newword == words ... !", again

    	with "!" by itself.  LIBRA, MODULE, HIDE, etc. will not work;

    	multiple definitions will not work.

    These restrictions will be lifted before this version is complete,

    and the other primitives will be added.

    If you have Chicken Scheme installed on your system, you can run Joy in

    the interpreter using "csi joy80.scm" and then "(joy-repl)".

    Here are the primitives that aren't implemented yet:

    	echo localtime gmtime mktime strftime format formatf include

    	feof ferror fread fwrite fseek ftell compare opcase case set

    	setecho ifset condlinrec fold primrec filter split some all

    	treestep treerec treegenrec help _help helpdetail manual abort

    In addition, sets are not supported at all.

    --

    I suggest you call for help,                    John Cowan

    or learn the difficult art of mud-breathing.    cowan@...

            --Great-Souled Sam                      http://www.ccil.org/~cowan

## John Cowan — 2006-05-29 16:51:30

    I should add that Joy comments don't work either.

    --

    John Cowan  cowan@...  http://ccil.org/~cowan

    If I have not seen as far as others, it is because giants were standing

    on my shoulders.

            --Hal Abelson

## Greg Buchholz — 2006-05-29 17:43:09

    --- John Cowan <cowan@...> wrote:

     > I'm announcing version 0.80 of Joy-in-Scheme

         URL?

    Greg Buchholz

    __________________________________________________

    Do You Yahoo!?

    Tired of spam?  Yahoo! Mail has the best spam protection around

    http://mail.yahoo.com

## John Cowan — 2006-05-29 18:33:49

    Greg Buchholz scripsit:

     > --- John Cowan <cowan@...> wrote:

    > > I'm announcing version 0.80 of Joy-in-Scheme

    >

    >     URL?

     /me facepalms.

    http://www.ccil.org/~cowan/joy80.tar.gz

    Sorry about that.

    --

    He played King Lear as though           John Cowan <cowan@...>

    someone had played the ace.             http://www.ccil.org/~cowan

            --Eugene Field

## Manfred Von Thun — 2006-06-23 09:21:38

    I  am sorry I have not been able to take part in the interesting

    discussions on the group. I have emptied my house of 34 years,

    disposed of accumulated junk and not quite junk, moved to a

    much smaller rented flat, instructed an estate agent to sell my

    house  and I am exhausted!

    I am reading the group mail every one or two weeks, but I am far

    behind in doing anything but the most superficial. Just unpacked

    and started reading John¹s Joy in Scheme. It sure looks better

    than my original in C. Well done John, I do hope people will

    try it out  as I cannot at the moment.

    I expect to be more active in a little while. Best wishes to all.

      - Manfred

     On 30/5/06 4:33 AM, "John Cowan" <cowan@...> wrote:

    > Greg Buchholz scripsit:

    >

    >> > --- John Cowan <cowan@...> wrote:

    >>> > > I'm announcing version 0.80 of Joy-in-Scheme

    >> >

    >> >     URL?

    >

    > /me facepalms.

    >

    > http://www.ccil.org/~cowan/joy80.tar.gz

    >

    > Sorry about that.

    [Non-text portions of this message have been removed]

## Manfred Von Thun — 2006-10-13 07:56:22

    On 30/5/06 2:43 AM, "John Cowan" <cowan@...> wrote:

     > I'm announcing version 0.80 of Joy-in-Scheme, eventually to become Joy2.

    > You do not need a Scheme system to run this version; it should work

    > anywhere that there is a C compiler.  I'd like as many different people

    > to test it as possible.

    >

    > Download it, say "touch joy80.c", and then "make".  You may need to

    > fiddle with the Makefile a bit, but it should be simple.

     [..]

    Hi John,

    after many months in limbo while being forced off my beloved mainframe, my

    little Apple eMac now has a new version of the operating system and a GCC. I

    was told that I am the first person in our Humanities faculty to ever even

    ask for a C-compiler. Anyhow, it all happened eventually, and today I used

    the compiler for the first time  of course on your Joy-in-Scheme. I had

    already commented on the Scheme code that you put together so carefully, I

    found it quite intelligible even on first reading. Now I compiled it at

    last, just ³make², and bingo! there it was. I ran a few simple tests just

    now, and all seems to be working. I hope that you will not give up on this

    project, with the lack of interest and encouragement so far.

    At this stage I have one question. It is prompted by some of the features of

    your version  especially the ³!² instead of ³.²  as a terminator (not that

    it matters which one is used). But I get the impression that writing the

    scanner in Scheme is not as straightforward as one might imagine, and that

    Scheme is not the best character-fiddling language there is. Is this so?

    Related to this, would it be desirable  and possible - to write the really

    low-level parts of Joy in C and only the high-level parts in Scheme? Where

    one should draw the line might well be decided on pragmatic grounds.

    As part of the answer to my own question I offer this: whatever needs

    a garbage collector will need to be written in Scheme  and that is mainly

    what in my implementation is in  the file interp.c.

    I also noticed that somewhere your parser reads code by consing it onto a

    list, but then reverses that list to get it in the right order again for

    execution. I am not talking about efficiency. In my version the parser kept

    a pointer to the last item and kept on appending there. I would have thought

    that Scheme¹s setcdr! is just for that sort of thing. Or is there some deep

    reason for using the reversal technique?

    I look forward to studying your implementation in much more detail.

    (And I now want to compile my own Joy with my brand new GCC)

    Thanks John

      - Manfred

    [Non-text portions of this message have been removed]

## John Cowan — 2006-10-13 16:18:03

    Manfred Von Thun scripsit:

     > I hope that you will not give up on this

    > project, with the lack of interest and encouragement so far.

     I have not given up, but I did suspend work on it until I had some

    detailed review.

     > But I get the impression that writing the

    > scanner in Scheme is not as straightforward as one might imagine, and that

    > Scheme is not the best character-fiddling language there is. Is this so?

     Not at all.  I simply wanted to push something at least partly usable

    out there, and I had stopped working on 0.80 a month or two before.

    (My bad luck that when I published it was the beginning of when you

    would be unable to review or work on it.)  The simplest, most expeditious

    solution was therefore to simply exploit the Scheme scanner and parser,

    even taking advantage of the fact that Chicken's scanner supports []

    as equivalent to ().

     > Related to this, would it be desirable  and possible - to write the really

    > low-level parts of Joy in C and only the high-level parts in Scheme? Where

    > one should draw the line might well be decided on pragmatic grounds.

     Possible but not I think desirable.  Chicken makes it easy to interface

    with low-level C code, even embedded directly in Scheme (though of course

    only in compiled code -- the interpreter does not understand C!).

    But Scheme is in fact an excellent language for writing scanners

    and parsers; notably, its guarantee of proper tail recursion makes

    recursive-descent scanners particularly nice.

     > I also noticed that somewhere your parser reads code by consing it onto a

    > list, but then reverses that list to get it in the right order again for

    > execution. I am not talking about efficiency. In my version the parser kept

    > a pointer to the last item and kept on appending there. I would have thought

    > that Scheme¹s setcdr! is just for that sort of thing. Or is there some deep

    > reason for using the reversal technique?

     Again, a matter of expeditiousness.  Since this part of the implementation

    is due to be replaced, I didn't bother to construct a proper queue.

     > I look forward to studying your implementation in much more detail.

     Please do!

    --

    There are three kinds of people in the world:   John Cowan

    those who can count,                            cowan@...

    and those who can't.

## Manfred Von Thun — 2006-10-23 09:48:58

    A little preamble: one of the criticisms of Pascal was that it has some

    builtin procedures have features which cannot be given to user defined

    procedures - example the write statement (write(a,b,c,d,e)) can take any

    number of arguments, but you cannot define your own procedures that can have

    any number of arguments. The printf statement in C is similar. Joy commits

    the same kind of sin: some combinators, like map and filter traverse a list

    left to right, building another list left to right by appending to the end

    (as a queue). But user defined combinators cannot do this (at least not in a

    clean fashion), because lists (and quotations) are singly linked starting at

    the first element. I have often thought that perhaps Joy¹s lists should be

    circular  a pointer to the last element, which in turn contains a pointer

    to the first element. That way first and last are (almost) equally

    accessible and modifyable  admittedly, perhaps destroying the purely

    functional nature of Joy.

     On 14/10/06 2:18 AM, "John Cowan" <cowan@...> wrote:

    >

    > Manfred Von Thun scripsit:

    >

    > [..]

    >

    >> I also noticed that somewhere your parser reads code by consing it onto a

    >> list, but then reverses that list to get it in the right order again for

    >> execution. I am not talking about efficiency. In my version the parser kept a

    >> pointer to the last item and kept on appending there. I would have thought

    >> that Scheme¹s setcdr! is just for that sort of thing. Or is there some deep

    >> reason for using the reversal technique?

    >>

    > Again, a matter of expeditiousness.  Since this part of the implementation is

    > due to be replaced, I didn't bother to construct a proper queue.

    >

    The parser is one of many functions which could benefit from circular lists,

    and presumably users could find all sorts of other uses in which lists need

    to be constructed from first to last, allowing something like setcdr! or

    whatever. Perhaps the functional nature of Joy is not entirely destroyed if

    the use of such operators is restricted in some way. I realise that circular

    lists are a just a little harder to implement, and that there will also be

    an efficiency penalty.

    To your implementation: I think this is a good opportunity to think about

    extending Joy perhaps with some new concepts. The Joy manual is not carved

    in granite, and much of Joy needs serious revision anyhow. In particular I

    think my design of the libraries was rather ad hoc and pretty amateurish. I

    should have modelled them on libraries in well-established languages. With

    your knowledge of Scheme (including its impure features) you might well have

    some thoughts about how Joy could benefit from adopting some of the pure and

    impure features. It would not bother be in the slightest if your

    implementation departs from mine in quite substantial ways, and takes over

    as the principal implementation. I have always said that I welcome

    experimentation, and many members of the concatenative mailing group have

    taken that to heart with all sorts of variant concatenative languages.

    I look forward to hearing your views, John,  and the views of others.

      - Manfred

    >

## John Cowan — 2006-10-23 15:25:58

    Manfred Von Thun scripsit:

     > A little preamble: one of the criticisms of Pascal was that it has some

    > builtin procedures have features which cannot be given to user defined

    > procedures - example the write statement (write(a,b,c,d,e)) can take

    > any number of arguments, but you cannot define your own procedures that

    > can have any number of arguments. The printf statement in C is similar.

     No longer true of C, BTW; ANSI C allows you to write your own

    variadic functions in a standards-conformant fashion.

     > I have often thought that perhaps Joy's lists should be circular --

    > a pointer to the last element, which in turn contains a pointer

    > to the first element. That way first and last are (almost) equally

    > accessible and modifyable -- admittedly, perhaps destroying the purely

    > functional nature of Joy.

     I think that would be too big a loss for a modest gain in efficiency.

    Stop-and-copy garbage collectors (like Chicken's) make it fairly cheap

    to create transient garbage, as it will never be copied or otherwise

    looked at again -- at worst the GC runs more often.

    I think Joy's statelessness (except for I/O) is part of its essence,

    being what assures the purity of its concatenativeness.

     > To your implementation: I think this is a good opportunity to think

    > about extending Joy perhaps with some new concepts. The Joy manual

    > is not carved in granite, and much of Joy needs serious revision

    > anyhow. In particular I think my design of the libraries was rather ad

    > hoc and pretty amateurish. I should have modelled them on libraries in

    > well-established languages. With your knowledge of Scheme (including

    > its impure features) you might well have some thoughts about how Joy

    > could benefit from adopting some of the pure and impure features. It

    > would not bother be in the slightest if your implementation departs

    > from mine in quite substantial ways, and takes over as the principal

    > implementation. I have always said that I welcome experimentation,

    > and many members of the concatenative mailing group have taken that

    > to heart with all sorts of variant concatenative languages.

     I'd like to concentrate on getting Joy1 ported first, and would

    welcome any assistance in doing so.  I'm not too clear on the

    appropriate implementation of some of the combinators, for example.

    There is a very interesting nearly-functional language called Q

    <http://q-lang.sourceforge.net> which is based on equational term

    reasoning rather than lambda calculus.  I've recently provided a Chicken

    interface to the Q interpreter; it'd be interesting to make that

    accessible from Joy.

    Here's a tiny example that puts symbolic Boolean algebra expressions

    into disjunctive normal form (capitalized identifiers are variables):

    /* dnf.q: This is a tiny example for symbolic expression manipulation. It

       transforms logical expressions into disjunctive normal form (DNF).

       05-08-1993 AG */

    // eliminate double negations:

    not not A               = A;

    // push negations inward (de Morgan's laws):

    not (A or B)            = not A and not B;

    not (A and B)           = not A or not B;

    // distributivity laws:

    A and (B or C)          = A and B or A and C;

    (A or B) and C          = A and C or B and C;

    // associativity laws:

    A and (B and C)         = (A and B) and C;

    A or (B or C)           = (A or B) or C;

    --

    He made the Legislature meet at one-horse       John Cowan

    tank-towns out in the alfalfa belt, so that     cowan@...

    hardly nobody could get there and most of       http://www.ccil.org/~cowan

    the leaders would stay home and let him go      --H.L. Mencken's

    to work and do things as he pleased.              Declaration of Independence

## Manfred Von Thun — 2006-10-31 09:13:00

    On 24/10/06 1:25 AM, "John Cowan" <cowan@...> wrote:

     >  [..]

    > I'd like to concentrate on getting Joy1 ported first, and would

    > welcome any assistance in doing so.  I'm not too clear on the

    > appropriate implementation of some of the combinators, for example.

    >

     I am still studying your Scheme version, with some envy. For example

    your joy-stable function is just what I should have written as a macro

    or something to eliminate many duplications in the code of the

    interpreter.

    Currently I have been looking at your implementation of step

    and map, and presumably the implementation of fold and filter

    end up looking pretty much the same. I think you are right in

    making, for X = step,map,(fold,filter), a function

     > (joy-prim-void (X a p) ...

     which inspects the type (string/list) of parameter a and

    then dispatches to specialised version joy-X-string or joy-X-list.

    That is useful because you need recursion at least for some of them.

    At any rate, this is how I understood your code.

    I did not need to do that for these simple list processing

    combinators because I was able to  use loops, always

    appending something to the end in the case of the result list

    for map and filter. However, I did need some auxiliary functions

    for the more contorted combinators like treerec and nestrec.

    But my studying is hampered by the fact that I come in to

    my office at most twice a week, and I have quite a few

    things to do in  very short time. So please be patient with

    me; but you should also recognise that so far Scheme has

    been little more that a spectator sport for me.

    Maybe there is some Schemer in the concatenative group

    who is willing to contribute to your Scheme implementation?

      - Manfred

    [Non-text portions of this message have been removed]

## John Cowan — 2006-11-01 00:06:02

    Manfred Von Thun scripsit:

     > But my studying is hampered by the fact that I come in to

    > my office at most twice a week, and I have quite a few

    > things to do in  very short time. So please be patient with

    > me; but you should also recognise that so far Scheme has

    > been little more that a spectator sport for me.

     /me delicately suggests a printout.

     > Maybe there is some Schemer in the concatenative group

    > who is willing to contribute to your Scheme implementation?

     That would be great.  So far, I haven't been able to interest

    anyone.

    --

    Income tax, if I may be pardoned for saying so,         John Cowan

    is a tax on income.  --Lord Macnaghten (1901)           cowan@...

## Manfred Von Thun — 2006-11-06 05:36:17

    I have been thinking about Joy in Scheme, especially how to

    write Scheme code for the combinators. Here is what I came

    up with for the map combinator. I am supposing that we

    already have a Scheme function which does the equivalent

    of ³exeterm² in my Joy-in C. Its type is

     > exeterm:  quotation * stack  ->  stack

     This means it takes two parameter, a quotation and a stack

    (really the remainder of what is below the quotation) as

    parameters and produces a stack as result. The body of

    exeterm must do this: step through the quotation, look

    at each item  if it is a literal (number, char, list ..) push

    if onto the stack, if it is an inbuilt, call that code, if it is

    user defined, look up its body and exeterm that.

    For map we need a Scheme function which checks that

    there is a quotation on top of the stack, and below that

    an aggregate, and possibly below that further items.

    It has the type

     > map:  stack  ->  stack

     Very roughly the code will look like this:

    (define (map s)

     >> ( here check that there are two items on stack

    >>   and check that top is a quotation )

    >> (cond

    >>> ((= (type (second s)) list)

    >>>  (cons (maplist (first s) (second s) (rest (rest s))))

    >>> ((= (type (second s)) string)

    >>>  ( call the special function for mapping strings)

    >>> ((= (type (second s)) set)

    >>>  ( call the f for mapping sets)

    >>> (default

    >>>  ( error ³bad aggregate for map²) ) ) )

     Pardon my Scheme, it has been 10 years since I wrote my

    one an only 10-liner in Scheme. If some common Lisp

    has crept in, sorry.

    The maplist function has the type

     > maplist: quotation * list * stack -> stack

     where the stack parameter is the remainder of the stack. The others,

    mapstring and mapset, would have a similar type. Whether

    these others should be recursive I do not know. But certainly

    maplist is most easily written recursively.

    I start with a version (untested) for ordinary map in

    Scheme, which I think looks approximately like this:

     >

    > map: function * list -> list

    >

    > (define (map f l)

    >> (if

    >>     (null l)

    >>         nil

    >>     (cons

    >>         (f (first l))

    >>         (map (f (rest l)) ) ) )

    >>>>

     Finally, I use this outline to write that maplist  needed

    for Joy-in-Scheme, by making just a few changes:

     > (define (maplist q l r)

    >> (if

    >>> (null l)

    >>>> (cons nil r)

    >>> (cons

    >>>> (first (exeterm q (cons (first l) r)))

    >>>> (maplist q (rest l) r) ) ) )

     Explanation of the interesting lines, contrasted with

    the lines on the ordinnary map for Scheme.

    (cons nil r)

     > instead of returning just nil,

    > push nil onto the (remainder of)

    > the stack, and return that.

     (first (exeterm q (cons (first l) r)))

     > instead of taking the first of l,

    > push the first of l onto the remainder r.

    > Instead of calling a function f,

    > call exeterm with the quotation

    > and the augmented stack.

    > When that¹s done, take the first

    > of the result stack as the first argument

    > for cons.

     (maplist q (rest l) r) ) ) )

     > instead of a recursive call with just the

    > rest of the list, do a recursive call with

    > the rest of the list and the remainder of

    > the stack. The result is a list, the second

    > argument for the cons.

    >

     There is still something not quite right: If the

    quotation q does some IO, then this should be

    guaranteed to be in the order of the list elements.

    That would be ok BUT ONLY IF Scheme evaluates

    the arguments of cons in a left to right sequence.

    I doubt whether Scheme does strict left to right

    evaluation, somehow it is not the sort of thing

    that goes with the purely functional core of Scheme.

    To fix it one needs to ask explicitly for sequential

    execution. So, assign the mapped value  of the first

    of the list to a local variable v, then do the cons

    with the result of the recursive call.

    I can¹t remember how that is done in

    Scheme, so I¹ll write it my way:

     > (define (maplist q l r)

    >> (if

    >>> (null l)

    >>>> (cons nil r)

    >>> (begin

    >>> (let v (first (exeterm q (cons (first l) r)))

    >>> (cons

    >>>> v

    >>>> (maplist q (rest l) r) ) ) )

     It  looks a mess, but I know that Scheme programmers are

    kind people who will put up with that sort of thing.

    I hope this will make things clearer. If required I shall

    write similar pseudo-Scheme clarifications for other

    combinators.

      - Manfred

     >>>>

    >>>>

     [Non-text portions of this message have been removed]