A new concatenative language -- FACTOR

Slava Pestov — 2004-04-16 04:17:18

Hi all,

For the last 7 months, I have been developing a concatenative language
called FACTOR. It is hosted on the Java virtual machine, supporting both
compiled and interpreted execution.

Download it from http://slava.kicks-ass.org/slava/Factor.jar. It
requires Java 2 version 1.4 or later to run. The JAR file includes
source and binaries, under a BSD-style license. Enter 'help' in the
interpreter to get an idea of some useful commands.

Right now, the available documentation is sparse:

http://slava.kicks-ass.org/slava/ftut.html
http://slava.kicks-ass.org/slava/fcom.html

(It is used for scripting in a game I'm working on, which will be
released later. The game uses Java OpenGL bindings is about 40 KLOC of
Java and 10 KLOC of factor code at the moment. But that is not the
subject of the e-mail.)

The main features of Factor are:

- Lisp-like cons cells are a central part of the language
- Control structures are Joy-like combinators; 'code quotations' are
passed on the stack
- Explicit access to the return stack, as in Forth
- Shuffle definitions: ~<< swap a b -- b a >>~ etc.
- Stack effect inference for simple, conditional and recursive forms
- Continuations!
- Compiler for (some) forms (basically those whose stack effect can be
inferred) targetting JVM bytecode; everything else is interpreted
- Big number, ratio, integer, float arithmetic with automatic coercions
- Dynamically-scoped nested 'namespaces' for holding variables
- Reasonably small and elegant core
- (Somewhat incomplete but already comprehensive) test suite
- Full reflective inspection of interpreter state
- 3 front-ends:
- http server
- text mode console
!!! GUI with hyperlinked inspection of source and variables, etc

This language owes a lot to Joy and Lisp, and to a lesser extent, Forth.
I'd like to thank the inventor of Joy especially for leading me to see
the elegance and simplicity of concatenative languages.

I'd love to write a bit more but it is getting late. If anybody gets a
chance to play around with this, I'd appreciate some feedback.
--
Slava Pestov

andrew cooke — 2004-04-16 12:29:43

how have you implememented continuations? in otuto i have two stacks -
one for pending operations and one for values (i think the first of these
is the same as your call stack; apologies for not knowing the standard
terminology). a continuation is then the copying of a chunk of the
operations stack to the value stack (which is possible because, like joy
and factor, operations can be added to the value stack too).

also, how similar is your "stack effect deduction" to static typing? i
intend to add (hindley miller -like) typing to otuto - i think it is
possible using an approach like ocaml (i can't remember the details, but
iirc it has extensible records, which would be used for the stack, since
you obviously canot treat them like homogenous lists).

two other differences between factor and otuto that i can see are that you
seem to treat the operations and values stacks equally (in otuto you can
only match the head of the operations stack; continuations require
additional semantics) and you use joy's list-as-quoting (which i convinced
myself was a mistake - otuto has separate quoting and lists). also otuto
has lazy evaluation if required, but that's just because i'm a haskell fan
:o)

sorry to talk in terms of a language that doesn't exist and that no-one
uses - i was just surprised by how close the two are. i guess that's
encouraging if you find that it works! (it may also just be beginnners
enthusiasm - maybe these are things that all concatenative languages
have).

cheers,
andrew

ps also, out of curiousity, what ava parser generator did you use (i've
used sablecc and javacc in the past - always curious to know people's
experiences with others)?

Slava Pestov said:
> Hi all,
>
> For the last 7 months, I have been developing a concatenative language
> called FACTOR. It is hosted on the Java virtual machine, supporting both
> compiled and interpreted execution.
>
> Download it from http://slava.kicks-ass.org/slava/Factor.jar. It
> requires Java 2 version 1.4 or later to run. The JAR file includes
> source and binaries, under a BSD-style license. Enter 'help' in the
> interpreter to get an idea of some useful commands.
>
> Right now, the available documentation is sparse:
>
> http://slava.kicks-ass.org/slava/ftut.html
> http://slava.kicks-ass.org/slava/fcom.html
>
> (It is used for scripting in a game I'm working on, which will be
> released later. The game uses Java OpenGL bindings is about 40 KLOC of
> Java and 10 KLOC of factor code at the moment. But that is not the
> subject of the e-mail.)
>
> The main features of Factor are:
>
> - Lisp-like cons cells are a central part of the language
> - Control structures are Joy-like combinators; 'code quotations' are
> passed on the stack
> - Explicit access to the return stack, as in Forth
> - Shuffle definitions: ~<< swap a b -- b a >>~ etc.
> - Stack effect inference for simple, conditional and recursive forms
> - Continuations!
> - Compiler for (some) forms (basically those whose stack effect can be
> inferred) targetting JVM bytecode; everything else is interpreted
> - Big number, ratio, integer, float arithmetic with automatic coercions
> - Dynamically-scoped nested 'namespaces' for holding variables
> - Reasonably small and elegant core
> - (Somewhat incomplete but already comprehensive) test suite
> - Full reflective inspection of interpreter state
> - 3 front-ends:
> - http server
> - text mode console
> !!! GUI with hyperlinked inspection of source and variables, etc
>
> This language owes a lot to Joy and Lisp, and to a lesser extent, Forth.
> I'd like to thank the inventor of Joy especially for leading me to see
> the elegance and simplicity of concatenative languages.
>
> I'd love to write a bit more but it is getting late. If anybody gets a
> chance to play around with this, I'd appreciate some feedback.
> --
> Slava Pestov
>
>
>
>
> Yahoo! Groups Links
>
>
>
>
>
>


