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
ulmont
Sep 15, 2010

IF I EVER MISS VOTING IN AN ELECTION (EVEN AMERICAN IDOL) ,OR HAVE UNPAID PARKING TICKETS, PLEASE TAKE AWAY MY FRANCHISE

Zamujasa posted:

I might be misreading this, but it looks like an infinite recursion, since if you give it a value of "EXAMPLE" it will try to return the result of IsNullOrEmpty("EXAMPLE".Trim()) (essentially, the same function call), which will call itself again and so on and so forth.

Nah. Hibame said this was in a custom StringUtil class, so the stack will just go StringUtil.IsNullOrEmpty("EXAMPLE") -> String.IsNullOrEmpty("EXAMPLE".Trim()).

Adbot
ADBOT LOVES YOU

That Turkey Story
Mar 30, 2003

Vanadium posted:

Also D lets you assign non-static member functions to function pointers without a cast or anything, and the function pointers will segfault when called while this doesn't happen to have the right type in the lexical context of the call. :stare:

Wait, what? What was even the rationale for this?

Vanadium
Jan 8, 2005

That Turkey Story posted:

Wait, what? What was even the rationale for this?

http://d.puremagic.com/issues/show_bug.cgi?id=8114

I don't entirely see what they're getting at. Edit: Here's a more elaborate example:
code:
import std.stdio;

class C {
  void f() { writeln(i); }
  void call(void function() fp) { fp(); }
  int i;
}

void main() {
  // fortunately, won't compile
  // C.f();

  assert(is(typeof(&C.f) == void function()));
  auto fp = &C.f;

  C c = new C;
  c.i = 42;
  c.call(fp); // this is fine

  fp(); // Segmentation fault
}
also is(T1 == T2) is fairly ugly syntax too.

Vanadium fucked around with this message at 21:55 on Sep 11, 2012

hobbesmaster
Jan 28, 2008

That Turkey Story posted:

Wait, what? What was even the rationale for this?

I hope it segfaults in the same way boost::bind segfaults if you don't pass it this as the first parameter. :stare:

Workaday Wizard
Oct 23, 2009

by Pragmatica
Thank you all for your replies. I bookmarked the docs for the languages suggested and will be reading them as soon as I get free time.

Suspicious Dish posted:

...
Actually, let's rephrase the question: what features of OOP (because there are a lot of them, because it's a thing, and C++ doesn't provide nearly half of them) do you want in C? Inheritance? Virtual functions? Something else entirely?
...

...
I don't know what I really want... I am the coding horror:gonk:

Language design is hard. I just want some sane scoping.


Content:
Back when I was a student one of my classes required us to write caching web proxies in C in pairs. We didn't have source control (of course) so what my partner and I ended up doing is write a main file that #includes "myname.c" and "hisname.c" and just write our code in separate files.

Coding that proxy was fun!

Vanadium
Jan 8, 2005

I'd like to suggest that the D motto is "Those who cannot learn from history are doomed to repeat it" but I can't really argue against the combined Walter Bright and Andrei Alexandrescu C++ learnin'.

shrughes
Oct 11, 2008

(call/cc call/cc)
The problem with StringUtil.IsNullOrEmpty is that it shouldn't have the same name as String.IsNullOrEmpty while having different behavior.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

Shinku ABOOKEN posted:

I don't know what I really want... I am the coding horror

When you figure it out, let me know. I'll be glad to help.

Shinku ABOOKEN posted:

Content:
Back when I was a student one of my classes required us to write caching web proxies in C in pairs. We didn't have source control (of course) so what my partner and I ended up doing is write a main file that #includes "myname.c" and "hisname.c" and just write our code in separate files.

Coding that proxy was fun!

I've seen that in real code (I've done it, even). It's a poor man's form of linking, at some level. The simple example is if you have a lot of code in one file that manages two components, especially if one is a subcomponent of another, splitting it out into its own #include is one of the easiest ways to manage it. I usually put a comment at the top, saying /* this file is part of foomp.c */ or whatever.

