Path: csiph.com!x330-a1.tempe.blueboxinc.net!newsfeed.hal-mli.net!feeder1.hal-mli.net!weretis.net!feeder4.news.weretis.net!eternal-september.org!feeder.eternal-september.org!.POSTED!not-for-mail From: Julian Fondren Newsgroups: comp.lang.forth Subject: Re: multi-threading in Forth? Date: Fri, 05 Aug 2011 19:02:15 -0500 Organization: A noiseless patient Spider Lines: 104 Message-ID: <8662mb5rw8.fsf@gmail.com> References: <07679799958436@frunobulax.edu> <4e3aa6ce.690183008@192.168.0.50> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: mx04.eternal-september.org; posting-host="cO8zBIpB9LiP7q+vFZIJrA"; logging-data="3037"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/N5XUyEJID61wkboQRBCqrg8iiUKz7diU=" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (windows-nt) Cancel-Lock: sha1:iU+6GX9S376pfIyVcu5xGgSe7o4= sha1:yIkF8VeEImvzw25TnDQQ8p62vWQ= Xref: x330-a1.tempe.blueboxinc.net comp.lang.forth:4609 Andrew Haley writes: > I think so. There is the matter of whether, say, return stack > manipulation is more useful than tail call optimization. I'd choose > tail call optimization every time, but IME code that (ab)uses the > return stack for control flow is hard to understand and maintain. > Whatever the problem, there's almost always a better way to do it than > fiddling with the R-stack. Can you elaborate on your IME? I'm not being flippant; I'm privately becoming more and more confident that fiddling with the return stack is a huge readability and therefore maintainability win, so I'd appreciate a course correction. I recall that you prefer immediate words for a good subset of what return-stack words can do. E.g., : with-base ( u -- ) r> BASE @ >r swap BASE ! ['] call catch r> BASE ! throw ; : base[ ( u -- ) postpone BASE postpone @ postpone >r postpone BASE postpone ! ; immediate : ]base ( -- ) postpone r> postpone BASE postpone ! ; immediate : x1 ( ... "to end of line" -- ... ) 16 with-base 0 parse evaluate ; : x2 ( ... "to end of line" -- ... ) 16 base[ 0 parse evaluate ]base ; Return-stack access must be balanced after WITH-BASE and between BASE[ ]BASE ; only WITH-BASE will reset the BASE if there's an exception (maybe not desirable, but when it isn't WITH-BASE can be easily defined to not do this). In the presence of tail-call optimization, WITH-BASE _can_ be used to do perverse things that only sometimes work : in-hex 16 with-base ; : x3 ( c-addr u -- ) in-hex evaluate ; \ only works if WITH-BASE was JMP'd to. , but I oppose that. You can take any feature too far. You can have a Forth word that accepts twenty arguments on the data stack. But, these are so similar; how is only one of them hard to understand and maintain? Another class of return-stack words are words that validate some input: : -too-small ( c-addr u -- c-addr u | *returns from caller ) dup 2 > ?exit 2drop r>drop ; : -not-forth ( c-addr u -- c-addr u | *returns from caller ) 2dup 2 - + 2 s" .f" compare(nc) 0= ?exit 2drop r>drop ; : .forth-file ( dirent-addr -- ) USING dirent filename zcount -too-small -not-forth type space ; "If it's not too small, and if it's not not forth, TYPE SPACE it." Maybe S" .f" HAS-EXT; would be a better name, with the semicolon to suggest the potential exit. With immediate wordS: : -too-small ( c-addr u -- c-addr u | *exit ) postpone dup 2 postpone literal postpone <= postpone if postpone 2drop postpone exit postpone then ; immediate And so on. It's used in exactly the same way, it has exactly the same issue of "to test this, I need to use it within a temporary definition", and it could be neater with a macro to replace the POSTPONEs. So these are _exactly the same_. How is the only of them hard to understand and maintain? I could have also "not done that" - have written : .forth-file ( dirent-addr -- ) USING dirent filename zcount dup 2 <= if 2drop exit then 2dup 2 - + 2 s" .f" compare(nc) if 2drop exit then type space ; Or: : .forth-file ( dirent-addr -- ) USING dirent filename zcount ( c-addr u ) dup 2 > if 2dup 2 - + 2 s" .f" compare(nc) 0= if type space exit then then 2drop ; Or: : .forth-file ( dirent-addr -- ) USING dirent filename zcount 2dup long-enough? if 2dup is-forth? if type space exit then then 2drop ; The last is nice and conventional, but is the return-stack version really any harder to read? Which classes of return-stack-fiddling word do you object to?