--
` __ _ __ ___ ___| |_____ work web site: http://www.ctio.noao.edu/~andrew
/ _` / _/ _ \/ _ \ / / -_) personal web site: http://www.acooke.org/andrew
\__,_\__\___/\___/_\_\___| personal gallery: http://www.acooke.org/pancito

stevan apter — 2004-04-16 12:56:47

it's wonderful to hear that there is activity on these fronts.

i have no idea how many people are lurking, and working on their
own ideas, but i worry that low activity on the list might discourage
further efforts along these lines.

andrew, slava: please report back on your progress, and (possibly?)
give us urls where we can keep abreast.

best

sa


----- Original Message -----
From: "andrew cooke" <andrew@...>
To: <concatenative@yahoogroups.com>
Sent: Friday, April 16, 2004 8:29 AM
Subject: Re: [stack] A new concatenative language -- FACTOR


>
> how have you implememented continuations? in otuto i have two stacks -
> one for pending operations and one for values (i think the first of these
> is the same as your call stack; apologies for not knowing the standard
> terminology). a continuation is then the copying of a chunk of the
> operations stack to the value stack (which is possible because, like joy
> and factor, operations can be added to the value stack too).
>
> also, how similar is your "stack effect deduction" to static typing? i
> intend to add (hindley miller -like) typing to otuto - i think it is
> possible using an approach like ocaml (i can't remember the details, but
> iirc it has extensible records, which would be used for the stack, since
> you obviously canot treat them like homogenous lists).
>
> two other differences between factor and otuto that i can see are that you
> seem to treat the operations and values stacks equally (in otuto you can
> only match the head of the operations stack; continuations require
> additional semantics) and you use joy's list-as-quoting (which i convinced
> myself was a mistake - otuto has separate quoting and lists). also otuto
> has lazy evaluation if required, but that's just because i'm a haskell fan
> :o)
>
> sorry to talk in terms of a language that doesn't exist and that no-one
> uses - i was just surprised by how close the two are. i guess that's
> encouraging if you find that it works! (it may also just be beginnners
> enthusiasm - maybe these are things that all concatenative languages
> have).
>
> cheers,
> andrew
>
> ps also, out of curiousity, what ava parser generator did you use (i've
> used sablecc and javacc in the past - always curious to know people's
> experiences with others)?
>
> Slava Pestov said:
> > Hi all,
> >
> > For the last 7 months, I have been developing a concatenative language
> > called FACTOR. It is hosted on the Java virtual machine, supporting both
> > compiled and interpreted execution.
> >
> > Download it from http://slava.kicks-ass.org/slava/Factor.jar. It
> > requires Java 2 version 1.4 or later to run. The JAR file includes
> > source and binaries, under a BSD-style license. Enter 'help' in the
> > interpreter to get an idea of some useful commands.
> >
> > Right now, the available documentation is sparse:
> >
> > http://slava.kicks-ass.org/slava/ftut.html
> > http://slava.kicks-ass.org/slava/fcom.html
> >
> > (It is used for scripting in a game I'm working on, which will be
> > released later. The game uses Java OpenGL bindings is about 40 KLOC of
> > Java and 10 KLOC of factor code at the moment. But that is not the
> > subject of the e-mail.)
> >
> > The main features of Factor are:
> >
> > - Lisp-like cons cells are a central part of the language
> > - Control structures are Joy-like combinators; 'code quotations' are
> > passed on the stack
> > - Explicit access to the return stack, as in Forth
> > - Shuffle definitions: ~<< swap a b -- b a >>~ etc.
> > - Stack effect inference for simple, conditional and recursive forms
> > - Continuations!
> > - Compiler for (some) forms (basically those whose stack effect can be
> > inferred) targetting JVM bytecode; everything else is interpreted
> > - Big number, ratio, integer, float arithmetic with automatic coercions
> > - Dynamically-scoped nested 'namespaces' for holding variables
> > - Reasonably small and elegant core
> > - (Somewhat incomplete but already comprehensive) test suite
> > - Full reflective inspection of interpreter state
> > - 3 front-ends:
> > - http server
> > - text mode console
> > !!! GUI with hyperlinked inspection of source and variables, etc
> >
> > This language owes a lot to Joy and Lisp, and to a lesser extent, Forth.
> > I'd like to thank the inventor of Joy especially for leading me to see
> > the elegance and simplicity of concatenative languages.
> >
> > I'd love to write a bit more but it is getting late. If anybody gets a
> > chance to play around with this, I'd appreciate some feedback.
> > --
> > Slava Pestov
> >
> >
> >
> >
> > Yahoo! Groups Links
> >
> >
> >
> >
> >
> >
>
>
> --
> ` __ _ __ ___ ___| |_____ work web site: http://www.ctio.noao.edu/~andrew
> / _` / _/ _ \/ _ \ / / -_) personal web site: http://www.acooke.org/andrew
> \__,_\__\___/\___/_\_\___| personal gallery: http://www.acooke.org/pancito
>
>
>
>
>
> Yahoo! Groups Links
>
>
>
>
>

