Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Is there a better way?

730 views
Skip to first unread message

Mark Wills

unread,
Oct 31, 2012, 7:58:24 AM10/31/12
to
The following routine is checking to see if a string is "}}" i.e.
consists of two consequtive right curly braces.

: }}? ( addr len -- addr len flag)
dup 2= if
over dup c@ swap 1+ c@ 125 = swap 125 = and
else
false
then ;

As can be seen, the first check is the length; if the length is not
exactly 2 then we just return false. If the length is 2 then we check
to see if both characters are ASCII 125. That's the bit I am looking
at and saying "Meh... seems a bit convoluted/lengthy.

Is there a better way?

I was thinking maybe:

... c@ 125 OR swap 1+ c@ 125 OR 125 XOR 0=

Which is perhaps "cleverer" but not as clear as to the intention of
the code and no shorter...

Paul Rubin

unread,
Oct 31, 2012, 8:22:25 AM10/31/12
to
Mark Wills <forth...@gmail.com> writes:
> The following routine is checking to see if a string is "}}" i.e.
> consists of two consequtive right curly braces.
>
> : }}? ( addr len -- addr len flag)

: }? ( caddr -- flag ) c@ 125 = ;
: }}? ( caddr len -- flag )
2 = if dup }? swap }? and else 0 then ;

or if you like to live dangerously:

: }}? ( caddr len -- flag )
\ assumes caddr points to at least 2 valid chars even if len<2 .
2 = swap dup }? swap }? and and ;

If you really want to keep the args on the stack (your original type
signature) just put 2dup at the beginning of }}? .

Mark Wills

unread,
Oct 31, 2012, 8:44:28 AM10/31/12
to
On Oct 31, 12:22 pm, Paul Rubin <no.em...@nospam.invalid> wrote:
Thanks Paul!

I think I've settled on:

: }}? ( addr len -- addr len flag)
dup 2 = if
over dup c@ swap 1+ c@ or 125 xor 0=
else
false
then ;

Which is two instructions shorter than my original code.

humptydumpty

unread,
Oct 31, 2012, 8:53:59 AM10/31/12
to
Hi!

: '}? ( ca -- f ) c@ 125 = ;
: }}? ( ca u -- f )
2 <> IF 0= ELSE dup 1+ '}? swap '}? and THEN ;

Have a nice day,
humptydumpty

Doug Hoffman

unread,
Oct 31, 2012, 9:23:31 AM10/31/12
to
2dup s" }}" compare 0= ;

-Doug

Mark Wills

unread,
Oct 31, 2012, 9:41:08 AM10/31/12
to
> -Doug- Hide quoted text -
>
> - Show quoted text -

That's cheating ;-) COMPARE is in the ANS optional string word-set.
I'm still stuck in the 80's I'm afraid, using Forth 83 on a 30 year
old computer! Everyone should have a hobby!

Doug Hoffman

unread,
Oct 31, 2012, 10:20:46 AM10/31/12
to
On 10/31/12 8:22 AM, Paul Rubin wrote:
> Mark Wills <forth...@gmail.com> writes:
>> The following routine is checking to see if a string is "}}" i.e.
>> consists of two consequtive right curly braces.
>>
>> : }}? ( addr len -- addr len flag)
>
> : }? ( caddr -- flag ) c@ 125 = ;
> : }}? ( caddr len -- flag )
> 2 = if dup }? swap }? and else 0 then ;

Both uses of }? are checking the same address. You need to bump the
address up by one for one of the checks:

: }}? ( caddr len -- flag )
2 = if dup }? swap 1+ }? and else 0 then ;

There is value in unit testing (type checking would not have helped here).

-Doug

Rod Pemberton

unread,
Oct 31, 2012, 11:29:14 AM10/31/12
to
"Mark Wills" <forth...@gmail.com> wrote in message
news:55836290-5cf4-4261...@b12g2000vbg.googlegroups.com...
...

> I think I've settled on:
>
> : }}? ( addr len -- addr len flag)
> dup 2 = if
> over dup c@ swap 1+ c@ or 125 xor 0=
> else
> false
> then ;

The 'or 125' means it'll detect more than just '}}'. It'll also detect '}'
followed by a zero or nul too...


Rod Pemberton


Albert van der Horst

unread,
Oct 31, 2012, 11:26:52 AM10/31/12
to
In article <70a117c1-ba9f-474b...@k20g2000vbj.googlegroups.com>,
I can't help it.

WANT $=
: }}? 2DUP "}}" $= ;

As a general point, unless you want to go the c-abomination of zero-ended
strings, it can't be helped that you have to consider the length as well
as the content of the string.

Groetjes Albert

Rod Pemberton

unread,
Oct 31, 2012, 11:40:44 AM10/31/12
to

"Rod Pemberton" <do_no...@notemailnotz.cnm> wrote in message
news:k6rfsn$ue4$1...@speranza.aioe.org...
Sigh, that wasn't as clear as it could be. 125 has many set bits. So,
or-ing varous values with 125 will result in many other matches.
E.g., 5 or 125 = 125, 112 or 125 = 125, 36 or 125 = 125, etc etc.


RP


Mark Wills

unread,
Oct 31, 2012, 11:45:56 AM10/31/12
to
On Oct 31, 3:36 pm, "Rod Pemberton" <do_not_h...@notemailnotz.cnm>
wrote:
> "Rod Pemberton" <do_not_h...@notemailnotz.cnm> wrote in message
>
> news:k6rfsn$ue4$1...@speranza.aioe.org...
>
>
>
>
>
> > "Mark Wills" <forthfr...@gmail.com> wrote in message
> >news:55836290-5cf4-4261...@b12g2000vbg.googlegroups.com...
> > ...
>
> > > I think I've settled on:
>
> > > : }}? ( addr len -- addr len flag)
> > >     dup 2 = if
> > >       over dup  c@ swap  1+ c@ or 125 xor 0=
> > >     else
> > >       false
> > >     then ;
>
> > The 'or 125' means it'll detect more than just '}}'.  It'll also detect
> > '}' followed by a zero or nul too...
>
> Sigh, that wasn't as clear as it could be.  125 has many set bits.  So,
> or-ing varous values with 125 will result in many other matches.
> E.g., 5 or 125 = 125, 112 or 125 = 125, 36 or 125 = 125, etc etc.
>
> RP- Hide quoted text -
>
> - Show quoted text -

Good catch, Rod. Guess I'll go back to my original code. Clunky, but
it works!

Doug Hoffman

unread,
Oct 31, 2012, 12:22:05 PM10/31/12
to
On 10/31/12 11:26 AM, Albert van der Horst wrote:

> WANT $=
> : }}? 2DUP "}}" $= ;

With an ANS Forth I can't compile this. I get three undefined words
error messages:

WANT
$=
"}}"

-Doug

Andrew Haley

unread,
Oct 31, 2012, 12:46:06 PM10/31/12
to
Mark Wills <forth...@gmail.com> wrote:
> On Oct 31, 1:23?pm, Doug Hoffman <glide...@gmail.com> wrote:
>> On 10/31/12 7:58 AM, Mark Wills wrote:
>>
>> > The following routine is checking to see if a string is "}}" i.e.
>> > consists of two consequtive right curly braces.
>>
>> > : }}? ( addr len -- addr len flag)
>> > ?dup 2= if
>> > over dup c@ swap 1+ c@ 125 = swap 125 = and
>> > else
>> > false
>> > then ;
>>
>> > As can be seen, the first check is the length; if the length is not
>> > exactly 2 then we just return false. If the length is 2 then we check
>> > to see if both characters are ASCII 125. That's the bit I am looking
>> > at and saying "Meh... seems a bit convoluted/lengthy.
>>
>> > Is there a better way?
>>
>> > I was thinking maybe:
>>
>> > ... c@ 125 OR swap 1+ c@ 125 OR 125 XOR 0=
>>
>> > Which is perhaps "cleverer" but not as clear as to the intention of
>> > the code and no shorter...
>>
>> : }}? ( addr len -- addr len flag)
>> 2dup s" }}" compare 0= ;
>
>
> That's cheating ;-) COMPARE is in the ANS optional string word-set.
> I'm still stuck in the 80's I'm afraid, using Forth 83 on a 30 year
> old computer! Everyone should have a hobby!

Well, yes, but the *correct* answer to your problem is therefore
"Write COMPARE, then use it". COMPARE is not hard to write.

Andrew.

Graham

unread,
Oct 31, 2012, 1:05:54 PM10/31/12
to
On 31/10/2012 11:58, Mark Wills wrote:
> The following routine is checking to see if a string is "}}" i.e.
> consists of two consequtive right curly braces.
>
> : }}? ( addr len -- addr len flag)
> dup 2= if
> over dup c@ swap 1+ c@ 125 = swap 125 = and
> else
> false
> then ;
>
> As can be seen, the first check is the length; if the length is not
> exactly 2 then we just return false. If the length is 2 then we check
> to see if both characters are ASCII 125. That's the bit I am looking
> at and saying "Meh... seems a bit convoluted/lengthy.
>
> Is there a better way?
>
> I was thinking maybe:
>
> .... c@ 125 OR swap 1+ c@ 125 OR 125 XOR 0=
>
> Which is perhaps "cleverer" but not as clear as to the intention of
> the code and no shorter...
>

There's the 'obvious' way:

: }}? ( addr len -- addr len flag)
2dup 2 = over c@ 125 = and swap 1+ c@ 125 = and
;

But why not the more conventional one

: }}? ( addr len -- flag)
2 = over c@ 125 = and swap 1+ c@ 125 = and
;



--
GCS

Peter Fälth

unread,
Oct 31, 2012, 3:07:54 PM10/31/12
to
If this is a 16 bit Forth you can simplify further

: }}? ( addr len -- f)
2 = swap @ $7D7D = and ;

or if you need to be sure not to fetch outside the string

: }}? ( addr len -- f)
2 = if @ $7D7D = exit then
drop false ;

BR
Peter

Paul Rubin

unread,
Oct 31, 2012, 3:12:26 PM10/31/12
to
Peter Fälth <peter...@tin.it> writes:
> If this is a 16 bit Forth you can simplify further
> : }}? ( addr len -- f)
> 2 = swap @ $7D7D = and ;

What if addr is not on a word boundary?

Mark Wills

unread,
Oct 31, 2012, 5:17:27 PM10/31/12
to
On Oct 31, 7:12 pm, Paul Rubin <no.em...@nospam.invalid> wrote:
That's a great solution Peter, but as Paul mentioned, it's a problem
if the string doesn't fall on a word boundary. Unfortunately, that is
*always* the case the with my system. For example, S" HELLO" compiles
as (S") 5 H E L L O where (S") is a 16 bit word (address of (S")) 5
is the length byte, and then the bytes of the string follow.

Lovely solution though!

Mark Wills

unread,
Oct 31, 2012, 5:21:44 PM10/31/12
to
On Oct 31, 5:10 pm, Graham <""gray\"@forth...@plus.com"> wrote:
> There's the 'obvious' way:
>
> : }}? ( addr len -- addr len flag)
>      2dup 2 = over c@ 125 = and swap 1+ c@ 125 = and
> ;
>

I think this the winner so far, without implementing COMPARE of
course :-)

My code is a close second! ;-)

I like how Graham's code does not require and IF/ELSE/THEN. Very nice.

Mark Wills

unread,
Oct 31, 2012, 5:26:08 PM10/31/12
to
On Oct 31, 3:27 pm, alb...@spenarnc.xs4all.nl (Albert van der Horst)
wrote:
> In article <70a117c1-ba9f-474b-97f3-6440be3d4...@k20g2000vbj.googlegroups.com>,
Wow! That's a nice command!

Mark Wills

unread,
Oct 31, 2012, 5:27:10 PM10/31/12
to
On Oct 31, 4:47 pm, Andrew Haley <andre...@littlepinkcloud.invalid>
wrote:
17.6.1.0935 COMPARE
STRING

( c-addr1 u1 c-addr2 u2 -- n )

Compare the string specified by c-addr1 u1 to the string specified by
c-addr2 u2. The strings are compared, beginning at the given
addresses, character by character, up to the length of the shorter
string or until a difference is found. If the two strings are
identical, n is zero. If the two strings are identical up to the
length of the shorter string, n is minus-one (-1) if u1 is less than
u2 and one (1) otherwise. If the two strings are not identical up to
the length of the shorter string, n is minus-one (-1) if the first non-
matching character in the string specified by c-addr1 u1 has a lesser
numeric value than the corresponding character in the string specified
by c-addr2 u2 and one (1) otherwise.

WTF??????????????????????????????

Why can't COMPARE just push a flag for God's sake! Oh my goodness me!
I think I need to go for a lie down!

Just bonkers!!

Paul Rubin

unread,
Oct 31, 2012, 5:32:44 PM10/31/12
to
Mark Wills <forth...@gmail.com> writes:
> Why can't COMPARE just push a flag for God's sake!

It's an ordered comparison function, e.g. you might want to sort a list
of strings lexicographically.

Coos Haak

unread,
Oct 31, 2012, 5:49:42 PM10/31/12
to
Op Wed, 31 Oct 2012 14:27:10 -0700 (PDT) schreef Mark Wills:
It does a subtraction, and can return three states: first string is less
than the second, both are equal and the first string is greater than the
second. Why is that bonkers?

: less compare 0< ;
: equal compare 0= ;
: greater compare 0> ;

--
Coos

CHForth, 16 bit DOS applications
http://home.hccnet.nl/j.j.haak/forth.html

Pablo Hugo Reda

unread,
Oct 31, 2012, 5:50:19 PM10/31/12
to
Why not?

: }}? ( addr len -- addr len flag)
over w@ $7b7b = ;

Pablo Hugo Reda

unread,
Oct 31, 2012, 5:51:50 PM10/31/12
to
sorry $7d7d

Paul Rubin

unread,
Oct 31, 2012, 5:57:20 PM10/31/12
to
1) not sure if that works if addr is not a word boundary
2) returns wrong value if len != 2.

Mark Wills

unread,
Oct 31, 2012, 6:07:12 PM10/31/12
to
I think WANT is the equivalent of a #include in C. Is this ciForth? So
WANT conditionally includes $= if it's not already in memory.
Presumably.



Mark Wills

unread,
Oct 31, 2012, 6:11:10 PM10/31/12
to
Hi Pablo. What is W@ ?

Andrew Haley

unread,
Oct 31, 2012, 6:13:20 PM10/31/12
to
Mark Wills <forth...@gmail.com> wrote:
> On Oct 31, 4:47?pm, Andrew Haley <andre...@littlepinkcloud.invalid>
> wrote:
>> Well, yes, but the *correct* answer to your problem is therefore
>> "Write COMPARE, then use it". COMPARE is not hard to write.
>>
>> Andrew.
>
> 17.6.1.0935 COMPARE
> STRING
>
> ( c-addr1 u1 c-addr2 u2 -- n )
>
> Compare the string specified by c-addr1 u1 to the string specified
> by c-addr2 u2. The strings are compared, beginning at the given
> addresses, character by character, up to the length of the shorter
> string or until a difference is found. If the two strings are
> identical, n is zero. If the two strings are identical up to the
> length of the shorter string, n is minus-one (-1) if u1 is less than
> u2 and one (1) otherwise. If the two strings are not identical up to
> the length of the shorter string, n is minus-one (-1) if the first
> non- matching character in the string specified by c-addr1 u1 has a
> lesser numeric value than the corresponding character in the string
> specified by c-addr2 u2 and one (1) otherwise.
>
> WTF??????????????????????????????
>
> Why can't COMPARE just push a flag for God's sake! Oh my goodness me!
> I think I need to go for a lie down!
>
> Just bonkers!!

Please try to act like a grownup. It's just a matter of subtracting
one string from the other, character-by-character. until you get a
nonzero result or the end of the string is reached.

Andrew.

Pablo Hugo Reda

unread,
Oct 31, 2012, 6:44:30 PM10/31/12
to
Hi,
if c@ get a byte.. w@ get a word..

sorry, I use my own forth
about the len.. I use 0 delimited string.. i not need worry

Coos Haak

unread,
Oct 31, 2012, 6:47:54 PM10/31/12
to
Op Wed, 31 Oct 2012 14:57:20 -0700 schreef Paul Rubin:
That's why Hugo uses W@: a 16 bit fetch. Gforth, Swiftforth, Win32Forth
have this.
There were proposals in the past to call a 32 bits fetch L@ (long) but
native (cell-wide) fetch kept the name @.
@ is 32 bits fetch in a 32 bit Forth and 64 bits fetch in a 64 bit Forth.
There seems little need for a 32 bits fetch in 64 bit Forths.

Ha, now I know why 64 bit Ciforth has L@ and L!

Rod Pemberton

unread,
Oct 31, 2012, 7:13:01 PM10/31/12
to
"Mark Wills" <forth...@gmail.com> wrote in message
news:53c1b304-a287-4580...@h16g2000vby.googlegroups.com...
...

> 17.6.1.0935 COMPARE
> STRING
>
> ( c-addr1 u1 c-addr2 u2 -- n )
>
> Compare the string specified by c-addr1 u1 to the string specified by
> c-addr2 u2. The strings are compared, beginning at the given
> addresses, character by character, up to the length of the shorter
> string or until a difference is found. If the two strings are
> identical, n is zero. If the two strings are identical up to the
> length of the shorter string, n is minus-one (-1) if u1 is less than
> u2 and one (1) otherwise. If the two strings are not identical up to
> the length of the shorter string, n is minus-one (-1) if the first non-
> matching character in the string specified by c-addr1 u1 has a lesser
> numeric value than the corresponding character in the string specified
> by c-addr2 u2 and one (1) otherwise.
>
> WTF??????????????????????????????
>
> Why can't COMPARE just push a flag for God's sake! Oh my goodness me!
> I think I need to go for a lie down!
>
> Just bonkers!!

Well, Forth has _counted_ strings ... ;-)

Or, pre-empting Hugh Aguilar's response:
The ANS Forth committee is attempting to turn Forth into C. ANS Forth's
COMPARE is now just C's strcmp() ...

lol!


RP


Hugh Aguilar

unread,
Oct 31, 2012, 7:10:33 PM10/31/12
to
On Oct 31, 4:58 am, Mark Wills <forthfr...@gmail.com> wrote:
> The following routine is checking to see if a string is "}}" i.e.
> consists of two consequtive right curly braces.
>
> : }}? ( addr len -- addr len flag)
>   dup 2= if
>     over dup c@   swap 1+ c@   125 =   swap 125 =   and
>   else
>     false
>   then ;
>
> As can be seen, the first check is the length; if the length is not
> exactly 2 then we just return false. If the length is 2 then we check
> to see if both characters are ASCII 125. That's the bit I am looking
> at and saying "Meh... seems a bit convoluted/lengthy.
>
> Is there a better way?
>
> I was thinking maybe:
>
> ... c@ 125 OR swap   1+ c@ 125 OR  125 XOR 0=
>
> Which is perhaps "cleverer" but not as clear as to the intention of
> the code and no shorter...

I think that nested conditionals should be avoided as much as
possible. I just EXIT out. Here is mine:

: }}? ( adr cnt -- flag )
2 <> if drop false exit then
dup c@ [char] } <> if drop false exit then
1+ c@ [char] } <> if false exit then
true ;

Here is a more readable one with locals (the { is in my novice
package):

: }}? { adr cnt -- flag }
cnt 2 <> if false exit then
adr c@ [char] } <> if false exit then
adr 1+ c@ [char] } <> if false exit then
true ;

Here is one with a macro to get rid of some of the redundancy:

macro: bounce
if false exit then ;

: }}? { adr cnt -- flag }
cnt 2 <> bounce
adr c@ [char] } <> bounce
adr 1+ c@ [char] } <> bounce
true ;

All of this is untested as I haven't yet installed a Forth system on
my new computer. This is pretty simple though, so it should work.

I don't like nested conditionals because they are ugly and confusing.
In this case you are only testing three things, which isn't too bad.
Imagine if you were testing more though --- you would have a stair-
step Pascal-like function and it would be very confusing as to what
was going on. This is Forth not Pascal --- use EXIT. The vast majority
of the time, several things have to all be true to get a TRUE, so if
anything is false, you can immediately EXIT with a FALSE and you are
done.

Also, don't be afraid to add some extra white-space as I did to make
everything line up. There is no law that says your source-code has to
be compressed up against the left margin. I make my source-code line
up like this all the time --- see the novice package for examples.
http://www.forth.org/novice.html

Note that I did not factor out the test of the } char. That would be
bad factoring. It is unlikely that you are going to test the same char
more than once. In this case you are, but that is unusual. It is more
readable if you explicitly test each char as I did above. This way the
reader can easily see which chars are being tested for.

P.S. Look at my alien-alphabet program
https://groups.google.com/group/comp.lang.forth/browse_thread/thread/dd8e30fcc7589749
for an example of generating pattern-matching code and compiling it,
at run-time. This is a very Forthy method, I think.

P.P.S. Look at SPLIT in my novice package (list.4th) for code that
splits strings up. This is primarily for comma-delimited data, such as
from a database dump. That is somewhat similar.

Hugh Aguilar

unread,
Oct 31, 2012, 7:15:10 PM10/31/12
to
On Oct 31, 2:32 pm, Paul Rubin <no.em...@nospam.invalid> wrote:
Hey Mark, does this mean that binary trees are godless?

Doug Hoffman

unread,
Oct 31, 2012, 7:16:15 PM10/31/12
to
On 10/31/12 6:07 PM, Mark Wills wrote:
> On Oct 31, 4:22 pm, Doug Hoffman <glide...@gmail.com> wrote:

>>
>>> WANT $=
>>> : }}? 2DUP "}}" $= ;
>>
>> With an ANS Forth I can't compile this. I get three undefined words
>> error messages:
>>
>> WANT
>> $=
>> "}}"


> I think WANT is the equivalent of a #include in C. Is this ciForth? So
> WANT conditionally includes $= if it's not already in memory.
> Presumably.

Maybe someday there will some kind of standardization effort for this
kind of stuff. Might prove useful.

-Doug

Mark Wills

unread,
Nov 1, 2012, 2:39:15 AM11/1/12
to
On Oct 31, 10:13 pm, Andrew Haley <andre...@littlepinkcloud.invalid>
wrote:
Well here's the thing... They way you described it is clear and
simple. The way the ANS doc describes is somewhat torturous! It is
useful that it can return < = or > though.

Elizabeth D. Rather

unread,
Nov 1, 2012, 2:58:14 AM11/1/12
to
A standard is not a tutorial. It has to be precise and define
specifically things that the casual reader would think are common sense
(but another casual reader would think common sense to interpret
slightly differently). My Forth Programmer's Handbook (of which a pdf is
included with the free download of evaluation versions of SwiftForth)
describes it in words, with examples:

3.5 COMPARING CHARACTER STRINGS
Character-string comparisons operate on two separate character
strings. This allows the two to be compared by use of the ASCII
collating sequence.

The words in the following glossary are provided. Both of them compare
strings, but they are intended for entirely different situations.
COMPARE is intended for finding a match in a list or table, or in a sort
or binary search operation when the collating order of non-matching
strings is relevant. SEARCH is intended for finding a short string in a
longer string, as in an editor’s search function.

As an example of their use, you could compare a string whose address is
returned by NAME with one temporarily stored at PAD, testing as follows:

PAD <length> DUP NAME SWAP COMPARE

For a more detailed example, consider the two strings in Figure 12.

addr1 addr1+56
v v
This is the forest primeval, the murmuring pines and them

addr2 addr2+56
v v
This is the forest primeval, the murmuring pines and that

Table 6: String comparison examples

Phrase Result Remarks
<addr1> 55 <addr2> 55 COMPARE 0 Strings are equal
<addr1> 56 <addr2> 56 COMPARE 1 String at addr1 is later
in collating sequence
<addr1> 55 <addr2> 56 COMPARE -1 String at addr1 is
shorter, hence earlier in
collating sequence

(Hard to reproduce in text form, check out the actual book!)

Cheers,
Elizabeth

--
==================================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com

"Forth-based products and Services for real-time
applications since 1973."
==================================================

Hugh Aguilar

unread,
Nov 1, 2012, 5:04:33 AM11/1/12
to
In Straight Forth I will have COMPARE, but I will also have a word
that checks strings for equality. If all you want is to check for
equality, that is faster because you can return FALSE when the strings
are different lengths without doing the char-by-char comparison at all
--- and it will save everybody from the non-intuitive return of 0 for
equal (0 usually means false, which would intuitively be not-equal).

Mark is right that most of the time the user only wants to check for
equality.

A lot of people already have this for clarity:

macro: str= ( adr1 cnt1 adr2 cnt2 -- equal? )
compare 0= ;

This might as well be in the standard so it can be written in assembly-
language and so it will be the same for everybody.

Mark Wills

unread,
Nov 1, 2012, 9:31:59 AM11/1/12
to
I also thought $= was quite useful, so I set about writing a version.
I found it quite torturous to write! I'd be interested to see other
versions.

: $= ( addr1 len1 addr2 len2 -- flag)
2 pick <> if drop 2drop false else rot begin
dup c@ >r 1+ -rot dup c@ >r 1+ -rot
r> r> = if 1- else drop -1 then dup >r -rot
r> 0<= until then ;

Quite a lot of return stack bashing required. It works by via a
BEGIN...UNTIL loop, checking each character. The length is decremented
each time a character is checked. If two characters are different, it
sets the length to -1. The UNTIL loop terminates with a 0<= so the
loop exits early if a difference is found. If the string is exactly
equal, then the length will have been decremented to 0 (duh!) since
every character will have been checked. If the length is found to be
-1 then the strings were not equal. This is taken care of with the
final 0= at the end.

Here it is showing the stack:
(a=address l=length)

rot \ l1 a2 a1
begin
dup c@ >r 1+ \ l1 a2 a1 r: c1
-rot \ a1 l1 a2 r: c1
dup c@ >r 1+ \ a1 l1 a2 r: c1 c2
-rot \ a2 a1 l1 r: c1 c2
r> r> = \ a2 a1 l1 flag r: --
if 1- else drop -1 then \ a2 a1 l1/0 r: --
dup >r \ a2 a1 l1/0 r: l1/0
-rot \ l1/0 a2 a1 r: l1/0
r> 0<= until \ l1/0 a2 a1 r: --
2drop \ l1/0
0= \ flag
then

Is there an easier way (that is, showing the *implementation* not just
some high level word). I was surprised at how difficult it was. It's
much easier in C!

In fairness, I think this type of routine is a good candidate for
locals or variables. With locals the difficulty would evaporate I
think. C, of course, has locals/variables. I was trying to see if I
could do it without variables, however. What would seasoned Forth
programmers do here? Reach for locals/variables or is there something
much more obvious that I'm missing?

Doug Hoffman

unread,
Nov 1, 2012, 10:34:30 AM11/1/12
to
On 11/1/12 9:31 AM, Mark Wills wrote:

> I also thought $= was quite useful,

COMPARE is fine by me, I already have it so $= is redundant.

Nonetheless...

> so I set about writing a version.
> I found it quite torturous to write! I'd be interested to see other
> versions.
>
> : $= ( addr1 len1 addr2 len2 -- flag)
> 2 pick <> if drop 2drop false else rot begin
> dup c@ >r 1+ -rot dup c@ >r 1+ -rot
> r> r> = if 1- else drop -1 then dup >r -rot
> r> 0<= until then ;

This crashes for me. Here's a dump:

s" }}" s" }}" $= .
( 4 ) \ -1073750320 \ 2 \ -1073750318 \ 2
2 ( 5 ) \ -1073750320 \ 2 \ -1073750318 \ 2 \ 2
pick ( 5 ) \ -1073750320 \ 2 \ -1073750318 \ 2 \ 2
<> ( 4 ) \ -1073750320 \ 2 \ -1073750318 \ 0
if ( 3 ) \ -1073750320 \ 2 \ -1073750318
rot ( 3 ) \ 2 \ -1073750318 \ -1073750320
begin ( 3 ) \ 2 \ -1073750318 \ -1073750320
dup ( 4 ) \ 2 \ -1073750318 \ -1073750320 \ -1073750320
c@ ( 4 ) \ 2 \ -1073750318 \ -1073750320 \ 125
>r ( 3 ) \ 2 \ -1073750318 \ -1073750320
1+ ( 3 ) \ 2 \ -1073750318 \ -1073750319
-rot ( 3 ) \ -1073750319 \ 2 \ -1073750318
dup ( 4 ) \ -1073750319 \ 2 \ -1073750318 \ -1073750318
c@ ( 4 ) \ -1073750319 \ 2 \ -1073750318 \ 125
>r ( 3 ) \ -1073750319 \ 2 \ -1073750318
1+ ( 3 ) \ -1073750319 \ 2 \ -1073750317
-rot ( 3 ) \ -1073750317 \ -1073750319 \ 2
r> ( 4 ) \ -1073750317 \ -1073750319 \ 2 \ 125
r> ( 5 ) \ -1073750317 \ -1073750319 \ 2 \ 125 \ 125
= ( 4 ) \ -1073750317 \ -1073750319 \ 2 \ -1
if ( 3 ) \ -1073750317 \ -1073750319 \ 2
1- ( 3 ) \ -1073750317 \ -1073750319 \ 1
else ( 3 ) \ -1073750317 \ -1073750319 \ 1
dup ( 4 ) \ -1073750317 \ -1073750319 \ 1 \ 1
>r ( 3 ) \ -1073750317 \ -1073750319 \ 1
-rot ( 3 ) \ 1 \ -1073750317 \ -1073750319
r> ( 4 ) \ 1 \ -1073750317 \ -1073750319 \ 1
0< ( 4 ) \ 1 \ -1073750317 \ -1073750319 \ 0
= ( 3 ) \ 1 \ -1073750317 \ 0
until ( 2 ) \ 1 \ -1073750317
dup ( 3 ) \ 1 \ -1073750317 \ -1073750317
c@ ( 3 ) \ 1 \ -1073750317 \ 125
>r ( 2 ) \ 1 \ -1073750317
1+ ( 2 ) \ 1 \ -1073750316
-rot ( 2 ) \ -1073750320 \ 1
dup ( 3 ) \ -1073750320 \ 1 \ 1
c@


Largely untested:

: $= ( addr1 len1 addr2 len2 -- flag)
rot \ addr1 addr2 len2 len1
over \ addr1 addr2 len2 len1 len2
<> if 2drop drop 0 exit then \ out if len1<>len2
\ addr1 addr2 len2
over + swap \ addr1 addr2+len2 addr2
?do dup c@ i c@ <> if drop 0 unloop exit then loop
drop true ;

Some define "over + swap" as bounds.

-Doug

Andrew Haley

unread,
Nov 1, 2012, 10:37:08 AM11/1/12
to
Mark Wills <forth...@gmail.com> wrote:
> On Oct 31, 11:16?pm, Doug Hoffman <glide...@gmail.com> wrote:
>> On 10/31/12 6:07 PM, Mark Wills wrote:
>>
>> > On Oct 31, 4:22 pm, Doug Hoffman <glide...@gmail.com> wrote:
>>
>> >>> WANT $=
>> >>> : }}? 2DUP "}}" $= ;
>>
>> >> With an ANS Forth I can't compile this. ?I get three undefined words
>> >> error messages:
>>
>> >> WANT
>> >> $=
>> >> "}}"
>> > I think WANT is the equivalent of a #include in C. Is this ciForth? So
>> > WANT conditionally includes $= if it's not already in memory.
>> > Presumably.
>>
>> Maybe someday there will some kind of standardization effort for this
>> kind of stuff. ?Might prove useful.
>
> I also thought $= was quite useful, so I set about writing a version.
> I found it quite torturous to write! I'd be interested to see other
> versions.
>
> : $= ( addr1 len1 addr2 len2 -- flag)
> 2 pick <> if drop 2drop false else rot begin
> dup c@ >r 1+ -rot dup c@ >r 1+ -rot
> r> r> = if 1- else drop -1 then dup >r -rot
> r> 0<= until then ;
>
> Quite a lot of return stack bashing required.

You need to factor:

Return 1 if +ve, -1 if -ve
: flagify ( n -- n' )
0< if -1 exit then
1 ;

\ Bump a pair of c-addrs
: bump ( c-addr1 c-addr2 -- c-addr1 c-addr2 )
1+ swap 1+ swap ;

: compare ( c-addr1 u1 c-addr2 u2 -- n )
rot min 0 do
over c@ over c@ -
?dup if >r 2drop r> flagify unloop exit then
bump
loop 2drop 0 ;

Andrew.

Paul Rubin

unread,
Nov 1, 2012, 10:41:11 AM11/1/12
to
Mark Wills <forth...@gmail.com> writes:
> could do it without variables, however. What would seasoned Forth
> programmers do here? Reach for locals/variables or is there something
> much more obvious that I'm missing?

I'm no seasoned Forther by any means, but I think if the first thing in
your word uses PICK, you are already out of the purity zone, so you
should use variables or locals. The version you wrote is (while
impressive) sort of an anti-advertisement for Forth.

In Colorforth, I guesss you'd use the A and B registers to hold the two
pointers. That might actually work out ok.

Doug Hoffman

unread,
Nov 1, 2012, 10:48:15 AM11/1/12
to
On 11/1/12 10:34 AM, Doug Hoffman wrote:

oops

Should be:

: $= ( addr1 len1 addr2 len2 -- flag)
rot \ addr1 addr2 len2 len1
over \ addr1 addr2 len2 len1 len2
<> if 2drop drop 0 exit then \ out if len1<>len2
\ addr1 addr2 len2
over + swap \ addr1 addr2+len2 addr2
?do dup c@ i c@ <> if drop 0 unloop exit then 1+ loop \ added 1+
drop true ;

-Doug

rickman

unread,
Oct 31, 2012, 9:42:03 PM10/31/12
to
On 10/31/2012 11:40 AM, Rod Pemberton wrote:
> "Rod Pemberton"<do_no...@notemailnotz.cnm> wrote in message
> news:k6rfsn$ue4$1...@speranza.aioe.org...
>> "Mark Wills"<forth...@gmail.com> wrote in message
>> news:55836290-5cf4-4261...@b12g2000vbg.googlegroups.com...
>> ...
>>
>>> I think I've settled on:
>>>
>>> : }}? ( addr len -- addr len flag)
>>> dup 2 = if
>>> over dup c@ swap 1+ c@ or 125 xor 0=
>>> else
>>> false
>>> then ;
>>
>> The 'or 125' means it'll detect more than just '}}'. It'll also detect
>> '}' followed by a zero or nul too...
>>
>
> Sigh, that wasn't as clear as it could be. 125 has many set bits. So,
> or-ing varous values with 125 will result in many other matches.
> E.g., 5 or 125 = 125, 112 or 125 = 125, 36 or 125 = 125, etc etc.

You are right that the code doesn't work, but he isn't ORing anything
with 125. He is oring the two chars which is incorrect. Each one needs
to be compared to the value 125. At least I assume 125 is the right
ascii value.

How about this?

: }}? ( addr len -- addr len flag )
2dup s" }}" compare 0= ;

Rick

Mark Wills

unread,
Nov 1, 2012, 11:49:02 AM11/1/12
to
Hi Doug. Strange that it crashes for you. Runs fine on my system. Odd.

Mark Wills

unread,
Nov 1, 2012, 11:52:17 AM11/1/12
to
On Nov 1, 2:41 pm, Paul Rubin <no.em...@nospam.invalid> wrote:
> I'm no seasoned Forther by any means, but I think if the first thing in
> your word uses PICK, you are already out of the purity zone, so you
> should use variables or locals.  The version you wrote is (while
> impressive) sort of an anti-advertisement for Forth.
>
Well... If it's such a bad word, then it shouldn't be available ;-)
But I know what you mean. There didn't seem to be any better
alternative though at the time (though Doug's code is better than mine
and avoids PICK).

> The version you wrote is (while impressive) sort of an anti-advertisement for Forth.

I agree. I had multiple attempts, and this was the best I could come
up with. Andrew notes that I should factor more. I did consider that,
but it seems excessive for a single function, and adds a performance
penalty on ITC systems such as mine.

Graham NEWS

unread,
Nov 1, 2012, 11:52:40 AM11/1/12
to
No need for locals at all. Just factor a bit. Try the following. (By the
way, I prefer the name STR= rather than $=. I'm used to it now I suppose.)

[undefined] bounds [if]
: bounds \ addr len -- addrhi addrlo
over + swap
;
[then]

: s= \ addr1 addr2 len -- flag
bounds ?do
dup c@ i c@ <> \ addr1 flag1
if drop unloop FALSE exit then
char+
loop
drop True
;

: str= ( addr1 len1 addr2 len2 -- flag)
rot tuck = \ addr1 addr2 len2 flag1
if s= \ flag
else drop 2drop FALSE \ false
then
;

Or, less efficient but without the IF..ELSE..THEN, you could define..

: str= ( addr1 len1 addr2 len2 -- flag)
rot 2dup = >r \ addr1 addr2 len1 len2 R: flag1
min s= r> and \ flag
;


Regards,

Graham

--
GCS

Mark Wills

unread,
Nov 1, 2012, 11:55:17 AM11/1/12
to
Thank you Doug. That's very nice. I had to add unloop, which was
trivial.

Doug Hoffman

unread,
Nov 1, 2012, 12:46:04 PM11/1/12
to
It's OK. ANS doesn't have 0<=. It somehow got munged when I ran it
into "0< =" which caused the crash. My error.

-Doug

Andrew Haley

unread,
Nov 1, 2012, 1:18:51 PM11/1/12
to
Mark Wills <forth...@gmail.com> wrote:

> Andrew notes that I should factor more. I did consider that, but it
> seems excessive for a single function, and adds a performance
> penalty on ITC systems such as mine.

That is a huge, huge, mistake. In fact, it's the biggest mistake you
can make in Forth programming. It's also one of the most common. An
ideal forth word is a line or two, and your compare word is much
longer than that.

Andrew.

rickman

unread,
Nov 1, 2012, 1:42:30 PM11/1/12
to
On 10/31/2012 5:26 PM, Mark Wills wrote:
> On Oct 31, 3:27 pm, alb...@spenarnc.xs4all.nl (Albert van der Horst)
> wrote:
>>
>> I can't help it.
>>
>> WANT $=
>> : }}? 2DUP "}}" $= ;
>>
>> As a general point, unless you want to go the c-abomination of zero-ended
>> strings, it can't be helped that you have to consider the length as well
>> as the content of the string.
>>
>> Groetjes Albert
>
> Wow! That's a nice command!

