11 Replies - 2188 Views - Last Post: 06 August 2012 - 02:55 PM Rate Topic: -----

#1 atraub  Icon User is offline

  • Pythoneer
  • member icon

Reputation: 759
  • View blog
  • Posts: 2,010
  • Joined: 23-December 08

Spot The Error

Posted 06 August 2012 - 01:43 PM

At work, I'm using a NoSQL db called Redis. I test and play with the db using Python (the interpreter makes it pretty painless to really get my hands dirty with it). Then, once I work the kinks out, I translate my code to C++. I came across an interesting error today and it made me smile, so I thought I'd share it with you guys.

Here's the code:

import redis

def deleteUser(userID):
    addToUnregistered = False

    for key in x.keys("user:"+str(userID)+":*"):#for each key associated with a user
        addToUnregistered = addToUnregistered or x.delete(key)#delete the key and 'or; the result of that delete against addToUnregistered
    
    if addToUnregistered: #if a key was deleted
        x.lpush("unregisteredUserIDs",str(userID)) #add the userID to the list of unregistered User Id's



A quick explanation. Redis is a NoSQL database. Based on some company requirements, all information that is associated with a given user will have "user:userIDNumber:" at the beginning of the data. So, a quick example might be "user:1:age". When a user gets deleted, we add his userID to a list of unregistered ID's.

So, I create a variable called addToUnregistered and set it to False. When redis deletes a key, redis returns True. So, I do a logical "or" against the output of deleting the key and addToUnregistered. This ensures that addToUnregistered is only true if I successfully deleted a key. If it's true, I add it to the unregisteredUserIDs list.

BUT SOMETHING WENT WRONG! If I try to delete a bad UserID, everything works perfectly, but if I try to delete a good one, only the first key gets deleted and the userID does get added to the unregistered list. Can Anyone spot my error?

The redis commands are correct.

Haha this spoiler doesn't hold the answer, but it does have some proof that I know the answer... just incase you guys thought I was trying to get you to do my job lol
Spoiler

This post has been edited by atraub: 06 August 2012 - 01:50 PM


Is This A Good Question/Topic? 1
  • +

Replies To: Spot The Error

#2 xclite  Icon User is offline

  • LIKE A BOSS
  • member icon


Reputation: 905
  • View blog
  • Posts: 3,167
  • Joined: 12-May 09

Re: Spot The Error

Posted 06 August 2012 - 01:51 PM

Are you allowed to modify the structure you're iterating over?
Was This Post Helpful? 1
  • +
  • -

#3 jon.kiparsky  Icon User is online

  • Pancakes!
  • member icon


Reputation: 7739
  • View blog
  • Posts: 13,075
  • Joined: 19-March 11

Re: Spot The Error

Posted 06 August 2012 - 01:51 PM

Looks like a concurrent modification issue to me, but I don't know how x handles deletes - could be safe, for all I know.
Was This Post Helpful? 1
  • +
  • -

#4 atraub  Icon User is offline

  • Pythoneer
  • member icon

Reputation: 759
  • View blog
  • Posts: 2,010
  • Joined: 23-December 08

Re: Spot The Error

Posted 06 August 2012 - 01:53 PM

Not bad guesses guys, but I don't actually modify the structure. The query returns a list that I don't alter, instead I modify the database keys associated with the strings in the list. verbal vomit sounds like verbal vomit, I said it better below the edit lol

EDIT:
x is the redis database connection, I was using globals in the interpreter XD shoulda mentioned that


In other words, x.delete() only affects the values in the database, not the output from my previous query, so that part is completely safe :)

This post has been edited by atraub: 06 August 2012 - 01:57 PM

Was This Post Helpful? 0
  • +
  • -

#5 xclite  Icon User is offline

  • LIKE A BOSS
  • member icon


Reputation: 905
  • View blog
  • Posts: 3,167
  • Joined: 12-May 09

Re: Spot The Error

Posted 06 August 2012 - 01:57 PM

Oh. Duh. Shortcircuiting.

