This following introduce some fundamental information about writing script in E-Basic.
Logical Operators
Logical operators allow comparison and conditional execution (e.g., If trial > 5 Then…). Often, in script, expressions are used, which compare items using simple mathematical expressions.
> |
Greater than |
< |
Less than |
= |
Equal to |
>= |
Greater than or equal to |
<= |
Less than or equal to |
<> |
Not equal to |
Logical operators are also commonly used in compound expressions. Essentially, logical operators evaluate two expressions and use a set of rules to determine if the total expression is true or false.
Operator | Returns True | Example | Result |
And |
If both expressions are true |
5 > 2 And 6 + 3 = 9 | True |
3 * 3 = 9 And 7 < 6 | False | ||
Or | If either expression is true | 5 > 7 Or 8 * 2 = 16 | True |
8 < 4 Or 3 > 2 | False | ||
Xor | If only one expression is true. Note that it is False if expressions are either both true or both false. | 3 + 2 = 5 Xor 5 + 5 >10 | True |
3 + 2 = 5 Xor 5 + 5 = 10 | False | ||
Flow Control
Controlling the flow of the script is a critical component of programming. There are two major types of controlling the flow: conditional statements and loops.
Conditional Statements
Conditional statements determine or specify which part of the script should be executed based on
a condition. Contingent branching is often utilized in behavioral research and is based on whether a specific item is true or false. Specifically, If…Then statements are very commonly used to control the flow of the code.
If…Then statements simply are equated to making a choice (e.g., if I have money, then I can go to the movies). If…Then statements are the foundation of all logic. Although they seem to be very simple statements, they are quite powerful in a programming language.
There are actually 3 conditional expressions available in E-Basic. They are: If…Then, Select Case, and Do…Loop. These expressions are conditional statements simply because they perform a task based on a single true or false test. All 3 types of conditional expressions are explored in this section.
If…Then statements
The single most commonly used flow control statement is If…Then. Simply put, an If…Then statement will execute a block of code if the condition is true. If the condition is false, it will do nothing unless “Else” is used in the flow control statement.
If condition, then |
<Block of code statements to execute if the condition is true> |
End If |
Rules:
- Notice the “Then” portion of the statement is on the same line as the “If” portion. If there is a need to drop it to the next line, indicate that to the E-Basic compiler. This is done by placing an underscore (i.e., E-Basic line continuation character) at the end of the line to be continued.
- The End If statement is critical. It identifies the last statement in the block of code to be executed based on the condition.
- When the If…Then statement is only a one-line statement, the End If is not used. In fact, it will produce an error if used. In the following two examples, the code works exactly the same, but it is syntactically different.
Example 1: One-line If…Then statement
Dim a As Integer |
a = 12 |
If a > 10 Then MsgBox "A is greater than 10." |
Example 2: If…Then…End If statement
Dim a As Integer |
a = 12 |
If a > 10 Then |
MsgBox "A is greater than 10." |
End If |
If…Then…Else statements
If the program must choose between two alternative blocks of code to execute based on the conditional, then the Else statement is included.
Dim a As Integer |
a = 12 |
If a > 10 Then |
MsgBox "A is greater than 10." |
Else |
MsgBox "A is not greater than 10." |
End If |
Select Case statements
Nested If…Then statements are ideal for testing different values before executing the next block of code. Select Case statements are more appropriate for testing the same value against many different conditions.
Select Case Variable | ||
Case test1 | ||
<block of code statements to be executed if the | ||
value of variable meets test1 criteria> | ||
Case test2 | ||
<block of code statements to be executed if the | ||
value of variable meets test2 criteria> | ||
Case Else | ||
<block of code statements to be executed if the | ||
value of variable doesn't meet any of the | ||
listed Case criteria above> | ||
End Select |
The Select Case structure indirectly uses condition expressions. An expression may be A + B > C. In the example above, think of the variable being what is to the left of the operator (A + B) and test as everything to the right, including the operator (>C).
Rules:
- An unlimited number of cases may be used as test criteria.
- The Else case is optional. It is not required to be used, but can be useful in behavioral research.
Loops
The loop flow control structures are also quite commonly used in programming. They are useful when a block of code needs to be executed more than once. There are three major types of loops available in E-Basic: Do…Loop, For…Next, and For Each…Next.
Type of Loop |
Function |
Do…Loop |
Repeats the block of code until a condition is true. |
For…Next |
Repeats the block of code a specified number of times. |
For Each…Next |
Repeats the block of code for each object within a collection. |
Do…Loops
There are a variety of Do …Loops available in E-Basic.
Statement |
Description |
Do…Loop |
Repeats the block of code until a condition is true and then executes an Exit Do not End Do statement. |
Do…While…Loop |
Repeats the block of code only while a condition is true. |
Do Loop…While |
Executes the block of code once and then repeats it until the condition is false. |
Do Until…Loop |
Executes and repeats the block of code only while the condition is false. |
Do…Loop Until |
Executes the block of code once and then repeats it until the condition is true. |
Do While… Loop
The most typically used Do…Loop is the Do While…Loop. The basic syntax is:
Do While condition |
<block of statements that are executed while condition is true> |
Loop |
E-Basic evaluates the condition when it encounters a Do While statement. If the condition is true, then the block of code within the Loop structure will be executed. When it reaches the Loop statement, the entire process is repeated including re-evaluation of the condition. When the condition is false, the entire loop structure is skipped and E-Basic executes the next statement immediately following the Loop statement of the structure. In theory, no limit exists on the amount of times the block of code within the structure may be executed.
Do…Loop While
The only difference between a Do While…Loop and a Do… Loop While is the location of the condition. The Do While …Loop evaluates the condition before executing the block of code within the structure. The Do Loop…While evaluates the condition after executing the block of code within the structure. The While in this case determines if the block of code within the structure should be repeated based on the value of the condition. The major resulting difference is that a Do… Loop While will always execute the block of code at least once.
Do |
<block of statements that are executed while condition is true> |
Loop While condition |
The Do…Loop While structure is useful when the block of code within the structure sets a value for the condition before it is evaluated. This structure is also useful when performing an action on an item which has more than one element (e.g., a string or an array). Since the item has at least one element, execute the block of code at least once and then repeat it based on the total number of elements within the item.
Do Until…Loop
The Do Until Loop is essentially equivalent to the Do While…Loop structure. They both execute a block of code after evaluating a condition. The Do While structure will repeat a block of code until the condition is false. A Do Until structure repeats a block of code until the condition is true.
Do Until condition |
<block of statements that are executed while condition is true> |
Loop |
Do…Loop Until
Like the Do While Loop varieties, the Do Until Loop also offers the option of setting when the condition is evaluated. In this case, the condition is evaluated at the end of the block of code. Therefore, the block of code is executed at least once.
Do |
<block of statements that are exectured while condition is true> |
Loop Until Condition |
Do Loops with If..Then or Select Case statements
Exit Do
Occasionally, the Do Loop structure doesn’t quite meet the need for the intended flow. For instance, a loop may need to be broken immediately within the block of code contained within the structure. This is accomplished by nesting an If…Then…End If or Select Case structure within the block of code executed by the Do Loop.
Do While condition1 |
If condition2 Then |
Exit Do |
End If |
<block of statements that are executed while condition is true> |
Loop |
Exit Do is particularly helpful in debugging code. Specifically, Exit Do will allow the loop to be bypassed without having to manually comment out the entire Do Loop structure.
Do
While the previously described varieties of Do Loops evaluate a condition at either the beginning or the end of a block of code to be executed (and possibly repeated), it is also possible to evaluate the condition within the actual block of code itself. This requires the use of a nested If..Then or Select Case structure.
Do |
(block of statements to be executed while in the Loop structure) |
If condition Then |
Exit Do |
End If |
<block of statements that are executed while condition is true> |
Loop |
This process is useful when part of the block of code within the loop should be executed, but not the entire block of code.
For…Next Loops
If the number of times a block of code should be repeated is definite, a For…Next loop structure is most appropriate. With this structure, the loop is repeated based on the start and end values supplied. These values can be integers, variable expressions. A counter is used to keep track of the number of times the loop is repeated.
For counter = start To end |
<block of statements to be executed> |
Next counter |
When the loop begins, the counter is set to start. When the Next statement is executed, the counter is incremented by one. When the counter is equal to the end value supplied, the loop terminates and the next line of code outside the loop structure is executed.
Tips:
- Keep it simple. Unless there is a specific reason to start the counter at another value, use 1 to n.
- Although the counter variable is not required to follow the Next statement, it is good practice to include it. It may seem verbose, but makes parsing through the code a bit easier.
- Avoid changing the value of the counter within the loop structure manually. Let the Next statement increment the counter unless there is a specific reason to change the counter (e.g., set it to the end value to terminate early).
For…Next loops are particularly useful when working with arrays. An array is similar to a storage bin with numbered slots.
Exit For
Similar in concept to Exit Do, the Exit For statement allows the loop to terminate early. This is typically used in conjunction with If..Then and Select Case statements within the For…Next loop.
For Each…Next Loop
This version of the For…Next Loop is similar to the previous version. However, the primary distinction is that it is used to perform a block of code for each element within a set, rather than for a specified number of times. For Each…Next requires an element or variable that corresponds to the object types within the collection.
For Each variable In collection |
<block of statement to be executed> |
Next variable |
Notice a counter is not specifically used in this version of a For Loop. Instead, E-Basic figures out how many times to repeat the block of code based on the items in the collection specified. This is particularly useful when debugging. If a problem is suspected with perhaps one of the TextDisplay objects within a block, try ‘stepping’ through the processing of each object displaying a marker to the screen to help track down the problem.
Interrupting the Flow
GoTo Label
When a design calls for jumping to another place within the script based on a specific flag, the Goto statement is useful. In behavioral research, this is often required for contingent branching experiments. For example, perhaps the execution flow should continue uninterrupted until a participant responds by pressing the “a” key. If the participant presses any other letter, the execution flow should jump, or Goto a specific location within the code. In the example below, a Label is placed prior to an input statement (i.e., AskBox). The input is examined, and if it is not the required input, the execution of the program jump back to the Label at the beginning of the script in order to perform the response collection again. If the required input is entered (i.e., “a”), the program jumps to a point later in the script.
Dim answer As String |
LabelB: |
answer = AskBox ("Type in a letter:") |
If answer = "a" Then |
Goto LabelA |
Else |
MsgBox "That is the wrong letter, try again!" |
Goto LabelB 'Ask for another letter |
End If |
LabelA: |
MsgBox "Way to go!" |
Examples and Exercises
To begin adding user code, it is important to understand the basics of programming. The following examples illustrate the simplicity of E-Basic code. Be sure to follow through these examples before progressing to more advanced topics. It is recommended that each user actually implement each example, run it and verify that it works as expected before moving on to the next section. Some of the initial examples can be created in a blank E-Studio file; other examples involve modifications to one of the supplied sample experiment files. Specific instructions are provided for each section.
Example 1: Display “Hello World” on the screen
To run this example, create a new E-Studio experiment which has only an InLine object on the
SessionProc. The InLine object should contain the script provided below:
' The following statement will display a dialog box on the screen with the text "Hello World."
' By default, an OK button is also displayed.
Display.MsgBox "Hello World"
Example 2: Setting Attributes in the Context Object
The SetAttrib method is used to create an attribute and assign it a value. Specifically, the SetAttrib method is used to place the attribute in the context so that it may be assigned, modified, and referenced. In the example below, “c” has been defined as the Context object. This is done internally by E-Prime, and need not be explicitly entered into the script. The SetAttrib method is used in conjunction with the dot operator to declare TotalTrial as an attribute of the context object (“c”) and assign it a value of 10.
As with Example #1 above, to run this example you should create a new E-Studio experiment with an InLine object on the SessionProc and enter the script below.
' Set TotalTrial =10
c.SetAttrib "TotalTrial", "10"
Once an attribute is put into the context, the information is logged in the data file and the attribute may be used to display information by way of a display object (e.g., a TextDisplay).
The TotalTrial attribute will be available in the context during the scope of the level at which it has been defined. For example, if TotalTrial is defined (using SetAttrib) during the block level Procedure, it will be available during the context of the block level, and any context levels subordinate to the block (e.g., trial level, sub-trial, etc.). However, outside of that scope, the TotalTrial attribute value will not be available. There is no backward inheritance possible, which would allow higher levels to inherit attribute information from lower levels.
Figure 1. Inheritance within the Context flows from top level (Session) to lower levels (Block and Trial)
An attribute must be defined before it is referenced, or error messages will result indicating that the attribute does not exist. For example, if an attribute is defined at the trial level, and referenced at the block level (prior to the trial), an error will occur related to the declaration of the attribute.
The inheritance of the value to assign to an attribute follows the hierarchical structure, and values may only be inherited by levels lower than the level at which the attribute is defined. Thus, if an attribute is defined at the block level, it may be referenced at the trial or sub-trial level. Inheritance occurs in a downward direction, while the search for a value occurs in an upward direction. For example, if an attribute is defined at the block level and referenced at the trial level, the value at the trial level will be inherited from the block level (i.e., downward). The resolution of the value occurs by first searching the current level (i.e., trial), then continuing the search at the next highest level (e.g., block), and upward until the value is resolved.
Example 3: Getting Attributes from the Context Object
The GetAttrib method is used to retrieve a value for an existing attribute in the context. Like SetAttrib, the GetAttrib method is used in conjunction with the dot operator.
In the example below, the TextStimulus object displays a stimulus “X” or “Y.” In the script, the IF… THEN clause is used to evaluate the current stimulus and set its display color. The GetAttrib method will retrieve the value of the current stimulus. When GetAttrib returns a value of “X” the ForeColor property of the TextStimulus is set to “Green,” so that all X’s will be displayed in the color green. When GetAttrib returns a value of “Y,” the ForeColor property is set to “Blue” so that all Y’s will be displayed in the color blue.
To run this example, open the BasicRT sample experiment file, copy the script below into an InLine object placed at the beginning of the TrialProc, and run the experiment.
'Retrieve value of "Stimulus" and set display color
If c.GetAttrib("Stimulus") = "X" Then
Stimulus.ForeColor = Color.Red
ElseIf c.GetAttrib("Stimulus") = "Y" Then
Stimulus.ForeColor = Color.Green
End If
Example 4: Global Variables
Often, it is desirable or useful to determine the participant’s performance over the course of the experiment, or perhaps after a specified number of blocks or trials. One method of assessing performance is to use a FeedbackDisplay object, which can automatically calculate summary statistics (e.g., mean accuracy, mean RT, etc.). Another method of assessing performance involves the use of the Summation object. This method requires more involvement from the user, because user-written script is required, but it enables you to control precisely if and when the participant is presented with performance feedback. (i.e., While the FeedbackDisplay object performs all of the performance calculations automatically, it also presents feedback automatically). The example below uses a Summation object to determine average accuracy after a specified number of trials, but without presenting feedback to the participant. This example is illustrated within the BasicRT sample experiment file.
To use a Summation object to determine the average accuracy per condition or block, declare the Summation object on the User tab in the Script window. In most cases, accuracy would only be examined after a minimum number of trials. Thus, in order to start evaluating mean accuracy after a certain number of trials had been run, it be is also necessary to declare a counter to manually count the number of trials that have occurred. In the script below, the PracticeProp summation variable is declared for use in evaluation of the practice trial performance; the TrialCount integer variable is declared to keep track of the running trial count. Enter this script on the User tab in the Script window.
'Declare Variables
Dim PracticeProp As Summation
DimTrialCount As Integer
Once declared in the User Script window, the variables are available globally, or for the scope of the entire experiment. The variables must be initialized prior to the point in the experiment at which they are referenced. This is accomplished using an InLine object, inserted on the Session Procedure timeline. The InLine may occur at any point prior to the referencing of the variables. However, it is a good practice to insert the initialization InLine as the first event in the Session Procedure, which can serve to set up or initialize any variables that will be used. To continue with this example, add an InLine object named Setup as the first event on the SessionProc in the BasicRT sample experiment, and enter the script below:
'Initialize Summation Variable
SetPracticeProp = New Summation
'Initialize TrialCount Variable
TrialCount = 0
The Set command is used to initialize the PracticeProp summation variable. This command defines the variable as a new instance of an existing object type. The TrialCount variable is initialized to zero since no trials have yet been run.
Once initialized, the variables may be assigned values and referenced within the context in which they were defined. In this case, the defined context was the top-level context (i.e., User tab at the experiment level). Thus, the variables are defined globally and may be referenced at any point in the program.
The script below illustrates how the Summation and counter variables are assigned values on each trial. The counter is manually incremented by one on each trial. The Summation variable collects accuracy statistics across trials during the entire block. In the BasicRT experiment, the responses are collected by the “Stimulus” object. Thus, the InLine that contains this script must follow the Stimulus object on the trial Procedure. In the BasicRT experiment file, add an InLine object following the Stimulus object on the TrialProc, and enter the script below:
'Increase counter by 1
TrialCount = TrialCount + 1
'Add accuracy stats to summation variable
PracticeProp.AddObservation Stimulus.ACC
'When trial count = 5, evaluate accuracy stats
If TrialCount >= 5 Then
'If accuracy is 80% or better exit block
If PracticeProp.Mean >= .80 Then
TrialList.Terminate
End If
End If
At five trials or more (i.e., TrialCount >=5), the mean of the values collected by the Summation is evaluated. If mean accuracy is greater than 80%, the currently running List (i.e., TrialList) is terminated. Thus, the script examines the overall accuracy of the block and terminates the block when a minimum accuracy of 80% is reached.
NOTE: Verify that the PreRelease property for the Stimulus object (on the Duration/Input tab of the Stimulus object Property Pages) is set to 0 to ensure that the InLine script is not processed prior to actually collecting a response to the stimulus.
Example 5: Trial Level Variables
Declaring global variables on the User tab of the script window permits the reference of these variables at any point in the experiment. Conversely, variables to be used only within a specific context (e.g., block or trial Procedure) may be declared using the Dim command in an InLine object on the appropriate Procedure. In the script below, the Dim command is used to declare a variable which collects a response on each trial. This script is entered in an InLine object, which is called from the trial-level Procedure object.
'Collect response from AskBox
Dim strAnswer As String
strAnswer = Display.AskBox ("Type in the recalled word:")
Stimulus.RESP = strAnswer
Stimulus.CRESP = c.GetAttrib("CorrectAnswer")
Example 6: Using Attribute References to Pass Information
Attributes allow the passing of variable information during a Procedure. List objects are used to organize data used within an experiment in attributes (see E-STUDIO: List Object [22700], and attribute values may be accessed using the c.GetAttrib command. The image below illustrates a List object defined within a basic Stroop task, in which the display color of the word varies per trial. The text stimuli (i.e., color words) and display colors (red, green, blue) are entered as values in the “Word” and “Color” attributes.
The values of the Word and Color (or other) attributes may be accessed in script using the c.GetAttrib command. For example, the script below illustrates use of c.GetAttrib and Debug.Print to access the values on a specific trial and write them to the Output window (e.g., for monitoring selection during testing).
‘ Write stimulus and color to the Debug tab in the Output window
Debug.Print "Word = " & c.GetAttrib("Word")
Debug.Print "Color = " & c.GetAttrib("Color")
Next Article: SCRIPTING: Programming: Intermediate [22905]
Previous Article: SCRIPTING: Steps for Writing E-Prime Script [22880]
See Also:
More advanced information concerning programming may be found in SCRIPTING: Programming: Intermediate [22905] and SCRIPTING: Programming: Advanced [22909].
NOTE: Detailed information concerning scripting in E-Basic can be found in the E-Prime Command Reference (https://pstnet.com/ecr).
Lastly, the E-Prime 2.0 Introduction to Scripting Webinar contains information on getting started with scripting in E-Basic. Materials for the webinar are attached to this article.
Comments
0 comments
Please sign in to leave a comment.