I agree...

WANT $$$

Rick

rickman

unread,
Nov 1, 2012, 1:55:10 PM11/1/12
to
On 10/31/2012 6:44 PM, Pablo Hugo Reda wrote:
> El mi�rcoles, 31 de octubre de 2012 19:11:10 UTC-3, M.R.W Wills escribi�:
>> On Oct 31, 9:50 pm, Pablo Hugo Reda<pablor...@gmail.com> wrote:
>>
>>> Why not?
>>
>>>
>>
>>> : }}? ( addr len -- addr len flag)
>>
>>> over w@ $7b7b = ;
>>
>>
>>
>> Hi Pablo. What is W@ ?
>
> Hi,
> if c@ get a byte.. w@ get a word..
>
> sorry, I use my own forth
> about the len.. I use 0 delimited string.. i not need worry

I think you miss the point. Your code will say that the string "}}"
matches as well as "}}}", "}}}}", etc. It needs to check length as well
as just the first two chars.

Rick

Marcel Hendrix

unread,
Nov 1, 2012, 3:28:26 PM11/1/12
to
Coos Haak <chf...@hccnet.nl> writes Re: Is there a better way?

[..]
> There were proposals in the past to call a 32 bits fetch L@ (long) but
> native (cell-wide) fetch kept the name @.
> @ is 32 bits fetch in a 32 bit Forth and 64 bits fetch in a 64 bit Forth.

> There seems little need for a 32 bits fetch in 64 bit Forths.
[,,]

Wrong!

reference:
@+ 2840 times

32b@ 164 times
32b@+ 42 times
s32b@ 27 times ( signed fetch )
s32B@+ 8 times

32b, 101 times
32b! 98 times
32b+! 98 times
32b!+ 4 times

32B2@ 7 times
32B2! 3 times

Most of these happen when converting sources that explicitly use
32-bittedness (cryptography, zipping etc., etc.).
A very large percentage is from interfacing with C libraries.

-marcel

Albert van der Horst

unread,
Nov 1, 2012, 5:00:52 PM11/1/12
to
In article <RrudnRYWh7RTyAzN...@supernews.com>,
Andrew Haley <andr...@littlepinkcloud.invalid> wrote:
>Mark Wills <forth...@gmail.com> wrote:
>> On Oct 31, 1:23?pm, Doug Hoffman <glide...@gmail.com> wrote:
>>> On 10/31/12 7:58 AM, Mark Wills wrote:
>>>
>>> > The following routine is checking to see if a string is "}}" i.e.
>>> > consists of two consequtive right curly braces.
>>>
>>> > : }}? ( addr len -- addr len flag)
>>> > ?dup 2= if
>>> > over dup c@ swap 1+ c@ 125 = swap 125 = and
>>> > else
>>> > false
>>> > then ;
>>>
>>> > As can be seen, the first check is the length; if the length is not
>>> > exactly 2 then we just return false. If the length is 2 then we check
>>> > to see if both characters are ASCII 125. That's the bit I am looking
>>> > at and saying "Meh... seems a bit convoluted/lengthy.
>>>
>>> > Is there a better way?
>>>
>>> > I was thinking maybe:
>>>
>>> > ... c@ 125 OR swap 1+ c@ 125 OR 125 XOR 0=
>>>
>>> > Which is perhaps "cleverer" but not as clear as to the intention of
>>> > the code and no shorter...
>>>
>>> : }}? ( addr len -- addr len flag)
>>> 2dup s" }}" compare 0= ;
>>
>>
>> That's cheating ;-) COMPARE is in the ANS optional string word-set.
>> I'm still stuck in the 80's I'm afraid, using Forth 83 on a 30 year
>> old computer! Everyone should have a hobby!
>
>Well, yes, but the *correct* answer to your problem is therefore
>"Write COMPARE, then use it". COMPARE is not hard to write.

+ one

>
>Andrew.
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

Hugh Aguilar

unread,
Nov 1, 2012, 10:19:25 PM11/1/12
to
On Oct 31, 6:42 pm, rickman <gnu...@gmail.com> wrote:
> How about this?
>
> : }}? ( addr len -- addr len flag )
>    2dup s" }}" compare 0= ;

Good Forth style is for functions to consume their arguments:

: }}? ( adr cnt -- equal? )
s" }}" compare 0= ;

If you want a stack picture of ( adr cnt -- adr cnt flag ) then do
this:

2dup }}?

I recommend that Mark read "Thinking Forth." These kinds of style
issues are covered in there.

BTW, Mark: When I wrote symtab, which is a binary tree, this whole
COMPARE thing confused the heck out of me. It is very difficult to
look at the code and understand what the result of COMPARE means. Are
we going left or right, or what? My solution was to define some
constants. I think they were LT EQ and GT as -1, 0 and 1, and compare
the result of COMPARE with these. That really improved the readability
of the code a lot. I did the same later on in ASSOCIATION, which may
be better code for you to study (more useful too, as it is a general-
purpose association array, whereas symtab is only for use as a symbol
table).

With these constants, you would have:

: }}? ( adr cnt -- equal? )
s" }}" compare EQ = ;

Hugh Aguilar

unread,
Nov 1, 2012, 10:38:47 PM11/1/12
to
On Nov 1, 10:18 am, Andrew Haley <andre...@littlepinkcloud.invalid>
wrote:
Andrew is right about this. Mark, I told you that "factoring is strong
magic." You put my quote in your system's manual, so you can read it
there if you have forgotten.

That was some really ugly Forth! For something like that, locals will
help a lot. In my novice package I have +TO that is useful for
stepping the pointers. You can also do without locals (I did for many
many years), but in this case factoring is going to help a lot (the
use of locals and the use of factoring are mutually exclusive, as
functions with locals can't really be factored).

You should write something clean first, without concern for speed.
There is no point in writing convulated code like you did. It takes
too long to get that kind of code working, and the result is just
ugly. After you have a clean version working, you can rewrite it as
necessary to make it faster.

You will notice in my novice package I often have two versions of a
function, with the readable one being commented out. It is okay to
leave a history of the evolution of your words in your source-code
like this.

Look at my word EXCHANGE in the novice package (it exchanges records
in an array during sorting), which is somewhat similar.

Charles Mélice

unread,
Nov 2, 2012, 4:10:09 AM11/2/12
to
What about:

: }}? ( a n -- flag )
2 = if h@ 0x7D7D = else drop false then ;

Charles Mélice

unread,
Nov 2, 2012, 4:18:54 AM11/2/12
to
Oups - Identical to the solution of Pablo...

Rod Pemberton

unread,
Nov 2, 2012, 4:48:57 AM11/2/12
to
"Mark Wills" <forth...@gmail.com> wrote in message
news:1c88cb95-3fe6-40ac...@s14g2000vba.googlegroups.com...
...

> Guess I'll go back to my original code.

Which was:

> : }}? ( addr len -- addr len flag)
> dup 2= if
> over dup c@ swap 1+ c@ 125 = swap 125 = and
> else
> false
> then ;

OVER DUP C@ 125 = SWAP 1+ C@ 125 = AND


RP


Mark Wills

unread,
Nov 2, 2012, 4:58:20 AM11/2/12
to
Nice. With the definition of h@ presumably being (for big endian):

: h@ ( addr -- n ) dup c@ 8 rshift swap c@ or ;

Charles Mélice

unread,
Nov 2, 2012, 5:14:25 AM11/2/12
to
Thank. A small correction for H@ ( or W@ )

: h@ ( addr -- n ) dup c@ 8 rshift swap 1+ c@ or ;

Charles Mélice

unread,
Nov 2, 2012, 5:16:56 AM11/2/12
to
Oops -> : h@ ( addr -- n ) dup 1+ c@ 8 rshift swap c@ or ;

Mark Wills

