• (cs) in reply to NateP
    NateP:
    Exception handling is expensive.. unwinding the stack and all..

    It is, but under certain circumstances -- and I am not claiming that this is one of them -- the expense can be justified by comparing the available options.

    For example, take the version of AppleScript that was in Mac OS 7.x. (Technically, AppleScript started off as a scripting language, not a programming language, but then VBScript did, too.) The recommended way to find out if a particular file already existed was to script the Finder:

    tell application "Finder" set file_exists to exists file "foo" of folder "bar" of disk "wtf" end tell

    Until one of the releases of Mac OS 8, though, sending events to programs (which is what a "tell" block does) was incredibly slow -- I remember hearing at the time that the version which speeded things up did so by a factor of several hundred on certain calls. As a result, exception handling within the flow of a script was much, much faster than waiting for a result from a program, and the following code, though twice as many lines, did the same thing in a fraction of the time:

    set file_exists to true try "wtf:bar:foo" as alias on error set file_exists to false end try

  • Denis Troller (unregistered) in reply to Erik

    I think the original formulation is wrong. He should have said "less than DateTime.Now can resolve", I believe.

    You might have to use a perfcounter to get an accurate measurement, depending on your actual running time.

  • Denis Troller (unregistered) in reply to Erik
    Erik:
    System dependent. It's probably about a millisecond

    You might want to look at the ticks property of the DateTime structure. You're not just wrong, you're four orders of magnitude wrong.

    Some way it is better when you hit "quote" instead of "Reply"...

    I think the original formulation is wrong. He should have said "less than DateTime.Now can resolve", I believe.

    You might have to use a perfcounter to get an accurate measurement, depending on your actual running time.

  • (cs) in reply to DOA

    throws

  • Borat (unregistered) in reply to akatherder

    Borat Says:

    Yes, especially when it causes recursion, it is not VERY NIICE!

  • brendan (unregistered)

    This is no WTF, the only thing that needs improvement is the removal of the recursive call, which would also mean that the index would not need to be passed to the procedure. Also, the incorrect catch of the generalized exception class should be specialized to catch the ArgumentException exception class. And also the use of global variables.

    Well now that I really think about it, it is WTF code.

       static string [] strObj = {"A","A","B","C","C","D","E","F","B","C","G","F"};
       static Hashtable UniqueHT = new Hashtable();
       [STAThread]
       static void Main(string[] args){
          FindUniqueElements();
       }
    
       private static void FindUniqueElements(){
          for(int i=index; i< strObj.Length; i++){
             try{
                UniqueHT.Add(strObj[i], "Any Value");
                Console.WriteLine(strObj[i]);
             }
             catch(Exception){}
    
          }
          Console.ReadLine();
       }
    

    anyway don't know if you guy's have read this comment from the source's message board:

    #12 as originally posted is an absolute moronic posting and SHOULD BE EXTRACTED IMMEDIATELY!!!! In my 15 years experience I have NEVER seen ANYTHING SO STUPID!!!! This is not a "Tip", but a sure way to get fired from a job.
    1. It's absolutely STUPID to depend on exceptions for a function to work correctly.

    As with everything exceptions have advantages and disadvantages. It's upto the developers how much exception handling he or she uses.

    2. What happens if the last element in the array is a DUPLICATE?

    Well then the for loop condition will fail and do nothing. It seems that in your 15 years of experience that you haven’t learned to read code correctly.

    BTW, Congratulations for making it on the Worse Than Failure site.

    One Too Many

    Look’s like you've made it here as well :)

  • Tarsius (unregistered) in reply to KattMan

    i've gotta say this code is great for those test at university where you have to "use recursion, use exception handling, arrays...etc"!! this guy must have had a 10 at his programming test!....

    seriously this code sucks...but lately every WTF has exception used for standard processing... why does everyone likes exceptions!!!?? do they like to feel like they are weeiirrd guys? ... i guess they liked "ugly duck" very much....

  • 57451 (swedish) (unregistered)

    Seriously, doesn't .NET have an AddIfAbsent-method? ;(

    Captcha: bling (gettostylee)

  • Captn. Pedant (unregistered)

    Does it bother anyone that neither of the two solutions offered meet the stated requirement "to take an array and find the unique values contained therein" or the suggestive name "FindUniqueElements"? In the example given, both "solutions" report 'A' is a unique element of the array when in fact it appears more than once. Discussion about asymptotic performance of the solutions would seem to be premature if they don't meet the requirements -- if we are willing to relax correctness, there is no reason the code shouldn't run in zero time.

  • AtariFan (unregistered) in reply to Captn. Pedant

    I guess the assumption which has been made is that while ugly, the code in the article is "correct." The original code does not report only elements which are unique, it merely ensures that all elements are reported once only. I guess this is an additional fault with the original: the name should be FindDistinctElements (e.g. SQL uses the word 'distinct' for the same purpose.)

  • petvirus (unregistered) in reply to brendan
    brendan:
    As with everything exceptions have advantages and disadvantages. It's upto the developers how much exception handling he or she uses.
    exactly. Only if we are talking about exceptions, you know those things that only happen exceptionally, not part of the regular flow of execution? i hope thats what you mean, otherwise, ill quote you:
    brendan:
    Look’s like you've made it here as well :)
  • Raw (unregistered) in reply to guy
    This person was probably translating VB6 code. I believe in VB6 collections did not have .contains, and using On Error Resume Next and checking the error number was the only way to check if the collection had a given key.

    There were ways to check it (although I can't remember the syntax for it now), but just trying to add and ignoring the exception was a lot faster. I used it a lot for treeviews when I had to add stuff without knowing if the parent levels where added yet, and for a large list, it made the difference between 20 seconds and 12 minutes.

    But, if VB6 screwed up the checking of if a hashtable/collection contains a value, C# (actually .Net) screwed up exception handling, big time. I've clocked the exception handling (in .Net 1.1), and an exception usually burns around 1.5 million clock cycles, making it useless in tight loops like this. I actually was so shocked that I at first thought it was a eff up in C#, so I ran the test in VB.Net and eventually directly in IL, all with similar results. That's something worthy of a WTF!

  • dkf (unregistered) in reply to joudanzuki
    joudanzuki:
    For what it's worth, Michael, there are languages which do optimize small hashtables to linear lists and somewhat larger ones to (possibly balanced) binary trees, only actually building a true hash tables when the size and certain other properties of the table indicate a good probability of getting a good tradeoff for the extra space consumed versus the running time.
    The downside to such sophistication is that it makes the mapping implementation much more complex. In practical code it is often better to keep things simple so that the code can be checked to the point where it really is free of bugs, so that after that you can focus on other things when tracking down mysterious crashes.

    On the other hand, there are several sorts of hashtables, with the highest-performance ones requiring tuning to the particular dataset being hashed, both for table size and for specific hash algorithm. I've found that for most apps, that's not a luxury you have.

  • (cs) in reply to guy
    guy:
    What part of the name "Hashtable" suggests that there is a tree involved?

    Welcome to the site formerly known as TDWTF. Nobody here knows what a hash function is. It grated me for a few months. I wrote several long rants. But eventually I just gave up.

    To his benefit, Twon might have been talking about the data structure at each hash bin. I've never heard of a mainstream library storing a tree at each bin, but I'm sure somebody (somewhere) is doing it.

  • (cs)
    Derrick Pallas:
    y'all'll
    WTF?!
  • orangutango (unregistered)

    foreach(string StringThatWillHoldTheValueToBeAssignedTo in CollectionOfStringsWithRandomWordsInsideThem ) if(! UniqueHT.ContainsKey(StringThatWillHoldTheValueToBeAssignedTo )) UniqueHT.Add(StringThatWillHoldTheValueToBeAssignedTo, "A Value");

  • someguy (unregistered)

    Heh, here's some actual code from an big company app that I maintain which also uses exceptions in non-exceptional flow:

    public boolean isCardInTable( String ccnumber ) throws SQLException { boolean retVal = false; ResultSet rs=null; CallableStatement stmt = null;

        try {
    	String procedure ="{call "+PACKAGE_NAME+".getCreditCardNumber(?)}";
                stmt = conn.prepareCall(procedure);
                stmt.setString(1,ccnumber);
                stmt.execute();
                retVal = true;
    
        } catch (SQLException e) {
       if (e.getErrorCode() != 1403) { // ORACLE NO DATA FOUND ERROR
            ExceptionLog.log(e);
            throw e;
      }
        } finally {
           if (stmt != null) stmt.close();
    }
        return retVal;
    }
    

    Threw me for a loop the first time I saw it...

  • Jon (unregistered) in reply to Zap
    Zap:
    Jim:
    Set unique = new HashSet();
    unique.addAll(Arrays.asList(strObj));
    strObj.uniq!
    Oddly, it's slightly shorter in Python:
    set(strObj)
  • Jon (unregistered) in reply to verisimilidude
    verisimilidude:
    or actually
    (let first_stone (cons stones) ... )
    You still need to cast it. I guess the closest thing to casting is 'the'.
    (let ((first-stone (the Stone (car stones))))
      ...)
  • (cs) in reply to zip
    zip:
    Hashtables have O(1) lookup.

    Are you sure about that?

  • opello (unregistered) in reply to Eduardo Habkost
    Eduardo Habkost:
    DOA:
    To get a bit biblical... He who has never used exceptions in this manner, cast the first stone
    first_stone = (Stone)stones[0];
    Or:
    throw stones[0];
  • Fixme (unregistered) in reply to Yartz
    Yartz:
    Lastchance:
    Ah, the old "use exception handling for non-exceptional logic" trick. That's the third time this week!

    Yes, I just got my "Get Smart" DVD set.

    Well, it's not such a big deal in many languages. Just because .Net exceptions are SO EXPENSIVE, does not mean catching exceptions in mainstream logic is so horrid.

    In Python, for instance, the try to insert then catch if it's there is a somewhat agreed on pattern (with the motto "it's easier to be forgiven than to be granted").

    Anyway, the code snippet was a little braindead anyway. And in .Net you should not merrily throw exceptions like this. No huge WTF, just poor code.

    Heh - "In python we can write stupid code and it's good anyway. That's how cool python is."

  • Mukund (unregistered)

    Hi,

    I am the original coder of this snippet. I want to understand this issue sincerely. Can you please tell me, in AJAX while creating XmlHttpRequest object using javascript we use catch block to create object depending on browsers? See the code here.(http://www.w3schools.com/ajax/ajax_browsers.asp).

    1. If Ajax way is acceptable then why not the snippet? In their Catch block a object is created while in my case I am just skipping the duplicate key and iterating with next element in array. Yes it may or may not be the preferred way. But it is wrong to say upright that mainstream logic cannot reside in catch block.

    2. Even in my code it is not something 180 degree opposite code which is there in catch block. It is very relevant to the exception that is thrown.

    3. By the way of exception if hashtable provides me a way of finding duplicate keys then why shouldn't I use it? It saves me from writing my own logic. Try to analyse this in general way and not only for hashtable.

    4. Using recursion may be causing performance overhead. But if you see the Ajax code it is also iterative in nature since it is drilling down through Try-Catch hierarchy.

  • (cs) in reply to Mukund
    Mukund:
    Hi,

    I am the original coder of this snippet. I want to understand this issue sincerely. Can you please tell me, in AJAX while creating XmlHttpRequest object using javascript we use catch block to create object depending on browsers? See the code here.(http://www.w3schools.com/ajax/ajax_browsers.asp).

    1. If Ajax way is acceptable then why not the snippet? In their Catch block a object is created while in my case I am just skipping the duplicate key and iterating with next element in array. Yes it may or may not be the preferred way. But it is wrong to say upright that mainstream logic cannot reside in catch block.

    2. Even in my code it is not something 180 degree opposite code which is there in catch block. It is very relevant to the exception that is thrown.

    3. By the way of exception if hashtable provides me a way of finding duplicate keys then why shouldn't I use it? It saves me from writing my own logic. Try to analyse this in general way and not only for hashtable.

    4. Using recursion may be causing performance overhead. But if you see the Ajax code it is also iterative in nature since it is drilling down through Try-Catch hierarchy.

    Mukund, I'll try to answer your questions clearly, without the usual sarcasm and rudeness we exhibit here.

    (1) This is C#, not Ajax. Even if your link shows the best way of doing it in Ajax (and I doubt it), it isn't a good idea to copy it blindly into any other language.

    Mainstream logic should never, under any circumstances, appear in a catch block. If nothing else, this confuses people and makes the program very hard to read. It is never necessary. It should be avoided.

    (2) You are catching "Exception," therefore the logic is not identical. Any other type of exception will also be caught here.

    (3) You probably need to read a book or take a course on "collections." (Hashtable is a collection.) In general, a collection allows you to check whether a given entry already exists. This is certainly true of Hashtable. Alvin's version of your code shows you how to do that. His version is not "writing your own logic." It is using the Hashtable interface appropriately.

    (4) Simple recursion is a very bad idea in this case. Your input can have any number of repeated strings in sequence. Each one will generate a new stack frame. Most operating systems have a limit to the number of stack frames they will allow before ... well ... throwing an exception.

    This code is completely unmaintainable. Consider: if someone later on wants to make it thread-safe, how are they going to do it? Alvin's version is far preferable from this point of view.

    Please try to understand why Alvin's version is the right way to solve the problem. It will be good for you. Honestly.

  • Mukund (unregistered) in reply to real_aardvark

    Hi,

    I know C# and Ajax(javascript) are different but the concept of try - catch remains the same.

    1. Please see this link from IBM (See Listing 2 and 3) http://www-128.ibm.com/developerworks/web/library/wa-ajaxintro1.html

    2. Another link: http://aspalliance.com/716#Page3

    3. Even I have books from standard publishers which show the same way of doing it.

    4. My code may not be the best example of doing this. But I want to understand this clearly.

    5. Then what is meant exactly by handling an exception . Is it just logging the error information and continue with rest of the program? I always thought that we can repair the error condition in catch block and continue.

  • (cs) in reply to Mukund
    Mukund:
    Hi,

    I know C# and Ajax(javascript) are different but the concept of try - catch remains the same.

    1. Please see this link from IBM (See Listing 2 and 3) http://www-128.ibm.com/developerworks/web/library/wa-ajaxintro1.html

    2. Another link: http://aspalliance.com/716#Page3

    3. Even I have books from standard publishers which show the same way of doing it.

    4. My code may not be the best example of doing this. But I want to understand this clearly.

    5. Then what is meant exactly by handling an exception . Is it just logging the error information and continue with rest of the program? I always thought that we can repair the error condition in catch block and continue.

    Hello again, Mukund.

    (1) Just to prove that I read the link, here's a quote from about halfway down: "The final parameter, when set to true, requests an asynchronous connection (thus making this Ajax)."

    Listing 2 is entitled "Listing 2. Grab and set field values with JavaScript code"

    Listing 3 is entitled "Create an XMLHttpRequest object on Microsoft browsers"

    This is all very interesting, but useless to the stated problem. I don't know why you think listing 2 is important. Listing 3 tells you how to deal with an exception in ActiveX. This is good. If you're "Creating an XMLHttpRequest object." But you're not. Listing 3 catches an exception because this is a client/server environment, with multiple layers of library calls. You may get an XMLHttpRequest object. You may not. This is why you use a try/catch.

    (2) Dear Lord, do I have to? OK. The quote here is "Properties and Functions of XMLHTTPRequest object used in the Sample Application."

    Once again, and I admire your focus on XMLHTTPRequest objects, listing 1 shows an attempt to "new" an object and a catch block if this fails. This is not relevant. You are not "newing" objects. You are inserting objects into a hash-table. You are checking whether an object is already in the hash-table. There is no memory allocation involved. There is no possibility of failure. The only reason for failure is that the object is already there. This is expected. It is not an exception. You can check whether an object is there with a simple function call. You do not need to rely on a (completely arbitrary) exception. Do the simple thing.

    (3) I very much doubt that you have a book on computer algorithms (linked lists, binary trees, hashes, heaps, sorting, etc) that throw and catch exceptions as part of their main logic. Your books are unlikely to mention XMLHTTPRequest objects. Please check the index.

    (4) Your code works. Actually, you ought to be proud of this. 99% of the code on this site is just plain wrong. 50% or more gives you the wrong result, every time. But your code works.

    (5) However, this is a really, really, really, really (goes into recursion here) pop pop pop pop bad way of doing it.

    A language that supports exceptions will allow you to do pretty much whatever you want with them. (Let's not get into things like preventing exceptions from escaping destructors in C++ right now. This is just a general observation.)

    You don't have a problem with "handling an exception." Your code has a problem with creating an exception in the first place. This isn't to do with the language. It's to do with the way you are thinking about the problem. The problem does not involve exceptional behaviour. Therefore it does not require exceptions.

    I really cannot put it any more plainly than this -- and I really am trying to help:

    foreach(string s in strObj) if(! UniqueHT.ContainsKey(s)) UniqueHT.Add(s, "A Value");

    Now, I don't know C# either. I would have to look this up myself. In CS (Unix) circles, we call this "RTFM," which stands for something ... er ... rather offensive. However, what it means is: look it up. There is probably a better way to use the hash map, or object, or whatever, that the one you first thought of.

    And maybe there isn't. Then you can go back and copy Ajax into C#, and add a static counter (not typical for recursion, by the way), and force everything else into place, and use about ten times as many lines and about a thousand times as much CPU as necessary, and not only will other people not understand the result. In six months' time, you won't understand the result.

    In six months' time, however, you will still understand

    foreach(string s in strObj) if(! UniqueHT.ContainsKey(s)) UniqueHT.Add(s, "A Value");

    And in six months' time, you will be asked to make it thread-safe. Or to port it to a platform that doesn't use exceptions. Or something else.

    Please, please, use your undoubted ability to think about code (and to look up examples on the Web), and think about code. Otherwise, it's a competitive environment. I wouldn't hire anybody at all who wrote your solution to the problem. I certainly wouldn't hire them if they didn't recognise that it was, basically, a very bad design indeed.

    I write this in memory of my father, John Michael Doubleday, who spent thirty years lecturing in Computer Science at Aston University.

    Jeez, Dad, was it always this difficult?

  • Mukund (unregistered) in reply to real_aardvark

    Just tell me one thing clearly. Is the catch block meant only for logging the exceptions?

  • Logan (unregistered) in reply to Jim
    Jim:
    There's no Set object in .Net?

    Strangely this has been missing from .NET 1.1 and 2, but I think there may finally be a Set class in 3.x, as well as a few other handy data constructs.

  • Robertdib (unregistered)
    Comment held for moderation.
  • DavidZes (unregistered)
    Comment held for moderation.
  • Felixvob (unregistered)
    Comment held for moderation.
  • Avenue 17 (unregistered)
    Comment held for moderation.
  • Micahsex (unregistered)
    Comment held for moderation.

Leave a comment on “Unique Ways to Play Catch”

Log In or post as a guest

Replying to comment #:

« Return to Article