Not-not



  • Found this in the Mozilla sourcecode. I don't know what it's supposed to be, maybe someone can answer.


    PRBool externalDOMEvent = !!(aDOMEvent);

    koders.com link to the file



  • WTF meter at a meager level 3

    • It works
    • It isn't unclear what is happening


  • In c you don't have a bool type. The PRBool type is probably typedefed to int. To ensure that (externalDOMEvent == TRUE) does what is expected you want to ensure that externalDOMEvent is either 0 or 1.

    You could do:

    if (aDOMEvent)
        externalDOMEvent = 1;
    else
        externalDOMEvent = 0;

     witch is rather stupid and long.Hence the shorthand:

    PRBool externalDOMEvent = !!(aDOMEvent);

    makes perfect sence for me.



  • Thank you for making it clear.



  • @Gnonthgol said:

    In c you don't have a bool type.
    Note that this code is in C++, not C.

    @Gnonthgol said:

    The PRBool type is probably typedefed to int.
    It's an enum, technically.

    @Gnonthgol said:

    You could do:

    if (aDOMEvent)
        externalDOMEvent = 1;
    else
        externalDOMEvent = 0;

     witch is rather stupid and long.

    You could also do PRBool externalDOMEvent = (aDOMEvent != 0) or PRBool externalDOMEvent = aDOMEvent ? PR_TRUE : PR_FALSE; which aren't stupid and long.  Double negation falls into that class of clever tricks that are more tricky than clever.


  • There's nothing wrong with !!, I've used it before on several projects, sometimes when allocating memory but the return type of the function specifies a boolean. 

    Eg. mem = malloc (256); return !!mem; 

    Sure, you could do return mem?true:false; but the first is quicker to type. Its the same as you can do var=var+1, but why bother when you can just do var++




  • @Mole said:

    Its the same as you can do var=var+1, but why bother when you can just do var++
    And why bother doing var++ when you should be doing ++var?



  • @bstorer said:

    @Mole said:
    Its the same as you can do var=var+1, but why bother when you can just do var++
    And why bother doing var++ when you should be doing ++var?
    But the language is called C++, not ++C.  I don't think you understand the syntax very well.



  •  With modern optimizing compilers, this probably won't make much difference, but the "if" statement or even the cond ? true : false both end up doing a compare and branch.  Where as !value can (on some CPUs) be done in one instruction.  Therefore !!value compiles to two instructions that don't interrupt the scheduler.



  • @dwilliss said:

     With modern optimizing compilers, this probably won't make much difference, but the "if" statement or even the cond ? true : false both end up doing a compare and branch.  Where as !value can (on some CPUs) be done in one instruction.  Therefore !!value compiles to two instructions that don't interrupt the scheduler.

     

    any crazy optimization like that should be commented as such in the code or it is very WTF.  



  • In a *very* strongly-typed language, doing this would be a pure wtf. In C++ not so much.

    --------------------

    TRWTF is programming languages making booleans interchangeable with everything.



  • @bstorer said:

    @Mole said:

    Its the same as you can do var=var+1, but why bother when you can just do var++
    And why bother doing var++ when you should be doing ++var?

    In the context it was in, they both do exactly the same, so I prefer to use var++.


  • @tster said:

    any crazy optimization like that should be commented as such in the code or it is very WTF.  

    It's not a crazy optimization, but a standard C (and C++ if you happen to have a stupid compiler that warns on (bool)x) idiom for converting something to it's logical value. Anybody who actually knows C should have little trouble understanding what it does.

    Besides, it's actually a readability optimization much more than performance one, since the compiler is quite probably smart enough to compile y = !!x, y = x ? 1 : 0 and if(x) y = 1; else y = 0 the same way, but once you once saw the !!x idiom, you know what it means while you always have to check which branch does what in the other two cases.



  • @Mole said:

    @bstorer said:

    @Mole said:

    Its the same as you can do var=var+1, but why bother when you can just do var++
    And why bother doing var++ when you should be doing ++var?

    In the context it was in, they both do exactly the same, so I prefer to use var++.
     

    It has always puzzled me why people tend to think that post-increment is more 'natural'. IMNSHO,'++var' reads naturally as 'increment var', whereas 'var++' looks sort-of RPN to me.



  •  @bullestock said:

    It has always puzzled me why people tend to think that post-increment is more 'natural'. IMNSHO,'++var' reads naturally as 'increment var', whereas 'var++' looks sort-of RPN to me.

    var++ fits a pattern of Object.method(), i.e. Integer.increment(); — a very natural perspective for many people.

    Humble thy opinion, for it is but one way of looking at it, and certainly not the 'correct' way, which doesn't exist.

    What does matter is that they're not just syntactic variations of the same thing. var++ returns the original value, while ++var returns the incremented value.



  • @bullestock said:

    It has always puzzled me why people tend to think that post-increment is more 'natural'. IMNSHO,'++var' reads naturally as 'increment var', whereas 'var++' looks sort-of RPN to me.
    It 'fits' better with the rest of the operators which do the same thing: eg. var = var + 1, var += 1, var ++. So I only use ++var if I need the incremented value as part of a bigger expression.



  • @belgariontheking said:

    @bstorer said:

    @Mole said:
    Its the same as you can do var=var+1, but why bother when you can just do var++
    And why bother doing var++ when you should be doing ++var?
    But the language is called C++, not ++C.  I don't think you understand the syntax very well.

    Since you are talking about C++ there is a difference if an object has overloaded the ++ operators; then usually var++ will make a copy of the old object and ++var will not.

    See the C++ FAQ Lite



  • If you use post increment, the compiler has to create a copy of the object being incremented, so it can return it after the operation

    With intrinsic types such as 'int' this can easily be optimised away, but with a class, it can't, since the compiler can't tell that the copy operation doesn't have any side effects.

    With pre-increment, the copy doesn't need to be made, since the operation returns the incremented object.

     

    So, if you are not using the return value of the increment, and you are incrementing an object rather than an intrinsic variable, you should consider using pre-increment rather than post-increment. (This is why in the C++ standard library, iterators are normally incremented like "for (iter=mymap.begin(); iter != mymap.end(); ++iter)" rather than "...iter++)"

    If you ARE using the return value, then obviously use the correct incrementor, and if you are incrementing an intrinsic variable it doesn't matter so much, but you may choose one or the other for either consistency or what you prefer.

     

     



  • Personally I use the pre-incrementer ever since I read Effective C++, but with today's computing power I don't think your average loop is going to perform so many iterations that you will actually be able to notice the extra 1 line of assembly.



  • It's not one line of assembly if it's a complex object you're incrementing. It has to call the copy constructor of your class, which might copy a few variables, or it might do memory allocation, reading databases and who knows what...

     

     



  •  Just think of !! as the "convert to boolean" operator.



  • @Bulb said:

    Besides, it's actually a readability optimization much more than performance one, since the compiler is quite probably smart enough to compile y = !!x, y = x ? 1 : 0 and if(x) y = 1; else y = 0 the same way, but once you once saw the !!x idiom, you know what it means while you always have to check which branch does what in the other two cases.
    Why such avoidance of y = (x != 0)?  It compiles without branching, optimization or no, and unlike !!x, it doesn't rely on knowing an idiom.  Not to mention that it clearly states what you're really doing: determining if x is not null.



  • To me, "var++;" just looks wrong, because you have an operator directly adjacent to a semicolon. Since it makes no real difference whether I type "var++;" or "++var;" in the end (when operator overloading is not an issue), I prefer "++var;" for aesthetic reasons.

    Now, when you have operator overloading involved, ++ might do anything. I've seen a socket class where "++sock" meant "connect to host on port" but "sock++" meant "listen on port and accept connections from host". Hideous.



  • @pscs said:

    It's not one line of assembly if it's a complex object you're incrementing. It has to call the copy constructor of your class, which might copy a few variables, or it might do memory allocation, reading databases and who knows what...

     

     

    If your constructors are connecting to databases (or doing any IO) you need to re-design your classes. 

    If your copy constructors are connecting to databases(or doing any IO) then you need to re-design your career.



  • @tster said:

    @pscs said:

    It's not one line of assembly if it's a complex object you're incrementing. It has to call the copy constructor of your class, which might copy a few variables, or it might do memory allocation, reading databases and who knows what...

     

     

    If your constructors are connecting to databases (or doing any IO) you need to re-design your classes. 

    If your copy constructors are connecting to databases(or doing any IO) then you need to re-design your career.

    I don't tend to think this is a problem.  Frequently I have constructors that take a row ID as an argument and call to the DB factory which lazily instantiates and connects to the DB and fetches the record info to populate the object.  Doing "obj = new Foo(foo_id);" seems better to me than doing something like "obj = new Foo(); obj.connectDb(); obj.fetchById(foo_id);"  YMMV. 



  • @morbiuswilters said:

    @tster said:

    @pscs said:

    It's not one line of assembly if it's a complex object you're incrementing. It has to call the copy constructor of your class, which might copy a few variables, or it might do memory allocation, reading databases and who knows what...

     

     

    If your constructors are connecting to databases (or doing any IO) you need to re-design your classes. 

    If your copy constructors are connecting to databases(or doing any IO) then you need to re-design your career.

    I don't tend to think this is a problem.  Frequently I have constructors that take a row ID as an argument and call to the DB factory which lazily instantiates and connects to the DB and fetches the record info to populate the object.  Doing "obj = new Foo(foo_id);" seems better to me than doing something like "obj = new Foo(); obj.connectDb(); obj.fetchById(foo_id);"  YMMV. 

     

    wait, do you mean the IO is happening inside the constructor call or later on when you try and use the object?



  • @morbiuswilters said:

    I don't tend to think this is a problem.  Frequently I have constructors that take a row ID as an argument and call to the DB factory which lazily instantiates and connects to the DB and fetches the record info to populate the object.  Doing "obj = new Foo(foo_id);" seems better to me than doing something like "obj = new Foo(); obj.connectDb(); obj.fetchById(foo_id);"  YMMV. 

     

    Sorry for double post.

    Why not have your object do things behind the scenes?

    Foo foo = new Foo(foo_id);

    print foo.getBars();

     

    when you call getBars() the object realizes it needs to initialize and goes to the database to get all it's values.



  • @tster said:

    @morbiuswilters said:

    @tster said:

    @pscs said:

    It's not one line of assembly if it's a complex object you're incrementing. It has to call the copy constructor of your class, which might copy a few variables, or it might do memory allocation, reading databases and who knows what...

     

     

    If your constructors are connecting to databases (or doing any IO) you need to re-design your classes. 

    If your copy constructors are connecting to databases(or doing any IO) then you need to re-design your career.

    I don't tend to think this is a problem.  Frequently I have constructors that take a row ID as an argument and call to the DB factory which lazily instantiates and connects to the DB and fetches the record info to populate the object.  Doing "obj = new Foo(foo_id);" seems better to me than doing something like "obj = new Foo(); obj.connectDb(); obj.fetchById(foo_id);"  YMMV. 

     

    wait, do you mean the IO is happening inside the constructor call or later on when you try and use the object?

    If you pass the constructor an ID, it will pull the data from the DB.  If you do not, it will create a new object with default settings and will not write to the DB until you save the record.  I prefer this idiom because it makes constructing record objects simple: just pass GET/POST/cookie/session vars containing the ID to the constructor and you get the object populated with the associated data. 



  •  @morbiuswilters said:

    If you pass the constructor an ID, it will pull the data from the DB.  If you do not, it will create a new object with default settings and will not write to the DB until you save the record.  I prefer this idiom because it makes constructing record objects simple: just pass GET/POST/cookie/session vars containing the ID to the constructor and you get the object populated with the associated data. 

     

    The problem with this is that lets imagine you want to show a user all your Books and when he clicks on a book it shows him all the info about it.

     So what you do is:

    List<Book> books = new List<Book>();

    Hash<int, string> books = getBooks();

    foreach book_id in books.Keys

    {

      books.add(new  Book(book_id, books.get(book_id)));

    }

     

     

    now you can show them the book titles and wait for a click.  If your constructors go to the database you just did something REALLY stupid.  Instead, wait 'till the user clicks on a book then you do:

    print aBook.getPrice();

     

    Within getPrice() you initialize the object.



  • @tster said:

    @morbiuswilters said:

    If you pass the constructor an ID, it will pull the data from the DB.  If you do not, it will create a new object with default settings and will not write to the DB until you save the record.  I prefer this idiom because it makes constructing record objects simple: just pass GET/POST/cookie/session vars containing the ID to the constructor and you get the object populated with the associated data. 

     

    The problem with this is that lets imagine you want to show a user all your Books and when he clicks on a book it shows him all the info about it.

     So what you do is:

    List<Book> books = new List<Book>();

    Hash<int, string> books = getBooks();

    foreach book_id in books.Keys

    {

      books.add(new  Book(book_id, books.get(book_id)));

    }

     

     

    now you can show them the book titles and wait for a click.  If your constructors go to the database you just did something REALLY stupid.  Instead, wait 'till the user clicks on a book then you do:

    print aBook.getPrice();

     

    Within getPrice() you initialize the object.

    I think we're talking about different approahes to architecture here, which is fine.  I would not go to the DB if the data for the object wasn't going to be used.  Generally I don't like pulling the data on first access because I don't use accessors/mutators but instead members that can act like them (AKA "properties" or "attributes") and then error handling for an invalid ID has to be done anywhere you access members of the record, rather than where the record is first pulled from the DB.



  • @morbiuswilters said:

    Generally I don't like pulling the data on first access because I don't use accessors/mutators but instead members that can act like them (AKA "overly-visible instance variables")
    FTFY. The Bean pattern isn't all that hard, and, with the right IDE, only six extra keystrokes or one context menu selection extra.@morbiuswilters said:
    and then error handling for an invalid ID has to be done anywhere you access members of the record, rather than where the record is first pulled from the DB.
    Which is why initialization should only have one or two places to happen, like you do in your code. Putting a database fetch in the constructor is mildly annoying since it hides what could be a very time-consuming operation, but it's definitely not wrong. The best place (IMNSHO) is an initialize() method, but constructor's second best; after all, that's what it's there for.



  • @TwelveBaud said:

    Putting a database fetch in the constructor is mildly annoying since it hides what could be a very time-consuming operation, but it's definitely not wrong. The best place (IMNSHO) is an initialize() method, but constructor's second best; after all, that's what it's there for.

     

    I'm pretty sure that's not what constructors are there for.



  • @tster said:

    I'm pretty sure that's not what constructors are there for.
    Yeah... I blame my written-like-VB-code textbook, my incomptent teacher, and the lack of coffee in the student union for my inability to think straight this morning. Disregard my earlier post, I suck cocks.


Log in to reply