Edit: To clarify, since after the first iteration, addToUnregistered is True, it never goes beyond the "or" because the interpreter knows the statement can't be false. Does Python have a non-short-circuited "or"?

This post has been edited by xclite: 06 August 2012 - 01:59 PM

Was This Post Helpful? 4
  • +
  • -

#6 jon.kiparsky  Icon User is online

  • Pancakes!
  • member icon


Reputation: 7739
  • View blog
  • Posts: 13,075
  • Joined: 19-March 11

Re: Spot The Error

Posted 06 August 2012 - 01:58 PM

In that case my next place to go would be short-circuit evaluation. Does
a or b


evaluate b if a is true?

(I'm still a python novice, so I haven't actually tried this yet)

EDIT: dammit xclite, get out of my head!

This post has been edited by jon.kiparsky: 06 August 2012 - 01:59 PM

Was This Post Helpful? 3
  • +
  • -

#7 atraub  Icon User is offline

  • Pythoneer
  • member icon

Reputation: 759
  • View blog
  • Posts: 2,010
  • Joined: 23-December 08

Re: Spot The Error

Posted 06 August 2012 - 01:59 PM

Winning! You guys hit the nail on the head. I only learned that Python implements short circuiting a few weeks ago from sepp2k.

Good eye guys, that was really fast!


The easier solution to a non-short circuit 'or' is simply to reverse the order of the variables ;)

This post has been edited by atraub: 06 August 2012 - 02:01 PM

Was This Post Helpful? 0
  • +
  • -

#8 xclite  Icon User is offline

  • LIKE A BOSS
  • member icon


Reputation: 905
  • View blog
  • Posts: 3,167
  • Joined: 12-May 09

Re: Spot The Error

Posted 06 August 2012 - 02:01 PM

I'm ashamed to have jumped to a more complicated conclusion first. Should have known that at first glance... most languages I use are short-circuited by default.
Was This Post Helpful? 0
  • +
  • -

#9 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2113
  • View blog
  • Posts: 3,234
  • Joined: 21-June 11

Re: Spot The Error

Posted 06 August 2012 - 02:03 PM

View Postxclite, on 06 August 2012 - 10:57 PM, said:

Does Python have a non-short-circuited "or"?


Yes: | (which also doubles as bitwise-or for integers and set-union for sets).

PS: Why are y'all so damn fast? This question was tailor-made to be answered by me :-(

This post has been edited by sepp2k: 06 August 2012 - 02:04 PM

Was This Post Helpful? 2
  • +
  • -

#10 jon.kiparsky  Icon User is online

  • Pancakes!
  • member icon


Reputation: 7739
  • View blog
  • Posts: 13,075
  • Joined: 19-March 11

Re: Spot The Error

Posted 06 August 2012 - 02:07 PM

I figured it had to be one of the two... mostly because there wasn't anything else it could be that wasn't part of your redis library, and this was a python problem.
Was This Post Helpful? 0
  • +
  • -

#11 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2113
  • View blog
  • Posts: 3,234
  • Joined: 21-June 11

Re: Spot The Error

Posted 06 August 2012 - 02:38 PM

Interesting (I hope) side-note: In Perl (and I guess in PHP, too) the or operator is often used as a control flow operator because of its short-circuiting nature, usually for error handling. In combination with the aptly named die function this leads to an interesting "do or die" pattern. An example would be:

db_connect(bla, bla, bla) or die("Couldn't connect to DB");


Was This Post Helpful? 2
  • +
  • -

#12 jon.kiparsky  Icon User is online

  • Pancakes!
  • member icon


Reputation: 7739
  • View blog
  • Posts: 13,075
  • Joined: 19-March 11

Re: Spot The Error

Posted 06 August 2012 - 02:55 PM

This was actually intentional on Larry Wall's part. He designed perl in large part to allow for, as he saw it, the most expressive formulations possible. Hence "there's more than one way to do it" - ie, pick the one that flows the best for you.
This, of course, is why perl is so very easy to write and so very hard to read
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1