Is there an easier way of doing this? End goal is a double number representing centi-secs.
Is there an easier way of doing this? End goal is a double number >representing centi-secs.
empty decimal
: SPLIT ( a u c -- a2 u2 a3 u3 ) >r 2dup r> scan 2swap 2 pick - ;
: >INT ( adr len -- u ) 0 0 2swap >number 2drop drop ;
: /T ( a u -- $hour $min $sec )
2 0 do [char] : split 2swap dup if 1 /string then loop
2 0 do dup 0= if 2rot 2rot then loop ;
: .T 2swap 2rot cr >int . ." hr " >int . ." min " >int . ." sec " ;
s" 1:2:3" /t .t
s" 02:03" /t .t
s" 03" /t .t
s" 23:59:59" /t .t
s" 0:00:03" /t .t
The HH:MM:SS format is easy but how to deal with the variants shown above? They occur in the real world.
Is there an easier way of doing this? End goal is a double number >representing centi-secs.
empty decimal
: SPLIT ( a u c -- a2 u2 a3 u3 ) >r 2dup r> scan 2swap 2 pick - ;
: >INT ( adr len -- u ) 0 0 2swap >number 2drop drop ;
: /T ( a u -- $hour $min $sec )
2 0 do [char] : split 2swap dup if 1 /string then loop
2 0 do dup 0= if 2rot 2rot then loop ;
: .T 2swap 2rot cr >int . ." hr " >int . ." min " >int . ." sec " ;
s" 1:2:3" /t .t
s" 02:03" /t .t
s" 03" /t .t
s" 23:59:59" /t .t
s" 0:00:03" /t .t
I know you don't care about this case, but:
Is there an easier way of doing this? End goal is a double number representing centi-secs.
empty decimal
: SPLIT ( a u c -- a2 u2 a3 u3 ) >r 2dup r> scan 2swap 2 pick - ;
: >INT ( adr len -- u ) 0 0 2swap >number 2drop drop ;
: /T ( a u -- $hour $min $sec )
2 0 do [char] : split 2swap dup if 1 /string then loop
2 0 do dup 0= if 2rot 2rot then loop ;
: .T 2swap 2rot cr >int . ." hr " >int . ." min " >int . ." sec " ;
s" 1:2:3" /t .t
s" 02:03" /t .t
s" 03" /t .t
s" 23:59:59" /t .t
s" 0:00:03" /t .t
On Sun, 6 Oct 2024 7:51:31 +0000, dxf wrote:
Is there an easier way of doing this? End goal is a double number representing centi-secs.
empty decimal
: SPLIT ( a u c -- a2 u2 a3 u3 ) >r 2dup r> scan 2swap 2 pick - ;
: >INT ( adr len -- u ) 0 0 2swap >number 2drop drop ;
: /T ( a u -- $hour $min $sec )
2 0 do [char] : split 2swap dup if 1 /string then loop
2 0 do dup 0= if 2rot 2rot then loop ;
: .T 2swap 2rot cr >int . ." hr " >int . ." min " >int . ." sec " ;
s" 1:2:3" /t .t
s" 02:03" /t .t
s" 03" /t .t
s" 23:59:59" /t .t
s" 0:00:03" /t .t
Why don't you use the fact that >NUMBER returns the given
string starting with the first unconverted character?
SPLIT should be redundant.
-marcel
mhx wrote:
On Sun, 6 Oct 2024 7:51:31 +0000, dxf wrote:
Is there an easier way of doing this? End goal is a double number representing centi-secs.
empty decimal
: SPLIT ( a u c -- a2 u2 a3 u3 ) >r 2dup r> scan 2swap 2 pick - ;
: >INT ( adr len -- u ) 0 0 2swap >number 2drop drop ;
: /T ( a u -- $hour $min $sec )
2 0 do [char] : split 2swap dup if 1 /string then loop
2 0 do dup 0= if 2rot 2rot then loop ;
: .T 2swap 2rot cr >int . ." hr " >int . ." min " >int . ." sec " ;
s" 1:2:3" /t .t
s" 02:03" /t .t
s" 03" /t .t
s" 23:59:59" /t .t
s" 0:00:03" /t .t
Why don't you use the fact that >NUMBER returns the given
string starting with the first unconverted character?
SPLIT should be redundant.
-marcel
: CHAR-NUMERIC? 48 58 WITHIN ;
: SKIP-NON-NUMERIC ( adr u -- adr2 u2)
BEGIN
DUP IF OVER C@ CHAR-NUMERIC? NOT ELSE 0 THEN
WHILE
1 /STRING
REPEAT ;
: SCAN-NEXT-NUMBER ( n adr len -- n2 adr2 len2)
2>R 60 * 0. 2R> >NUMBER
2>R D>S + 2R> ;
: PARSE-TIME ( adr len -- seconds)
0 -ROT
BEGIN
SKIP-NON-NUMERIC
DUP
WHILE
SCAN-NEXT-NUMBER
REPEAT
2DROP ;
S" hello 1::36 world" PARSE-TIME CR .
96 ok
mhx wrote:
On Sun, 6 Oct 2024 7:51:31 +0000, dxf wrote:
Is there an easier way of doing this? End goal is a double number representing centi-secs.
empty decimal
: SPLIT ( a u c -- a2 u2 a3 u3 ) >r 2dup r> scan 2swap 2 pick - ;
: >INT ( adr len -- u ) 0 0 2swap >number 2drop drop ;
: /T ( a u -- $hour $min $sec )
2 0 do [char] : split 2swap dup if 1 /string then loop
2 0 do dup 0= if 2rot 2rot then loop ;
: .T 2swap 2rot cr >int . ." hr " >int . ." min " >int . ." sec " ;
s" 1:2:3" /t .t
s" 02:03" /t .t
s" 03" /t .t
s" 23:59:59" /t .t
s" 0:00:03" /t .t
Why don't you use the fact that >NUMBER returns the given
string starting with the first unconverted character?
SPLIT should be redundant.
-marcel
: CHAR-NUMERIC? 48 58 WITHIN ;
: SKIP-NON-NUMERIC ( adr u -- adr2 u2)
BEGIN
DUP IF OVER C@ CHAR-NUMERIC? NOT ELSE 0 THEN
WHILE
1 /STRING
REPEAT ;
: SCAN-NEXT-NUMBER ( n adr len -- n2 adr2 len2)
2>R 60 * 0. 2R> >NUMBER
2>R D>S + 2R> ;
: PARSE-TIME ( adr len -- seconds)
0 -ROT
BEGIN
SKIP-NON-NUMERIC
DUP
WHILE
SCAN-NEXT-NUMBER
REPEAT
2DROP ;
S" hello 1::36 world" PARSE-TIME CR .
96 ok
Third, any statement must come with proof. And in this case that means extended benchmarking. I can tell you beforehand that I've never seen significant differences between locals and stack. I'm sorry to say that
- but it's true.
Once full native code compilation and optimisation is turned on, you
can get surprising results. At one stage we (MPE) de-localled a
substantial portion of the PowerNet TCP/IP stack - all in high-level
Forth. For the modified code, size decreased by 25% and performance
increased by 50%.
B. Pym wrote:
mhx wrote:
On Sun, 6 Oct 2024 7:51:31 +0000, dxf wrote:
Is there an easier way of doing this? End goal is a double number representing centi-secs.
empty decimal
: SPLIT ( a u c -- a2 u2 a3 u3 ) >r 2dup r> scan 2swap 2 pick - ;
: >INT ( adr len -- u ) 0 0 2swap >number 2drop drop ;
: /T ( a u -- $hour $min $sec )
2 0 do [char] : split 2swap dup if 1 /string then loop
2 0 do dup 0= if 2rot 2rot then loop ;
: .T 2swap 2rot cr >int . ." hr " >int . ." min " >int . ." sec " ;
s" 1:2:3" /t .t
s" 02:03" /t .t
s" 03" /t .t
s" 23:59:59" /t .t
s" 0:00:03" /t .t
Why don't you use the fact that >NUMBER returns the given
string starting with the first unconverted character?
SPLIT should be redundant.
-marcel
: CHAR-NUMERIC? 48 58 WITHIN ;
: SKIP-NON-NUMERIC ( adr u -- adr2 u2)
BEGIN
DUP IF OVER C@ CHAR-NUMERIC? NOT ELSE 0 THEN
WHILE
1 /STRING
REPEAT ;
: SCAN-NEXT-NUMBER ( n adr len -- n2 adr2 len2)
2>R 60 * 0. 2R> >NUMBER
2>R D>S + 2R> ;
: PARSE-TIME ( adr len -- seconds)
0 -ROT
BEGIN
SKIP-NON-NUMERIC
DUP
WHILE
SCAN-NEXT-NUMBER
REPEAT
2DROP ;
S" hello 1::36 world" PARSE-TIME CR .
96 ok
: SCAN-NUMBER-OR-SKIP ( n adr len -- n' adr' len')
DUP >R
0 0 2SWAP >NUMBER
DUP R> =
IF 2SWAP 2DROP 1 /STRING
ELSE
2>R D>S SWAP 60 * + 2R>
THEN ;
: PARSE-TIME ( adr len -- seconds)
0 -ROT
BEGIN
DUP
WHILE
SCAN-NUMBER-OR-SKIP
REPEAT
2DROP ;
S" hi 5 or 1 is 44 ho " PARSE-TIME CR .
18104
On 11-06-2025 03:49, dxf wrote:
On 11/06/2025 3:34 am, LIT wrote:
...
Fourth, if the definition is extremely time-critical, those
tricky stack manipulators, (e.g., ROT ROT) can really eat up
clock cycles. Direct access to variables is faster."
Pushing variables on the stack, executing them, along with their
associated @ and ! eats clock cycles. This is certainly the case
in the systems you use.
Agreed.
Yes, Brodie warns us next "but careful with variables' use
too" - and I still think my use of variables in two examples
I recently pasted wasn't "legit" in any way. It was just
applying the tips you see above.
When is it "legit" to give up? I've written routines I believed
needed VARIABLEs. But after a 'cooling off' period, I can look
at the problem again afresh and find I can do better. Folks will
say in the real world one couldn't afford this. That's true and
likely why I'm a hobbyist and not a professional programmer.
OTOH it's pretty rare that I write routines with variables in them
to begin with.
As a guy who used Forth programming in a professional environment, I can
at least tell you how I did it..
When you're on the spot, you're on the spot - and you got to provide in
the allotted time, even if it means making sub-optimal code. That's just
the way it is, that's corporate life.
If you tell your boss "Brodie told you to", he's gonna shake his head,
ask who Brodie is and then ship you to the corporate shrink for an
emergency session.
But what I did was to either collect stuff in advance ("Hey, that's a
nice comma'd printout word by Ed. Better make it work in 4tH!") - or
make certain libraries beforehand. In that case, all you have to do is
to shove all those elements together and you're done. The tricky stuff
is already in your tool chest..
Take a look at the 4tH library and notice how much of this stuff is of
no interest at all to the occasional user. Well, that was because it
wasn't written for you. It was written to be applied at work, so I can
do miracles and save my reputation. If you wanna win, you gotta cheat ;-)
Hans Bezemer
3. As Mr. Pelc remarked, stack operators are faster.
This is what Mr. Pelc remarked, regarding such style
of programming - yes, many years ago I was guilty of
that too - already 15 years ago:
https://groups.google.com/g/comp.lang.forth/c/m9xy5k5BfkY/m/FFmH9GE5UJAJ
"Although the code is compilable and can be made efficient,
the source code is a maintenance nightmare!"
Maybe he changed his mind since that time - well, since
he's here, you may want to ask him a question.
On 23-06-2025 20:48, LIT wrote:
OK, have another song: Mr. FIFO stating that
"arrays aren't variables" (maybe need a link?).
Where did they taught you that? At that 'college'
of yours, "elite programmer"? :D
Oh honey, you don't understand? That's not a problem, hon. Go to mummy,
she will explain it to you. But daddy doesn't have time for you. He's
talking to the grown ups. Go play with your dolls and be a good girl!
I'm also puzzled why there is always so emphasis on the "speed" issue. I
mean - if you want speed, do your program in C -O3 so to say. It'll blow
any Forth out of the water.
Forth forces an average programmer to adopt a level of organisation
sooner than a locals- based language. I suspect forthers that promote
locals are well aware forth is readable and maintainable but are
pursuing personal agendas of style which requires implying the
opposite.
Fundamentally. I explained the sensation at the end
of "Why Choose Forth". I've been able to tackle things I would never
have been to tackle with a C mindset. ( https://youtu.be/MXKZPGzlx14 )
dxf <dxforth@gmail.com> writes:
Forth forces an average programmer to adopt a level of organisation
sooner than a locals- based language. I suspect forthers that promote
locals are well aware forth is readable and maintainable but are
pursuing personal agendas of style which requires implying the
opposite.
IDK, I've seen some unreadable Forth code that was written by experts. >Whether locals could have helped, I don't know.
Maybe you are mistaken. I have seen unmaintainable code written by
some self-proclaimed experts.
I have not seen unmaintainable code written by real experts.
No really, I'm not kidding. When done properly Forth actually changes
the way you work. Fundamentally. I explained the sensation at the end of
"Why Choose Forth". I've been able to tackle things I would never have
been to tackle with a C mindset. ( https://youtu.be/MXKZPGzlx14 )
Like I always wanted to do a real programming language - no matter how primitive. Now I've done at least a dozen - and that particular trick
seems to get easier by the day.
And IMHO a lot can be traced back to the very simple principles Forth is based upon - like a stack. Or the triad "Execute-Number-Error". Or the dictionary. But also the lessons from ThinkForth.
You'll also find it in my C work. There are a lot more "small functions"
than in your average C program. It works for me like an "inner API". Not
to mention uBasic/4tH - There are plenty of "one-liners" in my
uBasic/4tH programs.
But that train of thought needs to be maintained - and it can only be maintained by submitting to the very philosophy Forth was built upon. I
feel like if I would give in to locals, I'd be back to being an average
C programmer.
I still do C from time to time - but it's not my prime language. For
this reason - and because I'm often just plain faster when using Forth.
It just results in a better program.
I still do C from time to time - but it's not my prime language. For
this reason - and because I'm often just plain faster when using Forth.
It just results in a better program.
The only thing I can say is, "it works for me". And when I sometimes
view the works of others - especially when resorting to a C style - I
feel like it could work for you as well.
Nine times out of ten one doesn't need the amount of locals which are applied. One doesn't need a 16 line word - at least not when you
actually want to maintain the darn thing. One could tackle the problem
much more elegant.
Define 'unreadable'. In general I don't need to understand the nitty
gritty of a routine. But should I and no stack commentary exists, I've
no objections to creating it. It's par for the course in Forth. If it bugged me I wouldn't be doing Forth.
Yet forthers have no problem with this. Take the SwiftForth source code.
At best you'll get a general comment as to what a function does. How do
they maintain it - the same way anyone proficient in C maintains C code.
On 26/06/2025 5:12 pm, Paul Rubin wrote:
dxf <dxforth@gmail.com> writes:
Define 'unreadable'. In general I don't need to understand the nitty
gritty of a routine. But should I and no stack commentary exists, I've
no objections to creating it. It's par for the course in Forth. If it
bugged me I wouldn't be doing Forth.
Unreadable = I look at the code and have no idea what it's doing. The
logic is often obscured by stack manipulation. The values in the stack
are meaningful to the program's operation, but what is the meaning? In
most languages, meaningful values have names, and the names convey the
meaning. In Forth, you can write comments for that purpose. Years
after cmForth was published, someone wrote a set of shadow screens for
it, and that helped a lot.
With no named values and no explanatory comments, the program becomes
opaque.
Yet forthers have no problem with this. Take the SwiftForth source code.
At best you'll get a general comment as to what a function does. How do
they maintain it - the same way anyone proficient in C maintains C code. >Albert is correct. Familiarity is key to readability. That's not to say >code deserving documentation shouldn't have it. OTOH one shouldn't be >expecting documentation (including stack commentary) for what's an everyday >affair in Forth.
But aren't 'locals' actually PICK/ROLL in disguise?Do PICK/ROLL skim all the values off the stack and stuff them in
variables to be later popped on and off the stack like a yo-yo?
The more common complaint is that you use some feature they dislike
(typically locals) when you would otherwise DUP ROT instead.
But aren't 'locals' actually PICK/ROLL in disguise?
What is POST ?
"Pick and Roll are the generic operators which treat the data stack as
an array. If you find you need to use them, you are probably doing it
wrong. Look for ways to refactor your code to be simpler instead."
On 25-06-2025 09:21, Paul Rubin wrote:
Hans Bezemer <the.beez.speaks@gmail.com> writes:
Fundamentally. I explained the sensation at the end
of "Why Choose Forth". I've been able to tackle things I would never
have been to tackle with a C mindset. ( https://youtu.be/MXKZPGzlx14 )
I just watched this video and enjoyed it, but I don't understand how a C
mindset is different. In C you pass stuff as function parameters
instead of on the stack: what's the big deal? And particularly, the
video said nothing about the burning question of locals ;).
It seems to me all the examples mentioned in the video (parsing CSV
files or floating point numerals) are what someone called
micro-problems. Today they much easier with languages like Python, and
back in Forth's heyday there was Lisp, which occupied a mindspace like
Python does now.
I agree that Thinking Forth is a great book.
It's hard to illustrate things with a multi-KLOC program IMHO. You can
only illustrate principles by using examples that are "contained" in a way.
But I'll try to illustrate a thing or two. Let's say you want to tackle
a problem. And it doesn't go your way. You have to add this thing and
that thing - and hold on to that value. You know what I mean.
about to add. Take a look at getopt() - I think that's a good example.
You can almost see how it grew almost organically by the authors hand.
He never seemed to think "Hmm, maybe I'll make a separate function of it".
The stack ops THEMSELVES may be, in a way, "canonical" — but not
solving "each and every" programming task using them
"no-matter-what", IMHO.
But such would indicate a deficiency in Forth. Do C programmers reach a point at which they can't go forward?
On 24-06-2025 18:23, Anton Ertl wrote:
Hans Bezemer <the.beez.speaks@gmail.com> writes:
I'm also puzzled why there is always so emphasis on the "speed" issue. I >>> mean - if you want speed, do your program in C -O3 so to say. It'll blow >>> any Forth out of the water.
Still, in general - GCC beats Forth. Although I have to admit I've got a renewed respect for VFX Forth! Kudos!
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 502 |
Nodes: | 16 (2 / 14) |
Uptime: | 216:40:52 |
Calls: | 9,878 |
Calls today: | 6 |
Files: | 13,791 |
Messages: | 6,205,686 |