Analysis and analogy are two ways to tackle complexity, but they are
also "opposites" in a certain sense.

Analysis involves resolving a complex entity into simpler components.
This tends to add information; think of how a parse tree adds bits
to make explicit the implicit structures in the string being parsed.

Analogy involves treating a complex entity as a simpler one.
This tends to remove information; if it suffices to know that we
have a "man", we can forget the bits which distinguish "Socrates"
from the rest of us.

One can think of analysis as taking a simpler object bunch S and
seeing how we can map it onto the original complex object C; also
one can think of analogy as doing the opposite and mapping C onto
a suitable S.


Python's conditional tests are
great for analogical coding:

        if animal():
        elif vegetable():
        elif mineral():

but they are not so good for
analytical coding; here C's

        if((c = getchar()) != EOF)

serves the same purpose as a
unification in pattern matching

        foo([X|Xs],A) = foo(Xs, A+X)

both breaking out a simpler term
and providing its value.

Note that the grouping operators
for a regexp allow it to return
more than a plain boolean result;
it also produces analyzed values.



> Chuck Moore is considering having colorForth's "if" not consume the
> conditional value.

I think there are reasons to consume,
and reasons not to consume.  (which
are analogous to the analogy/analysis
distinction made above) In my forth
variant, I wind up writing:

        32 = [ consequent ] continuation

in situations where the continuation
needs the value, and the consequent
is just some special case processing,
        32 - z[ consequent ; ] otherwise ;

when only the boolean result of the
comparison is needed.

The second form would have sufficed for
equality, but what about sign branching?

        32 - z[ 32 use-32 ; ] other ;
is verbose, but works because
equality is unique, but:
(*)     32 - n[ ?? use-neg ; ] other ;
doesn't determine a value for "??"

(if we prefix "dup", "id" might
work for ??, but then we need to
insert "drop" after "]"; also I
am interested in the forth style
for linearity, and gratuitous
dups are to be avoided.  Compare
        square0: dup * ;
        square1: log 2 * exp ;
for a contrived example.)


In my variant on colorForth, one
concatenates words to code their
sequential composition:

        foo bar bletch

Labels, instead of being colored,
are indicated by a colon, and a
semi-colon serves to terminate a
sequentially composed list:

entry:  foo bar bletch ;

Conditional execution (at the most
primitive level) is coded with the
brackets "[" and "]":
        pred [ cons ] cont
is similar to C's:
        if(pred) { cons } cont
and since "foo ; bar" = "foo ;",
one can also code alternation:
        pred [ then ; ] else ;
or, a bit more graphically:
        pred [ then ;
             ] else ;

"[" (and its variants z[ and n[*)
always consumes the top-of-stack

The various comparison operators
"<", "=", etc. replace the top of
the stack with the boolean result.

        '5 3 <' leaves '5 0'

This works well for the common
case where we compare a value
(needed later) with a constant
(not needed later).


* I haven't implemented signed
branches, because I have yet to
write code which only needs the
sign-bit, but not the value;
        16 < [ handle-small ; ] drop else-punt ;
but not:
(*)     n[ negative ; ] positive ;


# This whole forth project started
# in response to a kragen-tol or
# -hack a while ago involving the
# fibonacci numbers.
# This example runs about twice as
# as fast as gcc for me, and also
# demonstrates the conditionals.

fmain:  iarg
        0 = [ 33 + ]
        recfib digits cr ;

recfib: 2 > [ dup
                push 1 - recfib
                pop  2 - recfib
              + ;
            ] drop 1 ;

Reply via email to