Hey, haven't been around the TI-BASIC scene in a while, but recently thought of something I figured some of you might like that gives legitimate functionality to something (last I ever heard) considered without practical use.

Functions (the u, v, and w lowercase letters) are essentially strings that when called will return their expr() result, essentially, but few can find a good legitimate use of them. Acting as strings they can be changed while running a program and, acting as a function, they return results based on their string, but if you have no intention of changing their string while running the program you might as well type out the characters in their place instead of relying that the function will be what you need it to be, leading to potential instability in your program.

While thinking over some aspects of how to make a game recently, I remembered about functions and found a good use for them that can be extended to many different programs. Their ability to be changed while executing a program leads them to be a fantastic variable type for configurable options holding configured conditions.

My example for this would be from the game that lead me to making this post (thanks KermM) that I call Presidents, but it goes by many names, with even more play variants. The exact rules of the game aren't important. Do know, however, that according to one variant, you must play a card of lower value than the previously played card, another variant allows you to play equal value cards, and a third variant allows you to skip the next players turn if you play equal value cards. Although I never had such a play variant, for sake of argument, I'll add in a fourth that adds a card specifically to skip the next player's turn. In the following examples, C is the current card's value, P the previous card's value, V the current variant selected and 8 would be the constant used for the skip card.

Code:

-Options-

:Input V

-Code-

:If V=3 and P=C or V=4 and C=8
:Then
:[skip next player's turn]
:End
:If V=1 and P>C or (V=2 or V=3) and P≥C or V=4 and (C=8 or P>C)
:Then
:[continue with player's turn]
:Else
:[disallow attempted move]
:End

With only a few minor options in the game, some of the code can already start looking bloated and sloppy, but if in this code functions were used in place, it could look much cleaner:

Code:

-Options-

:Input V
:sub("000000P=CC=14",3V,3→u
:sub("P>C+000P≥C+000P≥C+000C=8 or P>C",7V,7→v

-Code-

:If u
:Then
:[skip next player's turn]
:End
:If v
:Then
:[continue with player's turn]
:Else
:[disallow attempted move]
:End


The 000 in the first string are used because there is no method to skip a players turn in the first two variants, and the +000 in the second string are used simply as buffers to take up the whole 7 characters without returning a Syntax Error.

This style of configurable options can mean better optimized code for conditions that are repeated several times throughout a program, and may mean better speed of execution of your code, but that depends on how well it can decode the string into its tokens and execute fewer tokens than executing a longer condition.

Although my example was specifically for a game, it can be used in any style of program that has or needs options. Hope you guys enjoy.
This is definitely a nifty trick that people should know. Of similar utility is the ability to store list-generating functions to a List variable as a string, and have them automatically recompute on access. Example:


Code:

"seq(J^2I,I,1,K)"->L1
Prompt J,K
L1


This is similar to:

Code:

Prompt J,K
seq(J^2I,I,1,K)->L1
L1

except that L1 is automatically updated for new values of J,K every time you retrieve it,

The ability to do this is documented in very few places, but is very nifty.
That's a great trick, and for some reason people (myself included) almost always forget about it and use seq() instead. Thanks for pointing out that trick as well, elfprince13. And Mufin, great call on how those automatically-expr()'d variables can be used for dynamic reconfiguration of programs' logic.
elfprince13 wrote:
This is definitely a nifty trick that people should know. Of similar utility is the ability to store list-generating functions to a List variable as a string, and have them automatically recompute on access. Example:
Code:
"seq(J^2I,I,1,K)"->L1
Prompt J,K
L1

This is similar to:

Code:
Prompt J,K
seq(J^2I,I,1,K)->L1
L1
except that L1 is automatically updated for new values of J,K every time you retrieve it.

The ability to do this is documented in very few places, but is very nifty.

I knew you could do something similar to that for the graphing variables like Y₁ (from http://tibasicdev.wikidot.com/selfmodify), which are internally stored as strings, but I had NO IDEA you could do that for regular lists. Thanks for that! Here, have a nonexistent cookie!

Are there any differences between using regular lists and lists as strings like this? So far, all I've noticed is that there's a dot at the end of the list name in the stat editor (bug?), and that if you enter L₁ on the home screen the result shows up on the left side of the screen, like a string.
Be aware that you're paying the expense of recomputing the list when you access it. I'm not sure if this happens line-by-line, or access-by-access, but either way, you need to be aware of it.
I started investigating what elfprince13 brought up: is a list with a formula stored in it recomputed once per line/statement, or once per access?

A useful feature of TI-BASIC for this type of investigation is the u/v/w equation variables. When u(something) is called, n is incremented after the equation is evaluated. Therefore, if we set "{u(n)}"->L1, we can see how many times L1 has been evaluated.

I tried this code:

Code:
"{u(n)}"->L1:0->n:augment(L1,L1


In the augment( statement, any sane parser (from what I've read of the shunting yard algorithm) should evaluate the left side first.

If it returned {0,0}, L1 would have been executed once, while if it returned {0,1}, L1 would have been executed twice.

It returns {1,1}, meaning that the list was evaluated twice, but the second value was the one used both times. This confuses me greatly, as I can't find a reasonable reason why a parser would do this.
Hot a that's bizarre. I just tried the same thing with "seq(u(n),I,1,4)"->L1 and got {4,5,6,7,4,5,6,7} as a result. However, if I follow this up with {L1(1),L1(1) I get {8,12}. So it seems to always be evaluated twice, but the output value depends on whether you're using the list directly, or indexing into it. I would guess the former behavior is a bug.
So it's worth pointing out that all of the "Y-Vars" are functions in the sense described above - shortcuts for
Code:
expr("SOME STRING HERE")
. What makes u/v/w special is they can be defined recursively in terms of previous entries, and called with multiple arguments to generate a list, which allows you to use them as a recursive form of seq().
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement