jschultzpedersen Posted October 7 Share Posted October 7 If I use a READLINE to input data, it is returned as a list. Suppose I wish to input a number (integer). Is there a simple way to convert a list like [45 ] to the number 45, or do I have to invent a BASIC VAL type routine to interpret and convert the list value to a number? I suppose I could use READCHAR and interpret each character as it it entered. But then I would potentially have to consider any reediting of the entered value and displaying it as well. Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 7 Share Posted October 7 Reading this is in manual is not a good sign. Warning: Words and Numbers In Tl Logo, you can form words whose characters are all digits. But these are not treated as numbers, even though they look like numbers. For example, the arithmetic operations will not accept something like "25 as an input. Conversely, the word-manipulating operations do not work on numbers. This distinction between words and numbers can be confusing, because error messages that result from inappropriate inputs do not distinguish between numbers and words. I can't find reference to a conversion function either. Page 145 in the manual has something to start with that converts numbers to a base 8. That gives you a skeleton I think. TO BASES :N IF :N < 8 OUTPUT DIGIT :N OUTPUT WORD BASE8 (:NI 8) DIGIT REMAINDER :N 8 END TO DIGIT :N OUTPUT PICK :N + 1 :DIGITLIST END (Note the 1 added to N: the first digit in the list, for example, is the digit 0.) Of course , there is nothing special about base 8. You can convert to any base less than 10 in the same way: TO BASE :N :B IF :N < :8 OUTPUT DIGIT :N OUTPUT WORD BASE (:N/:B) :B DIGIT REMAINDER :N :8 END 1 Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted October 8 Author Share Posted October 8 it turns out, that it can be done fairly easily. This morning I realised that it is possible to build a list of valid commands with the SENTENCE command, that can define a number from an element in a list. This list can the be executed using the RUN command and produce a numeric variable and that value can be OUTPUT from the procedure as a number. TO TEST2 MAKE "A READLINE MAKE "X SENTENCE [MAKE "Y ] :A RUN :X OUTPUT :Y END This example assumes that we enter 123 as input for READLINE. First we MAKE "A as a list from READLINE [123 ]. Then we SENTENCE a list with the elements [MAKE "Y ] and the single element list in :A and MAKE "X from it. This produces a valid command string like this [MAKE "Y 123 ]. Then we just RUN the command string. It produces a variable :Y with the numeric content 123. We OUTPUT it, and everyone is happy. Try PRINT 2 + TEST2 Enter... >123 and it prints 125. 3 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 10 Share Posted October 10 Ok, but never tell me that Forth is weird, ever again. That's a few convolutions to get there but good on you for finding the magic words. Note: This is interesting because the EVALUATE command in Forth, which is like RUN in LOGO I think, can be used the same way to convert a string to number. ie: Just give it to the interpreter. 1 Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted October 14 Author Share Posted October 14 After further reading i noticed that there is a section in the LOGO II manual, which has some examples of using the ability to RUN the content of a list to implement a WHILE command and other stuff. From another millennium I can remember, that the APL language also had an EXECUTE command, that could do something similar. I have always had a soft spot for APL, primarily because of its strong handling of vectors, matrices etc.. Perhaps Forth can be used to create an APL like language on the Ti99. LOGO II has the basics with its lists and ability to traverse a list, but it would be very slow as an interpreted language. As for home computers in the eighties there was a version of APL for the Amiga - It was very expensive and unfortunately very buggy. 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 15 Share Posted October 15 On 10/14/2024 at 5:07 AM, jschultzpedersen said: Perhaps Forth can be used to create an APL like language on the Ti99. That is possible. There is this a guy named Bob Armstrong who wrote a system for himself that is based on APL concepts. But he performs the same kind of magic that you see done with APL. CoSy uses "words" rather than symbols in true Forth form. For example the iota operator is written as ... iota In my opinion Bob's mind struggles with creating a linear way to present his language. It seems like he is thinking of everything simultaneously, to me anyway. Maybe his mind is running APL, or maybe I'm just not smart enough not follow it. You can try to figure it out here. /CoSy/CoSy Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted October 17 Author Share Posted October 17 It seems that CoSy is rarely downloaded. At least my antivirus software (Norton) does not like it and kills it off. Probably because it is suspect by being rarely used. I can bypass Norton, but, anyway, I think I will postpone further investigations for now. I made my first attempt at creating a command that will take a scalar value and for instance multiply (or add or subtract etc.) that value with all elements of an array of values of any length (actually a list) and return another list with the updated values. This can be solved with a recursive process in LOGO II and works for me. The next step will be to add another level so I can handle lists of lists (effectively multidimensional matrices of any size). Again I expect this can be done with recursion. If I can get this to work I can support a number of APL like capabilities. It will probably be dead slow in LOGO II, but fun..... 3 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 17 Share Posted October 17 Very interesting work you are doing. The hardest part of doing this stuff in Forth IMHO is dynamic memory management. LOGO has that solved for you so with your skill level you are off to the races. On tiny systems like TI-99 Forth typically does static allocations. I have a library from the Standard website that gives the ALLOCATE FREE ANS/ISO wordset. If I were to combine that with the SAMS card I might be able to make something work. I have implemented experimental versions of MAP REDUCE and FILTER that uses the dictionary memory in a crude way. Simple linear allocation like the Forth dictionary uses. The syntax ended up being pretty fun. I have however never done a project with it. : REDUCE ( inital addr size xt-- n) ['] REDUCER IS ACTION FOREACH ; \ Use REDUCE to do something real : .. ( 0 addr size -- ) ['] . REDUCE ; \ print array signed : U.. ( 0 addr size -- ) ['] U. REDUCE ; \ print array un-signed : SUM ( addr len ) 0 -ROT ['] + REDUCE ; : AVERAGE ( addr len ) DUP 2/ >R SUM R> / ; The [[ marks the start of memory and ]] updates the size in the header and returns the address. SIZE returns the start of data address ( past the header info) and the number of items on the data stack. \ MAP returns a new array as output : MAP ( initial addr size xt-- addr' size') [[ >R ['] MAPPER IS ACTION FOREACH R> ]] SIZE ; \ filter creates a temp counted array that might be a different size : FILTER ( initial addr size xt-- addr' size') [[ >R ['] FILTRATION IS ACTION FOREACH DROP R> DUP ]] DROP SIZE ; Then you can do: \ allocate some arrays [[ 20 CELLS ALLOT ]] DATA: B[] ( un-initialzed data example) [[ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , ]] DATA: A[] \ test code A[] .. \ prints A[] \ using REDUCE A[] SUM . A[] AVERAGE . \ MAP \ map requires operators that have this stack action ( n -- n') A[] ' 8* MAP .. A[] ' 1- MAP .. \ FILTER \ filter functions must have a stack diagram ( n n -- ?) \ This conforms to Forth comparison operators \ The flag determines if the data will be added to the output or not. 7 A[] ' < FILTER .. 4 A[] ' > FILTER .. 9 A[] ' = FILTER .. \ using the initial value 1, we can test for ODD/EVEN : EVEN ( initial n -- n ?) AND 0= ; : ODD ( initial n -- n ?) AND 0> ; 1 A[] ' EVEN FILTER .. 1 A[] ' ODD FILTER .. \ filter based on array element A[] 3 ]@ A[] ' > FILTER .. \ SEQUENTIAL actions 1 A[] ' ODD FILTER ' 8* MAP SUM . It's not APL, but it gets nearer to that kind of thinking. Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted October 17 Author Share Posted October 17 I think that if I were to try my hand at using Forth for this, I would start by creating a data structure with information on my object (dimensions, type of content etc.) this would be like a header for each object. With this data available I could then reserve the right amount of memory for an updated version of the object and also decide whether one object was compatible to another object. As an example a vector of 5 elements could multiply with the row of a matrix if the matrix also had 5 elements per row. A scalar could multiply with an object of any dimension and so on. Strings would be handled as a vector of characters and thus have similar behaviour. With LOGO II it is a bit different. With a scalar, because I use recursion, I don't have to know the number of elements in a list because I just cut out an element at a time and process it, then creates an altered version of the list minus the first element and repeats - until I have an empty list. Similarly I build the new list one element at a time from the processed item isolated from the old list. I still have a full STSC APL language package. It is DOS based and made for the original IBM PC. I did some work with it in the early eighties, but it has been mothballed ever since, and, to be frank, I can hardly understand my own code from back then. That is the downside of this highly 'concentrated' language. You have to analyse old code in detail to make sense of it. For now I am 'factoring' the problem and writing small procedures to solve each step. Just like Forth, actually... 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 17 Share Posted October 17 1 hour ago, jschultzpedersen said: I think that if I were to try my hand at using Forth for this, I would start by creating a data structure with information on my object (dimensions, type of content etc.) this would be like a header for each object. With this data available I could then reserve the right amount of memory for an updated version of the object and also decide whether one object was compatible to another object. As an example a vector of 5 elements could multiply with the row of a matrix if the matrix also had 5 elements per row. A scalar could multiply with an object of any dimension and so on. Strings would be handled as a vector of characters and thus have similar behaviour. With LOGO II it is a bit different. With a scalar, because I use recursion, I don't have to know the number of elements in a list because I just cut out an element at a time and process it, then creates an altered version of the list minus the first element and repeats - until I have an empty list. Similarly I build the new list one element at a time from the processed item isolated from the old list. I still have a full STSC APL language package. It is DOS based and made for the original IBM PC. I did some work with it in the early eighties, but it has been mothballed ever since, and, to be frank, I can hardly understand my own code from back then. That is the downside of this highly 'concentrated' language. You have to analyse old code in detail to make sense of it. For now I am 'factoring' the problem and writing small procedures to solve each step. Just like Forth, actually... From what I can gather your data structure header is the way CoSy works. My crude challenge was to get something working with just an integer array. The header in my case is just the number of elements. If I added a few more fields to my header with a type field and the size of each element, it could do a lot more, but I am just playing with learning the concepts at this stage. I toyed with LISP like CONS in Forth and it can be done but on a retro machine it's pretty memory hungry and I never did get a garbage collector working so that dies pretty fast. It is a very powerful concept however. I have tried grok APL code on occasion without doing the real legwork and I am happy to hear that even a seasoned user has to relearn what they wrote. Forth can do that to it you don't work hard to prevent it and even then ... Yes LOGO and Forth share that aspect of making you build much of your own stuff in small understandable pieces. Hat's off to you for putting the effort in on the TI LOGO system. Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted October 19 Author Share Posted October 19 Wisdom comes with age... or something like that. I just discovered that if I have a list with items where the first item is a valid numeric character, that item can be converted to a number by using the FIRST command. I don't think this is mentioned in the manual, but it works never the less. So I can do it like this... MAKE "LST [42 Doodle] PRINT 1 + FIRST :LST and the answer is 43 MAKE "LST [42 [43 44]] works too MAKE "LST [[42 43] 44] does not work since the first element is in itself a list. To test if the first item is a number, I can use... TEST NUMBER? FIRST :LST IFT PRINT [This is true] In this way I can test whether the first item is a list or a valid number. 2 Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted October 23 Author Share Posted October 23 Hmm!... The previous mail was a bit optimistic. If I take the first item in a LIST, and it happens to be a number type item, then it will be a number type item, obviously. I just got carried away 😀 Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted October 24 Author Share Posted October 24 A routine for multiplying all numeric elements in a list with a specific value is trivial in LOGO II. See code below, which multiplies a list of numbers with 5. As an alternative to using a recursive routine, you can use the combination of TELL and EACH to make a sort of WHILE-WEND loop that stops when there are no more elements in the list. TO MULTIPLY :LIST :M TELL :LIST MAKE "ARRAY [ ] EACH [MAKE "ARRAY LPUT YOURNUMBER * :M :ARRAY ] OUTPUT :ARRAY END PRINT MULTIPLY [1 2 3] 5 5 10 15 It gets more hairy, when you have a list where some of the members of the list are lists of numbers themselves. I haven't solved that one yet. Some sort of multilevel recursion I suppose. Work in progress... 2 Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted October 27 Author Share Posted October 27 (edited) I think this subject is about done now. So I will just publish a somewhat enhanced version of a MULTIPLY function. This version will multiply a number with all members of an array or it can multiply two equal-sized lists of numbers with each others. Results are returned as a list. Just make sure the last argument is a list. TO MULT :M :LST MAKE "L LENGTH :LST MAKE "ANSW [ ] TEST NUMBER? :M IFF IF NOT :L = LENGTH :M THEN OUTPUT [DIMENSION MISMATCH ] STOP IFT REPEAT :L [MAKE "ANSW LPUT FIRST :LST * :M :ANSW MAKE "LST BUTFIRST :LST ] IFF REPEAT :L [MAKE "ANSW LPUT FIRST :LST * FIRST :M :ANSW MAKE "M BUTFIRST :M MAKE "LST BUTFIRST :LST ] OUTPUT :ANSW END PRINT MULT [1 2 3] [4 5 6] 4 10 18 PRINT MULT 5 [4 5 6] 20 25 30 PRINT MULT [2 3] [4 5 6] DIMENSION MISMATCH Edited October 27 by jschultzpedersen attachment wrongly included 3 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 27 Share Posted October 27 Very neat. Now you've gone and done it. Now I have to see if my half baked system can be convinced to multiply an array by another array. 1 Quote Link to comment 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.