## An idea for forth?

forth

### Next

• 1. WANT and INDEX
so with : ANS ( ??? ) .... ; INDEX 2347238saggbdqe343434 ( 32 char max index string created by index ) WANT ANS FLASHTHING SOMETHINGELSE .. \to end of line could we have some ideas for what should be included in a standard index string generator. me first. 1) 16 user chars for system dependant possibility and 16 standard chars for the big bad forth index :-) 2) crc to prevant oops edits? 3) hash to indicate successful compile environment 4) link to correct vocab name space, to give a tree flavouring to namespace organiztion 5) optional master index number for the big forth index when index number assigned. maybe a 24 to 8 split is better, as 8 gives enough space to do a local linking chain cheers
• 2. REQUIRE and INDEX for blocks
seems both the how require handles thread, and the project org thread come to the point that how to find libs. have REQUIRE, which takes one word name, and looks it up in an index. have INDEX which exports all names. (use after colon def to export. when execution of INDEX happens, then assuming well spaced source, i.e. next line blank, then fill next line with an index entry which links all together (tree?) so that a block with a required word can be loaded nest fashion. this would require a word to delimit the inserted index line e.g. 'I ( tick i ) or be a dual use for \ a length of the index data less than 63 characters will work on most forths, but 31 would suffice. cheesr
• 3. 2nd Generation Stack CPU
I am sure everyone has noticed by now, but there is a story about stack processors on /. today.

### Re: An idea for forth?



Often, factoring can occur when multiple sections of code are similar,
but not identical.  In that case, refactoring the code requires some
amount of generalization.  Anticipating that generalization and
knowing exactly what to generalize can be problematic if done too
early, so I believe some case can be made against "premature
factorization".

As an example, I was once the main architect/developer on a software
configuration framework for industrial I/O modules.  While some
commonality was apparent and addressed early on, other forms of
commonality were not obvious until several instances of I/O modules
had been developed and supported by our framework.  Sometimes, you
just need to have several examples under your belt before you can
further generalize.

Trying to anticipate too much commonality (overgeneralization which
leads to a form of over factoring) up front can sometimes add
unnecessary complexity.  I believe Chuck warns of this effect and
advocates solving the specific problem as opposed to the more general
problem which may never see the light of day.

-- Greg


### Re: An idea for forth?

n Apr 29, 11:52m, Greg < XXXX@XXXXX.COM > wrote:

But even in the case of such generalization, I don't see a huge
downside to factoring early and often. At worst, you've created a
name for a span of code, and assuming you've picked a worthwhile name,
you've both reduced the effort needed to read the code and you've
reduced the cognitive complexity of understanding that code. If later
after seeing the problem evolve more you discover the factor was
overly generalized, then go back with your new understanding of the
code and rework the factors. Typing is cheap relative to suffering
through a bad design that is propagated merely because one doesn't
want to change existing code.
>> Sometimes, you just need to have several examples under >> your belt before you can further generalize.

Or alternatively, don't fear going back and changing those
generalizations. It's been a rare project I've worked on where things
that seemed obvious at the start didn't radically change later. And
if you could see my Subversion and git repositories at work, you would
see a lot of churn in the code. I see nothing wrong with this-- you
write the best code you can with the information you have. If that
information changes, go back and make the necessary changes to reflect
that new understanding.

What makes people hesitant to change existing working code is the fear
that a change might break functionality. That's where techniques like
automated and repeatable unit testing and the larger philosophy of
Test Driven Development come in. I can't say I always consistently
follow those principles and practices, but when I have, the confidence
of knowing that a refactoring didn't break anything was well worth the
additional effort. And certainly far better than the usual Forth
style ad-hoc sitting at a terminal and manually executing code
interactively.

The biggest danger I see of not factoring early and often is that it
never gets done. When you defer something until later because you're
hopeful that more code will show better factors, you run the risk of
the real world intruding and pulling your attention elsewhere. I
think it's far better to view code replication (or near replication)
as a problem and to address problems as fast as possible. The factors
you create now might be ripped up and thrown away later. So what?
It's just code.
>> Trying to anticipate too much commonality (overgeneralization >> which leads to a form of over factoring) up front can sometimes >> add unnecessary complexity. believe Chuck warns of this effect >> and advocates solving the specific problem as opposed to the more >> general problem which may never see the light of day.

But that's different. The factoring I'm advocating isn't anticipating
anything. It's seeing actual replications (or near replications) of
code and factoring those.

I have no problem with Charles Moore's advice in general. But I will
point out that during development, sometimes generalization and
"hooks" can be your friend. Quite often in the early stages of an
embedded system, I want to be able to do things like trigger an
oscilloscope or logic analyzer on a specific class of operations. Or
I might want to set a flag or start a timer or... whatever. If one
hasn't generalized or attached code to a hook, you are then forced to
hunt down each and every instance of what you're looking for and
instrument that.

Later

### Re: An idea for forth?



As long as there is a willingness to throw/away rewrite, I don't have
an issue unless the generalization would be too effort intensive.  To
make an extreme example, if I wrote a program that incorporated both a
graph coloring algorithm and a depth first search algorithm then later
realized one could be formlated as the other, I'm not sure I'd want to
figure out how to transform one problem representation into the in
order to do it.  I'd probably just leave a note in the code indicating
that it was a possibility that should be considered in the future.

Agreed.  In that case, the DRY principle (Don't Repeat Yourself) is a
good rule to consider.

I've been on both sides of that fence, and actually, I'm not as
"militant" about it as Chuck.  When developing frameworks, I have had
cases where experience and intuition have been successful guides.
I've also seen code that's overly complex because it's trying to
anticipate future functionality that usually never materializes.
Experience helps.

No doubt.  I'm not found of absolute maxims and I usually get
irritated when a co-developer spouts one off in a misguided
application.  First know and understand the rules.  That puts you in a
better position to know when one shouldn't be blindly applied.

It reminds me of "The No Free Lunch Theorem".  Basically, it means for
every optimization technique that works well in practice, one can
construct problems where it doesn't.

-- Greg



### Re: An idea for forth?



But if you factor the sections of code that are similar but not
identical as similar but not identical factors, then none of this or
the following applies.

So describing it as premature factoring is misleading. What you are
referring to is premature generalization.

Whenever the "right time" comes to provide a more general factor,
having those routines already factored with their specific factors
simplifies the process.


### Re: An idea for forth?



Since no one has provided a formal definition of "factoring" I'll fall
back on Brodie's examples as a reference model based on chapter 6 of
"Thinking Forth".

Some of those examples such as "Factoring Out Names" definitely
involve some level of generalization.  It has to do with recognizing
that a slew of variables are explicitly named, defined and
initialized.  This particular example of "factoring" raises the
abstraction level through the use of arrays and the addition of a
looping construct.  Other examples involve generalization via creation
of a new defining word.  Raising the level of abstraction is a form of
generalization as in "Forth is a Computer Language".

I'm not saying that Brodie's generalizations are necessarily
"premature", I'm just making the point that factoring frequently
involves making a generalization (some less trivial than others).
That being the case, some generalizations may be "premature".

-- Greg


### Re: An idea for forth?



A more formal definition is needed than naming a sequence of steps in
a process and calling the sequence by name rather than by specifying
each step in the sequence?

Its by analogy to 3x+6 = 3(x+2), and you are focusing on the factoring
out of 3 from 3x and 6 as well, but 6x = 3(2x) is also factoring all
on its own.


### Re: An idea for forth?



It appears so, if we are to reconcile a simple cut and paste
replacement with Brodie's examples which also involve differing levels
of generalization.

That's a pretty literal example of factoring.  An example that fit's
with Brodie style refactoring would be Horner's rule, e.g.:

evaluate:
2*x^2 + 3*x + 1

: 2*x^2+3*x+1 ( x -- ) DUP DUP * 2*  SWAP 3 * + 1+ ;

Using Horner's rule, one could rewrite this as:

: EvalPoly ( x degree coefficient-array -- result ) ( implementation
involving looping and reusing partial results omitted ) ;

This would allow one to replace all polynomials evaluations found in
the program with the above common word (it would also have the nice
property of reducing the algorithm complexity from O(n^2) to O(n) ).

A legitimate question becomes "Do I want to take on this particular
refactor now?"

It doesn't fit the simple "replace common sequence with named steps"
style of refactoring, but it does fit the Brodie definition of replace
duplicated code with a common and improved abstraction style of
refactoring.

-- Greg



### Re: An idea for forth?



It seems that there is nothing to to reconcile, as you demonstrate
that you have a perfectly good term to describe what else is going on,
to wit, generalization.

Brodie demonstrates how the scope of factors can be extended by
generalizing them, but it remains that case that what you are warning
against is not factoring _per se_, but premature generalization when
factoring.

Applying the rule of seven (plus or minus two) to a longer definition
can of course result in well chosen or maladroit factors, but there is
substantial freedom to shuffle steps between factors locally without
impacts outside the factored process until the factors *have* been
generalized, so its the generalization that can be premature in the
ways that you have described, not the factoring as such.


### Re: An idea for forth?



I would argue that practically all factorization involves some form of
generality even if it is only to remove identical code fragments.  I
say that because unless one does this mechanically:

e.g.
: */ ( x numerator denominator -- scaled-x ) * / ;

vs.

: scale ( x numerator denominator -- scaled-x ) * / ;

The latter (and generally preferred) form involves generalizing the
sequence to the concept of "scaling".  Perhaps a trivial
generalization, but a generalization nonetheless.

Factorization is a spectrum, the above case is at the low end of
generalization, but as one moves up the ladder, the stakes are raised
and it becomes reasonable to consider whether it is best done now or
in the future.

-- Greg



### Re: An idea for forth?



I think these days, it's widely recognized that passing in control
flags to functions can be an indication of lack of cohesion.  As you
point out, the problem is typically solved by creating single purpose
functions.

If we're talking about modern languages, then not necessarily.  For
example, if one later decides that polynomial evaluation needs to work
with complex numbers instead of being restricted only to floats, then
it's probably better to generalize the data type itself.  Polymorphic
types with operator overloading support that ability.  The evaluator
then becomes agnostic to the data type and only "knows" what it means
to evaluate a polynomial.  0ne nice property of this generalization is
that it would allow one to use vectors instead of numbers without
change to the original evaluator - one need only implement a vector
type that understands addition, multiplication, and exponentiation and
it just works.

Although I can think of specific counter-examples, that was my point
of choosing that particular example.

-- Greg


### Re: An idea for forth?



Restricting consideration to only the foibles of the present day seems
to be moving the goalposts a bit, after adopting a tacit definition
that factoring necessarily involves generalizing from the more
advanced examples of factoring from the 25yr+ old Thinking Forth,
which was intentionally more advanced coverage than the examples in
Starting Forth, where if you follow the approach laid out, your
definitions will be factored from the start of the problem definition
process.


### Re: An idea for forth?



I did say that even the simple act of naming a sequence of primitives
with a descriptive name is a form of abstraction which is another way
of saying generalization.  That's been one of the fundamental goals of
practically all programming languages, to raise the level of
abstraction.

If anything, making a side note concerning contemporary practices only
broadens discussion.  It in no way restricts it.

You seem to be agreeing that there are different levels of factoring,
starting from basic examples present in Starting Forth, followed by
more sophisticated examples (involving a higher degree of
generalization) in Thinking Forth.  This is exactly my point.
Factoring is a spectrum.  The additional point being that at as one
moves up the complexity ladder of factoring, there's greater risk of
"premature" generalization.  I never claimed that the "Starting Forth"
style of factoring out identical snippets of code is necessarily a bad
thing to do up front, however more sophisticated forms of factoring,
e.g. the "Thinking Forth" style that isn't the simple replace-common-
snippet-with-new_word style may first require observing a more subtle
pattern first, one that can't be easily anticipated and thus only
becomes apparent after a larger body of code has been written.  Anyone
who has written a large software system has likely seen this occur.

-- Greg

-- Greg