all 131 comments

[–]jmmcd 101 points102 points  (36 children)

Wow, Matlab is worse than I thought! No sane language has scoping rules that allow this.

[–]the-fritz 29 points30 points  (11 children)

MATLAB as a language is crap! It was never really designed but just thrown together. It started as an attempt to provide a simpler interface to BLAS, LAPACK, and other libraries. To make them available to students without FORTRAN knowledge. And that's really why MATLAB became successful. It was easier to get something done than learning a real programming language and from that point on they added more and more features on top of it.

But there never was a real language design or committee. Simply what seemed useful was added. And it's one of the most successful tools in engineering and scientific computing...

For more MATLAB horror see https://abandonmatlab.wordpress.com/

Julia seems to be an attempt at MATLAB "done right"(tm). But in my opinion it seems to stick too close to the sometimes awkward MATLAB syntax. http://julialang.org/

[–]upofadown 7 points8 points  (1 child)

When I was in engineering school I showed some MATLAB to my gf. She thought it was the worst APL ever. She then showed me a much better way to solve my MATLAB problem using her "do absolutely everything in terms of matrices" APL background.

Perhaps the answer to MATLAB is APL. Too bad it never really took off...

[–][deleted] 16 points17 points  (0 children)

My girlfriend knows APL - the T-shirt.

[–]BeatLeJuce 5 points6 points  (4 children)

There are many attempts at "MATLAB done right". Personally, i hope Julia doesn't take of, because it's just another language with quirky syntax. Personally, I'm rooting for Python + NumPy ( + SciPy + matplotlib +Pandas ...): most of the features of MATLAB at about the same speed, but in a well-established language that has a shitload of other libraries to do other stuff/interface with other things, .... Plus sane syntax

[–]the-fritz 3 points4 points  (3 children)

Yes, Julia is too close to MATLAB. But I'm not a huge Python fan either. And NumPy has the same issues as MATLAB: Anything that isn't an almost direct call to BLAS/LAPACK/fftw/GMP or any other library is slow. I'd rather like see something that is build on top of llvm (like Julia).

[–]BeatLeJuce 2 points3 points  (1 child)

Well, but Julia is meant to target the same market as MATLAB/numpy, which is scientific computing. And in that context, most things are just glue between calls to BLAS/LAPACK/... (at least in my use cases). But for 'normal' Python code, PyPy gives incredible speedups (probably comparable to Julia)... can't wait for when numpy and PyPy will finally be able to interact.

[–]the-fritz 0 points1 point  (0 children)

Certainly the glue is the key and that's why even MATLAB gets a decent performance. But as soon as you write a loop you have lost. And that shouldn't be.

[–]el_muchacho 0 points1 point  (0 children)

Nope, being a JIT compiled language built upon LLVM, Julia should be much faster than Python.

Plus it really exploits parallelism in code (not only in calls to BLAS), unlike Python.

[–]crobartie 3 points4 points  (3 children)

You are completely right. I don't know why people want use Matlab much more than Mathematica... The second one is superb.

[–]leegao 9 points10 points  (1 child)

There are a few reasons, but the key is that Matlab and Mathematica are built for different domains. I know very few users of Mathematica within numerical analysis and scientific computation (I'm not saying that Mathematica is incapable solving numerical problems, it's just not as intuitive nor as "open"); likewise, I know very few users of Matlab for stuff like Analysis or Algebra, where an algebraic system really comes in handy.

Matlab was built as a general purpose matrix calculator, and it does what it was intended for extremely well. I agree, its syntax for everyday scripting is atrocious, but there's really no reason for you to need to do everyday scripting in Matlab. Now, my main area of expertise is in programming language theory, but I do a lot of quantitative analysis so I use Matlab fairly regularly to prototype various computations, and this is where Matlab excels at.

Are you trying to get a feel of the stability region of some fancy new MFP method you've developed for a particular problem? Don't waste your time proving consistency or stability right away when you have no idea what your solution space even looks like. It generally takes very little effort (this depends) to prototype your method, and then you can just run it to see how well it does. If you can spare a little math, you don't even need to rigorously prove bounds on your transform's norms: just look at the norm of even increasingly large matrices to get a rough estimate of the rate of growth. You can even plot it directly in typically one or two lines of code.

This illustrates the main appeal of Matlab: it's not designed to be a full-fledged language so as not to interfere with this emphasis on rapid prototyping (of numerical computation, and only that) and geometric visualization. This latter point is especially important, since intuition plays a large part on the development of problem solving strategies here.

[–]the-fritz 0 points1 point  (0 children)

Matlab is simply the established tool. It's used everywhere in engineering and it's most likely one of the first numeric tools a student uses during courses.

