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

how to program in forth

289 views
Skip to first unread message

Bruce Axtens

unread,
Nov 18, 2022, 5:21:19 AM11/18/22
to
There's a programming exercise on Exercism called two-fer. It takes an optional parameter. If the parameter is absent it returns "One for you, one for me." If the parameter is present it is interpolated into the string in place of the "you".

As I understand it, and i'm no Forth programmer, optional items aren't a thing in
Forth. Rather, you either program for something or program for nothing. Thus, a two-fer word would expect a null-string or maybe even a null.

Am I understanding this right?

Bruce.

none albert

unread,
Nov 18, 2022, 6:02:55 AM11/18/22
to
In article <debd1ce9-7e04-4145...@googlegroups.com>,
It is impossible.
Any word can be executed in a nested situation, where there may be other
items on the stack.
So there is no way in Forth to determine if one or two stack items are
passed to it.
There is ways around it, like a place holder that has a value NONE.

>
>Bruce.

Groetjes Albert
P.S. restrict you lines to 72 char's
--
"in our communism country Viet Nam, people are forced to be
alive and in the western country like US, people are free to
die from Covid 19 lol" duc ha
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

minf...@arcor.de

unread,
Nov 18, 2022, 6:24:43 AM11/18/22
to
none albert schrieb am Freitag, 18. November 2022 um 12:02:55 UTC+1:
> In article <debd1ce9-7e04-4145...@googlegroups.com>,
> Bruce Axtens <bruce....@gmail.com> wrote:
> >There's a programming exercise on Exercism called two-fer. It takes an optional parameter. If the parameter is absent it returns "One for you, one for me."
> >If the parameter is present it is interpolated into the string in place of the "you".
> >
> >As I understand it, and i'm no Forth programmer, optional items aren't a thing in
> >Forth. Rather, you either program for something or program for nothing. Thus, a two-fer word would expect a null-string or maybe even a null.
> >
> >Am I understanding this right?
> It is impossible.
> Any word can be executed in a nested situation, where there may be other
> items on the stack.
> So there is no way in Forth to determine if one or two stack items are
> passed to it.
> There is ways around it, like a place holder that has a value NONE.
>

For code polymorphism in Forth one would need type info on the stack.
The only Forth system I know of that comes close to it is StrongForth:
https://www.stephan-becher.de/strongforth/

S Jack

unread,
Nov 18, 2022, 8:33:30 AM11/18/22
to
On Friday, November 18, 2022 at 4:21:19 AM UTC-6, bruce....@gmail.com wrote:
> There's a programming exercise on Exercism called two-fer. It takes an optional parameter. If the parameter is absent it returns "One for you, one for me." If the parameter is present it is interpolated into the string in place of the "you".

:) frogd
ELF32X86_64 Frog Version 1.0d

"job" /go
: two-fer
." One for "
drop depth if tell ii ." you" fi
." , one for me"
;

i. "FOO" two-fer ==> One for you, one for me
i. "FOO" "BAR" two-fer ==> One for FOO, one for me
+echo
-fin- ok
--
me

S Jack

unread,
Nov 18, 2022, 9:15:54 AM11/18/22
to
On Friday, November 18, 2022 at 7:33:30 AM UTC-6, S Jack wrote:

also:
:) frogd
ELF32X86_64 Frog Version 1.0d

"job" /go

: two-fer
." One for "
0= if tell ii ." you" fi
." , one for me"
;

i. "FOO" two-fer ==> One for you, one for me
i. "FOO" 0 two-fer ==> One for FOO, one for me

-fin- ok
--
me

Jan Coombs

unread,
Nov 18, 2022, 10:19:29 AM11/18/22
to
Yes. For example, this is a simple demo that runs under gforth.
The constant string, 'you', is still stored in 'two_fer', but
it's declaration is inline rather than in the header.

\ two_fer.fs

\ The strings are passed as two stack items, Address and Length

: two_fer ( pa pl -- ra rl ) \ parameter string -- return string

\ check and replace any empty string
dup 0=
if
2drop S" you"
then

\ concatenate and return new string
S" One for " pad place
pad +place
S" , one for me" pad +place
pad count ;


\ tests

: NoneString ( -- a l ) 0 0 ; \ return empty string

: NameString ( -- a l ) S" Fred" ;

: crtab ( -- ) cr 9 emit ;

NoneString two_fer crtab type
NameString two_fer crtab type
S" George" two_fer crtab type
S" " two_fer crtab type