Zamujasa
Oct 27, 2010



Bread Liar
I see. :shobon: I missed that detail and had assumed it would use the same method.

I have to agree about having the name be different, though, since it's technically NullOrEmptyOrWhitespace...

Munkeymon
Aug 14, 2003

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



I'd just go with ConsideredUseful at that point.

raminasi
Jan 25, 2005

a last drink with no ice
I want D's invariants.

Pilsner
Nov 23, 2002

Hibame posted:

In the core of all the applications here there is a shared C# lib that contains a StringUtil class, which has plenty of head scratchers. There is one method that piece de resistance

code:
public static bool IsNullOrEmpty(string value)
{
        return (value == null) ? true : String.IsNullOrEmpty(value.Trim());
}

Every time I see a project with one of those utility classes dealing with primitive types (or strings), they're always full of silly little methods, often one-liners anyway, and almost always re-invent the wheel instead of just using the framework. Just use ToString() with either standard or custom formatting strings, and cultures.

Also, that method is nasty. If I pass a string with " " (a spaces), it is not null nor empty, but that method would return true. That's a good example of a method name not doing what it promises.

ToxicFrog
Apr 26, 2008


GrumpyDoctor posted:

This is the succinct description of D that I've been looking for. I'm still disappointed about D. :(

I was disappointed about D, but then I found Scala and Go and forgot all about it. :D

Vanadium posted:

Also D lets you assign non-static member functions to function pointers without a cast or anything, and the function pointers will segfault when called while this doesn't happen to have the right type in the lexical context of the call. :stare:

Holy poo poo what :catstare:

I knew you could assign member functions to function pointers in D, but I kind of assumed that what you actually got would be a closure over the object the function was copied from.

Vanadium
Jan 8, 2005

If you grab it from an object, you do, I was taking it from the class in the example I posted.

I can kinda see what they wanted to use that for, but C++ actually engaged that problem with their pointers-to-member while D just throws even more type-safety away because pointers-to-member are clearly too clunky, I guess.

Senso
Nov 4, 2005

Always working

Same guy trashed linked lists in his next post. I'm a newbie regarding that but what's the general opinion of this thread, is he right? Linking directly in the object (intrusive lists) is preferred to using linked lists?

EDIT: Eh, he's also trashing Boost, since we're talking about it.

quote:

If you read the source code, I hope you’ll find it straightforward. For a start, the entire instrusive linked-list, including the comments and MIT license, clocks in at under 500 lines.

Compare this with boost instrusive list.hpp — which admittedly does have more functionality — at 1500 lines not including the eleven (11!!) subsidiary headers filled with all that unreadable modern C++ templately bollocks.

Senso fucked around with this message at 09:22 on Sep 12, 2012

omeg
Sep 3, 2012

Senso posted:

Same guy trashed linked lists in his next post. I'm a newbie regarding that but what's the general opinion of this thread, is he right? Linking directly in the object (intrusive lists) is preferred to using linked lists?

He's right if you're really worried about performance. Less pointers in your data structures = better data locality = better cache performance and simpler serialization. But if you're not writing something performance-critical you don't need to worry about that.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Intrusive lists are great if you want to avoid allocations while maintaining a collection. Since allocations are kind of pricy regardless of memory latency, this makes them pretty good on "slow" hardware where the memory latency is low and so the indirection matters less. As well as the obvious use case of writing the thing that manages the memory, of course.

shrughes
Oct 11, 2008

(call/cc call/cc)
WTF. My intrusive list types generally run 50 lines.

Sagacity
May 2, 2003
Hopefully my epitaph will be funnier than my custom title.

shrughes posted:

WTF. My intrusive list types generally run 50 lines.
But then, you are a programming messiah.

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

omeg posted:

He's right if you're really worried about performance. Less pointers in your data structures = better data locality = better cache performance and simpler serialization. But if you're not writing something performance-critical you don't need to worry about that.
If you're not writing something performance-critical should you be using C++? I thought that was the only reason anyone still bothered with it (outside legacy).

KaneTW
Dec 2, 2011

leper khan posted:

If you're not writing something performance-critical should you be using C++? I thought that was the only reason anyone still bothered with it (outside legacy).

There are different levels of performance required.

shrughes
Oct 11, 2008

(call/cc call/cc)
C++ is also a better language than Java, C#, et al, without taking into account performance.

Sagacity posted:

But then, you are a programming messiah.

Actually it runs around more like 80 lines. It could potentially balloon to 90 if I ever need to iterate the thing without consuming it.

Mine is designed to make nodes inherit from a base class though, so it's a bit different, you'd need some ugly inheritance to get an object into two lists at once. I'll have to write a non-base-class version though to see how that works out.

shrughes fucked around with this message at 13:40 on Sep 12, 2012

Zombywuf
Mar 29, 2008

Hibame posted:

In the core of all the applications here there is a shared C# lib that contains a StringUtil class, which has plenty of head scratchers. There is one method that piece de resistance

code:
public static bool IsNullOrEmpty(string value)
{
        return (value == null) ? true : String.IsNullOrEmpty(value.Trim());
}

This code is familiar to me. Is there a BooleanFormatter class lurking in that codebase?

Also, D. Man that language is annoying, I want some of its features so bad, but the language is terrible. Strings are arrays of const chars that are also ranges over unicode codepoints encoded in unicode in the array. The only way it seems possible to run the built in unit tests is to actually run your program, you can't just compile test runner binary (that I could find anyway). There's loads of mysterious poo poo in there to trip you up, the language feels like it's made of the frustrations of C++ programmers who couldn't get their ideas for the language past the committee.

Senso
Nov 4, 2005

Always working

shrughes posted:

Actually it runs around more like 80 lines. It could potentially balloon to 90 if I ever need to iterate the thing without consuming it.

Mine is designed to make nodes inherit from a base class though, so it's a bit different, you'd need some ugly inheritance to get an object into two lists at once. I'll have to write a non-base-class version though to see how that works out.

Can you share that or it's proprietary? I'm interested in seeing the different implementation since I'm just starting reading up on that.

That Turkey Story
Mar 30, 2003

Senso posted:

Same guy trashed linked lists in his next post. I'm a newbie regarding that but what's the general opinion of this thread, is he right? Linking directly in the object (intrusive lists) is preferred to using linked lists?
Intrusive containers are great, but they are certainly not universally better than non-intrusive ones, despite his claims. Rather than go through everything here, the Boost documentation has an actual sensible, not-one-sided list of advantages and disadvantages (and with an implementation that is much more usable than Patrick Wyatt's and actually gives them standard-compliant iterators, meaning that you may use them with generic algorithms... of course, the header file is longer than his so it's clearly inferior :rolleyes:).

Like anything else, you weigh your options. Lots of types (containers, smart pointers, etc.) may be implemented intrusively, with varying benefits. If you are dealing with value types, a std::list is often a better choice and is easier to reason about. Throwing down your fist and saying that users should always prefer intrusive over non-intrusive containers is ridiculous and at the very least forces people to intrusively alter their types simply because of the containers they may be stored in when it may not even be worthwhile, and it forces you to change your types if you simply change where/how they are stored.

Also, a fair amount of what he says is not entirely true:

Patrick Wyatt posted:

Here is code that safely removes a person record from the linked list:

code:
// NOTE: O(N) algorithm
// -- requires list scanning
// -- requires memory deallocation
void erase_person (person *ptr) {
    std::list <person*>::iterator it;
    for (it = people.begin(); it != people.end(); ++it) {
        if (*it != ptr)
            continue;
        people.erase(it);
        break; // assume person is only linked once
    }
}
Tragically, this unlinking code is awful: for a list with N entries, on average it is necessary to scan N/2 entries to find the element we’re interested in removing, which is why a linked list is a bad choice for storing records that need to be accessed in random order.

More importantly, it’s necessary to write list-removal functions like the code above, which takes programmer dev-time, slows compilation, and can have bugs. With a better linked-list library, this code is entirely unnecessary.
A few things here. First, if you want to remove something from the list in constant time, you usually hold on to an iterator instead of a pointer, which you get when you insert it into that list. This allows you to delete it from the list in constant time with no searching required. If your pointer originally came from somewhere else, then yeah, you will have to search, but again, that is only a subset of cases.

Second, his comment that it forces people to write "list-removal" functions such as the one he wrote out above are completely not true. Despite deciding that std::list is universally bad, he apparently doesn't even know the STL well enough to realize that std::list has a function for removal (imagine that) and it's called, unsurprisingly, "remove." You just have to write your_list.remove( your_person ); You don't have to manually write a search as he explicitly claims and cites as a reason why his intrusive list is "better" than std::list.

Third, but admittedly on somewhat of a tangent, in cases like these, very often people mistakenly choose a std::list over something like a std::vector simply because they want constant time removal from the container. There are a couple issues here. First, you can remove items from a vector in constant time, it just alters the stored order and potentially invalidates an iterator -- you do so by swapping the element you want to remove with the one in the back and then pop_back. Second, if you are dealing with something like a container of pointers (or really anything that is trivially movable), as is in the example, erasing something from the middle can generally just be a memmove on the chunk of data that appears after the removed element anyway, and will even preserve storage order. It's also important to note that neither of these operations will require a call to your allocator's deallocation function, unlike when using a std::list, since in the list case, a node has to be deleted. For small lists, it's unlikely the difference between the constant-time erasure and the erasure from the middle of a vector of trivially-movable types, such as pointers, is significant at all, and depending on a number of variables including the size of the container, how allocation/deallocation is performed, and where your list nodes happen to be in memory in relation to one another, the vector erase may end up being faster, even if you don't use the swap trick. Finally, linked lists provide constant removal, but iteration over them is potentially much slower and not cache-friendly. If you are iterating over the list frequently (I.E. every frame, or almost every frame), but are removing things from the list only on occasion (I.E. when an object moves from one sector to another, or when an item is removed from inventory or a selection list, etc.), you should probably be valuing fast iteration a lot more than fast removal (though in those cases, neither would likely be a bottleneck anyway).

Anyway, the point is, you always need to weigh your options. The differences between std::list, intrusive lists (whatever implementation you choose), std::vectors, and any container are trade-offs. One is not universally better than another.

Senso posted:

EDIT: Eh, he's also trashing Boost, since we're talking about it.
Not uncommon for game programmers and people who always roll their own datastructures because it's easy :rolleyes:. "This header file is big, but I can write it in fewer lines so therefore my version must be better! Whoa, a metafunction, what is this voodoo nonsense!?!" The boost containers provide compliant iterators so that you can actually use them with generic code, they are well tested, documented, and programmers know them. Even if they don't use boost, anyone who knows the language's standard library already knows 90% of how to work with a boost container, and if you are using some hand-rolled solution that doesn't do this, there is 0 chance that anyone else is going to be familiar with your code before being brought onto the team. In addition, with a solution such as boost's that provides compliant iterators, you don't have to write your own algorithms for everything because of it's iterator support. Of course, since he doesn't even know about std::list::remove I doubt he's ever touched <algorithm>.

Edit:

shrughes posted:

Actually it runs around more like 80 lines. It could potentially balloon to 90 if I ever need to iterate the thing without consuming it.

Mine is designed to make nodes inherit from a base class though, so it's a bit different, you'd need some ugly inheritance to get an object into two lists at once. I'll have to write a non-base-class version though to see how that works out.

Or, you could just use a peer-reviewed, efficient, tested, open source solution that people already know instead of making your own intrusive container, apparently for at least the second time, programming messiah. *cough*

That Turkey Story fucked around with this message at 22:58 on Sep 12, 2012

raminasi
Jan 25, 2005

a last drink with no ice
e: you know what, never mind. Not a productive post.

raminasi fucked around with this message at 19:19 on Sep 12, 2012

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

GrumpyDoctor posted:

I know I really shouldn't bite on this, but what the gently caress

Let it go. I thought the same thing, but it's not going to be a constructive discussion.

That Turkey Story
Mar 30, 2003

Vanadium posted:

I'd like to suggest that the D motto is "Those who cannot learn from history are doomed to repeat it" but I can't really argue against the combined Walter Bright and Andrei Alexandrescu C++ learnin'.
I find this to be the case with most languages. It seems like for every language that introduces something useful, they get rid of something else that is useful because it's "complicated" (who cares if it's useful and correct -- it's scary!).

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.

Vanadium posted:

I'd like to suggest that the D motto is "Those who cannot learn from history are doomed to repeat it" but I can't really argue against the combined Walter Bright and Andrei Alexandrescu C++ learnin'.
It's kind of a second-system effect where the first system was a second system

HORATIO HORNBLOWER
Sep 21, 2002

no ambition,
no talent,
no chance

Senso posted:

Same guy trashed linked lists in his next post. I'm a newbie regarding that but what's the general opinion of this thread, is he right? Linking directly in the object (intrusive lists) is preferred to using linked lists?

EDIT: Eh, he's also trashing Boost, since we're talking about it.

What a nonsense post. Part one was intriguing, but this is just a mess. My three favorite things about it: a) purports to explain how to avoid game crashes while concerning itself exclusively with performance; b) goes out of its way to point out that the author did not invent the concept of a linked list without seperate container objects, like, no poo poo, sherlock; and c) advocates hand-rolled code as less susceptible to bugs than standard libraries.

That Turkey Story
Mar 30, 2003

HORATIO HORNBLOWER posted:

What a nonsense post. Part one was intriguing, but this is just a mess. My three favorite things about it: a) purports to explain how to avoid game crashes while concerning itself exclusively with performance; b) goes out of its way to point out that the author did not invent the concept of a linked list without seperate container objects, like, no poo poo, sherlock; and c) advocates hand-rolled code as less susceptible to bugs than standard libraries.

C) is what really gets me more than anything else and it happens with tons of programmers. How big of an ego do you have to have to think that something you write ad-hoc for a project is going to have fewer bugs, be better designed, and be less buggy than a standard or open-source solution put together by one or more people who have devoted their time explicitly to it, usually with plenty of tests and other people using it, improving it, and potentially finding bugs. This is true even, if not especially, for something trivial -- I say especially for something trivial only because there are probably fewer potential trade-offs that could actually make a difference for a project.

Anyway, if the code really is so trivial that you could write it in an hour or two and be relatively convinced of its correctness, why would you spend any time making it at all, particularly with even the slightest chance that you may mess something subtle up. For something so trivial, there are probably plenty of already-written, known alternatives, that other people are aware of. What are you gaining by reinventing the wheel? Even if it just takes an hour, devote that hour to whatever specific task you are trying to accomplish, not some mundane little algorithm or datastructure.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

