+TheBF Posted July 14, 2022 Author Share Posted July 14, 2022 I have been trying to learn about higher-order-functions and programming without using loops. I took look at REDUCE() in Python and took a run at emulating that. Python's reduce(): From Functional to Pythonic Style – Real Python >>> def my_add(a, b): ... result = a + b ... print(f"{a} + {b} = {result}") ... return result >>> from functools import reduce >>> numbers = [0, 1, 2, 3, 4] >>> reduce(my_add, numbers) 0 + 1 = 1 1 + 2 = 3 3 + 3 = 6 6 + 4 = 10 10 It's kind of neat to see this kind of high level stuff in lowly Forth. Here we add REDUCE albeit for integer data only. Spoiler \ REDUCE for cell data \ INCLUDE DSK1.TOOLS DECIMAL VARIABLE REDUCER : REDUCE ( inital addr size xt-- n) OVER 0= ABORT" REDUCE: size cannot be 0" REDUCER @ >R \ allow this to be re-entrant REDUCER ! CELLS BOUNDS DO I @ REDUCER PERFORM 2 +LOOP R> REDUCER ! ; MyAdd is a little scarier. but Python has a lot of implicit stuff baked in. : MyAdd ( n n -- n) CR OVER . ." + " DUP . + DUP ." = " . ; This data has no length embedded so we have to provide it manually (that could be fixed) CREATE MYDATA 0 , 1 , 2 , 3 , 4 , And here is the result. Edit: This Forth REDUCE takes the initial value as an argument. (the zero in this case) Python does that too but it is an extra parameter. If you don't put it in the argument list zero is assumed. Variable number of parameters would take more effort in Forth and would be not worth the effort IMHO. 2 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5088097 Share on other sites More sharing options...
+TheBF Posted July 14, 2022 Author Share Posted July 14, 2022 So reading on in the Python page I see that SUM() is a standard Python function. With REDUCE in our pocket that becomes simple. Since '+' in Forth is a pure function where no global data is used, only stack data, we can use Forth's '+' to "REDUCE" the array. : SUM ( addr len ) 0 -ROT ['] + REDUCE ; And of course once we have SUM we can create AVERAGE: : AVERAGE ( addr len ) DUP>R SUM R> / ; In fact REDUCE can take any function with the stack diagram ( n1 n2 -- n3) Two inputs, one output. So find the maximum: 0 MYDATA 5 ' MAX REDUCE . Find the minimum: 0 MYDATA 5 ' MIN REDUCE . Test if all the data are equal to 2: 2 MYDATA 5 ' = REDUCE . Multiply all the elements in an array requires that the initial argument be 1 since if it was zero the result would always be zero. 1 MYDATA 5 ' * REDUCE . This is fun. 3 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5088399 Share on other sites More sharing options...
Willsy Posted July 15, 2022 Share Posted July 15, 2022 Talking of neat stuff, have you looked at OOP? I may have the authors name wrong, but if I remember correctly, Dick Pountain wrote a book on object oriented programming in Forth. IIRC it's based on Forth 83, and relies heavily on vocabulary manipulation to manage private class methods etc. I imagine it would be really fun to port it across to your Forth system - or, just use the book as a guide to learned how he modelled the design, and put something similar together from scratch. Just had a quick check. The author is indeed Dick Pountain. The title is Object Oriented Forth - Implementation of Data Structures. Object-oriented forth Implementation of data structures by Pountain, Dick (z-lib.org).pdf Source: https://archive.org/details/object-oriented-forth-implementation-of-data-structures-by-pountain-dick-z-lib.org The book is fetching ridiculous money online - around $50. I bought it probably ten years ago for a few quid! Not sure if you've seen this book before but I think you'll love it! Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5088759 Share on other sites More sharing options...
Tursi Posted July 15, 2022 Share Posted July 15, 2022 Object Oriented programming was a mistake - and even Alan Kay who originally published the idea has said so. The problem isn't really the basic concept of it. The problem is that, like all software paradigms, it's taken to ridiculous extremes. Whatever software approach you use, remember that the software needs two things from you: (a) it needs to be readable, and (b) it needs to be predictable. These two things go hand in hand - a new person should be able to read your code and predict exactly what it's going to do. A lot of modern software paradigms break the predictable part by hiding as much of the operation as possible, and abstracting things away so far that when you read a line of code, you might be able to guess what it was intended to do, but without digging it's impossible to predict what it /will/ do. Avoid that. I suspect Forth object oriented code won't take things that far, since words will be words, and not some random abstraction of words. 3 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5088777 Share on other sites More sharing options...
Tursi Posted July 15, 2022 Share Posted July 15, 2022 (Well, at least, he burned what it has become, hehe. ) 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5088778 Share on other sites More sharing options...
Willsy Posted July 15, 2022 Share Posted July 15, 2022 34 minutes ago, Tursi said: The problem isn't really the basic concept of it. The problem is that, like all software paradigms, it's taken to ridiculous extremes. Agree 100%. I'm currently developing a serial comms driver for old RTUs (like a PLC) in C#. The object model I've come up with is simple, and reflects how the RTU works. A very simple class structure. I'm also writing an emulator for these RTUs as the hardware is obsolete. Again, C#, but running in Linux. Lots of fun. I've already been asked why I'm not using abstract classes and methods etc. The answer? I don't need them. At the company I consult for, the developers are young and VERY sharp. Really clever guys. They laugh at me because I tell them to STOP WRITING CODE! Try and spend an hour or so every day REMOVING CODE if you can! Do not add unnecessary layers of abstraction. This isn't a dick-measuring contest. Just stop it. Write what you need to get the job done ONLY. That's probably why I liked Forth so much. That's the entire ethos behind the language. 3 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5088787 Share on other sites More sharing options...
D-Type Posted July 15, 2022 Share Posted July 15, 2022 Bernd Paysen's Mini-OOF I think is quite neat, I've never actually used it, but at least it's easy to understand as it's only one block of code: https://atariwiki.org/wiki/Wiki.jsp?page=Mini-OOF 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5088829 Share on other sites More sharing options...
+TheBF Posted July 15, 2022 Author Share Posted July 15, 2022 5 hours ago, Tursi said: (Well, at least, he burned what it has become, hehe. ) This is an interesting conversation you guys have set up. I watched this video a while back too. His statement "... I did not have C++ in mind..." reminds me that Chuck Moore also did not like the idea of ANS/ISO Forth. He says "Standards are great! Everybody should have one." (He's one of a kind himself) In both cases other people took their language concepts and did what ordinary people do. They "added" to it. As Willsy was saying taking things out is usually a productive effort. However I find that you have to be a bit smarter to remove stuff. Ordinary people seem to be adept at adding but the the Wizards among us are the ones who see the superfluous cruft. It's interesting that in the arts it is well understood by the masters that you are not finished until you have gone through the work and removed things. Elegance is valued. There is video of Alan exploring his Mac Classic interactively in Smalltalk. He is doing things that would take people hours in conventional languages. It shows how he envisioned OOP to be used. Coincidentally that's how Chuck envisioned using Forth. Have a conversation with the computer, interactively. This is not possible in the edit/compile/link/load/run/fail loop that we inherited from Fortran. For @D-Type : I have a copy of Mini-OOP that will compile on Camel Forth but I have never written anything with it but it would work. And ya, Bernd is one smart cookie. So I guess like all great ideas OOP, like any tool, should be used where it is the right tool. Used incorrectly it seems to have really messed up a lot of stuff. I have read about horrible things in Java requiring endless duplication of Classes just to let different parts of the program get access to get the methods they need. Yuk! 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5088870 Share on other sites More sharing options...
+TheBF Posted July 15, 2022 Author Share Posted July 15, 2022 5 hours ago, Tursi said: The problem isn't really the basic concept of it. The problem is that, like all software paradigms, it's taken to ridiculous extremes. Quite right. 5 hours ago, Tursi said: Whatever software approach you use, remember that the software needs two things from you: (a) it needs to be readable, and (b) it needs to be predictable. These two things go hand in hand - a new person should be able to read your code and predict exactly what it's going to do. A lot of modern software paradigms break the predictable part by hiding as much of the operation as possible, and abstracting things away so far that when you read a line of code, you might be able to guess what it was intended to do, but without digging it's impossible to predict what it /will/ do. Avoid that. This is the classic problem of the "programmable" languages I think. LISP and Forth live in this world. You are writing the "language", in the first page that is then used in the rest of the project. This is fantastic for the team on one developer, but requires docs and discipline for bigger teams. Chuck writes very short definitions (one line typically) that are "readable" and "predictable" at a glance and one more important thing... they are testable, immediately, at the console, for validation. Fail to use Forth as designed and you will be un-happy IMHO. 5 hours ago, Tursi said: I suspect Forth object oriented code won't take things that far, since words will be words, and not some random abstraction of words. Indeed. OOP Forth has a lot of flavours but they mostly enforce encapsulation to limit the brain space required for complex stuff. I understand it was VERY helpful to use OOP Forth for Windows since it was built with an OOP API. This is a mini-OOP example of a Class. No surprises. object class cell var text cell var len cell var x cell var y method init method draw end-class button Methods are Forth words assigned to the Class methods that seem to take the object's base address from the return stack (R@) so that's a bit ugly. (:noname is the ANS weird name for Lamda) :noname ( o -- ) >r r@ x @ r@ y @ at-xy r@ text @ r> len @ type ; button defines draw :noname ( addr u o -- ) >r 0 r@ x ! 0 r@ y ! r@ len ! r> text ! ; button defines init I would be tempted here to rename "defines" to 's so the code would read: button 's draw button 's init Maybe that's just too cute. 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5088884 Share on other sites More sharing options...
+TheBF Posted July 15, 2022 Author Share Posted July 15, 2022 5 hours ago, Willsy said: Agree 100%. I'm currently developing a serial comms driver for old RTUs (like a PLC) in C#. The object model I've come up with is simple, and reflects how the RTU works. A very simple class structure. I'm also writing an emulator for these RTUs as the hardware is obsolete. Again, C#, but running in Linux. Lots of fun. I've already been asked why I'm not using abstract classes and methods etc. The answer? I don't need them. At the company I consult for, the developers are young and VERY sharp. Really clever guys. They laugh at me because I tell them to STOP WRITING CODE! Try and spend an hour or so every day REMOVING CODE if you can! Do not add unnecessary layers of abstraction. This isn't a dick-measuring contest. Just stop it. Write what you need to get the job done ONLY. That's probably why I liked Forth so much. That's the entire ethos behind the language. To your point on simplicity, over on REDDIT Forth, a guy asked if there was a library like ncurses for Forth. I gave him my code for VT100 which makes a little mark-up language to control the terminal. https://github.com/bfox9900/CAMEL99-ITC/blob/master/LIB.ITC/VT100.FTH https://github.com/bfox9900/CAMEL99-ITC/blob/master/LIB.ITC/VT100COLR.FTH Another guy jumped in and said Forth was a control language and you shouldn't be used for such things. He should link to ncurses and blah blah. Meanwhile the original OP had already taken my stuff and made simple windowing system for his terminal! Forth for the win. I remember reading about NEON which I think Dick had a hand in writing. It was brilliant. It came out when OOP was the rage. It gave rise to Yerks Forth for Mac on 68000 which was used at the Yerks observatory and later that was re-written to a native code compiler called MOPS Forth which I understand has come back for Mac on ARM. The author Mike Hore had no taste for Intel code. There is also the FMS library by Doug Hoffman, for VFX, which brings a kind of SmallTalk to Forth. http://soton.mpeforth.com/flag/fms/index.html 2 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5088890 Share on other sites More sharing options...
+TheBF Posted July 16, 2022 Author Share Posted July 16, 2022 (edited) Down the Rabbit Hole and through the looking glass I went down the rabbit hole on this one. I have never done anything like this before in Forth. I continued down the road of "iterators" adding MAP and FILTER to Forth for integer data. These two are interesting because of this: "map() loops over the items of an input iterable (or iterables) and returns an iterator that results from applying a transformation function to every item in the original input iterable" map() in Python does not change the original data but makes a new "iterable" with a one to one relationship to the original data but each cell is changed. filter() produces a new iterable data that could be a different size than the original. Uhoh! Dynamic data required. I wanted to make this work without digging into the complexity of ALLOCATE FREE RESIZE etc. so I just used HERE and comma for testing. I created a new kind of array that writes into unused dictionary space at HERE, by using the comma operator. The first cell in the array is a link to the previous array or zero. I don't use that field yet. The 2nd cell is the number of bytes used by the array. These seem to be interesting in their own right. The word DATA: is a "namer" for one of these arrays and when the name is invoked it returns an (addr,size) pair. Spoiler DECIMAL \ ** EXPERIMENTAL DATA STRUCTURE *** \ COUNTED ARRAYS IN FREE MEMORY \ creator for counted arrays in empty memory \ Data structure has a 2 cell header \ Cell 1: LINK - to previous array or zero \ Cell 2: size - SIZE in bytes of this array \ Data ..... VARIABLE LAST[] : DLINK, HERE LAST[] @ , LAST[] ! ; : CLEAN LAST[] @ IF LAST[] @ DP ! THEN ; : [[ ( -- addr ) DLINK, HERE 0 , ; \ create header, return the address : ]] ( -- addr ) HERE OVER - 2- OVER ! ; \ end array, fill in the size : SIZE ( addr -- addr size) DUP CELL+ SWAP @ ; \ size is in BYTES : LINK ( addr -- 'array[] | 0) 2- @ ; \ a word to name a counted array and return the (addr,len) pair : DATA: CREATE ( addr --) , DOES> @ SIZE ( -- addr size) ; Of course this cannot go on forever without some kind cleaner so I just used MARKER for testing purposes to just pull the memory back to a specific point. Since these arrays are not always named this is better than using FORGET. Surprise After version one I realized that I had duplicated the iteration code three times which was stupid so that is now factored out as FOREACH. There is some complexity in the words ACTION, a variable that holds an XT and ACTOR a defer word that runs the ACTION and other code as needed inside the FOREACH loop. The comments try to explain it. Using FOREACH and ACTION made the definitions of MAP and FILTER much smaller. Using the iterator to make more iterators made a difference. : MAP ( initial addr size xt-- addr' size') [[ >R ['] MAPPER IS ACTION FOREACH R> ]] SIZE ; : FILTER ( initial addr size xt-- addr' size') [[ >R ['] FILTRATION IS ACTION FOREACH DROP R> ]] SIZE ; The screen captures show how this works. I like this concept but of course making a complete system to handle other data types would start to balloon in size. It was eye opening to me and makes me appreciate the array languages like APL a lot more. The entire file with test code EDIT: Replaced with newer version Spoiler \ iterators.fth MAP REDUCE FILTER for cell data 16JUL2022 B Fox INCLUDE DSK1.TOOLS INCLUDE DSK1.VALUES INCLUDE DSK1.DEFER INCLUDE DSK1.MARKER DECIMAL \ ** EXPERIMENTAL DATA STRUCTURE *** \ COUNTED ARRAYS IN FREE MEMORY \ creator for counted arrays in empty memory \ Data structure has a 2 cell header \ Cell 1: LINK - to previous array or zero \ Cell 2: size - SIZE in bytes of this array \ Data ..... VARIABLE LAST[] : DLINK, HERE LAST[] @ , LAST[] ! ; : CLEAN LAST[] @ IF LAST[] @ DP ! THEN ; : [[ ( -- addr ) DLINK, HERE 0 , ; \ create header, return the address : ]] ( -- addr ) HERE OVER - 2- OVER ! ; \ end array, fill in the size : SIZE ( addr -- addr size) DUP CELL+ SWAP @ ; \ size is in BYTES : LINK ( addr -- 'array[] | 0) 2- @ ; \ a word to name a counted array and return the (addr,len) pair : DATA: CREATE ( addr --) , DOES> @ SIZE ( -- addr size) ; \ Explanation: \ ACTOR holds the execution token (XT) for the operation that will be done \ to each data element. The XT is passed to ACTOR by the programmer. VARIABLE ACTOR \ ACTION is vector that holds code that does the ACTOR XT and it also \ runs EXTRA code that makes the difference between REDUCE, MAP or FILTER DEFER ACTION \ this code is run in a loop by FOREACH : REDUCER ( initial n -- n) ACTOR PERFORM ; \ reduce and return a value : MAPPER ( initial n -- ) REDUCER , ; \ reduce and compile value : FILTRATION ( initial n -- ) \ reduce with conditional value compilation 2DUP SWAP REDUCER ( -- n ? ) IF , \ if true compile n into array ELSE DROP \ otherwise throw it away THEN ; DECIMAL \ * changed argument order to allow sequential calls to foreach : FOREACH ( addr size initial xt-- n) \ primary iterator >R -ROT R> \ ugly but it works OVER 0= ABORT" FOREACH: size=0" ACTOR @ >R \ allow variable to be re-entrant ACTOR ! \ set the XT of action on each cell BOUNDS DO I @ ACTION 2 +LOOP R> ACTOR ! ; : REDUCE ( addr size inital xt-- n) ['] REDUCER IS ACTION FOREACH ; \ Use REDUCE to do something : .. ( addr size -- ) 0 ['] . REDUCE DROP ; \ print array signed : U.. ( addr size -- ) 0 ['] U. REDUCE DROP ; \ print array un-signed : SUM ( addr len -- n) 0 ['] + REDUCE ; : AVERAGE ( addr len -- n) DUP 2/ >R SUM R> / ; \ MAP returns a new array as output : MAP ( addr size xt-- addr' size) 0 SWAP \ add the intial value. Not used but need by FOREACH [[ >R ['] MAPPER IS ACTION FOREACH DROP R> ]] SIZE ; \ filter returns a new array as output that might be a different size : FILTER ( addr size inital xt-- addr' size') [[ >R ['] FILTRATION IS ACTION FOREACH DROP R> ]] SIZE ; \ ======================= ITERATORS ENDS =========================== \ TEST DATA [[ 20 CELLS ALLOT ]] DATA: B[] ( un-initialzed data example) [[ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , -1 , -2 , ]] DATA: A[] \ TEST CODE A[] .. \ using REDUCE A[] SUM . A[] AVERAGE . \ MAP * changed to require an initial value. '0' is most common. A[] ' 8* MAP .. A[] ' 2+ MAP .. \ FILTER \ filter functions must have a stack diagram ( n n -- ?) \ The flag determines if the data will be added to the output or not. A[] 7 ' < FILTER .. A[] 4 ' > FILTER .. A[] 9 ' = FILTER .. \ using the initial value 1, we can test for ODD/EVEN : EVEN? ( initial n -- n ?) AND 0= ; : ODD? ( initial n -- n ?) AND 0> ; A[] 1 ' EVEN? FILTER .. \ feed a filter into another filter :) A[] ' 2* MAP 3 ' > FILTER 16 ' < FILTER 2DUP CR .. CR SUM . Edited July 17, 2022 by TheBF Update code file 3 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5089613 Share on other sites More sharing options...
+TheBF Posted July 17, 2022 Author Share Posted July 17, 2022 One minor enhancement to these iterators and then I am done for now. EDIT: Latest version of the code with test examples is in the previous post. I realized that I could adjust the order of the arguments in FOREACH so that it was cleaner to feed the results from one iterator to another one. (no stack juggling at the programmer level) The side effect is that that the "initial" value parameter must be in the ACTION word before the XT. So SUM becomes: : SUM ( addr len ) 0 ['] + REDUCE ; I couldn't think of a reason for an initial value for MAP so I add a 0 in the definition of MAP (and DROP it later) so the programmer doesn't have to. : MAP ( addr size xt-- addr' size) 0 SWAP \ add the intial value. Not used but need by FOREACH [[ >R ['] MAPPER IS ACTION FOREACH DROP R> ]] SIZE ; This makes MAP look the same as before A[] ' 8* MAP .. A[] ' 2+ MAP .. The other benefit that changes is the syntax of FILTER becomes more Forth appropriate in terms of argument order. A[] 7 ' < FILTER .. A[] 4 ' > FILTER .. A[] 9 ' = FILTER .. And so now this is a VALID expression A[] ' 2* MAP 3 ' > FILTER 16 ' < FILTER 2DUP CR .. CR SUM . 2 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5090010 Share on other sites More sharing options...
GDMike Posted July 18, 2022 Share Posted July 18, 2022 BTW, what is the definition of include for how you load a routine from disk? Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5090081 Share on other sites More sharing options...
+TheBF Posted July 18, 2022 Author Share Posted July 18, 2022 47 minutes ago, GDMike said: BTW, what is the definition of include for how you load a routine from disk? Good question. So INCLUDE <file-path> is based on the reversed polish word that works like this: S" DSK1.MYFILE" INCLUDED So INCLUDED is a bit complicated because it can be "nested" ( a file can include another file) but here is all the source code. https://github.com/bfox9900/CAMEL99-ITC/blob/master/SRC.ITC/FILESYX2.HSF The neat thing is to make a command that parses the file name and loads the file we just do this: : INCLUDE PARSE-NAME INCLUDED ; ( PARSE-NAME outputs an address,length pair ie: a string) With that you can just type INCLUDE DSK1.TOOLS and compile the tools into the system. In my system the definition for INCLUDE is compiled when the system boots. https://github.com/bfox9900/CAMEL99-ITC/blob/master/SRC.ITC/SYSTEM.FTH 3 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5090113 Share on other sites More sharing options...
GDMike Posted July 18, 2022 Share Posted July 18, 2022 What I did, let me know if I'm ok with it, but I Did this..in TF I first created a blank image of 50 pages, blocks. It's called DISK1 and located on DISK 4. I added a line in my essentials boot block like this. : INDEX1 S" DSK4.DISK1" USE 30 LIST ; I figured I'd set up a text page starting at block 30 that would display a listing of WORDS that are defined (or will be in the future) for loading.. Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5090129 Share on other sites More sharing options...
GDMike Posted July 18, 2022 Share Posted July 18, 2022 (edited) Ok...I'm liking it .I'll setup a TurboForth for Mike post and quit hogging this one. Thxok..I'm off, teaching my son how to make tacos...lol Edited July 18, 2022 by GDMike 2 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5090132 Share on other sites More sharing options...
+TheBF Posted July 18, 2022 Author Share Posted July 18, 2022 Important to remember that you working BLOCKS on TF. They live in a file but are traditional Forth BLOCKS just the same. My system uses text files by default. Blocks can be added with... you guessed it... INCLUDE DSK1.BLOCKS 3 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5090163 Share on other sites More sharing options...
GDMike Posted July 18, 2022 Share Posted July 18, 2022 (edited) 38 minutes ago, TheBF said: Important to remember that you working BLOCKS on TF. They live in a file but are traditional Forth BLOCKS just the same. My system uses text files by default. Blocks can be added with... you guessed it... INCLUDE DSK1.BLOCKS Yes, I noticed that you're includes have been mostly text files. For what I see, for me in this case, I'll just use my blocks files for storing little routines for testing etc... I'm sure the blocks take up more space than text files would. I'm just limiting my blocks to 50 pages inside the block file. That way, I can quickly take notice of what they are if I see them in a directory list.. Edited July 18, 2022 by GDMike 2 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5090165 Share on other sites More sharing options...
+TheBF Posted July 18, 2022 Author Share Posted July 18, 2022 I read something on Hacker News and I had to try it. This made me laugh out loud. Just when you get used to reverse polish notation... This might hurt your Forth head. Spoiler INCLUDE DSK1.STACKS 20 LIFO: XSTK \ a stack : ( ' XSTK PUSH ; : ) XSTK POP EXECUTE ; 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5090357 Share on other sites More sharing options...
+Lee Stewart Posted July 18, 2022 Share Posted July 18, 2022 33 minutes ago, TheBF said: I read something on Hacker News and I had to try it. This made me laugh out loud. Just when you get used to reverse polish notation... This might hurt your Forth head. Hide contents INCLUDE DSK1.STACKS 20 LIFO: XSTK \ a stack : ( ' XSTK PUSH ; : ) XSTK POP EXECUTE ; Nah! It is precisely the Forth head that won’t hurt! ...lee 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5090377 Share on other sites More sharing options...
GDMike Posted July 18, 2022 Share Posted July 18, 2022 (edited) What he said before he said it. Can forth see back in time and deliver the good news today... Edited July 18, 2022 by GDMike 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5090383 Share on other sites More sharing options...
+TheBF Posted July 19, 2022 Author Share Posted July 19, 2022 Strange coincidence after my posts about high level functions Forth Over on Reddit Forth this article was posted that makes the case that Forth is useful in this world of functional programming written way back in 1993. ( I may be a member of the dis-functional programming group) :-) I am pretty sure the REDDIT poster wasn't reading my posts here. Linear Logic and Permutation Stacks--The Forth Shall Be First https://www.plover.com/~mjd/misc/hbaker-archive/ForthStack.html --- On another note: While watching a video on functional programming I learned that there is an operator called "after" that looks like a circle. It's used something like: x = func3() after func2 after func1 ( I am paraphrasing ) This made me laugh since if you just switched to RPN the "AFTER' operator is not even needed and everything reads left to right like English. func1() func2() func3() TO X Oh well. I don't think I can convince the world to toss infix and prefix notation from Atariage.com 1 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5091175 Share on other sites More sharing options...
+TheBF Posted July 25, 2022 Author Share Posted July 25, 2022 I have never liked the name of the word :NONAME in Forth 94 but I just realized it could do something useful in my little system. (LISP has LAMDA for this kind of thing and Forth could have stolen that name or maybe :LAMDA ? ) :NONAME lets you make a word definition that has of course no name. Instead it just leaves behind the "execution token" (the CFA) of the un-named word. Here is :NONAME in Camel99 Forth: (I should probably combine these now that it is working) \ (:noname) from studying gforth : (:NONAME) ( -- ) ['] DOCOL @ COMPILE, HIDE ] ; : :NONAME ( -- xt) HERE !CSP (:NONAME) ; Here is what I just realized. When you save the system as an executable program, with the SAVESYS command, you have to provide the EXECUTION token of some Forth code that will run when the system starts. Typically you make a short definition that must have the WARM word in it to initialize the Forth system and then the word (or words) you want to run. For example if the start word to run your program was called BRICKS this would work: : START WARM BRICKS ; Then do: ' START SAVESYS DSK1.MYCOOLPROG You can do the same thing without creating the START word like this: :NONAME WARM BRICKS ; SAVESYS DSK1.MYCOOLPROG It removes the bytes used for the START definition header, that have no use in the program, so why not. 2 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5094136 Share on other sites More sharing options...
+TheBF Posted July 25, 2022 Author Share Posted July 25, 2022 Just now, TheBF said: Here is :NONAME in Camel99 Forth: (I should probably combine these now that it is working) \ (:noname) from studying gforth : (:NONAME) ( -- ) ['] DOCOL @ COMPILE, HIDE ] ; : :NONAME ( -- xt) HERE !CSP (:NONAME) ; Actually no I should not combine them because (:NONAME) is a nice common factor as I learned from GForth. Here is the definition of colon ( X: and ;X are aliases in the cross-compiler so I don't get to confused when I have to re-define the colon with a colon) ? X: : !CSP HEADER (:NONAME) ;X (There is a colonoscopy joke in here somewhere but I can't find it right now) Or how about this: Did you hear about the Forth programmer who redefined his colon and disappeared up the orifice of his own fundament? 3 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5094143 Share on other sites More sharing options...
+TheBF Posted August 11, 2022 Author Share Posted August 11, 2022 While looking around for some information on local variables in Forth I found this huge repository of Forth related information maintained by Anton Ertl I believe at the Technical University of Vienna Index of /forth (tuwien.ac.at) One of the cool things an archive of Forth Dimensions magazines and there is a quicksort done as one definition. Index of /forth/forth-dimensions (tuwien.ac.at) I slightly modified it for Camel99 Forth. This version sorts an array of characters. \ FORTH DIMENSIONS jAN/FEB 1984 Vol5,No.5 QUICK SORT BY MARK PERCEL \ Ported to Camel99 Forth with small modification Brian Fox INCLUDE DSK1.TOOLS \ harness for CAMEL99 : 2OVER 3 PICK 3 PICK ; VARIABLE PIVOT \ changed from MIDDLE to PIVOT \ Replaced ROT ROT with -ROT \ Replaced NOT with 0= \ Replaced MYSELF with RECURSE : EXCHANGE ( adr adr -- ) 2DUP C@ SWAP C@ ROT C! SWAP C! ; : QSORT ( start len -- ) OVER + ( 'start 'end ) 2DUP 2DUP OVER - 2/ + C@ PIVOT ! BEGIN SWAP BEGIN DUP C@ PIVOT @ < WHILE 1+ REPEAT SWAP BEGIN DUP C@ PIVOT @ > WHILE 1- REPEAT 2DUP > 0= IF 2DUP EXCHANGE 1 -1 D+ THEN 2DUP > ( loop until partitions cross) UNTIL SWAP ROT 2OVER 2OVER - -ROT - < IF 2SWAP THEN 2DUP < IF RECURSE ELSE 2DROP THEN 2DUP < IF RECURSE ELSE 2DROP THEN ; 2 Quote Link to comment https://forums.atariage.com/topic/273872-camel99-forth-information-goes-here/page/56/#findComment-5103467 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.