Search code examples
pythonvalagenie

Fixing a for loop in Genie


I would like to make a simple password check routine in Genie, however I got stuck in a for loop. Here is the python code I want to mimic:

#-----------------------------------------------
# password_test.py
#    example of if/else, lists, assignments,raw_input,
#    comments and evaluations
#-----------------------------------------------
# Assign the users and passwords
users = ['Fred','John','Steve','Ann','Mary']
passwords = ['access','dog','12345','kids','qwerty']
#-----------------------------------------------
# Get username and password
usrname = raw_input('Enter your username => ')
pwd = raw_input('Enter your password => ')
#-----------------------------------------------
# Check to see if user is in the list
if usrname in users:
    position = users.index(usrname) #Get the position in the list of the users
    if pwd == passwords[position]: #Find the password at position
        print 'Hi there, %s. Access granted.' % usrname
    else:
        print 'Password incorrect. Access denied.'
else:
    print "Sorry...I don't recognize you. Access denied."

Here is as far I could get:

[indent=4]

init
    users: array of string = {"Fred","John","Steve","Ann","Mary"}
    passwords: array of string = {"access","dog","12345","kids","qwerty"}

    print "Enter user name"
    var usrname = stdin.read_line()
    print "Enter password"
    var pwd = stdin.read_line()

    var position = 1
    var i = 1
    for i=0 to i < users.length
        if (users[i]==usrname)
            position += 1
            if pwd == passwords[position]
                print "Hi there, %d. Access granted."
            else
                print "Password incorrect. Access denied."
        else
            print "Sorry...I don't recognize you. Access denied."

However, I have been getting the error on the compiler:

$ valac evenmores.gs 
evenmores.gs:15.18-15.18: error: syntax error, expected `do' but got `<' with previous identifier
    for i=0 to i < users.length
                 ^
Compilation failed: 1 error(s), 0 warning(s)

I also tried the for loop as suggested in here:

for (i = 0; i < users.length; i++)

With no avail. I would apreciate some help. Thanks.


Solution

  • You should remove var i = 1 and use for i:int = 0 to (users.length - 1)

    There are a couple of points here:

    • When the Genie for loop is used like this it is only to generate a number sequence. Be aware to generate a decreasing number sequence you need to use downto instead of to. A better way of iterating over an array is given below
    • Genie is strongly typed and block scoped. When you first tried the for loop you may have got the error "The name 'i' does not exist in the context of `main'" and this is why you added var i = 1. You can, however, declare the variable as part of the for loop as shown above. Generally for the fundamental types such as string and int I prefer to make the type explicit, but you can use type inference as well. for var i = 0 to (users.length -1) will also work

    To iterate over an array it is better to use the for item in array syntax. For your example this would look like:

    [indent=4]
    init
        users: array of string = {"Fred","John","Steve","Ann","Mary"}
        passwords: array of string = {"access","dog","12345","kids","qwerty"}
    
        print "Enter user name"
        usrname:string = stdin.read_line()
        print "Enter password"
        pwd:string = stdin.read_line()
    
        position:int = 0
        for var user in users
            if (user==usrname)
                if pwd == passwords[position]
                    print "Hi there, %s. Access granted.", usrname
                else
                    print "Password incorrect. Access denied."
            else
                print "Sorry...I don't recognize you. Access denied."
            position++

    There is a fundamental problem with your code as you will see when you run it. I think a better solution would be to use a dictionary:

    [indent=4]
    init
        var access = new dict of string,string
        access[ "Fred" ] = "access"
        access[ "John" ] = "dog"
        access[ "Steve" ] = "12345"
        access[ "Ann" ] = "kids"
        access[ "Mary" ] = "qwerty"
    
        print "Enter user name"
        username:string = stdin.read_line()
        print "Enter password"
        pwd:string = stdin.read_line()
    
        if !(username in access.keys)
            print "Sorry...I don't recognize you. Access denied."
        else
            if pwd == access[ username ]      
                print "Hi there, %s. Access granted.", username
            else
                print "Password incorrect. Access denied."

    The key points:

    • A Genie dictionary needs libgee to work so you will need to install Gee and its development files. To build the program use valac --pkg gee-0.8 my_example.gs
    • A dictionary is made up of keys and values. To test that a user name is not present the ! operator is used and the in keyword. Note also the .keys
    • To access the values in the dictionary square brackets containing the key is used: access[ username ]