unread,
Nov 2, 2012, 5:29:06 AM11/2/12
to
On Nov 2, 2:38 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
>
> That was some really ugly Forth! For something like that, locals will
> help a lot. In my novice package I have +TO that is useful for
> stepping the pointers. You can also do without locals (I did for many
> many years), but in this case factoring is going to help a lot (the
> use of locals and the use of factoring are mutually exclusive, as
> functions with locals can't really be factored).
>

He he! Yeah, it was a pretty good example of write-only wasn't it?! I
knew it was ugly, that's why I posted it asking for feedback.

By the way, I REALLY like your macro: in the novice package. I might
try to implement that in my system too. I need to implement evaluate
first though.

Andrew Haley

unread,
Nov 2, 2012, 7:16:25 AM11/2/12
to
Charles M?lice <charles...@gmail.com> wrote:
> Le vendredi 2 novembre 2012 10:14:26 UTC+1, Charles M?lice a ?crit?:
>> Le vendredi 2 novembre 2012 09:58:20 UTC+1, M.R.W Wills a ?crit?:
>>
>> > : h@ ( addr -- n ) dup c@ 8 rshift swap c@ or ;
>>
>> Thank. A small correction for H@ ( or W@ )
>>
>> : h@ ( addr -- n ) dup c@ 8 rshift swap 1+ c@ or ;
>
> Oops -> : h@ ( addr -- n ) dup 1+ c@ 8 rshift swap c@ or ;

rshift? Are you sure?

You're rather assuming little-endian. If you're going to be
nonportable you might as well go the whole hog and write in assembler.

Andrew.

Charles Mélice

unread,
Nov 2, 2012, 9:04:48 AM11/2/12
to
Le vendredi 2 novembre 2012 12:16:25 UTC+1, Andrew Haley a écrit :
You are right. It is LSHIFT.

rickman

unread,
Nov 2, 2012, 1:06:00 PM11/2/12
to
On 11/1/2012 10:19 PM, Hugh Aguilar wrote:
> On Oct 31, 6:42 pm, rickman<gnu...@gmail.com> wrote:
>> How about this?
>>
>> : }}? ( addr len -- addr len flag )
>> 2dup s" }}" compare 0= ;
>
> Good Forth style is for functions to consume their arguments:
>
> : }}? ( adr cnt -- equal? )
> s" }}" compare 0= ;

This is not what the OP asked for. I try to give people what they want
rather than asking them to change what they want to what I prefer to
offer them... unless that is the only choice of course.

Rick

rickman

unread,
Nov 2, 2012, 1:13:23 PM11/2/12
to
You are using the conditional to temporarily store the flag from the 2
=. I prefer to do it like this.

: }}? ( a n -- a n flag )
over h@ 0x7D7D over 2 = AND ;

I duped the inputs because that is what the OP specified for the
routine. But you see the point of using stack logic rather than the PC
to store the result of the 2 = and perform the AND. I won't say one is
more clear than the other because I think that is just what you are used
to. I'm used to simple logic to generate flags. If the logic was more
complex then maybe conditional execution would be a better way to
express it.

Rick

Andrew Haley

unread,
Nov 2, 2012, 1:18:41 PM11/2/12
to
This is a discussion group, not a helpline; people might get advice
they don't want to hear. As long as it's good advice, that's just
fine. And that 2DUP is poor style!

Andrew.

Anton Ertl

unread,
Nov 2, 2012, 1:31:08 PM11/2/12
to
Mark Wills <forth...@gmail.com> writes:
>Why can't COMPARE just push a flag for God's sake! Oh my goodness me!

Word-savers at work! Instead of specifying STR= and STR<, they
specified COMPARE with a more complicated interface, and saved one
word.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2012: http://www.euroforth.org/ef12/

Paul Rubin

unread,
Nov 2, 2012, 1:37:54 PM11/2/12
to
an...@mips.complang.tuwien.ac.at (Anton Ertl) writes:
> Word-savers at work! Instead of specifying STR= and STR<, they
> specified COMPARE with a more complicated interface, and saved one
> word.

Would the other way be to write separate implementations of STR=,
STR<, STR>, STR<=, and STR>= ? Seems easiest to write COMPARE
and then define the rest using it.

Anton Ertl

unread,
Nov 2, 2012, 2:12:17 PM11/2/12
to
Paul Rubin <no.e...@nospam.invalid> writes:
>an...@mips.complang.tuwien.ac.at (Anton Ertl) writes:
>> Word-savers at work! Instead of specifying STR= and STR<, they
>> specified COMPARE with a more complicated interface, and saved one
>> word.
>
>Would the other way be to write separate implementations of STR=,
>STR<, STR>, STR<=, and STR>= ?

The other way would be to write STR= and STR<, just like there is D=
and D< (and likewise, there is no F> F<= F>=, U<=, U>=, and U> is Core
Ext). Forthers know how to use this kind of comparison.

Sure, if we had generic COMP UCOMP DCOMP FCOMP words with a
COMPARE-like interfaces, we could combine them with 0= 0< 0> and save
some words compared to the traditional Forth approach (and some might
argue that the resulting inefficiency can be optimized away by modern
Forth compilers, like they did in discussions about sub-cell access).
But given that Forth-94 did not go that way for cell, double-cell, and
FP comparisons, it should not have gone that way for string
comparison, either.

Elizabeth D. Rather

unread,
Nov 2, 2012, 2:29:43 PM11/2/12
to
On 11/2/12 8:12 AM, Anton Ertl wrote:
> Paul Rubin <no.e...@nospam.invalid> writes:
>> an...@mips.complang.tuwien.ac.at (Anton Ertl) writes:
>>> Word-savers at work! Instead of specifying STR= and STR<, they
>>> specified COMPARE with a more complicated interface, and saved one
>>> word.
>>
>> Would the other way be to write separate implementations of STR=,
>> STR<, STR>, STR<=, and STR>= ?
>
> The other way would be to write STR= and STR<, just like there is D=
> and D< (and likewise, there is no F> F<= F>=, U<=, U>=, and U> is Core
> Ext). Forthers know how to use this kind of comparison.
>
> Sure, if we had generic COMP UCOMP DCOMP FCOMP words with a
> COMPARE-like interfaces, we could combine them with 0= 0< 0> and save
> some words compared to the traditional Forth approach (and some might
> argue that the resulting inefficiency can be optimized away by modern
> Forth compilers, like they did in discussions about sub-cell access).
> But given that Forth-94 did not go that way for cell, double-cell, and
> FP comparisons, it should not have gone that way for string
> comparison, either.

If you're doing a sort, it's far more useful to have a single comparison
word that gives you the answer. FORTH, Inc. had a word -TEXT which was
similar (simpler) and used in out database package. COMPARE is more general.

String comparisons are not used in applications in ways that are
directly analogous to numeric comparisons. The needs are a little
different. STR= and STR< would be far less useful than COMPARE, I think.

Cheers,
Elizabeth

--
==================================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com

"Forth-based products and Services for real-time
applications since 1973."
==================================================

Paul Rubin

unread,
Nov 2, 2012, 2:30:30 PM11/2/12
to
an...@mips.complang.tuwien.ac.at (Anton Ertl) writes:
> The other way would be to write STR= and STR<, just like there is D=
> and D< (and likewise, there is no F> F<= F>=, U<=, U>=, and U> is Core
> Ext). Forthers know how to use this kind of comparison.

How would you defined STR<= in terms of STR= and STR< without having
to scan the string twice? F<= doesn't face that issue to the same
extent, since floats are fixed-size.

rickman

unread,
Nov 2, 2012, 2:34:42 PM11/2/12
to
That's your opinion. There may be a perfectly good reason to include
the 2DUP.

Rick

Paul Rubin

unread,
Nov 2, 2012, 2:39:41 PM11/2/12
to
rickman <gnu...@gmail.com> writes:
> That's your opinion. There may be a perfectly good reason to include
> the 2DUP.

I think when a relatively inexperienced user asks a question that
contains an implicit assumption that goes against how experienced users
usually do things, it's appropriate for the folks answering to point out
the issue.

rickman

unread,
Nov 2, 2012, 2:43:58 PM11/2/12
to
That's fine, but the fact remains that I gave him the code he asked for.
I believe the "defacto" style suggestion has been pointed out some
four or five times. Unlike others here, I don't feel the need to pile on.

Rick

Mark Wills

unread,
Nov 2, 2012, 5:38:25 PM11/2/12
to
Indeed. I don't agree with the notion of having the 2DUP outside of
the definition in this particular case. It was a requirement that the
address and length be retained for further tests (the string might be
something else that I am looking for). Furthermore, in my opinion,
having the 2DUP outside of its associated definition injects 'noise'
into the 'main line' of the code. I prefer to hide the low-level noise
in the lower level functions to which they pertain.

For example:

isOdd? if ... else isEven? then ...

is much nicer than

dup isOdd? if ... else dup isEven? then ...

Lastly, if I choose to remove the test altogether, I only have to
remove the call to }}? in the main line of code. The 2DUP is directly
coupled/associated with the test itself, thus in this particular case
(not every case, sure) I believe the argument for including the 2DUP
inside the definition out-weighs the opposing argument.

So there ;-)

Bernd Paysan

unread,
Nov 2, 2012, 7:15:27 PM11/2/12
to
: str> ( addr1 u1 addr2 u2 -- flag ) 2swap str< ;
: str<= ( addr1 u1 addr2 u2 -- flag ) str> 0= ;
: str>= ( addr1 u1 addr2 u2 -- flag ) str< 0= ;

Should be obvious. You declare F<= the same way: FSWAP F< 0=.

I would go for str= and str<= as implemented primitives, because for
sorting, you want str<= ("already sorted"). Creating two-primitve
composites for the other three cases is not such a big problem, and the
two most performance critical parts have an easy interface.

--
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://bernd-paysan.de/

rickman

unread,
Nov 2, 2012, 7:21:21 PM11/2/12
to
I think you are missing his point. COMPARE gives you all this info. If
you want to do sorting you need to run more than one of these words.

