Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Janin posted:

Strictness optimizations like foldl' vs foldl aren't part of the compiler, though; there's no magical transformation which will make "sum = foldl (+) 0" work, because the definition of foldl precludes them.

You are aware that sum is defined as a left fold, and does in practice wildly change its behaviour depending on if optimizations were enabled? Strictness analysis and stream fusion are extremely general optimizations and Haskell very much depends on them in many common cases. The foldl to foldl' transformation is something that ghc really can do all on its own.

Janin posted:

It's not like somebody ever looks at a piece of Haskell code and wonders "gee, how much memory will this use?", and it certainly doesn't depend on compiler optimizations. The only compiler optimization which can change big-O behavior is stream fusion, which is performed only when requested by the code.

Ahaha wondering about the memory/time complexity of various pieces of Haskell is how I spend most of my days. When you have a long-running program that runs in constant memory on ghc 6.10, but grows at a constant rate in memory on ghc 6.12, it's a bit of a mystery. That turned out to be the common subexpression optimization getting a little bit more capable and deciding to never throw away some results that it might need in the future. Of course, turning off CSE resulting in both 6.10 and 6.12 never completing the task because I was missing a single let-binding I needed and without CSE the program wasn't sharing that value and would have to constantly recompute it.

I've worked with Haskell for years and I am still regularly surprised by various memory/time properties of large pieces of code. I can generally explain them eventually, and the profiling and debugging tools have been getting a lot better at helping programmers answer questions about performance, but it's still extremely hard to develop a good intuition for performance in Haskell.

Janin posted:

Most of the features you complain about are compiler-specific extensions, or have been removed from the language. This is the actual list of features, which I don't find particularly complex:

quote:

do notation, list comprehensions, pattern guards

do-notation is brain-dead simple to understand. List comprehensions and pattern guards are a bit more unusual, but hardly anywhere near LINQ.

Well, n+k patterns, bang notation in types, lazy patterns, and scoped type variables are all Haskell98. And they're all at least marginally crazy. Not to mention that the layout rules, especially when combined with do notation, are not all all predictable for new users to the language; there's no way you can look at the syntax for a if statement in a do block and tell me that the right decision was made there.

And if you want to use the extremely common State monad, you need to deal with undecidable/overlapping instances and functional dependencies. If you want any of the generic programming stuff, you'll probably want standalone deriving support. If you do anything with large data types you'll most likely find yourself using either record punning or GADTs (or both!). Programming Haskell without extensions in the current community is a joke.

Adbot
ADBOT LOVES YOU

TOO SCSI FOR MY CAT
Oct 12, 2008

this is what happens when you take UI design away from engineers and give it to a bunch of hipster art student "designers"

ShoulderDaemon posted:

You are aware that sum is defined as a left fold, and does in practice wildly change its behaviour depending on if optimizations were enabled? Strictness analysis and stream fusion are extremely general optimizations and Haskell very much depends on them in many common cases. The foldl to foldl' transformation is something that ghc really can do all on its own.
'sum' is only defined as a left fold in the H'98 report -- there's no reason to implement it using foldl, and I'm not aware of any compiler which does. Almost any Haskell code will break if optimizations are disabled, because so many are required for usable space/time performance.

ShoulderDaemon posted:

Ahaha wondering about the memory/time complexity of various pieces of Haskell is how I spend most of my days. When you have a long-running program that runs in constant memory on ghc 6.10, but grows at a constant rate in memory on ghc 6.12, it's a bit of a mystery. That turned out to be the common subexpression optimization getting a little bit more capable and deciding to never throw away some results that it might need in the future. Of course, turning off CSE resulting in both 6.10 and 6.12 never completing the task because I was missing a single let-binding I needed and without CSE the program wasn't sharing that value and would have to constantly recompute it.
This is more of a bug in the compiler implementation (which is chock-full of them). GHC, in my opinion, shouldn't be performing any CSE until they can figure out how to make it work (they never will).