\ Note: 'pad' is a single location.

>
> Bruce.

Jan Coombs

dxforth

unread,
Nov 18, 2022, 11:02:20 AM11/18/22
to
On 18/11/2022 9:21 pm, Bruce Axtens wrote:
> There's a programming exercise on Exercism called two-fer. It takes an optional parameter. If the parameter is absent it returns "One for you, one for me." If the parameter is present it is interpolated into the string in place of the "you".
>
> As I understand it, and i'm no Forth programmer, optional items aren't a thing in
> Forth.

I'd be surprised if it were 'a thing' anywhere. You say "If the parameter is absent".
That implies a test. AFAIK it's not possible to test nothing - only something.

S Jack

unread,
Nov 18, 2022, 11:37:34 AM11/18/22
to
Ok, my above was for one or two parameters. So for just one optional parameter:

"job" /go
: two-fer
." One for "
Depth if tell ii ." you" fi
." , one for me"
;

i. "FOO" two-fer ==> One for FOO, one for me
i. two-fer ==> One for you, one for me


-fin- ok
--
me

shtps

unread,
Nov 18, 2022, 12:12:43 PM11/18/22
to
Am 18.11.22 um 11:21 schrieb Bruce Axtens:
> There's a programming exercise on Exercism called two-fer. It takes an optional parameter. If the parameter is absent it returns "One for you, one for me." If the parameter is present it is interpolated into the string in place of the "you".
>
> As I understand it, and i'm no Forth programmer, optional items aren't a thing in
> Forth. Rather, you either program for something or program for nothing. Thus, a two-fer word would expect a null-string or maybe even a null.

They aren't a thing, but you can make it a thing if you want.

Some languages solve this by passing pointers to structures.

Here's a variant which uses the stack to pass the items and
the number of items to the word. If checking for individual
arguments is important I believe you need structures, or at
least some way to indicate that it is or isn't present.
e.g. NULL.

\ A helper to count values on the stack, "values" must be
\ terminated with "end-values" in the same word as it uses
\ the return stack to store the depth. Alternatively you could
\ use a variable to store the depth, but that comes with its
\ own advantages and disadvantages.

: values depth r> 2>r ;
: end-values depth r> r> rot swap - swap >r ;

: optional-print ( n..m -- )
dup 1 = IF drop . ." is just for me." cr ELSE
dup 2 = IF drop . ." is for me and " . ." is for you." cr ELSE
dup 0> IF 0 DO ." Person " I 1+ . ." gets " . cr LOOP cr ELSE
abort
THEN THEN THEN ;

values 123 end-values optional-print
values 456 123 end-values optional-print
values 777 999 789 456 123 end-values optional-print

Zbig

unread,
Nov 18, 2022, 1:46:49 PM11/18/22
to
> Ok, my above was for one or two parameters. So for just one optional parameter:
> "job" /go
> : two-fer
> ." One for "
> Depth if tell ii ." you" fi
^^^^^^^
DEPTH is no solution. How can you tell the values present on the stack
were for your two-fer word? Perhaps they were left there for subsequent word?

S Jack

unread,
Nov 18, 2022, 6:00:46 PM11/18/22
to
Play by the rules; Rule, if parameter exists it for u:)
--
me

Zbig

unread,
Nov 19, 2022, 5:25:41 AM11/19/22
to
> Play by the rules; Rule, if parameter exists it for u:)

The problem is: not in the case when parameter may exist,
or there may be no parameter „for u”.
That was the initial assumption, correct?

Anton Ertl

unread,
Nov 19, 2022, 9:43:52 AM11/19/22
to
Bruce Axtens <bruce....@gmail.com> writes:
>There's a programming exercise on Exercism called two-fer. It takes an optional parameter. If the parameter is absent it returns "One for you, one for me." If the parameter is present it is interpolated into the string in place of the "you".
>
>As I understand it, and i'm no Forth programmer, optional items aren't a thing in
>Forth.

Yes, optional parameters are not a thing. Instead, I would go for one
of the following approaches:

1) Pass the proper value for the now-non-optional parameter:

: two-fer ( c-addr u -- ) ." One for " type ." , one for me." ;
s" the emperor" two-fer
s" you" two-fer \ the case where you pass nothing in other languages

2) Use two different word names:

: two-fer ( c-addr u -- ) ." One for " type ." , one for me." ;
: two-fer1 ( -- ) s" you" two-fer ;

s" the emperor" two-fer
two-fer1