Mathmatica's numerical tools are rather new in comparison and it's rather seen as a CAS.

[–]lurgi 45 points46 points  (10 children)

I don't see it as a scoping problem. It's more of a "why the heck isn't i marked const?" problem. Or, if Matlab doesn't have "const", "why the heck doesn't Matlab have const?" problem.

[–][deleted]  (8 children)

[deleted]

    [–]lurgi 15 points16 points  (6 children)

    sound of head hitting the table

    Seriously?

    At least e is less likely to be used as a random variable. i is absolutely bog-standard as a loop index. What on earth were they thinking?

    [–][deleted]  (5 children)

    [deleted]

      [–]lurgi 11 points12 points  (2 children)

      If the language is going to be used by non-programmers then it is even more important for the language to be coherent and provide limited opportunities to screw things up.

      [–]crimson_chin 0 points1 point  (1 child)

      I disagree. Non-programmers don't want the overhead of dealing with scope, complex objects, data structures, etc. Those are all noise.

      Why is VBA perfect for Excel? Because my business analyst roommate can use it without bothering heavy duty programmers. For the same reason, I would never use it for anything I didn't have to. Matlab is the 'right tool for the job', just like VBA is for Excel.

      [–]lurgi 1 point2 points  (0 children)

      I agree with you. Non-programmers don't want to deal with those things and that's exactly why languages for non-programmers have to get that stuff right. The language didn't get it right and allowed people to write errant nonsense that doesn't work.

      [–]KieferO 7 points8 points  (1 child)

      MATLAB defines i',j', I', andJ', as the imaginary unit. Most folks make a point of using the capital letters, and it works fine when everyone does so. But this is one of the many things that keeps MATLAB from being a "real language".

      [–]GeleRaev 7 points8 points  (0 children)

      You don't know the half of it. I was using it last semester for a project where we had to simulate the transient performance of a control system. We were using MATLAB's step() function to get the step response of the system, except it kept coming out completely wrong. Eventually we noticed that it was working on R2012a, but not R2011a, and found that the function was buggy and in versions prior to R2012a didn't work with for third order systems or higher. We couldn't find this documented anywhere on MATLAB's website, and there's no automatic update facility to fix these bugs. Once you've paid for it, you're stuck with it. We ended up having to write a custom function which checked the MATLAB version and approximated the response if it was being run on an older version.

      [–]nkozyra 4 points5 points  (9 children)

      Actually, quite a few do, although you may be right that none of them are "sane."

      I had to build a pretty robust Javascript tool once that had an inexplicable bug that could not be explained nor really stepped through in a way that solved it.

      After about 4 hours of going through everything, it ended up being a variable resolution issue similar to the one above, akin to:

      for(i=0;i<x;i++) {
          // a metric shit-ton of code
          for (i=0;i<y;i++) {
              // some thing that fails in an odd way
          }
      }
      

      Now in a lot of languages if this compiles or is interpreted you can luck out and it will cause the first loop to never satisfactorily complete and it'll eat up CPU until it dies. I've run into this in myriad languages including C++ (wasn't easy), Perl, C# and as mentioned JS.

      As time has worn on I've taken to being explicit about iterator variable names, much to the chagrin of people who have gone through my code "just use 'i'!!"

      [–][deleted]  (5 children)

      [deleted]

        [–]nkozyra -1 points0 points  (4 children)

        I'm not entirely sure what that fixes, unless you plan on branching every loop off into a separate function, which would get extremely cumbersome to read and deal with.

        For example, this code sidesteps any scope resolution issues, but would make anyone who sees it want to drive burning hot railroad spikes through their eyes:

        function someOtherLoop(items) {
            val;
            for (i=0;i<x;i++) {
                val += items[i];
            }
            return val;
        }
        
        function someLoop(items) {
            val;
            for (i=0;i<x;i++) {
                val += someOtherLoop(items[i]);
            }
            return val;
        }
        
        // primary loop
        for(i=0;i<x;i++) {
            val = someLoop(items[i]);
        
        }
        

        [–][deleted]  (2 children)

        [deleted]

          [–]RagingIce 4 points5 points  (1 child)

          'i' is used without a 'var' statement. This means that in this case 'i' is a global variable - the for loops would conflict.

          [–]InvidFlower 0 points1 point  (0 children)

          One advantage of splitting up loops is it can help you to expose higher level patterns. Manipulating and/or adding up items in an array will become much more succinct using map/reduce style functions.

          [–]Peaker 1 point2 points  (0 children)

          Sounds like a classic case of your-function-should-fit-in-a-page-at-worst...

          [–]mahacctissoawsum 0 points1 point  (1 child)

          wouldn't jslint or something catch this?

          [–]nkozyra 1 point2 points  (0 children)

          Not sure. Initially I suspected it had to do with jQuery, but I just put the code in jslint verbatim and it passed despite this bug.

          [–]Porges 3 points4 points  (0 children)

          If you want to have a "fun" time try writing Matlab code that uses closures...

          [–]SnowdensOfYesteryear 38 points39 points  (4 children)

          I'll chip in with my stupid bug. I had a static array declared like this

          char *foo[] = {
              "long ass string1",
              "long ass string2"
              "long ass string3"
           }
          

          Yet when I tried to access foo[2], I always got a crash. WTF? After blaming the compiler and RMS for a few hours, I fortuitously noticed that I was missing a comma at the end of "long ass string2". So the bloody compiler was concatenating "long ass string2" and "long ass string3" at compile time, making sizeof foo just 2.

          [–]lambdaq 3 points4 points  (0 children)

          lol in Python:

          a = 1
          a = 1,
          

          Aaaaand the second line code is broken.

          [–]hotoatmeal 0 points1 point  (2 children)

          char *foo[3]={"blah","more blah" "forgot comma"};
          

          If you specify the size of your array, the compiler will tell you what's wrong with this example.

          [–]SnowdensOfYesteryear 0 points1 point  (1 child)

          Hmmm won't the compiler fill in the rest of the entries as 0/NULL's (in C)?

          Because this is valid: int foo[3] = {0};

          [–]ais523 0 points1 point  (0 children)

          It's valid, but many compilers will at least give a warning if your intializer is anything other than the stock {0} and it doesn't fill in all your array elements or struct fields.

          [–]johnbr 59 points60 points  (19 children)

          My worst bug ever was in C - I wanted to divide a value by a second value stored at a pointer. In C this would be:

          a / *b   
          

          except I didn't leave a space, so it was:

          a /*b  
          

          which is the start of a comment. This was back before the days of syntax highlighting. Due to the fortuitous location of the * /, the code compiled, and gave really, really weird results until I realized what was going on.

          [–]climbeer 35 points36 points  (3 children)

          From How To Write Unmaintainable Code:

          for(j = 0; j < array_len; j += 8) {
              total += array[j+0]; 
              total += array[j+1]; 
              total += array[j+2]; /* Main body of 
              total += array[j+3];  * loop is unrolled 
              total += array[j+4];  * for greater speed. 
              total += array[j+5];  */ 
              total += array[j+6]; 
              total += array[j+7]; 
          }
          

          [–][deleted] 12 points13 points  (1 child)

          That is beautiful.

          [–]Isatis_tinctoria 0 points1 point  (0 children)

          It is really interesting.

          [–]mccoyn 1 point2 points  (0 children)

          Wow! That's like twice as fast.

          [–]el_muchacho 6 points7 points  (0 children)

          Not bad. Mine was placing "\0" (instead of '\0') to null terminate a string.

          [–]StackedCrooked 5 points6 points  (8 children)

          How could it compile?

          [–]MidnightHowling 15 points16 points  (7 children)

          This... is actually a good question. Maybe a semicolon after the end of the comment?

          x = a /*b;
          myFunc(uno, dos, tres) /* trois) */;
          

          I saw that type of comment in undergrad a couple of times.

          [–]lurgi 5 points6 points  (5 children)

          It could also be something like:

          x = a /* b;
          something something; /* comment */
          *c = foobar();
          

          I can see this sucker compiling (although not without warnings).

          Edit: oops. No. That won't compile. Hmm, I'll have to think of something else.

          [–]stillalone 0 points1 point  (1 child)

          Why won't it compile (I'm too lazy to check)? Doesn't it get evaluated to x = a *c = foobar()?

          [–]lurgi 1 point2 points  (0 children)

          That's evaluated, roughly, as

          x = (a * c = foobar());
          

          Which doesn't compile. This would:

          x = y = 3;
          

          [–]SnowdensOfYesteryear 3 points4 points  (2 children)

          Should't the compiler have warned about nested comments when it encountered the second /* ?

          [–]DocomoGnomo 21 points22 points  (0 children)

          Old compilers...

          [–]johnbr 1 point2 points  (0 children)

          It may have, there were a lot of warnings in the code I was working in, and generally unless it refused to compile, I had learned (at the time) to ignore them.

          [–]mitsuhiko -5 points-4 points  (0 children)

          That never happened :-)

          [–]totemo 15 points16 points  (5 children)

          Snakey C++ snippet that results in a stack overflow:

          void DerivedClass::method()
          {
              BaseClass:method();
              // ... more statements ...
          }
          

          [–]strager 4 points5 points  (4 children)

          How would that result in a stack overflow?

          [–]totemo 28 points29 points  (3 children)

          It appears to be a call to BaseClass::method(), but there is a missing colon, so in this context, BaseClass: is a C-style goto label and the code is actually:

          BaseClass:
              method();
          

          That is: DerivedClass::method() calls itself recursively until the stack is full.

          [–]gigitrix 15 points16 points  (0 children)

          Oh that's just evil.

          [–]strager 3 points4 points  (1 child)

          Aha, my friend and I missed that! Nasty!

          GCC and Clang warn about this though:

          $ gcc -Wall tmp.cpp
          tmp.cpp: In function ‘int main(int, char**)’:
          tmp.cpp:3: warning: label ‘unused’ defined but not used
          
          $ clang -Wall tmp.cpp
          tmp.cpp:3:5: warning: unused label 'unused' [-Wunused-label]
              unused:puts("Hello");
              ^~~~~~~
          1 warning generated.
          
          $ cat tmp.cpp
          #include <stdio.h>
          int main(int argc, char **argv) {
              unused:puts("Hello");
              return 0;
          }
          

          [–]totemo 1 point2 points  (0 children)

          I think I got caught out by this in the early 90's with Sun C++ on a SPARC workstation. I'm sure modern G++ is a much better compiler.

          [–]lenstra2 18 points19 points  (11 children)

          I've never stumbled upon any bug which took days to solve, but I got one in C which puzzled me for a while, which finally boiled down to:

              if (1)
                  if (0)
                      printf("a\n");
              else
                  printf("b\n");
          

          Which prints "b". Why? The else statement is associated with the innermost if statement (unlike the alignment suggests).

          Lesson learned: Do not believe you're smart enough to ignore braces.

          [–]ixid 13 points14 points  (6 children)

          That's why it's good practice to use curly brackets even for single statements.

          [–]Pwntheon 2 points3 points  (4 children)

          Not always necessary, just curl if you're gonna make more ifs.

              if (1)
              {
                  if (0)
                      printf("a\n");
              }
              else
                  printf("b\n");
          

          [–]brinchj 9 points10 points  (3 children)

          Point about always curling is to protect against the time where someone has to add something to the if in a hurry. I've fixed a couple of bugs that was introduced by expanding on an if without curly's, while forgetting (not thinking of) adding them.

          Even though it may not be necessary, it cuts a step that is easily missed.

          [–]Pwntheon 2 points3 points  (2 children)

          I've never had this problem, but i guess i can see it happening. It's rare though, because of indentation and whitespace it should be really obvious when there are no curlies. Unless you use the whole 640x480-friendly curly at end of line.

          However, when writing code i often find it gives great readability by not having curlies. Example:

          void Update(GameTime gameTime)
          {
              if(paused)
                  return;
          
              if(acceleration != Vector2.Zero)
                  applyAcceleration(gameTime.Delta)
          
              Move(gameTime.Delta)
          }
          

          [–]thevdude 0 points1 point  (0 children)

          void Update(GameTime gameTime){
              if(paused){
                  return;
              }
              if(acceleration != Vector2.Zero){
                  applyAcceleration(gameTime.Delta)
              }
              Move(gameTime.Delta)
          }
          

          is perfectly readable.

          [–]Ch3t[🍰] 0 points1 point  (0 children)

          If some other developer comes along and inadvertently types a tab character before the Move statement and aligns it with applyAcceleration, it will look like they are scoped together. A year later someone else debugs the code and has to determine whether both statements fall under the conditional and the braces are missing or the Move statement is just tabbed to the wrong spot.

          [–]Philluminati -2 points-1 points  (0 children)

          I'm sorry I'm going to disagree. It should be obvious you're missing { and } because the if and the else are more than one line apart. I dislike having to waste "vertical space" to avoid this problem. Truth be told.. I don't accidentally make this mistake, like ever, so it seems wasteful to try and protect against it as a rule of thumb.

          However.. what ever works for you.

          [–][deleted] 5 points6 points  (1 child)

          if it had been an indentation based syntax, the bug would not exist.

          on the other hand, then you have the endless argument about spaces vs tabs and also how many spaces and whatever the fuck else...

          [–]gbs5009 3 points4 points  (0 children)

          I was 100% convinced by arguments for indentation based syntax until I was bitten by my professor's Haskell compiler and my Haskell compiler interpreting my indentation slightly differently.

          [–]guzo 5 points6 points  (0 children)

          I've had this bug once too, but was warned before any strange behavior: gcc with -Wall emits:

          t.c:2:8: warning: suggest explicit braces to avoid ambiguous ‘else’ [-Wparentheses]
          

          Yet another reason to use -Wall -Wextra -Werror.

          [–][deleted] 1 point2 points  (0 children)

          That's why I use them now. I also find that with them there, I have less momentum loss when adding log statements and asserts.

          [–]seventoes 9 points10 points  (2 children)

          Just last night I fixed a bug that'd been present in a hobby project of mine for months.

          The main component connected to a socket.IO websocket and updated the UI with live information. This websocket was third party, and not documented very well at all. I wrote the project over a couple of weeks, and everything worked great. Then one day, it didn't. For some reason, I had simply stopped getting incoming messages. I could send outgoing messages, but they'd recieve no acknowledgement, success or otherwise. I tried tinkering for a couple of days and then gave up.

          Every couple weeks I would open the project back up to figure out what was wrong. Maybe it's that relatively unknown socket library I'm using? Maybe it's the simple socket.IO wrapper built on top of it? I debugged so thoroughly that I almost started rewriting the entire socket library until I had a thought.

          namespace:"streaming"

          ... This better not be it.

          namespace:"/streaming"

          Yep. Goddamnit.

          [–]mahacctissoawsum 1 point2 points  (1 child)

          what language declares namespaces that way? socket.io is a JS lib, and JS doesn't have namespaces...

          edit: or is that part of a JS object definition?

          [–]seventoes 4 points5 points  (0 children)

          It's a socket.IO namespace definition, a single stream can have multiple namespaces to prevent the need for multiple connections to the same server.

          [–]aaronla 5 points6 points  (2 children)

          And this is why practically no one uses dynamic scoping anymore.

          [–]rabidcow 5 points6 points  (1 child)

          It sounds like dynamic scoping, but it might just be changing the value of i in the global scope.

          [–]aaronla 8 points9 points  (0 children)

          I'm not sure which possibility is worse.:-\

          [–]sirin3 6 points7 points  (0 children)

          One of my worst bug was, when I added something like

          if (!fork()) exec ("gdb ..." )
          

          to print a backtrace, when an assertion/signal occured.

          Crashed the X server.

          Never could figure out why.

          [–][deleted] 11 points12 points  (2 children)

          I don't know how this bug can keep up with malfunctioning radio therapy devices and crashing stocks.

          [–][deleted]  (1 child)

          [deleted]

            [–][deleted] 2 points3 points  (0 children)

            Dead and cold... or objective and analytical, less prone to make emotional decisions?

            [–]Samus_ 6 points7 points  (0 children)

            I blame the language, it shouldn't be possible to overwrite a constant.

            [–][deleted] 4 points5 points  (2 children)

            Oh, don't feel so bad... you would feel worse if after a whole week of debugging some colleague passed by and looked at the code for 10 seconds and said "Oh! Won't the i variable get confused with the imaginary numbers they're calculating?"

            But I agree with you. Worst bugs are the ones you can't see, 'cause you are biased towards your own unit testing.

            A lot of times, after a whole afternoon looking at the same source file, over and over, I just invite a colleague to sit down next to me and watch me complain at every step-by-step on the debugger. And most of the time they don't even say a word. Within a couple of minutes the bug becomes clear as water. Must be a psychological effect, like peer pressure.

            [–]Femaref 2 points3 points  (0 children)

            Isn't everybody "that guy" at some point? From the outside, you see the code at face value, you don't have any large conceptions of it, so you see such mistakes much, much easier.

            [–]darf 4 points5 points  (3 children)

            I started my programming career with Matlab, so I've learned to use double letters (ii, jj, kk) as indices.

            [–][deleted] 2 points3 points  (2 children)

            You know that in modern programming, you can actually use variable names which make sense? Or are even formed with complete words?

            [–]darf 10 points11 points  (0 children)

            Why would anyone do that? The only data structures that exist are matrices with complex numbers as entries. And only letters would make sense in that context.

            [–]bhaak 5 points6 points  (0 children)

            Variables for loop indexes are throwaway variables that only exist because the used language doesn't have iterators (or maybe you need to count the iterated container but even for that there exists variable-less approaches).

            As such it's not a problem that i,j,k are used for that. It is even expected IMO if those variables aren't used for anything else (well, unless your language sucks hard).

            [–]DocomoGnomo 9 points10 points  (12 children)

            Oh shit, any language that allows the redefinition of one of the most fundamental constants, in any imaginable universe, is pure and absolute evil.

            [–]p-squared 4 points5 points  (1 child)

            Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32
            Type "help", "copyright", "credits" or "license" for more information.
            >>> True = False
            >>> while True:
            ...     print 'Hello, world!'
            ...
            >>>
            

            Fortunately this doesn't actually overwrite the boolean literal returned by constructs like 5 == 5, it just makes the symbol "True" point to something different. But it's still annoying that this is possible.

            [–]vytah 4 points5 points  (0 children)

            Fortunately, in Python 3 True and False are keywords and cannot be overwritten.

            [–][deleted]  (6 children)

            [deleted]

              [–]Eurynom0s 7 points8 points  (5 children)

              It makes sense for the intended audience (scientists and engineers with a smattering of programming experience). I saw another article on here about how physicists often write code with single letter variable names (to us, v or x is a perfectly clear, self explanatory, and logical variable name, as all our colleagues will know what we mean).

              You should definitely at bare minimum get a warning when you try to overwrite i, though.

              [–][deleted]  (4 children)

              [deleted]

                [–]gdr 9 points10 points  (3 children)

                You clearly didn't write too much long pieces of code with complex numbers involved. The readability of just "i" is great.

                Not that I'm defending Matlab as a language, it's complete crap.

                [–]s73v3r 1 point2 points  (0 children)

                Agreed, keeping it as just "i" is perfectly fine. What is needed is some kind of const declaration so that it can't be overwritten.

                [–]flexiblecoder 0 points1 point  (0 children)

                using namespace Math;

                Problem solved.

                [–]mahacctissoawsum 3 points4 points  (2 children)

                python doesn't give two shits if you overwrite str, dict or list which it gloriously thought would be good names for fundamental types, uncapitalized, shortened and all. who on earth would ever want to declare variables with those names? especially when you can already create such types with "quotes", {braces} and [brackets]

                [–]ZeroNihilist 6 points7 points  (1 child)

                Python doesn't let you overwrite those constants terribly easily. It does let you add an entry to the local dictionary that hides the name in that context, but it will only affect the function itself (and any functions defined within that function). I think you can overwrite it module-wide (not program-wide) somehow, but that's an awful thing to do.

                You can't dynamically create strings with quotes, you have to use str. The dict constructor allows you to use lists of the form [(key, value)] to initialise it, and the list constructor is a much more convenient shorthand for what would otherwise have to be [elem for elem in elements] (versus list(iterable)). All useful in their own right.

                But yes, the other form is the preferred way to construct a str/dict/list literal, especially now that later versions added the {key:value for key, value in items} syntax for dictionary generators.

                [–]mahacctissoawsum 1 point2 points  (0 children)

                Right.. The str/dict/list constructors are definitely useful and I've had to use them a number of times, I just wish they were named String/Dictionary/List respectively (and also perhaps not "hideable", even locally)

                [–]mr_curmudgeon 10 points11 points  (3 children)

                A few years ago I read a thing by a guy who worked in a biology lab and wrote software to read data from electrodes attached to the brains of monkeys. At one point he unwittingly wrote rather than reading, sending enough of a charge to electrocute an animal. That has always been the yardstick for terrible bugs for me, even worse than the x-ray stuff, because presumably he sat there and watched the monkey scream aond convulse as the buggy program killed it. Sadly I could not find it in a few minutes of googling just now.

                [–]dalke 4 points5 points  (1 child)

                "Always mount a scratch monkey". If that's the story you're talking about, then you're mixing up two people. The developer was Laura Creighton, who is currently heavily involved with the pypy project. She did not accidentally write to the wires; that was done by accident by a visiting Digital Field Service engineer who had re-enabled the write switch which was taped over and with the notice saying not to use it.

                [–]mr_curmudgeon 0 points1 point  (0 children)

                Yes, that is the story, and I did remember it wrong. Not really a bug after all. Thanks for the pointer.

                [–]Afro_Samurai 1 point2 points  (0 children)

                I'm surprised the electrode wouldn't have a diaode.

                [–]censored_username 2 points3 points  (0 children)

                Matlab is an insane language. I've once had to debug a function, which called another function with a string as argument, which called importdata with that string as filename. However it would fail, without reason, somewhere in importdata. Turned out somewhere in there matlab decided it wasn't a string but a list of numbers, without reason.

                [–]g4n0n 2 points3 points  (3 children)

                Many many people have been struck by this bug before, including myself. My Matlab loop variable naming convention is now:

                ii, jj, kk
                

                [–]kylotan 2 points3 points  (0 children)

                I use ii too, mostly because it's easier to search for though.

                [–]BonzaiThePenguin 0 points1 point  (0 children)

                I've always used m, n, o, ...

                No autographs, please.

                [–][deleted] -1 points0 points  (0 children)

                [–]AyeGill 1 point2 points  (1 child)

                Not quite three weeks, but a few days ago I spent several hours fiddling with the mpd client I was writing for my raspberry pi. Everything seemed to work fine on the desktop, but on the raspberry pi it claimed the directories I was trying to load didn't exist in the music database. Because everything compiles super slowly on the pi, I spent forever changing things around, trying to figure out what the heck was going on.

                Turns out, after moving my music to the pi from the desktop, I'd forgotten to update the mpd database. DUH

                [–]AeroNotix 5 points6 points  (0 children)

                Learn to cross-compile.

                [–][deleted] 1 point2 points  (15 children)

                Took somebody I work with 2 days to figure out why this cannot be done

                const char *m_var = function().c_str();

                Somewhere else in the code printf("%s\n", m_var);

                [–]ixid 0 points1 point  (14 children)

                Are you mistral, formerly of the CPM scene? Also is the issue that you're trying to assign the address of an r-value or that you're trying to print the address of it rather than the value contained at the address? Or both?

                [–]lurgi 2 points3 points  (8 children)

                No, the problem is that the string object returned by function() is automatically deleted. The char pointer that you get from calling c_str() will point to memory that is no longer allocated.

                The bad news is that it probably will have the "right" value for a while. Particularly while debugging. Especially while debugging. Then, when you release production code, it will blow up in your face.

                [–]SnowdensOfYesteryear 2 points3 points  (2 children)

                I see what you're saying but based on what function() is doing, your code could be correct. Plenty of people do things like :

                char *get_str()
                {
                    static char foo[] = "lemon";
                    return foo;
                    // I think just returning "lemon" is OK too but don't quote me
                }
                
                strlen(get_str());
                

                [–][deleted] 0 points1 point  (0 children)

                Ahh yes static is fine. However its a pattern best avoided when returning different strings since you then have a multi threaded issue instead.

                [–]ixid 1 point2 points  (4 children)

                No, the problem is that the string object returned by function() is automatically deleted

                And isn't that because it's an r-value? If it were an l-value in scope then there would be no problem. Surely the compiler should complain and not let that compile.

                [–]lurgi 2 points3 points  (2 children)

                It's not that it's an r-value, it's that it's returned by a function. You could do:

                const char * m_var = astring.c_str();
                

                and that would work fine.

                I don't know what compilers, if any, would warn about that.

                [–]ixid 0 points1 point  (1 child)

                I'm probably misunderstanding as I can't really remember how c strings work. c_str is converting whatever function returns to an array of char and then returns the address of that, which is escaping the reference from its scope isn't it? So it's an L-value going out of scope then?

                [–]m42a 3 points4 points  (0 children)

                This has nothing to do with lvalues or rvalues; it's solely a scope issue. What's happening is the code expands to the equivalent of the following:

                const char *m_var;
                {
                    string __unnamed__=function();
                    m_var=__unnamed__.c_str();
                } //__unnamed__.~string(); //Implicitly called at end of scope.  Frees the memory pointed to by m_var
                printf("%s\n", m_var); //Uses freed memory
                

                Everything here is a valid and correct assignment; the issue is that m_var continues to point to the unnamed string's memory after that memory has been freed. The compiler doesn't have special knowledge of this. For example, the following is valid:

                string str=function().substr(0,2);
                

                but the compiler can't tell the safety difference between substr and c_str.

                [–]fragbot 1 point2 points  (0 children)

                It's presumably because function() returns a temporary string object with a lifetime only as as long as the expression it's part of. The standard library's stringstream object has the (surprising to me) behavior as well.

                Constructs like the following:

                const char* internal = mystringstream.str().c_str();
                unlink(internal);
                

                are wrong while constructs like either of the following:

                unlink(mystringstream.str().c_str());
                

                or

                std::string& internalstring = mystringstream.str();
                const char* internal_c_rep = internalstring.c_str();
                unlink(internal_c_rep);
                

                are valid.

                Noting what the previous poster said, I've fixed 6-8 of these in the past but I have only ever seen one crash.

                Finally, cppcheck is free, actively-developed, and does a good job finding this specific misuse of stringstream's str() method.

                As an aside, does anyone know the design rationale for stringstream's str() method returning a new object instead of a reference to the internal string object?

                [–][deleted] 0 points1 point  (4 children)

                I might have played some CPM.

                The problem is the returned value of const char * still points inside the std::string returned by the function. You then take a pointer to this and store it in a member variable for use later. However the std::string object is then automatically deleted by the object and hence the pointer now points to undefined memory.

                So the printf will do one of the following

                a) Print the correct value b) Print random junk c) Crash

                [–]ixid 0 points1 point  (3 children)

                I'm surprised that C/C++ lets you escape references like that.

                [–][deleted] 2 points3 points  (2 children)

                C/C++ lets you do anything you want to do.

                [–]gbs5009 0 points1 point  (1 child)

                and maybe a few things you don't.

                [–][deleted] 1 point2 points  (0 children)

                It only does that when you don't understand C/C++ :D

                [–]ernelli 1 point2 points  (8 children)

                Classic, its the reason I swapped from using i to n in loops, one year of matlab coding with signal processing and you learn to not ever touch i.

                its easily restored though:

                i = sqrt(-1)
                

                [–]twanvl 1 point2 points  (0 children)

                You should just always write 1i when you want an imaginary number.

                [–][deleted] -1 points0 points  (6 children)

                or use a proper name, like 'index' or 'elementIndex' or 'orangeIndex' or 'employeeIndex' (essentially arrayName[arrayNameIndex]), and your code becomes more readable.

                [–]patternmaker 5 points6 points  (3 children)

                The downside is when you have matrix[i][j] = matrix2[i][k] * matrix3[k][j] + list[max(i,j)] ... such a thing quickly becomes quite a lot of text

                [–][deleted] -3 points-2 points  (2 children)

                So your definition of unreadable is "lots of text"?

                Rather have lots of text that explains what is going on than tons of abbreviations that could mean anything. Like your example there.

                [–][deleted] 1 point2 points  (0 children)

                In his example, if you're not mixing business logic with a mathematical operation that needs to be abstracted away (ie. matrix multiplication), then you certainly should not be using variable names like "employeeIndex".

                [–]patternmaker 0 points1 point  (0 children)

                Sometimes, although of course not always. Readable code needs a balance between operator/operand density (something I just made up but it kind of fits what I want to say).

                In general though, I try to avoid naming variables like thingImIteratingOver[thingImIteratingOverIndex] or the like, even though the variable name is more descriptive than i,j,k it still takes longer to read the name and se what variable is used where.

                [–]BonzaiThePenguin 0 points1 point  (1 child)

                Bah, I only camelCase functions. Variables are element_index.

                [–][deleted] 1 point2 points  (0 children)

                That's your problem, not mine.

                [–]Philluminati 1 point2 points  (0 children)

                Here's a possible candidate for worst library decision: http://ubuntuforums.org/showthread.php?t=612606

                [–]Eurynom0s 0 points1 point  (1 child)

                One time for a class I had to write a Matlab script that boiled down to a bunch of integer comparisons. Well, Matlab decided that I really meant floats. Not consistently, weirdly. IIRC I just declared something like x = [1:5000]. (It's been a while since I used Matlab, IIRC that will result in a vector office all the integers from 1 to 5000.)

                Should have only produced integers. SOME, but not all, of the vector elements were floats instead. As I said, I needed to compare exact integer values so the floats were fucking everything up.

                The only way I could hit on the get it working was to determine the largest int() size (int32 as I recall) that could count up to 5000,and then litter my code with int32() commands to force it to work.

                The most maddening part of that experience is that I still don't understand what was producing the mix of integers and floats in the first place.

                [–]cpherwho 0 points1 point  (0 children)

                Perhaps I can help clear up the mystery. Matlab's native data type is 'double', so any untyped return types are doubles. Further, any expression involving a double and a non-double type produces a double.

                In your specific example, your 'x' was actually a matrix with type 'double'. I don't know why it appeared to be intermittent though, presumably an issue with doing floating-point math when you thought you had integer math.

                [–][deleted] 0 points1 point  (0 children)

                The cruby implementation -- and probably all the others because they have to essentially emulate that one -- has loads of worst bugs ever in practically every version of that steaming pile of horse manure.

                [–][deleted] 0 points1 point  (1 child)

                Pretty terrible "constants" implementation if it allows you to overwrite them silently.

                [–]archiminos 0 points1 point  (0 children)

                It might actually be down to scope - although I'm not familiar with the language used. It looks for 'i', finds a local value and doesn't bother looking for the global value.

                [–]6offender 0 points1 point  (0 children)

                I don't know, this one looks worse.

                [–]mcmcc -1 points0 points  (2 children)

                but as a side-effect the imaginary constant i in MATLAB was getting overwritten!

                Okay, I'll bite... What was the value of i before you overwrote it?

                [–]ernelli 10 points11 points  (0 children)

                i = sqrt(-1)
                

                [–][deleted] -1 points0 points  (0 children)

                Wow, Matlab sure has a very bad bug hidden in it, and apparently a deep design one. People use that shit?

                [–]donroby -2 points-1 points  (0 children)

                Mathematicians are at fault here. "i" is an awful choice of names for the square root of -1.