That Turkey Story posted:

C) is what really gets me more than anything else and it happens with tons of programmers. How big of an ego do you have to have to think that something you write ad-hoc for a project is going to have fewer bugs, be better designed, and be less buggy than a standard or open-source solution put together by one or more people who have devoted their time explicitly to it, usually with plenty of tests and other people using it, improving it, and potentially finding bugs. This is true even, if not especially, for something trivial -- I say especially for something trivial only because there are probably fewer potential trade-offs that could actually make a difference for a project.

Anyway, if the code really is so trivial that you could write it in an hour or two and be relatively convinced of its correctness, why would you spend any time making it at all, particularly with even the slightest chance that you may mess something subtle up. For something so trivial, there are probably plenty of already-written, known alternatives, that other people are aware of. What are you gaining by reinventing the wheel? Even if it just takes an hour, devote that hour to whatever specific task you are trying to accomplish, not some mundane little algorithm or datastructure.

Some individuals / organizations have an insane sense of pride that all of their software uses no third-party code. I interviewed at a place like that; they weren't amused when I suggested that they implement their own operating systems, web servers, and database servers to be truly 100% in-house.

shrughes
Oct 11, 2008

(call/cc call/cc)

HORATIO HORNBLOWER posted:

c) advocates hand-rolled code as less susceptible to bugs than standard libraries.

