conditionals in fig

this is part 6 of an introductory series on fig programming. for part 5, go here.

 

part 6: conditionals in fig

 

weve covered a couple kinds of block so far:

  • python marks lines written in python, then fig ends the block
  • while marks lines that will loop, then wend marks the bottom of the lines that will repeat
  • forin and for mark the beginning of a loop through numbers or arrays, and nextin or next marks the bottom of those loops

 

now we have another kind of block:

  • a condition describes part of the state of the running program, and:
  • the lines inside the block only run if the condition is satisfied / true

 

normally the “part of the state” is just the value of a variable.

like with python these blocks will end with the fig command. here is a very simple example:

iftrue 1
    now "that is true"  print
    fig

 

an iftrue conditional has one parameter, and if the parameter is “true” (non-zero) then it will run the code inside the block (between the conditional and the fig command.)

in the previous example, 1 is non-zero so it runs the code in the block:

now "that is true"  print

 

what isnt true? a zero, or a zero-length string:

iftrue ""
    now "this will not print"  print
    fig

 

so what about iffalse? for that, fig has a command that will invert a conditional, but first lets talk about blocks without code inside:

iftrue ""
    fig

 

will give you an error message when it runs. use pass as your placeholder for actual code:

iftrue ""
    pass
    fig

 

the ifequal conditional will compare two parameters, and is true if they are equal:

x "when is your birthday?"  print lineinput
d date

ifequal x d
    pass
else
    x "a very happy un-birthday to you!"  print
    fig

 

this program (assuming you type the date in using mm/dd/yyyy format) asks you to type in your birthday, and if the date is not today’s date, it wishes you a happy un-birthday.

the else command separates a conditional block into a two-part conditional block:

  • if the first part is true, it runs the code between the condition, and else
  • if the first part is NOT true, it runs the code between else and the bottom of the conditional

 

lets use the randint function with its “lowest” and “highest” parameters to product a number between 1 and 10. then ask the user to guess the number:

x randint 1 10
y  "guess a number from 1 to 10: "  print  lineinput

ifequal x y
    now "you guessed correctly!"  print
else
    now "good try, but you didnt guess it."  print
    fig

 

something is wrong with this program, and it will never work the way its intended to. but we can fix it!

the randint command returns an integer, but lineinput returns a string. when ifequal compares an integer and a string, it will NOT detect a match even when one is string “5” and the other is numeric 5!

we can fix this by making the value from randint into a string using str, or making the output from lineinput into a numeric using val. since we dont know what to expect from lineinput (the user could type anything) we will convert the randint:

x randint 1 10  str
y  "guess a number from 1 to 10: "  print  lineinput
ifequal x y
    now "you guessed correctly!"  print
else
    now "good try, but you didnt guess it."  print
    fig

 

by adding str to the end of the randint output, we ensure that when ifequal compares it to the number the user types in, at least a string is being compared to a string.

there are other improvements worth making, but for now this is good enough. (which commmands will compensate for extra spaces on either side of what the user types in?)

this is a great time to add a while loop. currently the user has one guess, and we could give an exact number of guesses with a for loop, but that wouldnt demonstrate a while loop doing something truly functional, would it? lets give unlimited guesses, so you can see how to do that:

while
    x randint 1 10  str
    y  "guess from 1 to 10: "  print  lineinput

    ifequal x y
        now "you guessed correctly!"  print
        break
    else
        now "good try, though."  print
        fig
    wend

 

4 things to notice here: the while at the top– the wend at the bottom– plus, a correct guess stops the loop using break after telling you that you guessed correctly.

but perhaps the most important thing is the line with randint on it. because once again, it will not work (exactly) the way that we intend it to:

while
    x randint 1 10  str
    y  "guess from 1 to 10: "  print  lineinput

 

do you see whats happening? it gets a random number and gets the user to input a guess. ok… when it loops, it gets another random number!

since the number is always 1-10, the user can just keep guessing 5 (or any other number in range) until the computer picks the users number randomly! so lets have it pick the number ONCE:

    x randint 1 10  str
while
    y  "guess from 1 to 10: "  print  lineinput

    ifequal x y
        now "you guessed correctly!"  print
        break
    else
        now "good try, though."  print
        fig
    wend

 

now it works the way it is designed to: the user has to keep guessing a different number until they can guess the one the computer picked.

but now that youve seen the while loop work in a way that the program can get out with a conditional break, lets replace it with a for loop so we can limit the number of guesses the user gets:

guesses 4
x randint 1 10  str
for r  1 guesses 1
    y  "guess from 1 to 10: "  print  lineinput

    ifequal x y
        now "you guessed correctly!"  print
        break
    else
        now "good try, though."  print
        fig
    next

 

we didnt have to change wend to next, it just looks more reasonable that way. also we didnt have to make a variable called guesses, we couldve just put a 4 between the 1 and 1. but this is clearer.

lets take a look at the output this program will show the user, along with the numbers the user might type in:

guess from 1 to 10:
5
good try, though.
guess from 1 to 10:
2
good try, though.
guess from 1 to 10:
8
you guessed correctly!

 

how about another condition to say the user ran out of guesses? the for loop keeps track of which guess the user is on, in the r variable, right? we can use that:

guesses 4
    x randint 1 10  str
for r  1 guesses 1
    gsss guesses  minus r  plus 1  str
    y "you have " plus gsss  plus " guesses."  print
    y  "guess from 1 to 10: "  print  lineinput

    ifequal x y
        now "you guessed correctly!"  print
        break
    else
        now "good try, though."  print
        ifequal guesses r
            now "sorry, no more guesses."  print
            fig
        fig
    next

 

here are the relevant lines of the changes we made:

guesses 4
    x randint 1 10  str
for r  1 guesses 1
    gsss guesses  minus r  plus 1  str
    y "you have " plus gsss  plus " guesses."  print

 

also:

        now "good try, though."  print
        ifequal guesses r
            now "sorry, no more guesses."  print
            fig

 

these two changes dont need each other; the second change would still work by itself, and the stuff at the top could work without the bottom part.

lets go over what we know:

  • the for loop will repeat guesses times, which in this case is 4.
  • the loop tracks which repeat (which guess) its on, in the variable r.
  • so if r is the same number as guesses, it is on the last guess (in this case, it was already used.)

 

that pretty much explains the part at the bottom. it doesnt run until after the program tells the user they guessed wrong, so if guesses is the same number as r, the last guess was used.

what about the top part? this is just addition and subtraction:

    gsss guesses  minus r  plus 1  str
    y "you have " plus gsss  plus " guesses."  print

 

  • gsss is set to the limited number of guesses (4.)
  • then r (which guess user is on: 1 or 2 or 3 or 4) is subtracted, so if guesses is 4 and r is 1 (first guess) then there are 3 guesses left.
  • but… the user hasnt guessed yet! so we add 1 more:  “plus 1” since guess 1 is still in play.
  • then we convert that number to str and put it in a string between “you have ” and ” guesses.”
  • then we print it.

 

from the top, it looks really complicated. but if you want this functionality, its just:

gsss guesses  minus r  plus 1  str
y "you have " plus gsss  plus " guesses."  print

 

you may find with logic like this, that the
stricter syntax in python is easier to work with.

here is what that looks like:

guesses = 4
from random import randint
x = str( randint(1, 10) )

for r in range(1, guesses + 1, 1):
    gsss = str(guesses – r + 1)
    y = "you have " + gsss + " guesses." ; print y
    y = "guess from 1 to 10: " ; print y
    y = raw_input()

    if x == y:
        print "you guessed correctly!"
        break
    else:
        print "good try, though."
        if guesses == r:
            print "sorry, no more guesses."

 

some of the differences between fig and python:

  • python cares what case you use (normally all-lower. but the same variable name, capitalized differently, counts as two different variables.)
  • parentheses are not usually optional (in fig they are.)
  • you must use = to set a variable, and == to compare (fig requires neither; = can set variables.)
  • functions(are(parenthetical + str(that) + can())) #### become complicated.
  • instead of starting blocks with one command marking the bottom with fig or another command, you have to indent (in fig, this is optional) everything after a block starter. when you are done with the block, you un-indent.
  • colons at the end of a block-starter are generally required, in python.
  • python 3 and python 2 differ from each other in how they use the print command.
  • many commands, like randint, have to be imported.

 