His point about floats is that they are not expensive to scan more than
one. Strings can be much longer and more wasteful to scan a couple of
times.

Rick

Bernd Paysan

unread,
Nov 2, 2012, 7:42:43 PM11/2/12
to
rickman wrote:
> I think you are missing his point. COMPARE gives you all this info.
> If you want to do sorting you need to run more than one of these
> words.

I think you are missing my point. When you are sorting, you are fine
with just STR<=. Yes, indeed, it is completely sufficient to have
exactly one word which tells you that the two elements in the sorted
array are "in order", for whatever order that is.

> His point about floats is that they are not expensive to scan more
> than one.

His point is that he can't imagine how you can make STR<= out of STR<
and STR= without resorting to scanning the string twice, i.e. he thinks

: str<= ( addr1 u1 addr2 u2 -- flag ) 2over 2over str= >r str< r> or ;

> Strings can be much longer and more wasteful to scan a couple of
> times.

Yes, but that's not needed. All you need is to swap inputs and invert
the flag; both true for floating point an for strings. One less (or
less-or-equal) operator is enough; the others can be derived through
input swap and output flag inversion.

COMPARE can be useful in a tree algorithm: You have three choices: left,
right, or leaf. You probably want a Fortran-style three-way IF, too
:-). Something like

compare
IFLEAF ." found"
LEFT >left @ recurse
RIGHT >right @ recurse
THEN

rickman

unread,
Nov 2, 2012, 8:21:17 PM11/2/12
to
On 11/2/2012 7:42 PM, Bernd Paysan wrote:
> rickman wrote:
>> I think you are missing his point. COMPARE gives you all this info.
>> If you want to do sorting you need to run more than one of these
>> words.
>
> I think you are missing my point. When you are sorting, you are fine
> with just STR<=. Yes, indeed, it is completely sufficient to have
> exactly one word which tells you that the two elements in the sorted
> array are "in order", for whatever order that is.

But that does not distinguish if they are equal in which case you may
need to toss one. It depends on what you are doing.


>> His point about floats is that they are not expensive to scan more
>> than one.
>
> His point is that he can't imagine how you can make STR<= out of STR<
> and STR= without resorting to scanning the string twice, i.e. he thinks
>
> : str<= ( addr1 u1 addr2 u2 -- flag ) 2over 2over str=>r str< r> or ;

That's not what he said.


>> Strings can be much longer and more wasteful to scan a couple of
>> times.
>
> Yes, but that's not needed. All you need is to swap inputs and invert
> the flag; both true for floating point an for strings. One less (or
> less-or-equal) operator is enough; the others can be derived through
> input swap and output flag inversion.
>
> COMPARE can be useful in a tree algorithm:

And in other cases where you need to know the three cases, < > AND =.

Rick

Bernd Paysan

unread,
Nov 2, 2012, 8:44:59 PM11/2/12
to
rickman wrote:
>> His point is that he can't imagine how you can make STR<= out of STR<
>> and STR= without resorting to scanning the string twice, i.e. he
>> thinks
>>
>> : str<= ( addr1 u1 addr2 u2 -- flag ) 2over 2over str=>r str< r>
>> : or ;
>
> That's not what he said.

His argument was that scanning the string several times was expensive
(true), and then asked how to make STR<= from STR< and STR= without that
problem (for which I provided an answer).

If you want an unique sort (where you drop dupes), you can sort first,
and then drop the non-unique strings, which is just a scan with the same
STR<=, this time with string[index+1]<=string[index], which holds only
true if it's a dupe. However, with mergesort, you probably want a
three-way compare, as you can remove dupes as you merge together sorted
arrays.

The three-way compare has its place, but where it doesn't, it's
overgeneralized, and therefore complicated the program.

Paul Rubin

unread,
Nov 2, 2012, 9:42:06 PM11/2/12
to
Bernd Paysan <bernd....@gmx.de> writes:
>> How would you defined STR<= in terms of STR= and STR< without having
>> to scan the string twice?
> : str> ( addr1 u1 addr2 u2 -- flag ) 2swap str< ;
> : str<= ( addr1 u1 addr2 u2 -- flag ) str> 0= ;

Aha, good point ;-).

rickman

unread,
Nov 3, 2012, 12:12:36 PM11/3/12
to
On 11/2/2012 8:44 PM, Bernd Paysan wrote:
> rickman wrote:
>>> His point is that he can't imagine how you can make STR<= out of STR<
>>> and STR= without resorting to scanning the string twice, i.e. he
>>> thinks
>>>
>>> : str<= ( addr1 u1 addr2 u2 -- flag ) 2over 2over str=>r str< r>
>>> : or ;
>>
>> That's not what he said.
>
> His argument was that scanning the string several times was expensive
> (true), and then asked how to make STR<= from STR< and STR= without that
> problem (for which I provided an answer).

Please reread his post with an open mind and consider the context. You
are reading content that isn't there.

Rick

Josh Grams

unread,
Nov 3, 2012, 12:38:07 PM11/3/12
to
Doug Hoffman wrote: <5091b13f$0$282$1472...@news.sunsite.dk>
> On 10/31/12 6:07 PM, Mark Wills wrote:
>> On Oct 31, 4:22 pm, Doug Hoffman <glide...@gmail.com> wrote:
>
>>>
>>>> WANT $=
>>>> : }}? 2DUP "}}" $= ;
>>>
>>> With an ANS Forth I can't compile this. I get three undefined words
>>> error messages:
>>>
>>> WANT
>>> $=
>>> "}}"
>
>
>> I think WANT is the equivalent of a #include in C. Is this ciForth? So
>> WANT conditionally includes $= if it's not already in memory.
>> Presumably.
>
> Maybe someday there will some kind of standardization effort for this
> kind of stuff. Might prove useful.

I've been working on one possible solution (a package database and
package loader) to this sort of trivial incompatibility issue in fits
and starts. In August I wrote a working proof-of-concept implementation
and Gerry Jackson ported it to several systems. Then I got bogged down
trying to figure out what to do next and how to modify the design to fix
the flaws that turned up, so I have only done minor work on it since
then. But I think I finally have that all worked out and I'm hoping to
have something release-worthy by the beginning of 2013.

If you're impatient, you can check out the WIP from the mercurial
repository at <https://code.google.com/p/halfpence/>. There is a bit of
documentation in the README (I just updated it so it matches the current
code), and I've been trying to be careful to refactor the code in small
bits and always keep the public repository in a working state.

--Josh

Bernd Paysan

unread,
Nov 3, 2012, 1:24:12 PM11/3/12
to
rickman wrote:
>> His argument was that scanning the string several times was expensive
>> (true), and then asked how to make STR<= from STR< and STR= without
>> that problem (for which I provided an answer).
>
> Please reread his post with an open mind and consider the context.
> You are reading content that isn't there.

Given that Paul also replied to my post, and his reply was "Aha, good
point ;-)", maybe you are reading something between the lines he hasn't
written.

Paul Rubin

unread,
Nov 3, 2012, 1:29:58 PM11/3/12
to
rickman <gnu...@gmail.com> writes:
>> His argument was that scanning the string several times was expensive
>> (true), and then asked how to make STR<= from STR< and STR= without that
>> problem (for which I provided an answer).
>
> Please reread his post with an open mind and consider the context.
> You are reading content that isn't there.

Bernd is right, I had a brain fart, forgetting that x <= y is just
!(y < x). There are still situations where you want the 3-way
compare and can't easily synthesize it, so it still seems like the best
choice if you are going to have just one primitive.

rickman

unread,
Nov 3, 2012, 2:00:44 PM11/3/12
to
On 11/3/2012 1:24 PM, Bernd Paysan wrote:
> rickman wrote:
>>> His argument was that scanning the string several times was expensive
>>> (true), and then asked how to make STR<= from STR< and STR= without
>>> that problem (for which I provided an answer).
>>
>> Please reread his post with an open mind and consider the context.
>> You are reading content that isn't there.
>
> Given that Paul also replied to my post, and his reply was "Aha, good
> point ;-)", maybe you are reading something between the lines he hasn't
> written.
>

I stand corrected.

Rick

Andrew Haley

unread,
Nov 4, 2012, 3:36:54 AM11/4/12
to
But, oddly, you do feel the need to pile on people giving good advice.

Andrew.

Andrew Haley

unread,
Nov 4, 2012, 3:38:40 AM11/4/12
to
rickman <gnu...@gmail.com> wrote:
> On 11/2/2012 1:18 PM, Andrew Haley wrote:
>> rickman<gnu...@gmail.com> wrote:
>>> On 11/1/2012 10:19 PM, Hugh Aguilar wrote:
>>>> On Oct 31, 6:42 pm, rickman<gnu...@gmail.com> wrote:
>>>>> How about this?
>>>>>
>>>>> : }}? ( addr len -- addr len flag )
>>>>> 2dup s" }}" compare 0= ;
>>>>
>>>> Good Forth style is for functions to consume their arguments:
>>>>
>>>> : }}? ( adr cnt -- equal? )
>>>> s" }}" compare 0= ;
>>>
>>> This is not what the OP asked for. I try to give people what they
>>> want rather than asking them to change what they want to what I
>>> prefer to offer them... unless that is the only choice of course.
>>
>> This is a discussion group, not a helpline; people might get advice
>> they don't want to hear. As long as it's good advice, that's just
>> fine. And that 2DUP is poor style!
>
> That's your opinion.

Of course it's my opinion. I wouldn't have posted it if it weren't.

> There may be a perfectly good reason to include the 2DUP.