Well, it's the use of hand-rolled code that can be less susceptible to bugs (if it has a simpler API or application-specific assertions or something). It's the hand-rolled code itself that is usually more susceptible to bugs. Especially the way that blog poster writes his code.

(The hand-rolled code can be less susceptible to bugs if it's just a better written implementation, which you're not likely to see for Boost libs but you are likely to see for, well, a lot of libraries out there.)

That Turkey Story
Mar 30, 2003

Ithaqua posted:

Some individuals / organizations have an insane sense of pride that all of their software uses no third-party code. I interviewed at a place like that; they weren't amused when I suggested that they implement their own operating systems, web servers, and database servers to be truly 100% in-house.
I wish I had the balls to do that, but I tend to feign admiration instead.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
I can see someone spending days tracking a bug and finding it in e.g. some goofy embedded implementation of stl and expanding that lovely experience to decree "all implementations of stl on all compilers on all architectures are buggy pieces of poo poo".

Hell, if that happens badly for ten consecutive third-party libraries you try to use I can see the general wariness of all code by others.

Doesn't mean it makes any sense for productivity, happiness, or even correctness, but I can empathize.

TheSkeletonMan
Feb 24, 2011

Zombywuf posted:

The only way it seems possible to run the built in unit tests is to actually run your program, you can't just compile test runner binary (that I could find anyway).