believe it or not, this isnt meant to discourage you from using python. if youre comfortable with mandatory indentation, it can be very beautiful (i wrote fig in python, so i know its a great language.)

but when i try to teach python to people, i noted what gripes came up the most. mandatory indentation is good for some and terrible to others. fig doesnt have it. case-sensitivity is fine for most coders– i preferred basic when it was not case-sensitive (in some dialects it is now.)

if you love python, here is an approximation of the same code in fig, using optional () and = and : and such:

# a program in pure fig code
guesses = 4
x = randint(1, 10) ; str()

for r (1, guesses, 1):
    gsss = guesses ; minus r ; plus 1 ; str()
    y= "You have ";plus gsss;plus " guesses.";print()
    y = "Guess from 1 to 10: " ; print()
    y = lineinput()

    ifequal x, y:
        now = "You guessed correctly!" ; print()
        break
    else:
        now = "Good try, though." ; print()
        ifequal guesses, r:
            now = "Sorry, no more guesses." ; print
            fig
        fig
    fig

 

obviously you cant dress up fig exactly like python (without putting it between python and fig commands, that is) but you can dress up fig, if you want to.

whatever you consider “simple” is what you should stick to code-wise, until you are ready and interested in getting more complicated. when youre ready, there are lots of things to try, including making new fig commands using function and/or inline python. and there are more conditionals!

to review: else inverts a conditional, and pass is a placeholder (in case you dont want to run code for every condition, but you do want to run code for some.)

using a comment # instead of pass will not work in loop and conditional blocks. python is the same way– the pass command does exactly the same thing in python code.

ifequal  x y
    now print "yes"
    fig
ifmore  x y
    now print "yes"
    fig
ifless  x y
    now print "yes"
    fig

 

the ifmore (x, y) conditional is true only if x is more than y.

the ifless (x, y) conditional is true only if x is less than y.

substitute x with some other variable or value; and/or substitute y with some other variable or value.

once you feel confident that you understand conditionals, else and pass, there is a very useful conditional-like block that is very special: the “condition” it handles is an error.

it works like this:

try
    pass
    # try to do this
except
    pass
    # run this code if there was an error before
    resume

 

resume is another substitute / alias for fig which you can use instead (as usual) if you prefer.

try
    x 5  divby 0
except
    x "you cant divide numbers by zero."  print
resume

 

catches a real error. of course no one thats paying attention is going to write “divby 0” in their program, but with divby y the y could be anything; so this example is more useful in a real program than it may first appear.

you dont need to use error catching on every use of the divby command, but its quite often worth it in situations where user input (or even input from a file) is involved.

you can use a try / except / resume to try opening a file that isnt available (or that the user didnt spell the name of correctly,) or you could put it in a loop that tries to convert user input to a numeric, and asks again if it cant:

while
    x "please enter a number: "  prints  lineinput
    try
        y x  val
        # if that didnt trip except, break loop
        break
    except
        now ""  print  "thats not a number."  print
        resume
    wend
now y  str  plus " times 5 is: "  prints
now y  times 5  print

 

that functionality we just created could be used more than once in a program that asks for numbers. lets simplify it before getting into functions:

while
    x "please enter a number: "  prints  lineinput
    try
        y x  val
        break
    except
        now ""  print  "thats not a number."  print
        resume
    wend


now y print # this is the number we know is numeric.

 

 

Advertisements

2 thoughts on “conditionals in fig

    1. like this, yes: (added newlines but changed nothing else.)

      ifmore x y
          iftrue 1 
              now "In if-clause 2" print 
              fig 
      else 
          now "Never enter second if-clause" print 
          fig

      and you coded it perfectly (the indents are optional) and the strings reflect the actual status (provided x and y are set, and depending on whether x is more or not.)

      if x is more, it puts “In if-clause 2” on the screen, and if x is not more, it says “Never enter second if-clause”

      Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s