Another approach which is rarely used is to have a parameter in the
input stream, and when the line ends after the word (without parameter
in the input stream), that has a different meaning. E.g., WORDS in
SwiftForth does the standard thing when it's at the end of the line,
but does something else when there is some word behind it. Likewise,
in Gforth HELP gives you general HELP at the end of the line, but help
on a word or recognizer if there is something behind it. Applied to
TWO-FER this approach would result in:

: two-fer ( "name"? -- )
parse-name dup 0= if 2drop s" you" then
." One for " type ." , one for me." ;
two-fer the_emperor
two-fer

- 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: https://forth-standard.org/
EuroForth 2022: https://euro.theforth.net

S Jack

unread,
Nov 19, 2022, 10:04:50 AM11/19/22
to
Not on my part. The spec was broad and left a lot of wiggle room
so I wiggled ( as I giggled if you catch the drift ).
--
me

Brian Fox

unread,
Nov 19, 2022, 2:07:08 PM11/19/22
to
This is true for all Forth parameters on the data stack is it not?

Another option is to invent a "syntax" for the problem and record the stack
position and test if a parameter is present.
It is an extendable language after all.

Example:
{ S" Foxy" } two-fer
{ } two-fer

Zbig

unread,
Nov 19, 2022, 4:00:39 PM11/19/22
to
> Another option is to invent a "syntax" for the problem and record the stack
> position and test if a parameter is present.

It could be made for example by adding always as a top parameter a value
that will confirm to each word like: „next 3 values are for you”. So the word
would firstly DUP and examine that „confirmation”, and if it means „the
following n parameters are for you” — then „eat” them in usual way.

But of course it'd significantly slow the Forth machine down — so although
it can be done, what's the sense? If anyone wants C/LISP/whatever — with
their advantages, like ability to set „default parameters” — they're ready to be
embraced.

dxforth

unread,
Nov 19, 2022, 9:16:21 PM11/19/22
to
AFAICS optional parameter is 'smoke and mirrors' in any language. It may
be easier to fool users of an abstracted language such exists. Harder to
do in Forth because one is already at base level.

Gerry Jackson

unread,
Nov 21, 2022, 5:32:26 PM11/21/22
to
It can be done with a bit of input stream manipulation and including the
optional parameter(s) in a comment before TWO-FER.

: ?? >r depth >r ')' parse depth r> - r> >in ! ;

: get-opt ( -- pari* n ) \ n (= 0 to i) optional parameter cells
source drop >in @ s" ??" search
if tuck evaluate exit then
2drop 0
;

: two-fer ( [ca u]? -- )
cr ." One for "
get-opt 1 >
if type else ." you" then
." , one for me" cr
;

( ?? Father Christmas) two-fer
\ displays: "One for Father Christmas, one for me"
two-fer
\ displays "One for you, one for me"

0 [if]
Note:
1) the optional parameters must be in a comment ( ?? ... ) just before
TWO-FER (this restriction need not apply to other definitions that know
which parameters are optional)
2) there can be other parameters before the comment
4) there can be executable Forth code on the same line after TWO-FER

Therefore the following display the appropriate message followed by the
preceding parameters
[then]
: others ." Other parameters: " ;

1 2 ( ?? Joe) two-fer others . . cr
3 two-fer others . cr
s" abc" ( ?? Mary) two-fer others type cr
0 two-fer others . cr
s" Fred" two-fer others type cr

--
Gerry

Ruvim

unread,
Nov 23, 2022, 4:25:09 PM11/23/22
to
On 2022-11-18 10:21, Bruce Axtens wrote:
> There's a programming exercise on Exercism called two-fer.
> It takes an optional parameter. If the parameter is absent
> it returns "One for you, one for me." If the parameter is present
> it is interpolated into the string in place of the "you".

The standard means for strings interpolation are the words "replaces"
and "substitute". Although they are not enough convenient and so rarely
used. NB: "replaces" may use data space.


> As I understand it, and i'm no Forth programmer, optional items aren't a thing
> in Forth. Rather, you either program for something or program for nothing.
> Thus, a two-fer word would expect a null-string or maybe even a null.
>
> Am I understanding this right?


Yes.

Positional parameters, except parameters at the tail of a parameters
list, cannot be missed in any programming language — you have to pass
something in every position.

Named parameters can be missed. But for a missed parameter some default
value is available anyway (e.g. "undefined" in JavaScript).

In Forth, a list of parameters is not delimited, so no parameters can be
missed.