andrew cooke — 2004-04-16 13:47:21

the only url i have that's relevant to otuto is notes in my diary. it's
only rough notes, and not corrected when things change, so the information
is inaccurate, incomplete and out of date! anyway, last entry is at
http://www.acooke.org/andrew/diary/2004/apr/15.html (and already out of
date because i'm adding error handling). earlier entries by clicking on
the left arrow, top right of the screen. again, this is really intended
more for personal use and for my family (i live in s america, they are all
in the uk, so it's a way for them to see that i'm still alive...) so don't
expect anything very useful.

cheers,
andrew

ps apologies - the year and month links on those pages don't work. i'm
supposed to be working on auto-generating indices, but, well, don't have
the time...

pps similarly to factor, the aim is to implement a scripting language for
a larger project (a program that plays go).

stevan apter said:
> it's wonderful to hear that there is activity on these fronts.
>
> i have no idea how many people are lurking, and working on their
> own ideas, but i worry that low activity on the list might discourage
> further efforts along these lines.
>
> andrew, slava: please report back on your progress, and (possibly?)
> give us urls where we can keep abreast.
>
> best
>
> sa

--
` __ _ __ ___ ___| |_____ work web site: http://www.ctio.noao.edu/~andrew
/ _` / _/ _ \/ _ \ / / -_) personal web site: http://www.acooke.org/andrew
\__,_\__\___/\___/_\_\___| personal gallery: http://www.acooke.org/pancito

Tanksley, William D. Jr. — 2004-04-16 14:21:54

From: andrew cooke [mailto:andrew@...]

>how have you implememented continuations? in otuto i have two
>stacks - one for pending operations and one for values (i
>think the first of these is the same as your call stack;
>apologies for not knowing the standard terminology). a
>continuation is then the copying of a chunk of the operations
>stack to the value stack (which is possible because, like joy
>and factor, operations can be added to the value stack too).

That sounds correct to me; Forth works the same way.

As for terminology: the only language I know of which exposes two stacks is
Forth, and it calls them the "data stack" and the "return stack".

>also, how similar is your "stack effect deduction" to static
>typing? i intend to add (hindley miller -like) typing to
>otuto - i think it is possible using an approach like ocaml (i
>can't remember the details, but iirc it has extensible
>records, which would be used for the stack, since you
>obviously canot treat them like homogenous lists).

For some good info on type enforcement in a concatenative language, check
out strongForth. Ooops, it's gone from the web!!! Oh no.

Er...

Well, at any rate, strongForth manages to perform strong static type
checking with type polymorphism in linear time. It takes clever advantage of
concatenativity. Its problem is that, as a proof of concept and working
program, it was made compatible with the ANSI Forth, which wasn't made for
strong static typing; the result is something of a hodgepodge (although it
works surprisingly well). A language designed for that sort of thing from
the start would be much more impressive.

The problem with doing strong static typechecking is that you can't have
variable stack effects. IMO the solution is to replace the variable stack
effect support with variable length array support (such support is seen in
cK). If you're willing to be REALLY daring, you could try to replace all
explicit iteration with array-driven implicit iteration (again, cK handles
implicit iteration, although it also provides all the explicit combinators).

>two other differences between factor and otuto that i can see
>are that you seem to treat the operations and values stacks
>equally (in otuto you can only match the head of the
>operations stack; continuations require additional semantics)

Hmm. I'll have to spend some time looking at this. I like the idea.

>and you use joy's list-as-quoting (which i convinced myself
>was a mistake - otuto has separate quoting and lists).

I agree with otuto :-).

> also
>otuto has lazy evaluation if required, but that's just because
>i'm a haskell fan :o)

What would lazy evaluation mean to a concatenative language? For an
applicative language, lazy evaluation means that parameters to functions are
bound without being evaluated; but for a concatenative language, you can't
bind parameters to functions, so what CAN you do?

>(it may also just be beginnners enthusiasm - maybe these are
>things that all concatenative languages have).

Yes, all concatenative languages have beginner's enthusiasm :-).

No, the combination of these features is really distinct and interesting.
I'm certainly interested in both of your work.

>andrew

-Billy

andrew cooke — 2004-04-16 15:17:11

Tanksley, William D. Jr. said:
> From: andrew cooke [mailto:andrew@...]
[...]
> As for terminology: the only language I know of which exposes two stacks
> is Forth, and it calls them the "data stack" and the "return stack".

thanks.

[...]
> The problem with doing strong static typechecking is that you can't have
> variable stack effects. IMO the solution is to replace the variable stack
> effect support with variable length array support (such support is seen in
> cK). If you're willing to be REALLY daring, you could try to replace all
> explicit iteration with array-driven implicit iteration (again, cK handles
> implicit iteration, although it also provides all the explicit
> combinators).

variable stack effects? i don't know what that means, but my idea was to
describe the type of an operation as a transformation from the list of
types on the data stack before to the list of types after. you only
specify the list to some depth, because after that it's irrelevant (not
used). this is like "tuples" in a "normal" functional language, but with
"..." on the right. (this is one reason why otuto doesn't match the
return stack, apart from the head element - the type of the head element
of the return stack is the type of the operation) (i may have return and
data stacks mixed up - you didn't say which was which!)

[...]
> What would lazy evaluation mean to a concatenative language? For an
> applicative language, lazy evaluation means that parameters to functions
> are
> bound without being evaluated; but for a concatenative language, you can't
> bind parameters to functions, so what CAN you do?

yeah, i asked the same question. :o)

http://www.acooke.org/andrew/diary/2004/apr/10.html is a sketch of what
went on in my head at the time. the following is an example of an
infinite list (modified to the current syntax of otuto):

{from | 'n} => { | 'n $(from + 'n 1) }

$ indicates lazy evaluation (see below for how this is evaluated).

so evaluating "{x} 7 from p p p" where p prints the top value on the data
stack gives (i'm writing return stack to the left of "|", extending
leftwards, and data stack to the right of "|" extending rightwards:

{ p p p from 7 {x} | ) (* {} is quoting, x is not used below *)
{ p p p from 7 | x }
{ p p p from | 7 x } (* numbers evaluate to themselves *)
{ p p p | 7 $(from + 7 1) x } (* definition of from, above *)
{ p p p | 7 $from $+ $7 $1 x } (* $(...) is sugar for $.$.$. *)
7
{ p p | $from $+ $7 $1 x } (* p tries to access thunk *)
{ from | $+ $7 $1 x } (* so evaluate thunk, hitting another *)
{ + | $7 $1 x } (* and another *)
{ 7 | $1 x } (* number evaluates to self *)
{ + | 7 $1 x } (* + takes two args, second a thunk, so.. *)
{ 1 | x }
{ + | 7 1 x } (* can finaly evaluate this thunk *)
{ from | 8 x } (* and this one *)
{ | 8 $(from + 8 1) x } (* looks familiar! *)
{ p p | 8 $(from + 8 1) x } (* and continue with p *)
8
{ p | $(from + 8 1) x }
etc

i'm not 100% sure about this. i think it's more useful that that example
because pattern matching means that thunks can be evaluated in sub-lists,
which lets them be "looked past" at times (a thunk directly on the data
stack is going to be evaluated by any pattern that goes that deep or
further, but in a list the pattern may not require evaluation).

for example, consider applying
{ swap | 'a 'b } => { | 'b 'a }
to a case like
{ swap | 1 [$thunk]}
{ | [$thunk] 1 }
- the thunk hasn't been evaluated because its contents were not pattern
matched.

does that make sense!?

since i haven't got this thing working yet i have no idea how useful it
will be. it's also possible that it makes the language much more complex
to implement (the sub-evaluation implies some kind of "hidden" return
stack; it's still not clear to me whether this makes everything a mess or
not)

cheers,
andrew

--
` __ _ __ ___ ___| |_____ work web site: http://www.ctio.noao.edu/~andrew
/ _` / _/ _ \/ _ \ / / -_) personal web site: http://www.acooke.org/andrew
\__,_\__\___/\___/_\_\___| personal gallery: http://www.acooke.org/pancito

Slava Pestov — 2004-04-16 15:18:31

On Fri, 2004-04-16 at 08:29, andrew cooke wrote:
> how have you implememented continuations? in otuto i have two stacks -
> one for pending operations and one for values (i think the first of these
> is the same as your call stack; apologies for not knowing the standard
> terminology). a continuation is then the copying of a chunk of the
> operations stack to the value stack (which is possible because, like joy
> and factor, operations can be added to the value stack too).

Indeed, this is pretty much how I do it.

A continuation is captured by the callcc word; it is given a quotation,
and it applies the quotation to the captured continuation. A captured
continuation is another quotation that when called, restores execution
to the point *after* the callcc call. So:

... code ... [ do something with continuation X ] callcc ... more ...
|
Calling X will restore execution here ---

Note that continuations are never compiled; this is ensured by giving
the primitives involved (see the definition of callcc) indeterminate
stack effects.

> also, how similar is your "stack effect deduction" to static typing? i
> intend to add (hindley miller -like) typing to otuto - i think it is
> possible using an approach like ocaml (i can't remember the details, but
> iirc it has extensible records, which would be used for the stack, since
> you obviously canot treat them like homogenous lists).

I intend to apply it to the problem of type inference later on; however
this will not be for error checking, but rather for efficiency; if the
types of operands can be inferred, the compiled JVM bytecode has less
casting operations and runs faster. If they cannot be inferred, well, it
will still execute...

> and you use joy's list-as-quoting (which i convinced
> myself was a mistake - otuto has separate quoting and lists).

Why do you think this is a mistake? Efficiency is not an issue since the
compiler can deduce which quotations end up being executed, and compile
those directly.

> ps also, out of curiousity, what ava parser generator did you use (i've
> used sablecc and javacc in the past - always curious to know people's
> experiences with others)?

I wrote my own parser. It is hand-coded, but extensible. It has three
main components:

- read table: maps characters to types (symbol constituent, whitespace,
special dispatch)
- scanner: splits up input stream into discrete tokens using read table
- parsing words: given a scanner instance, they read some form of
syntactic structure (for example, [ ] : ; and so on are parsing words).
- reader: uses a scanner to invoke parse words when necessary and build
a parse tree (really, a set of nested linked lists and other objects).

Everything is customizable by user code, eg to change the brackets from
[ ] to { } you can use something like:

#=[ [ $parsing ] bind #={ [ @parsing ] bind
#=] [ $parsing ] bind #=} [ @parsing ] bind

{ "Hello world" } print

#=XXX pushes a word literally without executing it (in fact #= is a
parsing word that simply expands to "XXX" intern)
--
Slava Pestov

andrew cooke — 2004-04-16 15:37:04

Slava Pestov said:
[...]
>> and you use joy's list-as-quoting (which i convinced
>> myself was a mistake - otuto has separate quoting and lists).
>
> Why do you think this is a mistake? Efficiency is not an issue since the
> compiler can deduce which quotations end up being executed, and compile
> those directly.

not a big mistake - i just found it confusing. my main sticking point was
that i couldn't see how to get a single operator on the data stack
directly, yet it could occur by manipulating the stack (maybe what you use
#= for below?)

[...]
> Everything is customizable by user code, eg to change the brackets from
> [ ] to { } you can use something like:

does this mean that in factor you can define new words at run-time? if
you can modify the parser can you not introduce mutable state? maybe you
define x to parse as 5, then later as 7...

i don't know if this worries you - it is one reason why i am keeping
compile and run-time completely separate. but i am impressed by the
flexibility of your solution (the other reason they are separate in my
case is laziness!)

cheers,
andrew

ps no more email from me for a while - i must write code! i have only a
few days before i am back on shift...

--
` __ _ __ ___ ___| |_____ work web site: http://www.ctio.noao.edu/~andrew
/ _` / _/ _ \/ _ \ / / -_) personal web site: http://www.acooke.org/andrew
\__,_\__\___/\___/_\_\___| personal gallery: http://www.acooke.org/pancito