Replace your main() with this:

code:
version(unittest) void main() { } else
void main()
{
	...
}

Cocoa Crispies
Jul 20, 2001

Vehicular Manslaughter!

Pillbug

pokeyman posted:

I can see someone spending days tracking a bug and finding it in e.g. some goofy embedded implementation of stl and expanding that lovely experience to decree "all implementations of stl on all compilers on all architectures are buggy pieces of poo poo".

Hell, if that happens badly for ten consecutive third-party libraries you try to use I can see the general wariness of all code by others.
What's more likely is nobody in an organization has integrated third-party code successfully, and that becomes the source of hubris.

Zombywuf
Mar 29, 2008

TheSkeletonMan posted:

Replace your main() with this:

code:
version(unittest) void main() { } else
void main()
{
	...
}

And that is D in a nutshell.

Why can't we have nice things damnit.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.

pokeyman posted:

I can see someone spending days tracking a bug and finding it in e.g. some goofy embedded implementation of stl and expanding that lovely experience to decree "all implementations of stl on all compilers on all architectures are buggy pieces of poo poo".
That and "embedded programming" is just every coder's attempt at "manly" and irrefutable evidence for hating things. "GARBAGE COLLECTION? IF YOU WERE ON A 15-BITS OF RAM TINKERBELL NIGHT-LIGHT LIKE ME YOU'D KNOW THAT'S ALL BULLSHIT"

Adbot
ADBOT LOVES YOU

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

pokeyman posted:

I can see someone spending days tracking a bug and finding it in e.g. some goofy embedded implementation of stl and expanding that lovely experience to decree "all implementations of stl on all compilers on all architectures are buggy pieces of poo poo".

That's why I always look for unit tests in third-party code I download. If it's not there, I write tests for at least the aspects I'm interested in using.

Case in point, I found a library to generate USPS barcodes for mail tracking purposes. I converted the USPS's provided test cases to unit tests and found several bugs.

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