ShoulderDaemon posted:

Well, n+k patterns, bang notation in types, lazy patterns, and scoped type variables are all Haskell98. And they're all at least marginally crazy. Not to mention that the layout rules, especially when combined with do notation, are not all all predictable for new users to the language; there's no way you can look at the syntax for a if statement in a do block and tell me that the right decision was made there.
Scoped type variables and bang notation are GHC-specific language extensions. Lazy patterns are simply part of pattern matching; there's nothing complex there. n+k patterns were removed from the language.

Could you elaborate on what's wrong with do-if syntax? I find it quite readable, especially compared to (for example) Ruby or LISP.
code:
foo x = do
    startFoo
    if someTest x
        then fooLoudly
        else fooQuietly
    doneFoo

ShoulderDaemon posted:

And if you want to use the extremely common State monad, you need to deal with undecidable/overlapping instances and functional dependencies. If you want any of the generic programming stuff, you'll probably want standalone deriving support. If you do anything with large data types you'll most likely find yourself using either record punning or GADTs (or both!). Programming Haskell without extensions in the current community is a joke.

!?

'State' doesn't require any language extensions, and certainly not anything as dangerous as undecidable/overlapping instances. You'll need type families to define a 'MonadState m' class/instance, but those can be understood after about a minute of reading.

Generic programming in Haskell is a catastrophe; from where I stand, it looks like a bunch of type-system wankery and bad ideas. Anybody trying to implement it in Haskell via a half-dozen unsafe extensions deserves their migraines.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Janin posted:

'sum' is only defined as a left fold in the H'98 report -- there's no reason to implement it using foldl, and I'm not aware of any compiler which does. Almost any Haskell code will break if optimizations are disabled, because so many are required for usable space/time performance.

You have to implement as something equivalent to foldl, because otherwise it has the wrong strictness properties - in particular, compilers are required to support Num instances with non-strict (+) operators correctly, even though there aren't any such instances in common usage. The optimization is just a special-case based on feedback from the strictness checker.

And yeah, optimizations change the correctness and complexity of Haskell programs, which is sort of what I was complaining about here. It should be possible to determine the correctness of a program independently of whatever magic your compiler does behind your back.

Janin posted:

This is more of a bug in the compiler implementation (which is chock-full of them). GHC, in my opinion, shouldn't be performing any CSE until they can figure out how to make it work (they never will).

Granted. The various automatic inlining rules are also chock-full of this kind of crap that they will never be able to make work "correctly".

Janin posted:

Scoped type variables and bang notation are GHC-specific language extensions. Lazy patterns are simply part of pattern matching; there's nothing complex there. n+k patterns were removed from the language.

Nope. Creating typeclasses or typeclass instances creates local scopes for some type variables which are larger than a single declaration, although fortunately not in a manner which is particularly likely to be confusing. Bang notation in constructors is Haskell98. n+k patterns are Haskell98, and if you get to dismiss them for not being part of the next version of Haskell, then you also have to acknowledge all the extensions that will be part of the next version of Haskell.

Janin posted:

Could you elaborate on what's wrong with do-if syntax? I find it quite readable, especially compared to (for example) Ruby or LISP.
code:
foo x = do
    startFoo
    if someTest x
        then fooLoudly
        else fooQuietly
    doneFoo

This is a syntax error in Haskell98:
code:
foo = do
  if x then
    actionOne
  else
    actionTwo
Programming languages should not forbid you from using the if-then-else indentation style that 99% of programming languages in the world use, especially if they only forbid that syntax in some constructs while allowing and encouraging it in pure code. Fortunately, this is being corrected.

Janin posted:

'State' doesn't require any language extensions, and certainly not anything as dangerous as undecidable/overlapping instances. You'll need type families to define a 'MonadState m' class/instance, but those can be understood after about a minute of reading.