Slava Pestov — 2004-04-16 22:56:20

On Fri, 2004-04-16 at 11:37, andrew cooke wrote:
> does this mean that in factor you can define new words at run-time? if
> you can modify the parser can you not introduce mutable state? maybe you
> define x to parse as 5, then later as 7...

One of the inspirations for Factor's is SmallTalk. Both are imperitive
languages at the core, but also very dynamic...

: square dup * ; is just syntax sugar for "square" [ dup * ] define.

If you evaluate this:

"Enter your first name: " print
read
"Enter your last name: " print
read
unit define

And enter "andrew" then "cooke", evaluating

andrew

Will push the string "cooke" on the stack.

The language has explicit support for variables, in fact nested
namespaces of variables.

2] 5 @x
3] $x .
5
4] 7 @x
5] $x .
7

In fact $x is syntax for "x" $, and @x is syntax for "x" @...

Another non-FP aspect is mutable data structures, for example, compare:

!!! Classic FP list append that copies the first list (non-destructive)
18] [ 1 2 3 ] @list
19] $list [ 4 5 6 ] append .
[ 1 2 3 4 5 6 ]
20] $list .
[ 1 2 3 ]

!!! What a Java or C programmer is used to:
21] $list [ 4 5 6 ] nappend .
[ 1 2 3 4 5 6 ]
22] $list .
[ 1 2 3 4 5 6 ]

Use of the latter is discouraged! In fact, I can only think of a few
instances where destructive list operations are used. However, where
they are used, they prove *very* useful.

Just because the language *lets* you do something does not mean that its
always good style to do so.

In the game, I use a very functional style of programming, using
variables mostly for constants.

Pretty much the only factor code that does runtime introspection is the
"IDE"; the prettyprinter, namespace inspector, and (what little there is
of) the debugger.
--
Slava Pestov

andrew cooke — 2004-04-16 23:46:29

now i can see where 7 months went :o)

you should document this more - the web pages don't do it justice.

thanks,
andrew

Slava Pestov said:
> On Fri, 2004-04-16 at 11:37, andrew cooke wrote:
>> does this mean that in factor you can define new words at run-time? if
>> you can modify the parser can you not introduce mutable state? maybe
>> you
>> define x to parse as 5, then later as 7...
>
> One of the inspirations for Factor's is SmallTalk. Both are imperitive
> languages at the core, but also very dynamic...
>
> : square dup * ; is just syntax sugar for "square" [ dup * ] define.
>
> If you evaluate this:
>
> "Enter your first name: " print
> read
> "Enter your last name: " print
> read
> unit define
>
> And enter "andrew" then "cooke", evaluating
>
> andrew
>
> Will push the string "cooke" on the stack.
>
> The language has explicit support for variables, in fact nested
> namespaces of variables.
>
> 2] 5 @x
> 3] $x .
> 5
> 4] 7 @x
> 5] $x .
> 7
>
> In fact $x is syntax for "x" $, and @x is syntax for "x" @...
>
> Another non-FP aspect is mutable data structures, for example, compare:
>
> !!! Classic FP list append that copies the first list (non-destructive)
> 18] [ 1 2 3 ] @list
> 19] $list [ 4 5 6 ] append .
> [ 1 2 3 4 5 6 ]
> 20] $list .
> [ 1 2 3 ]
>
> !!! What a Java or C programmer is used to:
> 21] $list [ 4 5 6 ] nappend .
> [ 1 2 3 4 5 6 ]
> 22] $list .
> [ 1 2 3 4 5 6 ]
>
> Use of the latter is discouraged! In fact, I can only think of a few
> instances where destructive list operations are used. However, where
> they are used, they prove *very* useful.
>
> Just because the language *lets* you do something does not mean that its
> always good style to do so.
>
> In the game, I use a very functional style of programming, using
> variables mostly for constants.
>
> Pretty much the only factor code that does runtime introspection is the
> "IDE"; the prettyprinter, namespace inspector, and (what little there is
> of) the debugger.
> --
> Slava Pestov
>
>
>
> Yahoo! Groups Links
>
>
>
>
>
>


--
` __ _ __ ___ ___| |_____ work web site: http://www.ctio.noao.edu/~andrew
/ _` / _/ _ \/ _ \ / / -_) personal web site: http://www.acooke.org/andrew
\__,_\__\___/\___/_\_\___| personal gallery: http://www.acooke.org/pancito

phimvt@lurac.latrobe.edu.au — 2004-04-30 07:52:31

On Fri, 16 Apr 2004, stevan apter wrote:

> it's wonderful to hear that there is activity on these fronts.

Yes, indeed. I very much welcome experimentations with
concatenative languages.

> i have no idea how many people are lurking, and working on their
> own ideas, but i worry that low activity on the list might discourage
> further efforts along these lines.

I myself have not contributed at all lately. I have been rather
unwell for quite some time, but seem to be getting better somewhat.
So you'll see a bit more of me, I hope.

[..]

- Manfred

Heiko.Kuhrt@t-online.de — 2004-04-30 14:45:24

...
> I myself have not contributed at all lately. I have been rather
> unwell for quite some time, but seem to be getting better somewhat.
...
I'm sorry to read that. I have had a lot of fun with Joy and your papers
about it.

Gute Besserung!! [ well bettering ]
--Heiko

> - Manfred

Ben — 2004-04-30 15:27:44

phimvt@... wrote:

> On Fri, 16 Apr 2004, stevan apter wrote:
>>it's wonderful to hear that there is activity on these fronts.
>
> Yes, indeed. I very much welcome experimentations with
> concatenative languages.

Speaking of experimenting with concatenative languages, I've been
playing around with writing dc(1) macros lately and got to wondering if
anyone else has any thoughts about it as a concatenative language -
starting, I suppose, with whether or not it /is/ one.


>>i have no idea how many people are lurking, and working on their
>>own ideas, but i worry that low activity on the list might discourage
>>further efforts along these lines.

I've been lurking for a long time and will probably re-enter that
mode hereafter. The level of erudition on this list is both fascinating
and intimidating.

> I myself have not contributed at all lately. I have been rather
> unwell for quite some time, but seem to be getting better somewhat.
> So you'll see a bit more of me, I hope.

I'm sorry to hear that you've been feeling unwell, though glad that
it's passing. Get well soon! I look forward to your future writings.

Ben

Nick Forde — 2004-04-30 21:07:08

Ben wrote:
> Speaking of experimenting with concatenative languages, I've been
> playing around with writing dc(1) macros lately and got to wondering if
> anyone else has any thoughts about it as a concatenative language -
> starting, I suppose, with whether or not it /is/ one.

Hi Ben,

I'm not sure I should admit to this but in my early Unix days I used
dc a lot and got to quite like it. Well at least I liked the RPN
notation and ability to write scripts.

I'm not sure whether it classifies as a concatenative language but if
my memory serves me correctly it does has an evaluation command 'x' and
the ability to define macros. I think very limited function composition
is also possible but only through the definition of nested macros. So
maybe it is? Early implementations of the bc(1) calculator, which
uses a c like syntax, simply compiled bc scripts into dc format.

Here are a couple of my very old scripts which illustrate what is
possible. The first draws a Mandelbrot set and the second Sierpinskis
gasket.

#!/usr/bin/dc
[[nickf@nospam_.com]n17lc+sc0.6375la+sa]sR[lpan]sP[2lx*ly*lb+si]sK
[0sr0si0snlCx46lm-splPx0.03750la+salc1+scll12=Qlc80>O]sO[lc40=R]sQ
[lnsmlIxlKxlJxln1+snln15>C]sC[15sn]sD[lrsxlisylxlx*lyly*-la+sr]sI#
[lxlx*lyly*+4<D]sJ[_2sa0sclOx0.096lb+sbll1+slll25>L]sL_1.2sb0sllLx

#!/usr/bin/dc
[li1+sili;cPlsli2-<p]sp[lzsilz80+sslpx[]p]sP[32li:cli1+si160li<j]sj
[88lx80+lz-:c]su[32lx80+lz-:c]st[lzlx+1-;clzlx1++;c-0!=ulzlx+1-;clz
lx1++;c-0=tlx1-sx0lx>X]sX[lPx77sxlXx80lz-szld1-sd_1ld>K]sK[0dsiszlj
x0si0 79:c88 39:c31sdlKx]dsmx

Joy examples of both of these have been discussed on this list in the
past. Of course the Joy versions are much more elegant, and certainly
easier to maintain :-)

> I'm sorry to hear that you've been feeling unwell, though glad that
> it's passing. Get well soon! I look forward to your future writings.

Yes, get well soon Manfred. I'm missing your insightful comments.

Best regards,

Nick.

Ben — 2004-04-30 21:36:37

Nick Forde wrote:

> Ben wrote:
>
>> Speaking of experimenting with concatenative languages, I've been
>>playing around with writing dc(1) macros lately and got to wondering if
>>anyone else has any thoughts about it as a concatenative language -
>>starting, I suppose, with whether or not it /is/ one.
>
>
> Hi Ben,
>
> I'm not sure I should admit to this but in my early Unix days I used
> dc a lot and got to quite like it. Well at least I liked the RPN
> notation and ability to write scripts.

In that case I probably shouldn't admit that I really quite enjoy
scripting in dc and wrote a short introductory article[1] about it as I
found my footing in the language!


> I'm not sure whether it classifies as a concatenative language but if
> my memory serves me correctly it does has an evaluation command 'x' and
> the ability to define macros. I think very limited function composition
> is also possible but only through the definition of nested macros. So
> maybe it is?

My main stumbling point is that it doesn't seem possible for
functions to return other functions, since dc has - as far as this
neophyte can tell - extremely impoverished string-handling capabilities
(and there doesn't seem to be any meaningful distinction between strings
and macros).

The only idea I had to circumvent this was a dc program that
constructs programs by manipulating a numeric representation of itself
plus the newly-defined function, then invokes a new instance of dc and
feeds it that environment and the additional program.

> Early implementations of the bc(1) calculator, which uses a c like
> syntax, simply compiled bc scripts into dc format.

I've heard that from many sources, but so far I haven't been able to
track down any open-source implementation of bc with this execution
model. I've read through the source code for GNU bc and dc and
discovered nothing revelatory. I feel rather silly asking this, but can
anyone point me toward the source for a bc implementation that /does/
compile down to dc, and/or a the source for a non-GNU dc so I can
compare and contrast?

James P. Howard claims to have implemented a version of dc based
around the gmp library, but I cannot find the source to it anywhere;
Greg Ubben implemented dc in sed, but reading that is an exercise in
masochism.

I want to write a front-end to dc to allow the definition of
functions and variables with names longer than a single character
(written, of course, in dc), but so far I've been stymied by the
aforementioned string awkwardness.


> Here are a couple of my very old scripts which illustrate what is
> possible. The first draws a Mandelbrot set and the second Sierpinskis
> gasket.
[snip]

/Nifty/! Thank you kindly for the fascinating examples!


> Joy examples of both of these have been discussed on this list in the
> past. Of course the Joy versions are much more elegant, and certainly
> easier to maintain :-)

Wholeheartedly agreed! :)


Thanks for your response and pointers; they've been interesting and
helpful!

Ben

-
[1]:
http://cpe000103c34069-cm014300001653.cpe.net.cable.rogers.com/weblogs/ben/programming/dc/Prime-Sieve-in-DC.writeback
--

John Cowan — 2004-05-01 13:49:48

Ben scripsit:

> > Early implementations of the bc(1) calculator, which uses a c like
> > syntax, simply compiled bc scripts into dc format.
>
> I've heard that from many sources, but so far I haven't been able to
> track down any open-source implementation of bc with this execution
> model. I've read through the source code for GNU bc and dc and
> discovered nothing revelatory. I feel rather silly asking this, but can
> anyone point me toward the source for a bc implementation that /does/
> compile down to dc, and/or a the source for a non-GNU dc so I can

You want the 7th Edition source (now available under a close variant
of the BSD license), which is online in many places. One of them is
http://mirror.cc.vt.edu/pub/projects/Ancient_Unix/PDP-11/Trees/V7/usr/src/cmd/bc.y

The Caldera (now SCO Group) license is at
http://www.tuhs.org/Archive/Caldera-license.pdf .

Note that it's Yacc source with embedded C. To get it running on modern
Unix, I needed to make these changes:

Change all calls to exit() to exit(0)
Change "int in;" in line 19 to "FILE* in;"

So after "yacc bc.y; gcc -o my-bc y.tab.c; ./my-bc -c" I could type in
bc statements and watch it spew the corresponding dc code!

The man page is at
http://mirror.cc.vt.edu/pub/projects/Ancient_Unix/PDP-11/Trees/V7/usr/man/man1/bc.1
as you might expect.

--
"They tried to pierce your heart John Cowan
with a Morgul-knife that remains in the http://www.ccil.org/~cowan
wound. If they had succeeded, you would http://www.reutershealth.com
become a wraith under the domination of the Dark Lord." --Gandalf