Though, you can pass a counter (or a map of parameters) as the top
parameter, and then the number of parameters can vary.

For example:

: two-fer ( sd1 1 | 0 -- sd2 )
0= if s" you" then s" another-side" replaces
s" One for %another-side%, one for me." pad 84 substitute
0< if 2drop 0. then
;

0 two-fer cr type
s" World" 1 two-fer cr type


Another solution is to pass some default value, which means that the
actual value is missed for the parameter. E.g. the pair ( 0 0 ) for a
missed string.

: two-fer ( sd1 | 0 0 -- sd2 )
over 0= if 2drop s" you" then s" another-side" replaces
s" One for %another-side%, one for me." pad 84 substitute
0< if 2drop 0. then
;

0 0 two-fer cr type
s" World" two-fer cr type



--
Ruvim

Lorem Ipsum

unread,
Nov 23, 2022, 5:16:16 PM11/23/22
to
Tell me if I am understanding this right. The typical program that this is being programmed in, is being invoked from a command line with or without arguments. In this case, there is something like argc/argv that provides the command line input along with info as to how many arguments there are. So that would be easy.

In a Forth program, there is an assumed operating environment that would need to be configured to provide the same argc/argv functionality, so the authored program would get this info from the Forth system, or a stand alone Forth program would have this functionality in the Forth system runtime code.

I've not worked with Forths other than Win32Forth much, but I believe it will support that.

If your Forth were running on a system without a separate OS, such as KimForth or FigForth on an embedded MCU board, there would be no way to add such an argc/argv command line option. The input option would need to be a parameter on the stack. To detect such a parameter would require the use of the system word DEPTH. However, as others have mentioned, if your twofer word was run from within another program with other data on the stack, the test could fail.

So if the other programs are using an argc/argv parameter passing method, it would be reasonable to use something similar with Forth.

: two-fer ( argv argc -- ) ... ;

Even if this is running on an embedded processor with no OS, argv and argc can be manually set prior to running the word two-fer.

--

Rick C.

- Get 1,000 miles of free Supercharging
- Tesla referral code - https://ts.la/richard11209

Lorem Ipsum

unread,
Nov 23, 2022, 5:21:20 PM11/23/22
to
I just realized that the "Forth" way of doing this would be similar to how values are implemented using "to". Rather than setting parameters on the stack, they would be on the command line after the word two-fer. Two-fer would then read the remainder of the input string and be able to tell if it was empty or not.

Did someone mention this idea already? I kinda skimmed a few posts.

--

Rick C.

+ Get 1,000 miles of free Supercharging
+ Tesla referral code - https://ts.la/richard11209

dxforth

unread,
Nov 23, 2022, 9:08:23 PM11/23/22
to
Anton gave such an example, and sure, it has all the appearance of an optional parameter;
but ultimately one is testing a string and that's not optional. I had a look at several
C solutions on the website and AFAICT they just test a string too. IMO the 'two-fer'
exercise was poorly worded.

minf...@arcor.de

unread,
Nov 24, 2022, 3:10:55 AM11/24/22
to
C does not have method or type polymorphism, even if one looks very long time.
The only multi-parameter words in Forth are N>R and SET-ORDER.

OTOH for amusement there are a number of words with multi-results like
?DUP or SEARCH-WORDLIST which cannot be processed by single words.

Ruvim

unread,
Nov 24, 2022, 3:48:44 AM11/24/22
to
On 2022-11-24 08:10, minf...@arcor.de wrote:
> dxforth schrieb am Donnerstag, 24. November 2022 um 03:08:23 UTC+1:
[...]
>
> C does not have method or type polymorphism, even if one looks very long time.
> The only multi-parameter words in Forth are N>R and SET-ORDER.

Also EXECUTE, CATCH, EVALUATE, INCLUDED

>
> OTOH for amusement there are a number of words with multi-results like
> ?DUP or SEARCH-WORDLIST which cannot be processed by single words.

Also GET-ORDER, "ENVIRONMENT?"

Sure, the results of such a word can be processed by a single
user-defined word.


--
Ruvim

dxforth

unread,
Nov 24, 2022, 4:46:56 AM11/24/22
to
On 24/11/2022 7:10 pm, minf...@arcor.de wrote:
>
> C does not have method or type polymorphism, even if one looks very long time.
> The only multi-parameter words in Forth are N>R and SET-ORDER.

Actually the latter are one-parameter words - the parameter being the count.
The rest is data. Since those functions know where to find the data, a
second parameter is not required.

0 new messages