You can't write automatic instances for MonadState of the form "(MonadState s m) => MonadState s (t m)" for some transformer t, which are the most common form of instance you will want to write if you are building transformer stacks, without undecidable instances. You can't build or import the mtl on a compiler which does not allow undecidable instances or overlapping instances, because the mtl itself creates a number of these instances so that things like RWS work correctly. In short, because data families weren't introduced early enough, many of the more critical modules in the Haskell world now depend directly or indirectly on unsafe bypasses of the type checker.

Janin posted:

Generic programming in Haskell is a catastrophe; from where I stand, it looks like a bunch of type-system wankery and bad ideas. Anybody trying to implement it in Haskell via a half-dozen unsafe extensions deserves their migraines.

Granted, but you frequently cannot escape it if you are using other peoples' code.

TOO SCSI FOR MY CAT
Oct 12, 2008

this is what happens when you take UI design away from engineers and give it to a bunch of hipster art student "designers"

ShoulderDaemon posted:

And yeah, optimizations change the correctness and complexity of Haskell programs, which is sort of what I was complaining about here. It should be possible to determine the correctness of a program independently of whatever magic your compiler does behind your back.
Correctness and performance are separate. Compiler optimizations will not (unless they're erroneous) transform a correct program into an incorrect one. However, they might be required for a program to perform within particular time or space constraints.

It's possible to determine the output of a program based only on the source code. Determining how much time or space it will require to run depends on the compiler, by necessity.

ShoulderDaemon posted:

Nope. Creating typeclasses or typeclass instances creates local scopes for some type variables which are larger than a single declaration, although fortunately not in a manner which is particularly likely to be confusing. Bang notation in constructors is Haskell98. n+k patterns are Haskell98, and if you get to dismiss them for not being part of the next version of Haskell, then you also have to acknowledge all the extensions that will be part of the next version of Haskell.
"all the extensions"? The only significant extension added in H'10 was the FFI, which is only of interest to people writing language bindings. It's not any more complex than the C# FFI. The others are minor tweaks to the grammar or widely-supported improvements (eg, hierarchical modules).

Scoped type variables and bang notation are not supported in H'98, nor H'10.

ShoulderDaemon posted:

This is a syntax error in Haskell98:
code:
foo = do
  if x then
    actionOne
  else
    actionTwo
Programming languages should not forbid you from using the if-then-else indentation style that 99% of programming languages in the world use, especially if they only forbid that syntax in some constructs while allowing and encouraging it in pure code. Fortunately, this is being corrected.
The Haskell designers agree with you (it was changed), but I disagree. That style ought to be a syntax error. Just because a human reading it can understand the purpose, doesn't mean that an ambiguous syntax is acceptable.

ShoulderDaemon posted:

You can't write automatic instances for MonadState of the form "(MonadState s m) => MonadState s (t m)" for some transformer t, which are the most common form of instance you will want to write if you are building transformer stacks, without undecidable instances. You can't build or import the mtl on a compiler which does not allow undecidable instances or overlapping instances, because the mtl itself creates a number of these instances so that things like RWS work correctly. In short, because data families weren't introduced early enough, many of the more critical modules in the Haskell world now depend directly or indirectly on unsafe bypasses of the type checker.
Writing 'MonadState' instances is trivial -- it's usually something like:

code:
instance (MonadState m) => MonadState (MaybeT m) where
    type StateType (MaybeT m) = StateType m
    get = lift get
    put = lift . put
Again, the only language extension needed is type families, which are used to declare the 'MonadState' class anyway.

It's not possible to write most modules without depending indirectly on bypassing the type checker, because most of them will call into foreign libraries at some point.

manero
Jan 30, 2006

Today's Ruby/Rails coding horror, variables slightly changed to protect the innocent:

code:
  def format_time(thing)
    t = ((thing.time.to_i % 1000000) / 100)
    sprintf("%02d:%02d GMT", t/100, t % 100)
  end
Edit: Edited for coherence

Double edit: I just realized the time column from our database is a double, but it's not a unix epoch timestamp, it's stored as 20100603160000 which is actually 06/03/2010 16:00

manero fucked around with this message at 17:13 on Jun 3, 2010

jandrese
Apr 3, 2007

by Tiny Fistpump
Maybe I'm nuts, but I don't see the horror there, other than the way you store your time in the database. That's pretty much what I would do if I had to work with that format.

HFX
Nov 29, 2004

jandrese posted:

Maybe I'm nuts, but I don't see the horror there, other than the way you store your time in the database. That's pretty much what I would do if I had to work with that format.

Yep the only problem I'd have with that is storing the time as a double. It would be better to have it as a packed Integer.

rivals
Apr 5, 2004

REBIRTH OF HARDCORE PRIDE!
In my peripheral interfacing class (working with AVR stk500 and atmega8) we were discussing how to deal with shared data and hardware interrupts. He was showing us examples of how one might solve a problem given a simple example and then asking the class if the solution would/wouldn't work and why or why not etc. Here was one example:
code:
uint16_t  Seconds_Since_Midnight(void)
{
cli();  // disable interrupt
return ( (((hrs*60) + mins)*60) + secs);  
sei();  // enable interrupt
}
At first a few people said that it wouldn't work but he didn't want anyone to say why. After a minute or two (and a couple more people realizing it wouldn't work) he said "yeah it will never enable the interrupts again". No less than 3 people raised their hands to ask why and were honestly confused as to why this solution was incorrect. :ughh:

trex eaterofcadrs
Jun 17, 2005
My lack of understanding is only exceeded by my lack of concern.

HFX posted:

Yep the only problem I'd have with that is storing the time as a double. It would be better to have it as a packed Integer.

That reminds me of php's microtime() function. Goddamnit whoever wrote that is a cocksucker.

Lysidas
Jul 26, 2002

John Diefenbaker is a madman who thinks he's John Diefenbaker.
Pillbug

TRex EaterofCars posted:

That reminds me of php's microtime() function. Goddamnit whoever wrote that is a cocksucker.

If you're unfortunate enough to use PHP on Windows, microtime() will make you want to tear your eyes out.

code:
Value returned from microtime(): 0.73437900 1272042042
Type of value returned from microtime(): string
A string!? What kind of brain damage do you have to suffer from in order to think that this is a good idea?

mr_jim
Oct 30, 2006

OUT OF THE DARK

Lysidas posted:

If you're unfortunate enough to use PHP on Windows, microtime() will make you want to tear your eyes out.

code:
Value returned from microtime(): 0.73437900 1272042042
Type of value returned from microtime(): string
A string!? What kind of brain damage do you have to suffer from in order to think that this is a good idea?

This kind of brain damage.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Lysidas posted:

If you're unfortunate enough to use PHP on Windows, microtime() will make you want to tear your eyes out.

code:
Value returned from microtime(): 0.73437900 1272042042
Type of value returned from microtime(): string
A string!? What kind of brain damage do you have to suffer from in order to think that this is a good idea?

php manual posted:

Parameters
get_as_float
When called without the optional argument, this function returns the string "msec sec" where sec is the current time measured in the number of seconds since the Unix Epoch (0:00:00 January 1, 1970 GMT), and msec is the microseconds part. Both portions of the string are returned in units of seconds.

If the optional get_as_float is set to TRUE then a float (in seconds) is returned.

see? problem solved :v:

Using php 4?
php:
<?
$ohgodwhy = array_sum(explode(' ', microtime()));
?>

TOO SCSI FOR MY CAT
Oct 12, 2008

this is what happens when you take UI design away from engineers and give it to a bunch of hipster art student "designers"
Just discovered a new take on the for-case pattern (bonus points: spot the bug which brought me to discover this):

code:
for (unsigned int index = 0; index < tokens.size(); index++) {
  if (index == 0) {
    this->foo = tokens[0];
  }
  else if (index == 1) {
    if (tokens[1] == "0" || tokens[1] == "false" || tokens[1] == "no") {
      this->bar = false;
    }
    else {
      this->bar = true;
    }
  }
  else if (index == 2) {
    if (tokens[2] == "0" || tokens[2] == "false" || tokens[1] == "no") {
      this->baz = false;
    }
    else {
      this->baz = true;
    }
  }
  // ...
  else if (index == 28) {
    this->ohgodjustshootme = tokens[28];
  }
  else {
    cerr << "invalid index!";
    abort();
  }
}

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
The only thing dumber than using the copy-paste design pattern is making edits to the pasted code without tool assistance (e.g. find-and-replace).

Painless
Jan 9, 2005

Turn ons: frogs, small mammals, piles of compost
Turn offs: large birds, pitchforks
See you at the beach!

Janin posted:

Just discovered a new take on the for-case pattern (bonus points: spot the bug which brought me to discover this):

That's like a matryoshka of horrors

Crazy RRRussian
Mar 5, 2010

by Fistgrrl
Where in the gently caress did that come from?

TOO SCSI FOR MY CAT
Oct 12, 2008

this is what happens when you take UI design away from engineers and give it to a bunch of hipster art student "designers"

Crazy RRRussian posted:

Where in the gently caress did that come from?

Your tax dollars and a summer intern

king_kilr
May 25, 2007

Janin posted:

Your tax dollars and a summer intern

Jesus. Christ. It at this moment I thank god that all of my coworkers are not only competent, but exceptional. We have no coding horrors (at least compared to the poo poo in this thread).

litghost
May 26, 2004
Builder
code:
std::ifstream file;
... open file, etc ...
std::vector<std::string> filters;
std::list<std::string> result;
std::string line;

while(!file.fail())
{
   std::getline(file, line);

   for(size_t i = 0; i < filters.size(); ++i)
   {
      if(line.substr(0,std::min(line.size(),filters[i].size())) == filters[i])
      {
          results.push_back(line);
      }
   }
}
I coded this horror myself. I decided a linear search was good enough for applying the filter. End result was the run-time when into >3 minutes for filter sizes above 1000 (which was easy to do). Replaced for loop with a Trie lookup and run-time went from several minutes to .3 seconds. Opps. I didn't notice the run-time performance problem until <1 days before release, so we are just going to release the slow version with a warning about running a large filter.

Crazy RRRussian
Mar 5, 2010

by Fistgrrl
Dude, just rewrite the code to avoid the substr operation. substr runs in linear time as every time you call it the STL needs to allocate new buffer and copy part of old string into it. From looking at the code you gave us it seems like you could rewrite your code to avoid substr rather easily and this will likely result in significant speed up. Do this and let me know what speed up you get with filters of size above 1000.

EDIT: Also compare the time needed to make prefix tree with time needed to do naive string matching but avoiding substr.

Crazy RRRussian fucked around with this message at 03:50 on Jun 4, 2010

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Crazy RRRussian posted:

Dude, just rewrite the code to avoid the substr operation.

He already rewrote it you dingleberry.

Crazy RRRussian
Mar 5, 2010

by Fistgrrl

Avenging Dentist posted:

He already rewrote it you dingleberry.

Yea sure, but hes saying he had to do a radix trie for it. I am just curious how the time needed to construct the tree impacts performance here with naive string matching.

litghost
May 26, 2004
Builder

Crazy RRRussian posted:

Dude, just rewrite the code to avoid the substr operation. substr runs in linear time as every time you call it the STL needs to allocate new buffer and copy part of old string into it. From looking at the code you gave us it seems like you could rewrite your code to avoid substr rather easily and this will likely result in significant speed up. Do this and let me know what speed up you get with filters of size above 1000.

EDIT: Also compare the time needed to make prefix tree with time needed to do naive string matching but avoiding substr.

I have to admit there is another horror here and that is I didn't profile the code to determine the problem, I assumed it was the linear search. So I did remove the substr, and here are the results:

code:
Original: ~62 sec
Without substr: ~6 sec
With trie: ~.17 sec
The thing I didn't mention is that the filter is applied over a file with >20,000 lines. So a change from O(N*M*k) to O(N*k) is significant if M approaches N (which in the worst case it can).

Kharya
Sep 23, 2005
So how DO you chase off a half blind, crazed, sugar addict?
This gem is from my company's CTO. He has a base set of libraries he's used for everything for at least the last 5 years.

php:
<?
...
$sql = "SELECT * FROM user WHERE ";
foreach ($query as $key => $value) {
    $sql .= $key." = '".$value."' AND ";
}
$sql = substr($sql, 0, -4);
...
?>
:downs:: "I thought you only had to escape SQL queries on INSERT, UPDATE, and DELETE"

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Crazy RRRussian posted:

Yea sure, but hes saying he had to do a radix trie for it. I am just curious how the time needed to construct the tree impacts performance here with naive string matching.

Probably pretty good given that many implementations of std::string use copy on write.

Crazy RRRussian
Mar 5, 2010

by Fistgrrl
I believe specification for string says they must be null terminated. Thus they could not use COW unless const [] operator does checks, which would make it slow. Also in my experience the standard STL implementation (whatever comes with Ubumtu) could not be doing COW because substr seems to be a heavy operation in them even if retrieved substring is never modified. Same with STL implementation on windows. This is coming from optimizing cpp prograns on both linux and windows to avoid using substr operation and this always resulting in nice speed up.

Crazy RRRussian fucked around with this message at 18:59 on Jun 4, 2010

floWenoL
Oct 23, 2002

Crazy RRRussian posted:

I believe specification for string says they must be null terminated. Thus they could not use COW unless const [] operator does checks, which would make it slow. Also in my experience the standard STL implementation (whatever comes with Ubumtu) could not be doing COW because substr seems to be a heavy operation in them even if retrieved substring is never modified. Same with STL implementation on windows. This is coming from optimizing cpp prograns on both linux and windows to avoid using substr operation and this always resulting in nice speed up.

This paragraph is the real coding horror.

Crazy RRRussian
Mar 5, 2010

by Fistgrrl

floWenoL posted:

This paragraph is the real coding horror.
Why?

b0lt
Apr 29, 2005
code:
i = i++;
:psyduck:

floWenoL
Oct 23, 2002

Crazy RRRussian posted:

Why?

Because almost every sentence has an error?

shrughes
Oct 11, 2008

(call/cc call/cc)

Crazy RRRussian posted:

I believe specification for string says they must be null terminated.

It's "believe the specification," not "believe specification."

It's NUL-terminated, not "null terminated."

Also your belief is wrong.

Crazy RRRussian posted:

Thus they could not use COW unless const [] operator does checks, which would make it slow.

Based on a wrong belief, hence wrong. Also it would be wrong if the belief was not wrong.

Crazy RRRussian posted:

Also in my experience the standard STL implementation

There is no standard STL implementation. gently caress THERE WAS A FLY ON MY HAND. How could you say "standard STL implementation"?

Crazy RRRussian posted:

(whatever comes with Ubumtu) could not be doing COW because substr seems to be a heavy operation in them even if retrieved substring is never modified.

substr is a different operation, obviously. COW simply refers to the copy constructor, and the assignment operator, and maybe other things I can't think of, but certainly not substr. Its implementation of std::string has sizeof(std::string) = sizeof(void*), which consists of a pointer to the buf member of a structure that looks like this (I may have mixed up the limit and length fields).

code:
struct { size_t refcount, limit, length; char buf[0]; };
It's specifically designed so that you can cast a std::string to a char* and have it work like a C style string, presumably because GNU developers are loving retarded. Having substr not actually copy would require abandoning that design decision and it would also be a potential memory leak and be something which is not expected by smart people.

Crazy RRRussian posted:

Same with STL implementation on windows.

It's the STL implementation on windows.

Crazy RRRussian posted:

This is coming from optimizing cpp prograns on both linux and windows to avoid using substr operation and this always resulting in nice speed up.

Hexadecimal, master substr optimizer. He even optimizes substrs from his own sentences.

Crazy RRRussian
Mar 5, 2010

by Fistgrrl
Yea ok, I said some stupid stuff about STL, however I am still right in that substr is loving slow and runs in linear time.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Crazy RRRussian posted:

substr is loving slow and runs in linear time.

These two have nothing to do with each other. In most cases where substr is slow, it's because of dynamic memory allocation, not because it's "linear time". Any string comparison is also linear time, so (in absence of allocations) you're just adding a scalar multiple (2) to the asymptotic behavior of the code.

I'm actually surprised libstdc++ doesn't use COW on substr starting at 0, but then COW is stupid as gently caress for strings to begin with, and in violation of the C++0x spec (due to the requirements of move ctors, I believe). I long for the day that clang and libcxx are the defaults on all systems.

shrughes
Oct 11, 2008

(call/cc call/cc)

Crazy RRRussian posted:

Yea ok, I said some stupid stuff about STL, however I am still right in that substr is loving slow and runs in linear time.

You're wrong, by default, because you care about whether you were once right. Also, you not only are wrong, you were wrong. substr is loving fast -- it runs in linear time!

shrughes
Oct 11, 2008

(call/cc call/cc)

Avenging Dentist posted:

(due to the requirements of move ctors, I believe)

How so?

The real horror is that C++ is so complicated that you can only "believe" it's in violation of the C++0x spec.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

shrughes posted:

The real horror is that C++ is so complicated that you can only "believe" it's in violation of the C++0x spec.

I haven't read the whole proposed spec since I see little point in trying to hit a moving target (especially since the semantics of rvalue references have changed several times now). I'm actually just going on something said on the GCC mailing list.

EDIT: Ah, sorry, it's because C++0x provides new concurrency guarantees for std::string, namely that 1) two threads may read from the same string object, and 2) a thread may copy and manipulate a string even if another thread is holding on to the original (short version: strings can't be retarded in C++0x). http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2668.htm if you care.

Avenging Dentist fucked around with this message at 21:42 on Jun 4, 2010

TOO SCSI FOR MY CAT
Oct 12, 2008

this is what happens when you take UI design away from engineers and give it to a bunch of hipster art student "designers"
gently caress my life

code:
string SomeClass::GetSomeBullshit(int which) {
  stringstream stream;
  switch (which) {
    case PRIMARY_BULLSHIT:
      stream << primaryBullshit;
      break;

    case SECONDARY_BULLSHIT:
      stream << secondaryBullshit;
      break;

    default:
      stream << "";
      break;
  }
  if (stream.str().empty() == false) {
    return stream.str();
  }
  return primaryBullshit;
}

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

The real real horror is that Hexadecimal is still managing to pull people into arguments with hardly any effort :rolleye:

POKEMAN SAM
Jul 8, 2004
A solution to "database is locked":

code:
def executeRepeated(db, query):
	try:
		res = db.execute(query)
		return res
	except sqlite3.OperationalError:
		return executeRepeated(db, query)

Adbot
ADBOT LOVES YOU

A A 2 3 5 8 K
Nov 24, 2003
Illiteracy... what does that word even mean?

Ugg boots posted:

A solution to "database is locked":

code:
def executeRepeated(db, query):
	try:
		res = db.execute(query)
		return res
	except sqlite3.OperationalError:
		return executeRepeated(db, query)

But this automatically works when the database is unlocked. Automatically.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply