GENTUT46.TXT General Tutorial for Lisa GJ2 Fic3 -- the f3 language explained as a series of tiny essays Written by Aristo Tacoma with L.A.H. Date: 2011:3:2 Numbers 01..99 in this series of gentutNN are circulated as needed, when more recently written articles make earlier ones unnecessary. Each article: copyright author, further distribution license the usual www.yoga4d.org/cfdl.txt. Kids: there are other tutorials for you. But you should find pieces here and there which are easy to read. In B9, use the search function, CTR-F or F4 within each. Beware ;-) This is written as a flow, quickly, and wherever there is a reference to concrete f3 syntax, it may have been written from memory and so not every word is guaranteed to be written here exactly correct. Search up with the CTR-F and repeated search CTR-L in the F3DOCS manual or in example programs if things here are not clear enough or precise enough for your present purposes. Good luck!!! ***THE MAIN SIMPLE RICH VARIABLE WAYS OF F3 When you are going to make a program in F3, you are faced with two-three obvious choices. One, do you want to write it line by line from scratch? Two, do you want, rather, to copy an existing program and rename this and that and modify this and that and add so and so, growing a new cultivated flower out of another type of cultivated flower? Or, three, some kind of combination of the two? Each F3 program, each program in Lisa GJ2 Fic3, which can be started by command :PROGNAME IN when you have just started up F3, and perhaps, for some very rare selected lucky cases, as by lottery, set up on a menu for graphical loading, for a while -- in which case it has been appended to the FIC3.TXT and put in a certain folder -- each such program consists of smaller programs, or functions. They are up to you entirely, but at some stage, they must have in them a reference to the set of already existing functions. When a very suitable function exists already, you don't usually want to put it into a newly named function having just that single word in it. For instance, the word CLS clears the screen, both for text mode and for the graphical mode, and it doesn't require any input to it to work, this function, nor does it leave any output which must be handled, so it is a superbly easy function to call. Its name is also easy and so there is no need to put it inside a function that you define if that's the only line in the function. But when you do have some stuff that you want to put inside a function, the question arises of whether you want give this function some input, and also whether you want to give this function an opportunity to communicate with other functions after it has performed, by leaving some output. For this, then, you can use various approaches. The most obvious approach is to use that which we call 'stacks'. More indirectly, you can put stuff in that which we call 'variables', or the usually larger structures we call 'matrices'. Still more indirectly, you can store it to a file on disk by one function, and retrieve it from the disk by another function. In rare cases such as used by the WT or WildTone program we find that the output at the screen is directly thrown into a file without any need to store what's on the screen inside the program directly. This is okay for a drawing program, but normally a program should communicate directly with itself about all the things it wants to store. Let's very briefly look at the stacks. If you know what you are doing, and apply a good measure of intuition to do unusual things right, you can use any stack you like. In praxis, it tends to become easier to get programs shaped so that they work on the computer when we apply the conventions found in the main bundle of example programs, as for what stacks are used when. In Lisa GJ2 Fic3, the by far easiest stack to use is the main stack, which also can be called just 'the stack', and since it can contain lines of text up to some two hundred and fifty characters it is also called the 'the text line stack'. (Acknowlegdements: the use of this type of data item came from realising its elegant size and speed of use in work with a language not oriented towards such stacks, but which had such text lines as a main variable type, namely "Free Pascal".) Here are examples of functions which use the main stack and each line gives something directly out on the screen, if you have just started F3 so it is in the text mode: }Hello world!} => POP 15000000 => TWICE => POP :first :second => BRIDGE => POP => POP => POP :first :second :third => ANGEL => POP => POP => POP 0.235 => COS => POP In the case of BRIDGE, that which is added not quite recently, but just before the most recent item, is copied and put on top. So there are three POPs there. Numbers need no colon, single words need a colon straight up front, while sentences or phrases with blanks or such need a curly bracket before and after. You can also put curly brackets inside such a phrase, but then it must be doubled: }This is a curly bracket: }} -- one, not two} POP You can drop writing (( and )) and => when typing directly, except when they are melted in with a word like for ((DATA. These are optional punctuations. Note that adding an asterix after the completing curly bracket }like this}* makes it into a comment line, ignored by F3, for F3 reads all that is outside of comments as part of its active mechanism, -- and so watch out for not leaving an asterix there where you don't intend the phrase to become a comment, and vice versa, so you don't get peculiar results when compiling your sweet program. You see that the COS or cosine function, which, when given a measure of the angle, shows the position on the X axis of a point on the circle of radius 1, if I remember correctly, with SIN or sinus giving the Y axis position of same point -- it does work on the main stack as well. But the main stack isn't much oriented towards handling such decimal numbers. So we therefore have the rich stack, -- the dollar sign is used to throw numbers over there instead, and so it is called RICHSTK. You can always type in STK to see what's on the main stack when you do quick work in the textmode of F3 directly, and RICHSTK to see the rich stack content. (R is its POP: $3.14159265358 => TWICER => (R $0.217 => COSR => (R 315 => STKTORICH ; $0.0005 => ADDR => (R $1000000 ; $2.15 => \R => RICHTOSTK => POP You see that the completing letter R is often used to do things on the rich stack. You have BRIDGER and ANGELR and so on. Look up BRIDGE, ANGEL, SWITCH, YANTRA, TANTRA, MANTRA and such in the F3DOCS to see how to move things around on the stacks, copying it and such. The addition with decimals is ADDR. I made it first +R but realised that anything beginning with + or - is defined as being a number going to main stack, and so ADDR and SUBR are to be used at the rich stack while ADD and SUB deals with main stack, but division is \R and multiplication is *R while on main stack it is DIV and MUL. Be sure to notice that DIV on the main stack rounds. STKTORICH and RICHTOSTK moves back and forth between the two. The semicolons ; can also be avoided when you type in directly. Equal to the RICHSTK in that they take only numbers, but different in that these numbers can only be whole, and different in some other respects as well (especially for the simple stack), is the so-called SIMPLESTK and VARSTK, or simple stack and variable stack. Try 5 >N11 234325 >N10 N10 ; N11 => ADD => POP Now I first made this imagining how nice it would be to have the N1..N11, slightly more than the psychological natural amount of about 6 or 8 to be used inside a neat function, as easy to be handled inside a function in order to avoid too much of BRIDGE and YANTRA and all that. But since N1..N11 refers to the top eleven numbers of a stack, common in principle to all functions, I then added the following criterion: on entering each function, eleven fresh slots are given to this function. This led the simple stack to be used, by convention, not usually for communication between functions but rather for communication within the function. It is of value that it is more than the psychological natural amount of a whole unit, of 6 or 8, since the N1 is very naturally used when we do counting, using the (COUNT .. COUNTUP) form, with N2 then holding the top amount that N1 is to up to. You can then manually change the N1 to skip over numbers if you want it to complete faster. For instance, if you put INCN1 inside such a loop, it goes into every second number. Or N2 => >N1 will cause it to exit at once. And so on. But this means that the simple stack will have a modification in how it is being used. The N1..N9 will become N3..N11 inside the loop. Somewhat often, a second (COUNT .. COUNTUP) loop is inside the loop, meaning that the N1..N7 will become N5..N11 inside the inmost loop, if you follow -- you add four instead of adding two to get from e.g. N1 to N5 when you have two loops. And so the N1..N11 is the natural psychological amount for a neat function which doesn't overdo amount of loops inside one another. There is another way of doing a loop also, in which you yourself choose entirely where to place the counter values, and that uses up to four so-called "labels", a feature found within an early programming language called Fortran. It is however of value to limit to four since each such GOLABEL1..GOLABEL4 has either one (and only one! -- watch out for that) GOFORWARD1..GOFORWARD4 or else one GOUP1..GOUP4 associated with it, leading again to the natural psychological amount of maximum about 8 items. Too much such (which in an early programming language called Basic is called) GOTO can lead to a complicated cluttered type of structure. So also, in F3, the harmonious design decision is to keep each such go-to action within the function, not allowing confusing jumps across functions, with the potential big range of messy errors. In doing a GOLABEL with either a GOUP (when label is higher up on the page) or GOFORWARD (when label is further on in the code), you can e.g. keep the counter in a variable, defined by ((DATA .. )), which can be accessed afterwards by other functions. You check then with a number comparison such as INTGREATER or EQN, and combine this with .. (MATCHED .. MATCHED) in order to make the jump happen on the condition that such and such is the case. Or, by adding the "boolean" function NOT, on condition that such and such is NOT the case. (Look up NOT, AND, ORR -- the three main boolean functions, and others also, like TRIPLEAND, in F3DOCS). Instead of (MATCHED .. MATCHED) .. you can write their synonyms, = .. === .. -- this is smart when the thing to be done is written in terms of e.g. a single word. Often you will find that when a function checks whether it has got enough data to work on, it has a phrase like this quite in the beginning: .. .. => NOT = EXIT === And this means, of course, EXIT from the function back to the function that called it, unless such and such conditions is fulfilled. Remember then that although it is possible to do such things as BRIDGES (rather than BRIDGE or BRIGDER) at the simple stack, it is usually used simplistically with the N1..N11 and to modify these, such as >N1..>N11 and INCN1 and such, and also simplistically in the sense that usually great care is taken not to leave anything extra in it when exiting a function, nor take anything out of it which was there before. Since a (COUNT .. COUNTUP) loop pushes two new numbers on top of it, which becomes N1 and N2, when the loop is going on (ie, before it has reached the COUNTUP part), any use of a sudden EXIT inside of such loop must manually remove the content, then, as a rule of thumb, and so the command to remove from the simple stack, namely RMS is usually called twice right before such EXIT. To double an item on the main stack, write ONE. To remove from the main stack, write RM. For rich stack, ONER and RMR. To find the length of anything, a number or word or sentences or whatever, which is on the main stack, write LENGTH. The content is still there after LENGTH is performed. To get the length and remove the content, write TOLEN instead. E.g.: }Hi!!} => LENGTH => POP => POP }Hi!!} => TOLEN => POP Remember that to check whether such a function indeed behaves as you think it does, with regard to how much it leaves on the stack, type STK and press ENTER button before and after. If you want to clear the stacks from debris, type CHICHI. If anything is left on the stacks after your program has performed, then, if the program finishes (for text mode programs) with RAM-REFRESH or with (for graphical programs) with GJ-DONE, it will usually show up briefly then (except, if I remember correctly, for RICHSTK, which you should put it manually in order to check that you have done it right with this one if you use it much in a program). If a program doesn't leave with RAM-REFRESH nor with GJ-DONE (nor with XO, but normally XO shouldn't be called directly inside a program), it will, at least for text mode programs, typically remain in the F3 text mode. To check what's on the stack of a text mode program after it has performed, and enquire into variable values and such manually, simply comment out the RAM-REFRESH. The variable stack shares, then, with the simple stack, that it has only numbers, but it is typically used to hold warps to matrices. This is simpler than it sounds. It means it holds a certain type of numbers. [[[All numbers which are whole and not treated as a text line are within about two billion, plus or minus, and this is a psychological natural amount, for we are talking of less than ten digits -- which is the 32-bit number. The next number type would be 64-bit, but that is made out of twice that many digits and so not meaningful and cannot be actively used for conscious enlightened programming; while 16-bit numbers, which by means of data machine construction comes electronically before 32-bit, haven't capacity beyond about four digits, and so leads to impractical working conditions -- so 32-bit is the par excellence standard, the sine qua none of pure programming, in how this author sees it, a quite original stance I took there a long time ago .]]] -- as far as I am aware, neither it nor the whole notion of psychological first-hand programming hadn't been stated before. This went back to my first working with an alternative to object-oriented programming in what I called Knit, a slightly modified and extended Forth, from the beginning of the 1980s in a company connection with the company Arcen Informasjonsbehandling A/S led by Kolbjoern Braa). While the variable stack has some similar features to the simple stack in that numbers can be injected straight into the slots V1..V11, these are not automatically allocated during the start of a function. This is rather done manually by the & or >>V command. The removal from the stack is done by the && or V>> command. To fetch from the top of the variable stack -- the most recently added item there, # can be used; the second on top, ##, the third, ###. Normally, we don't use such as BRIDGEV and all that stuff much, although these words in principle exist. Anything which is too big to be on the stack can be made into a matrix or an array or such. On the stack you can then simply have the warps to these places, so that the functions can handle them. So, when you have a matrix called MY-LOVE-MATRIX, you have made it by a phrase like (( 1000 ; 5 => RAM-PM MY-LOVE-MATRIX <>> => & )) Be sure to get the >>> there, for this activates the meaning of the variable to be a retrieval of the value, rather than, with < GM ; )) In this case, the N1 might refer to a (COUNT and the N3 to another (COUNT, one going for rows, another for columns. Be sure to respect the limits you gave your matrix and be sure to realise that the quantity of bytes that such a matrix will occupy is four (a 32-bit number is four bytes and each byte or 0..255 number is 8 bits) times rows times colums, about, -- in other words, don't overstrain the machine. But throw in a little extra amount of rows for good measure, have a luxury about what you do. Note that CLEAR-MATRIX sets stuff to zero, that basis is the word for zero and dance is the word for one and words like SETBASIS and SETDANCE, VISBASIS and VISDANCE can be used with ordinary variables to set and check for these values, while ISBASIS and ISDANCE checks rather on a retrieved value by e.g. GM on the main stack. A very fast way but looking somewhat complicated of looping through all the non-basis numbers of a matrix is by means of warps given to the functions FORVPM and FORVPM2. This is best learned by example. In such cases, you typically find a function warp being stored in a variable being called ..-HOUSE, while the function itself is called ..-ESSENCE, and all this stuff is organised in a higher level function which is neither called -HOUSE nor -ESSENCE but has the same first name. It is this that calls FORVPM or FORVPM2 and this uses (in contrast to an even more rarely used FORPM) the variable stack. The FIC3.TXT has some examples of this, it is used when B9 searches and/or replaces, and the CTR-L repeats the most recent warp. When a function starts up, it starts up from somewhere -- perhaps you typed it in directly in F3 interactive mode, or it is started from within another function. The place from which it starts is stored in an exotic stack which is rarely looked into directly by the programmer, for there is no need to, called RETURNSTK. It is this which is worked on by the EXIT function in order for EXIT to get back to the place it was called. Note that it is up to you what you want a function to do with the stacks, just be consistent. Show that you want a function to receive e.g. three values by throwing in such as three semicolons with blanks in between them in the (( )) which is after (LET .. BE on the first line. Use main stack where you easily can. Use more digits on main stack without dot instead of using decimal numbers if you know where the dot ought to be, and can throw it in at the moment before it is to be used exactly as a decimal numbers. Don't store rich stack numbers as ((DATA )) but in principle, if you can't remove the dot, put them into a textline variable (( VARSTRING .. )) and use the STKTORICH phrase after getting it with VARSTR>. It is also up to you what the function is to leave on the stack after it has performed, but again, be clear about it. Throw in => => after the phrase which leaves something. If more than one thing, show how many, e.g. by (( ; ; ; => => )) And in such a case, leave the ; higher up in the function, one for each thingy, so one quickly can see where they came from. I have seen earlier programmers advocating commentary lines about input and output and action of each function but I advice you to rather write good programs, instead of writing good English prose which will draw all attention to itself and perhaps make program correction difficult since it can hypnotise the way a function is being read. All these stacks are called LIFO, last in, first out. An alternative is FIFO, first in, first out. Stacks are relatively easy to make by a program but rarely it is necessary to make more stacks when one has these, and these which are inbuilt are intimate to the syntax in a way which other stacks, built as functions, never can be. I mentioned the $3.14 as a syntax to get stuff into the richstack. If you turn the V on its head, you can use the little hat symbol ^ to put numbers to the variable stack, such as in this phrase, which gives you an RFFG number between 1 and 28: ^28 FR GETV => POP And in principle, S looks like ~ so ~23423 adds to the simple stack. Relatively Free Fluctuation Generation is an important factor to add to all choice situations with votes in order for an element of synchronicity and lively fluctuation to be added to the richness of human decisions. Alternatively, 10000000 => FUNNYRFFG => POP -- this gives a different take on RFFG numbers. To clarify what big numbers you are using, but don't use it within big loops for it takes computation efforts, 10,000,000 RICH => FUNNYRFFG => POP gives the similar result. RFFG is crucial to all events in cosmos, WITHIN harmony and beauty, beauty as the 46 chromosones of the healthy longlegged girl, as she longs to bring 23 of these in meeting with 23 to bring about other girls: so sex, too, is about numbers and RFFG and absolutely exact harmony. That's the main simple rich variable ways!!