There may be, but that's unlikely.

Andrew.

Andrew Haley

unread,
Nov 4, 2012, 4:01:36 AM11/4/12
to
Mark Wills <forth...@gmail.com> wrote:
> On Nov 2, 6:34?pm, rickman <gnu...@gmail.com> wrote:
>> On 11/2/2012 1:18 PM, Andrew Haley wrote:
>>
>> > rickman<gnu...@gmail.com> ?wrote:
>> >> On 11/1/2012 10:19 PM, Hugh Aguilar wrote:
>> >>> On Oct 31, 6:42 pm, rickman<gnu...@gmail.com> ? wrote:
>> >>>> How about this?
>>
>> >>>> : }}? ( addr len -- addr len flag )
>> >>>> ? ? ?2dup s" }}" compare 0= ;
>>
>> >>> Good Forth style is for functions to consume their arguments:
>>
>> >>> : }}? ( adr cnt -- equal? )
>> >>> ? ? ? s" }}" compare 0= ;
>>
>> >> This is not what the OP asked for. ?I try to give people what they want
>> >> rather than asking them to change what they want to what I prefer to
>> >> offer them... unless that is the only choice of course.
>>
>> > This is a discussion group, not a helpline; people might get advice
>> > they don't want to hear. ?As long as it's good advice, that's just
>> > fine. ?And that 2DUP is poor style!
>>
>> That's your opinion. ?There may be a perfectly good reason to include
>> the 2DUP.
>
> Indeed. I don't agree with the notion of having the 2DUP outside of
> the definition in this particular case. It was a requirement that the
> address and length be retained for further tests (the string might be
> something else that I am looking for). Furthermore, in my opinion,
> having the 2DUP outside of its associated definition injects 'noise'
> into the 'main line' of the code. I prefer to hide the low-level noise
> in the lower level functions to which they pertain.

While you're entitled to an opinion, this one is just inexperience
talking. Many beginning Forth programmers think that way, but it's a
mistake. I think you will, if you keep writing Forth programs, cease
to believe it. Consistent stack discpline makes it much easier for
the reader to see the flow of data on the stack without having to dig
down to see the stack diagram of every word.

> For example:
>
> isOdd? if ... else isEven? then ...
>
> is much nicer than
>
> dup isOdd? if ... else dup isEven? then ...

No, it's not, because in the former I (and every experienced Forther)
would be looking for the that generated the argument to the isEven? .
Also, isOdd? doesn't know that a copy of its arg is going to be
needed. It's much less useful as a factor if you have to clean up
after it every time.

> Lastly, if I choose to remove the test altogether, I only have to
> remove the call to }}? in the main line of code. The 2DUP is directly
> coupled/associated with the test itself, thus in this particular case
> (not every case, sure) I believe the argument for including the 2DUP
> inside the definition out-weighs the opposing argument.
>
> So there ;-)

You'll learn. Probably.

Andrew.

Alex Wegel

unread,
Nov 4, 2012, 5:07:50 AM11/4/12
to
Mark Wills <forth...@gmail.com> wrote:

> It was a requirement that the
> address and length be retained for further tests (the string might be
> something else that I am looking for).

Maybe you really want a proper parsing function?

I.e. more along the lines of sth like:

( c-addr1 u1 -- c-addr1 u1 false | c-addr2 u2 true )

Where c-addr2 u2 is the original string with the leading part (the "}}")
cut off.

There are some packages out there for doing stuff like that.

Alex Wegel

unread,
Nov 4, 2012, 5:36:48 AM11/4/12
to
On a second thought: If you just want to collect some words up to the
terminating "}}", you might just define a word called }} and let the
interpreter look for it, like in:

: }} ;

: {{ ( -- )
begin bl word find while ( xt )
dup ['] }} = if drop exit then
( xt ) do-sth ( )
repeat
( c-addr ) drop
;

My point is: As usual, it all depends on what you *really* want this
for, and thus can't be answered (in the sense of "what's better")
without knowing more about the context.

Mark Wills

unread,
Nov 4, 2012, 6:48:52 AM11/4/12
to
On Nov 4, 10:36 am, awe...@arcor.de (Alex Wegel) wrote:
> Alex Wegel <awe...@arcor.de> wrote:
I agree with you Alex.

In fact, my first incarnation of the code did *exactly* that. I may
actually revert to that method, we'll see. The code is exeperimental.

To supply some context, this code is a small part of a local variable
implementation for my 16-bit home-brew Forth 83 system:

: word {{ tom dick harry }}
... ... ... ;

Top of stack goes to harry, next to dick, next to tom. The locals are
fleeting, they do not exist within the dictionary. They exist on a
separate stack; thus they can be nested for recursion etc as one would
expect normal local variables to nest in other languages.

The names of the locals are hashed. At this time, I'm using a simple
CRC-16 algorithm to perform the 'hash' though I think it's probably
unsuitable for use I am putting it to. I have already proved (by
running the algorithm through words on a web page) that collisions are
quite common. I may have to move to a 32 bit CRC. Not really a
problem. It just takes a little longer at compile time; there's no run-
time overhead. Locals, when compiled into definitions, actually
produce run time code that produces an offset into the locals stack.

That's currently how my (planned) implementation will work :-) I kind
of got side-tracked into writing a tagged object assembly code loader
(anyone that worked on TI mini's back in the 70's and 80's will know
what they are) for a guy that is developing a floating point package
for my system. I hope to get back at it next week.

I am still enjoying writing Forth code and I think I am improving with
each application I write.

Mark Wills

unread,
Nov 4, 2012, 6:54:27 AM11/4/12
to
On Nov 4, 9:01 am, Andrew Haley <andre...@littlepinkcloud.invalid>
wrote:
Well, a famous man once said: "Opinions are like ass-holes. Everyone
has one, and they're different".

Is there any word naming convention that you (or anyone else) is aware
of that could indicate that a word does not consume its arguments?

Alex Wegel

unread,
Nov 4, 2012, 7:31:10 AM11/4/12
to
Mark Wills <forth...@gmail.com> wrote:

> To supply some context, this code is a small part of a local variable
> implementation for my 16-bit home-brew Forth 83 system:
>
> : word {{ tom dick harry }}
> ... ... ... ;

Ah so.
Hmm - changing this to

: word { tom dick harry } ... ;

would solve half of the problem already (and save two chars for each
word using locals :-).

I don't really want to go into the locals stuff itself, mostly because i
don't use them very often (and i feel that there are multiple possible
strategies, the [dis-]advantages of which are another complex topic,
esp. on a 16-bit system).

Coos Haak

unread,
Nov 4, 2012, 7:29:00 AM11/4/12
to
Op Sun, 4 Nov 2012 03:48:52 -0800 (PST) schreef Mark Wills:
Why do you need hashing? Are you planning to use more than a couple of
locals per definition? I use normal strings. When the word is finished,
there are no local names to be foundy. When interpreting, looking for
locals is senseless anyway. When compiling, find them in a simple locals
dictionary, with string matching. Fast enough for any processor.

--
Coos

CHForth, 16 bit DOS applications
http://home.hccnet.nl/j.j.haak/forth.html

Mark Wills

unread,
Nov 4, 2012, 7:42:50 AM11/4/12
to
Hi Coos

Simply because it makes looking them up during compilation very simple
indeed - the names of the locals have been changed to 16-bit cells.
You're looking for numbers, rather than strings.

The original intention was to make look-ups faster. There's a little
bit of expense to crunch the string to a number (I hesitate to use the
word hash here, because I'm not sure it's a hash; it's actually a
widely known CRC algorithm that I'm using) but subsequent searches
through the (temporary) locals dictionary are very fast.

Perhaps I'll try both methods, there may actually be very little
difference in search times, given the number of times the names of the
locals may actually appear.

Thanks for the comment.

Andrew Haley

unread,
Nov 4, 2012, 8:59:09 AM11/4/12
to
Mark Wills <forth...@gmail.com> wrote:
> On Nov 4, 9:01?am, Andrew Haley <andre...@littlepinkcloud.invalid>
> Well, a famous man once said: "Opinions are like ass-holes. Everyone
> has one, and they're different".

Not in this case. There are some serious disagreements among
experienced Forthers, but this isn't one of them.

> Is there any word naming convention that you (or anyone else) is aware
> of that could indicate that a word does not consume its arguments?

I don't think so.

Andrew.

Elizabeth D Rather

unread,
Nov 4, 2012, 1:34:54 PM11/4/12
to
On 11/4/2012 1:54 AM, Mark Wills wrote:
...
> Well, a famous man once said: "Opinions are like ass-holes. Everyone
> has one, and they're different".
>
> Is there any word naming convention that you (or anyone else) is aware
> of that could indicate that a word does not consume its arguments?
>

Some opinions have more years of experience behind them than others. An
example in a vacuum may look like one usage is prettier, but when you've
been through the application development wars a bit you learn that
certain useful habits will pay off for you.

Such a naming convention doesn't exist because most programmers using
Forth in "real world" applications, particularly large ones, learn the
value of a word that is reusable, and also learn that something that
appears to be an optimization in one place may make the word less usable
in others. "A word should consume its arguments" is a rule that has been
time-tested, independently, by many professionals.

Cheers,
Elizabeth

--
==================================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com

"Forth-based products and Services for real-time
applications since 1973."
==================================================

rickman

unread,
Nov 4, 2012, 2:18:44 PM11/4/12
to
I recognize when I am beating a dead horse. This is pretty pointless.

Rick
It is loading more messages.
0 new messages