Pocket Forth/QForth question
Author |
Message |
Eric Schiss #1 / 14
|
Pocket Forth/QForth question
Really stupid question I know, but I have two versions of Forth on one of my Macintosh disks. One is a recent version of Pocket Forth. Another is QForth. Neither Pick nor Roll, both of which are 79-Standard according to my ancient copy of a probably quite obsolete book called "The Complete Forth" ('83; I can't afford the latest, generally speaking), seems to be implemented. Aren't these commands so basic that they should be implemented even in a "pocket" version of Forth? Or has Forth (which I should be writing FORTH, but I want it to be quite clear what a novice I am :( ) changed so much since '83 that these commands have been completely replaced by others? (Option 3- there are even more basic commands in terms of which I can simply define pick and roll myself.) Thanks for any help-Eric Schissel
|
Sun, 24 Oct 1999 03:00:00 GMT |
|
|
Hans Bezem #2 / 14
|
Pocket Forth/QForth question
Quote:
>Really stupid question I know, but I have two versions of Forth on one of >my Macintosh disks. One is a recent version of Pocket Forth. Another is >QForth. Neither Pick nor Roll, both of which are 79-Standard according to >my ancient copy of a probably quite obsolete book called "The Complete >Forth" ('83; I can't afford the latest, generally speaking), seems to be >implemented. >Aren't these commands so basic that they should be implemented even in a >"pocket" version of Forth? Or has Forth (which I should be writing FORTH, >but I want it to be quite clear what a novice I am :( ) changed so much >since '83 that these commands have been completely replaced by others?
PICK an ROLL are just bad style. They allow you to treat the stack like an array which it isn't. If you need to grab values on the stack that deep there is something wrong with your application in the first place. I didn't build them into my forth either, although I could have easily. I'll probably be flamed for this, but that the heck, Leo Brodie thinks the same way too ;) <sigh> Hans
|
Tue, 26 Oct 1999 03:00:00 GMT |
|
|
benh.. #3 / 14
|
Pocket Forth/QForth question
[ .. about PICK and ROLL .. ] >>Aren't these commands so basic that they should be implemented >PICK an ROLL are just bad style. >They allow you to treat the stack like an array which it isn't. If >you need to grab values on the stack that deep there is something >wrong with your application in the first place. Agreed. It's not *usually* Forthy. Anyway, I only put 'em in my Forth to be standard. But I only use PICK in one place, ROLL never, that is in .s : .s ( n -- ) \ prints top (10) stack values depth 10 min dup 0 ?do dup i - pick . loop drop ; So it *may* be a good thing to put at least PICK in a Forth if for no other reason than .s ... :) Oh BTW, will check out your new version of M4th..
.. That tagline is TRUE -> <- That tagline is FALSE
|
Tue, 26 Oct 1999 03:00:00 GMT |
|
|
Jonah Thom #4 / 14
|
Pocket Forth/QForth question
Quote:
>[ .. about PICK and ROLL .. ] > >>Aren't these commands so basic that they should be implemented > >PICK an ROLL are just bad style. > >They allow you to treat the stack like an array which it isn't. If > >you need to grab values on the stack that deep there is something > >wrong with your application in the first place. >Agreed. It's not *usually* Forthy. Anyway, I only put 'em in my Forth >to be standard. But I only use PICK in one place, ROLL never, that is >in .s >: .s ( n -- ) \ prints top (10) stack values > depth 10 min > dup 0 ?do > dup i - pick . > loop > drop ;
If that's the only place you use it, you might handle it another way. For example: : .S ( -- ) DEPTH DUP BEGIN ?DUP WHILE ROT >R 1- REPEAT BEGIN ?DUP WHILE R> DUP U. SWAP 1- REPEAT ; This is more complicated, but it does avoid PICK . Or you could allot space. : .S ( -- ) DEPTH DUP 0 ?DO DROP , I LOOP 1+ 0 ?DO
I haven't tested either of these, I rewrote them from memory and may have gotten something wrong. The 2nd one does a formally bad thing, it unallots the space first and then reads it. This shouldn't be a
a multitasking system other tasks won't do things to this task's HERE . But it would be allowable for someone to make a compiler where this fails, even though I've never heard of one like that. The idea is to move the data onto a 2nd stack, perhaps a virtual one, and then when you take it off the other stack it will be in the right order. If you want to make a portable implementation of PICK you'll need to do something like that anyway because none of the neat efficient tricks you'd like to use are portable. But then if you only use it for .S you don't need it to be efficient since the time you spend printing it to the screen (and the time it takes you to look at the result) will far outweigh any inefficiency in moving data around in memory.
|
Wed, 27 Oct 1999 03:00:00 GMT |
|
|
benh.. #5 / 14
|
Pocket Forth/QForth question
[ .. about PICK and ROLL .. ] >If that's the only place you use it, you might handle it another >way. For example: >: .S ( -- ) > DEPTH DUP BEGIN ?DUP WHILE ROT >R 1- REPEAT > BEGIN ?DUP WHILE R> DUP U. SWAP 1- REPEAT ; >This is more complicated, but it does avoid PICK . Or you could >allot space. Ok, that's a *reasonable* way to do it, but it's a lot cleaner to use PICK in that case. So there are two reasons I have PICK, a) because I wanted to have all the ANS Core and Core Extension words and b) because it tidies up definitions (the one or two you might have) like .S >: .S ( -- ) > DEPTH DUP 0 ?DO DROP , I LOOP 1+ 0 ?DO
>task's HERE . But it would be allowable for someone to make a >compiler where this fails, even though I've never heard of one like Actually I believe that kind of thing is ANS standard because ALLOT is *supposed* to unALLOT if n is negative. But it's very ugly & slow :) >the right order. If you want to make a portable implementation of >PICK you'll need to do something like that anyway because none of >the neat efficient tricks you'd like to use are portable. Really? I guess it depends what one might mean by portable, for example
But if you're talking about 100% ANS portability no, you can't.
|
Wed, 27 Oct 1999 03:00:00 GMT |
|
|
Jonah Thom #6 / 14
|
Pocket Forth/QForth question
Quote:
>[ .. about PICK and ROLL .. ] > >: .S ( -- ) > > DEPTH DUP 0 ?DO DROP , I LOOP 1+ 0 ?DO
> >task's HERE . But it would be allowable for someone to make a > >compiler where this fails, even though I've never heard of one >Actually I believe that kind of thing is ANS standard because ALLOT >is *supposed* to unALLOT if n is negative.
Yes, that isn't the problem. The problem is that I'm reading the data _after_ it's been uallotted. If I did something that used WORD or that printed a number or something like that, some systems would do it at HERE and would trash my data. I don't know of any systems that would trash it before I fetch it, but there _could_ be standard systems that did. Quote: >But it's very ugly & slow :)
I want to argue that "slow" is completely irrelevant here. If you want everything to be as fast as possible regardless of need, you should probably be programming in C where you can optimise to your heart's content. Or assembler, even better. I agree with you about the ugly part. 8-) Quote: > >the right order. If you want to make a portable implementation of > >PICK you'll need to do something like that anyway because none of > >the neat efficient tricks you'd like to use are portable. >Really? I guess it depends what one might mean by portable, for
>efficient. But if you're talking about 100% ANS portability no, you >can't.
Practically, in the short run, you're right. There are some forth
some important ones coming down the road, but they aren't that important yet. There's the question whether you want your _compiler_ to be portable or your _code_. Your compiler will have to know all the details about how to use the data stack, and you might as well use them. If you want to port the compiler to hardware that doesn't meet its assumptions then you've got some rewriting to do, but if you try to make it so it's easy to port to every possible piece of hardware then it probably won't be very good on any of them. You can probably go a long way toward portability, but at some point it stops being worth it. If you want to have portable _code_ that you can load on systems that don't already have the particular command, then it might as well be maximally portable. Get it right once and you can use it without ever thinking about it again. If it's too slow on some particular system then you can rewrite it for that system. But it's more important for the portable version to run correctly everywhere than for it to be fast on some systems -- you're providing it in case it isn't already there, and if it isn't already there and your version doesn't work then there's a problem. In that context I prefer my first ugly version to the second one. It requires that the return stack have enough room to hold the entire data stack, but it doesn't use data that's been unallotted and it doesn't trash previous data at HERE unless U. does. It is ugly but once it works correctly you don't have to look at it again.
|
Wed, 27 Oct 1999 03:00:00 GMT |
|
|
Eric Schiss #7 / 14
|
Pocket Forth/QForth question
Well, here's the particular application I'm trying to write, I can probably learn from suggestions as to how to write it better. It's supposed to take in n at the top of the stack and release m at the top of the stack, where m is the sum of all numbers that divide n evenly. Due to the absence of ROLL I have been unable to test this, and it is my first Forth definition. : SIGMA (x) 0 (x 0) SWAP (0 x) DUP (0 x x) 1 DO (sigma x) (0 becomes sigma, the eventual answer) DUP (sigma x x) I (sigma x x n) (n, the counter for the do loop) DUP (sigma x x n n) 3 ROLL (sigma x n n x) SWAP (sigma x n x n) MOD (sigma x n (x mod n)) 0 = (sigma x n (x mod n=0)) * (sigma x (n if n|x, 0 otherwise)) 3 ROLL (x (n if n|x, 0 otherwise) sigma) + (x new-sigma) SWAP (new-sigma x) Now, we're in the same situation as at the beginning of the DO loop, and can LOOP DROP (new-sigma at end); Now it occurs to me that 3 ROLL is .almost. the same as ROT, so I probably can replace it with ROT and one or two other words. (If I remember, ROT sends (x y z) to (z y x); since I want (y z x), then SWAP sends (z y x) to (z x y), ROT sends this to (y x z), and SWAP sends this to (y z x), which should do. But my other definition, the one I worked on first, THETA, uses 5 ROLL and needs it. Its BASIC "equivalent" is a triple-nested-loop. It takes x and produces theta(x), the number of numbers between 1 and x(inclusive) relatively prime to x.) Ok... I have now wasted your time utterly, since I can do 3 ROLL with what I already have. (Though I'm a little annoyed by the tone of the post that says there's something wrong with my application! :) ) I still need 5 ROLL, and welcome suggestions... -Eric Schissel, with thanks for help
|
Wed, 27 Oct 1999 03:00:00 GMT |
|
|
Mike Coughl #8 / 14
|
Pocket Forth/QForth question
Quote:
>Really stupid question I know, but I have two versions of Forth on one of >my Macintosh disks. One is a recent version of Pocket Forth. Another is >QForth. Neither Pick nor Roll, both of which are 79-Standard according to >my ancient copy of a probably quite obsolete book called "The Complete >Forth" ('83; I can't afford the latest, generally speaking), seems to be >implemented.
In order for the old books on Forth to become obsolete somebody will have to write new books on Forth. Until this happens, keep using the old books and just worry if they explain things clearly or not. Then ask questions on comp.lang.forth. Quote: >Aren't these commands so basic that they should be implemented even in a >"pocket" version of Forth?
NO! Quote: >Or has Forth (which I should be writing FORTH, >but I want it to be quite clear what a novice I am :( ) changed so much >since '83 that these commands have been completely replaced by others?
You are confused by the term "standard". Forth standards are not what you think. Forth programmers use the word standard with many different conflicting meanings. No Forth word has ever been replaced by a new standard. Every Forth system sets its own standard. Forth has never been a finished project. You don't have a programming language, you have a set of tools to write your own programming language. People who implement Forth systems and programs are very independent and opinionated. There are certain words that should never be used in any Forth system, and nobody agrees on what these are. It may be that pick and roll were left out since the authors of the systems you are using considered them to only lead to the writing of bad code; or they may have just not gotten around to including them. There are versions of Forth that seek to write all possible computer programs with the least number of different words and there are others that want to include every interesting word from every known computer language. They are all Forth and they can all be claimed to follow a standard, or several standards. Quote: >(Option 3- there are even more basic commands in terms of which I can >simply define pick and roll myself.)
If you think pick and roll are good words, you can add them yourself. A big problem with these words is that they give different results on different systems since there is no agreement to start counting at 1 or 0. --
|
Wed, 27 Oct 1999 03:00:00 GMT |
|
|
W.Bad #9 / 14
|
Pocket Forth/QForth question
: Well, here's the particular application I'm trying to write, I can : probably learn from suggestions as to how to write it better. It's : supposed to take in n at the top of the stack and release m at the top of : the stack, where m is the sum of all numbers that divide n evenly. ( This looks like another job for UNDER+ ) : UNDER+ ROT + SWAP ; ( a b c -- a+c b ) : sigma ( n -- <Sum of all divisors of n> ) 0 SWAP ( sum n) DUP 2/ 1+ 1 ?DO DUP I MOD 0= IF I UNDER+ THEN LOOP DROP ( sum) ; ( `I UNDER+' can be replaced by `SWAP I + SWAP' ) ( Note the consistency of the stack. I have ( put stack-status on every line where it changes. ) ( If PocketForth doesn't have ?DO then special case 0. ) ( A number that is equal to the sum of its divisors it called ( a _perfect_ number. The first two are 6 and 28; use sigma ( to find the next one. ) ( -- Procedamus in pace. Wil Baden Costa Mesa, California )
|
Thu, 28 Oct 1999 03:00:00 GMT |
|
|
benh.. #10 / 14
|
Pocket Forth/QForth question
> remember, ROT sends (x y z) to (z y x); since I want (y z x), then ROT rotates the third stack item, x, in ( x y z -- ) to the top and pushes the other two, y z, down. Like ( x y z -- ) to ( y z x -- ). So ROT is what you originally intended. > (Though I'm a little annoyed by the tone of the post that says > there's something wrong with my application!) I still need 5 ROLL.. Ok. Well I would assume you're *relatively* new to Forth. Anyway, purchase a book for $20 (plus $5 or something P&P) called "Thinking Forth" by Leo Brodie. Excellent book, it'll show ya how to factor things and make things really Forthy so no need for messy/slow 5 ROLLs everywhere :) No offense but there is probably something wrong with your app in this case as wrongness goes with Forth.. :) "Thinking Forth" is a great book, and depending on how well you know the basics of Forth you'll wanna get "Starting Forth" by the same author too. Awesome books, get them from FIG - Forth Interest Group.
|
Fri, 29 Oct 1999 03:00:00 GMT |
|
|
benh.. #11 / 14
|
Pocket Forth/QForth question
>Yes, that isn't the problem. The problem is that I'm reading the >data _after_ it's been uallotted. If I did something that used Oh sorry, hadn't looked at your definition closely enuff. :-( :-) >I want to argue that "slow" is completely irrelevant here. If you >want everything to be as fast as possible regardless of need, you >should probably be programming in C where you can optimise to your >heart's content. Or assembler, even better. I agree with you >about the ugly part. 8-) Agreed that slow is completely irrelavent here. .S can probably take up to 1/4 of a second without anyone noticing.. :) Anyway, what I meant was that if you defined PICK like that it would be pretty bad for people who use PICK like nothing else. (ugh! :) But I suppose a slow PICK is good because it forces people to get rid of the habit. <grin> Anyway, about that C thing, I've said byebye to C already.. 8-) "Thinking Forth" and general learning since has made me see that Forth is *much* more than a language... And assembler, well only for speed crit stuff like blatting text to the screen and whatnot. (BTW, just as an aside, my For32's PICK is as fast as DUP which is not good because it almost encourages PICK.. Oh well :) >There's the question whether you want your _compiler_ to be >portable or your _code_. Your compiler will have to know all the >details about how to use the data stack, and you might as well use >them. Yes that's what I think. I would much rather have a fast compiler and fast running yet portable code than a slow but VERY portable *compiler*. On that topic, with Leo Wong's LF editor, the video output is as fast on my system as a "real" text editor. So portable progs can be fast if the running Forth's implementation is fast. Yet the text entry is slow on files bigger than about 40k on my 386 because of the simple (hence slow in this case) techniques he's using. But the video.. even I didn't expect my Forth to be so fast! <grin> >particular system then you can rewrite it for that system. But >it's more important for the portable version to run correctly >everywhere than for it to be fast on some systems -- you're Agreed but I would probably do [IF] statement or selectively loaded files some that we're portable and and others that worked fast with say, a specified system, say For32. This way it is fast for For32 but *works* on any standard system.
|
Fri, 29 Oct 1999 03:00:00 GMT |
|
|
Be #12 / 14
|
Pocket Forth/QForth question
Quote: > > (Though I'm a little annoyed by the tone of the post that says > > there's something wrong with my application!) I still need 5 ROLL..
If you *NEED* PICK or ROLL the following are from eForth. : PICK ( n -- n ) ?DUP IF SWAP >R 1 - RECURSE R> SWAP EXIT THEN DUP ; : ROLL ( n ... +n -- ... n ) ( never never ROLL ) ?DUP IF SWAP >R 1 - RECURSE R> SWAP THEN ; : -ROLL ( ... n +n -- n ... ) ( never never never -ROLL ) ?DUP IF ROT >R 1 - RECURSE R> THEN ; : .S ( i*n -- i*n ) ?STACK DEPTH BEGIN ?DUP WHILE DUP PICK . 1 - REPEAT ; Bill Muench Bill Muench OntoLogic
Santa Cruz CA 95065
|
Fri, 29 Oct 1999 03:00:00 GMT |
|
|
W.Bad #13 / 14
|
Pocket Forth/QForth question
: If you *NEED* PICK or ROLL the following are from eForth. [CHOP] ( What a wonderful example of recursion. ) : PICK ?DUP 0= IF DUP EXIT THEN SWAP >R 1- RECURSE R> SWAP ; : digit>char DUP 9 > 7 AND + 48 + ;
: .S DEPTH BEGIN ?DUP WHILE DUP PICK .# 1- REPEAT ; ( Stack comments and phrasing left as a headache to the reader. ) ( .# bypasses <# ... #> ) ( -- Procedamus in pace. Wil Baden Costa Mesa, California Oops -- I forgot something. : ?? POSTPONE IF BL WORD COUNT EVALUATE POSTPONE THEN ; IMMEDIATE )
|
Fri, 29 Oct 1999 03:00:00 GMT |
|
|
Mary Murphy and Leo Won #14 / 14
|
Pocket Forth/QForth question
Quote:
> On that topic, with Leo Wong's LF editor, the video output is as fast > on my system as a "real" text editor. So portable progs can be fast > if the running Forth's implementation is fast. Yet the text entry is > slow on files bigger than about 40k on my 386 because of the simple > (hence slow in this case) techniques he's using.
Oh, dear, I was knew that LF was slow, but 40k on a 386? That is bad. Leo Wong --
http://www.albany.net/~hello/
|
Sat, 30 Oct 1999 03:00:00 GMT |
|
|
|