Coding: Fleeting Thoughts

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
Jplus
Posts: 1709
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Coding: Fleeting Thoughts

Postby Jplus » Mon Feb 10, 2014 8:42 pm UTC

phlip wrote:Does anyone have any great suggestions for lightweight Python web frameworks?

I don't have a lot experience with Python webdev, but I know that Django is fairly nice.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

Maelstrom.
Posts: 76
Joined: Tue Oct 21, 2008 12:18 pm UTC

Re: Coding: Fleeting Thoughts

Postby Maelstrom. » Mon Feb 10, 2014 8:57 pm UTC

Jplus wrote:
phlip wrote:Does anyone have any great suggestions for lightweight Python web frameworks?

I don't have a lot experience with Python webdev, but I know that Django is fairly nice.

Django is very nice, but it is by no means lightweight. Django tries to do everything for you. It does most of it well, and this is not a problem if you are developing a large app and are happy to buy in to the Django philosophy, but it is very heavy.

I second the recommendation for Flask. If you want something lightweight and simple, Flask is a good choice. My only objection to Flask is how difficult the docs make it to find information on building larger apps. It tries so hard to present itself as a very small, no cruft framework (hello world in 3 lines!) that it does itself a disservice in hiding anything to the contrary.

Read up on Blueprints and Pluggable views for Flask if your application is outgrowing a single views.py file:

EvanED
Posts: 4330
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Mon Feb 10, 2014 10:43 pm UTC

Yakk wrote:A pointer to T is never a pointer to an array of T.

A pointer to an array of T is a distinct type from a pointer to T.
Not to C++'s type system, which is the point.

(You could also phrase it as saying 'there is no such thing as a "pointer to a T array" type' or perhaps 'you can't declare a variable as a "pointer to a T array" type', but this is a pretty meaningless distinction.)

lgw wrote:Similarly, C pointers are rarely a good parameter in C++: better a reference, unless you're transferring ownership for which a shared_ptr (really, the only reason to use a pointer now is if NULL really means something, or when dealing with funky hardware with interesting stuff at fixed real memory addresses).
To be honest, I have a weak preference for pointers, rather than references, as output parameters. I like the extra explicitness at call sites. I don't insist it's The Right Way to do things, but it's my current position anyway.

User avatar
phlip
Restorer of Worlds
Posts: 7550
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Coding: Fleeting Thoughts

Postby phlip » Mon Feb 10, 2014 10:54 pm UTC

EvanED wrote:Not to C++'s type system, which is the point.

Well, if we're being strict, a pointer to an array is this:

Code: Select all

int (*ptr)[10];
Notably, this is the pointer type that a two-dimensional array degrades into.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
Xenomortis
Not actually a special flower.
Posts: 1412
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Mon Feb 10, 2014 11:06 pm UTC

That's static though.
Or is the correct interpretation "a dynamic array isn't really an array"?
Which is true, I guess, but not helpful when it comes to casual talk.

More to the point:
heatsink wrote:

Code: Select all

struct Base {
  virtual void foo(void) {}
};

struct Derived : public Base {
  int i;
};

int main() {
  Base *p = new Derived[10];
  p[3].foo(); // boom
  return 0;
}


The array is there; you're just accessing it badly.
It's breaking because sizeof( Derived ) != sizeof( Base ).
So your array offset doesn't point to anything valid. p[4].foo() should work fine.*

*MSVC gives sizeof( Base ) == 4, whilst sizeof( Derived ) == 8
Image

EvanED
Posts: 4330
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Mon Feb 10, 2014 11:33 pm UTC

phlip wrote:
EvanED wrote:Not to C++'s type system, which is the point.

Well, if we're being strict, a pointer to an array is this:

Code: Select all

int (*ptr)[10];
Notably, this is the pointer type that a two-dimensional array degrades into.
I guess that's true, and what like Xenomortis said is closer: you could also say that C++ doesn't have the ability to dynamically allocate an array. (Ironically, that's actually more true in C than in C++.) But it's an equally meaningless distinction. :-)

Xenomortis wrote:The array is there; you're just accessing it badly.
That's... pretty much heatsink's point. Type systems are supposed to stop you from doing things like that, and heatsink was just pointing out a somewhat non-obvious deficiency in the C++ type system. (Meaning: it's obvious in retrospect, but it seems like it'd be easy enough to make a mistake like that without thinking about it. That's in contrast to most other type issues, where you have to at least put in a cast or do something like an out-of-bounds array access that's on everyone's mind.)

User avatar
Yakk
Poster with most posts but no title.
Posts: 11077
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Tue Feb 11, 2014 2:26 am UTC

Xenomortis wrote:That's static though.
Yes. There are no first class pointers to dynamically sized arrays in C++.

You can have a pointer to the first element.
Or is the correct interpretation "a dynamic array isn't really an array"?

Sure it is. You just cannot have a first-class statically typed pointer to it that respects its type and size!

You can have a derived type pointer that respects its type. std::vector is a wrapper around a dynamic array, as an example, and has little overhead for its growth ability.

std::dynarray is coming in C++1y (or at least before C++1z), and other than the on-stack support they are hoping to have, nothing stops you from creating a clone type.

std::unique_ptr<Base[]> is a dynamic array type, and you cannot implicitly convert a std::unique_ptr<Derived[]> to a std::unique_ptr<Base[]>.

The array is there; you're just accessing it badly.

Yes, through an unsafe raw pointer. You also called new directly, in code not specifically designed to manage memory. You stored a pointer to the first element of an array with no static information that it was an array.

This is another reason why using raw pointers as iterators is a bad idea.

In general, if you are working with raw pointers in modern C++, you have taken the safety lines off. Stop using new outside of memory management classes, and stop using raw pointers for anything besides implementation details of memory management classes or low overhead indirection in temporary objects where reference semanatics is annoying (even then, consider reference_wrapper).
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Diadem
Posts: 5653
Joined: Wed Jun 11, 2008 11:03 am UTC
Location: The Netherlands

Re: Coding: Fleeting Thoughts

Postby Diadem » Tue Feb 11, 2014 3:33 pm UTC

So while we're talking about C++

Code: Select all

class A {
public:
    int x;
};

void function(const A& a) {
//    a.x = 3;  // compile error
    ((A&) a).x = 3; // No compile error
}


Why is this allowed? What is the point of const if you can just cast it away like that?
It's one of those irregular verbs, isn't it? I have an independent mind, you are an eccentric, he is round the twist
- Bernard Woolley in Yes, Prime Minister

letterX
Posts: 535
Joined: Fri Feb 22, 2008 4:00 am UTC
Location: Ithaca, NY

Re: Coding: Fleeting Thoughts

Postby letterX » Tue Feb 11, 2014 4:11 pm UTC

Diadem wrote:\Why is this allowed? What is the point of const if you can just cast it away like that?

Because C-style casts regularly break the type system and you shouldn't use them? There's also const_cast, which does the same thing, but is easier to grep for and specifically alerts anyone reading the code to the fact you're requesting non-const-ness. It can be useful when, for instance, you've got library code where you know that the member function x.foo() is const (because you can see the source) but the original developers suck at declaring their methods const and you need to call x.foo() on a const x in your code.

You can also use it for keeping member variables which are allowed to change during "logically const" operations (e.g., caching, performance counters...) but declaring those variables mutable is probably a better solution there.

But yes: don't use C-style casts.

EvanED
Posts: 4330
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Tue Feb 11, 2014 4:17 pm UTC

You might as well say

Code: Select all

int x = 0;
*((double*)&x) = 5.5; // no warning or error with GCC 4.5 -Wall -Wextra

"what's the point of types if you can cast them away like that?"

As letterX said, that's one of the reasons that C casts are bad. If you use static_cast, you can't use it to cast away const:

Code: Select all

 static_cast<A&>(a).x = 3; // invalid static_cast from type ‘const A’ to type ‘A&’


---
One "big" time that const_cast is useful is if you have a member function overloaded on const-ness. For instance, suppose you're writing something like std::vector. You could write:

Code: Select all

T const & operator[] (size_t index) const {
#if DEBUGGING
    if (index > _size) {
        throw out_of_range();
    }
#endif
    return _storage[index];
}

T & operator[] (size_t index) {
#if DEBUGGING
    if (index > _size) {
        throw out_of_range();
    }
#endif
    return _storage[index];
}

but that's a lot of duplication. (I'm being deliberately obtuse by not putting the range check in another function and just calling it, which would change those 5 lines into 1, but stick with me. :-))

Instead, you can do some const-casting:

Code: Select all

T & operator[] (size_t index) {
    return const_cast<T&>(const_cast<vector const &>(*this)[index]);
}

(or something like that). The inner const_cast is so you call the const overload of the function (do it this way and not the other way around), and the outer const_cast is to return the right type. The inner one is safe because you're adding const, and the outer one is safe because you know you're starting with a non-const object and returning a reference to something in that object.

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 5777
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Tue Feb 11, 2014 4:31 pm UTC

Where C gets annoying with const is with this:

Code: Select all

#include <stdio.h>

int foo (const int a[][3]) {
   return a[0][0];
}

int main() {
   int a[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}};
   printf("%d\n",foo(a)); //AHHH!!!! MAKE THE WARNINGS GO AWAY!
}
The rage in their eyes, torches in their hands
And the power of the cross bringing fear to all the land
And darkness will come to us all.

lgw
Posts: 435
Joined: Mon Apr 12, 2010 10:52 pm UTC

Re: Coding: Fleeting Thoughts

Postby lgw » Tue Feb 11, 2014 9:59 pm UTC

EvanED wrote:To be honest, I have a weak preference for pointers, rather than references, as output parameters. I like the extra explicitness at call sites. I don't insist it's The Right Way to do things, but it's my current position anyway.


I think that's just a habit a lot of people still have - and it does make the semantics obvious, which never hurts. But once you get in the habit of using const references for all your input parameters, the missing "const" on output parameters starts to jump out at you. The lack of const on input references is actually my biggest problem with Java and C#.

Yakk wrote:
Xenomortis wrote:That's static though.
Yes. There are no first class pointers to dynamically sized arrays in C++.

You can have a pointer to the first element.


The whole idea in C++ is that dynamically sized arrays are called vectors. Stroustrup has ranted about this in the past.

The biggest weakness IMO of C++ is that people write C-style code in it. C is a fine language to itself, but the C++ standard libraries are quite important to writing maintainable C++ code. It used to be a real problem that students were taught C, then taught a little C++, as if it were "C with classes" (which it was in the early 80s, to be fair). Now of course it's rare to see C++ in school, and really moving from Java to C++ probably makes for a better approach than moving from C to C++.

There are still many programmers who are C programmers at heart, but coding in C++ for some reason, and wow is C++ a horrible minefield that way. If you're scared of exceptions, if you refuse to use vector and string, if you write functions such that they "don't return from the middle of the function" so that you don't bypass that all-important clean-up code at the bottom, C++ frankly sucks as a language.
"In no set of physics laws do you get two cats." - doogly

EvanED
Posts: 4330
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Tue Feb 11, 2014 10:29 pm UTC

lgw wrote:
EvanED wrote:To be honest, I have a weak preference for pointers, rather than references, as output parameters. I like the extra explicitness at call sites. I don't insist it's The Right Way to do things, but it's my current position anyway.


I think that's just a habit a lot of people still have - and it does make the semantics obvious, which never hurts. But once you get in the habit of using const references for all your input parameters, the missing "const" on output parameters starts to jump out at you. The lack of const on input references is actually my biggest problem with Java and C#.
At call sites, not function definition.

The biggest weakness IMO of C++ is that people write C-style code in it. C is a fine language to itself, but the C++ standard libraries are quite important to writing maintainable C++ code. It used to be a real problem that students were taught C, then taught a little C++, as if it were "C with classes" (which it was in the early 80s, to be fair). Now of course it's rare to see C++ in school, and really moving from Java to C++ probably makes for a better approach than moving from C to C++.

There are still many programmers who are C programmers at heart, but coding in C++ for some reason, and wow is C++ a horrible minefield that way. If you're scared of exceptions, if you refuse to use vector and string, if you write functions such that they "don't return from the middle of the function" so that you don't bypass that all-important clean-up code at the bottom, C++ frankly sucks as a language.
As a counter argument for C programmers at heart: IMO C++ is still a better C than C is.

korona
Posts: 495
Joined: Sun Jul 04, 2010 8:40 pm UTC

Re: Coding: Fleeting Thoughts

Postby korona » Wed Feb 12, 2014 12:50 am UTC

I think what EvanED said is correct: I've written a lot of C code in C++ (and a lot of C++ code in C++) because sometimes you just need that extra performance that you get by not using a smart pointer (i.e. a shared_ptr, unique_ptr has no overhead), not using virtual functions, not using the new operator to initialize classes or not using STL containers etc.
Templates and classes are still important and enable you to write better C code than you could in plain C.

lgw
Posts: 435
Joined: Mon Apr 12, 2010 10:52 pm UTC

Re: Coding: Fleeting Thoughts

Postby lgw » Wed Feb 12, 2014 5:52 am UTC

EvanED wrote:
lgw wrote:
EvanED wrote:To be honest, I have a weak preference for pointers, rather than references, as output parameters. I like the extra explicitness at call sites. I don't insist it's The Right Way to do things, but it's my current position anyway.

I think that's just a habit a lot of people still have - and it does make the semantics obvious, which never hurts. But once you get in the habit of using const references for all your input parameters, the missing "const" on output parameters starts to jump out at you. The lack of const on input references is actually my biggest problem with Java and C#.
At call sites, not function definition.

Yes, I did read carefully. Do people really still code in editors that don't show the function definition while typing out a call? How very strange.

korona wrote:I think what EvanED said is correct: I've written a lot of C code in C++ (and a lot of C++ code in C++) because sometimes you just need that extra performance that you get by not using a smart pointer (i.e. a shared_ptr, unique_ptr has no overhead), not using virtual functions, not using the new operator to initialize classes or not using STL containers etc.
Templates and classes are still important and enable you to write better C code than you could in plain C.

There's a lot of myth around this, though. STL containers, when used expertly, give the same performance as C arrays and char*s (sometimes producing the same object code under optimization). Pre-allocating the sizes at construction counts for a lot. I'm not sure that the new operator really matters either (depends on how slow your malloc is underneath, I guess), though a constructor that does a lot of work is of course a different story. Virtual function pointers are a waste unless the class is polymorphic, of course, but are usually faster than a tagged union.

Of course, all of those things can be slower than the C approach, if done casually, but then neither language is particularly friendly to junior coders.
"In no set of physics laws do you get two cats." - doogly

Ubik
Posts: 1016
Joined: Thu Oct 18, 2007 3:43 pm UTC

Re: Coding: Fleeting Thoughts

Postby Ubik » Wed Feb 12, 2014 7:20 am UTC

Operator overloading to allow shell syntax in a program.

Code: Select all

// Using >> just because
// Also, common programs are already defined, otherwise a string should be used or maybe program(string)
shell >> grep("pattern", "file") | sort | uniq > "somefile.txt";

User avatar
Diadem
Posts: 5653
Joined: Wed Jun 11, 2008 11:03 am UTC
Location: The Netherlands

Re: Coding: Fleeting Thoughts

Postby Diadem » Wed Feb 12, 2014 9:13 am UTC

letterX wrote:
Diadem wrote:\Why is this allowed? What is the point of const if you can just cast it away like that?

Because C-style casts regularly break the type system and you shouldn't use them?

Yes, that's what they say.

Don't use C-style casts, use these ridiculously long and impossible to remember expressions instead.
Don't use raw arrays, use vectors instead, which we've conveniently not put in the core language, so you have to type 10 times as may letters each time you use one.
Don't use character arrays, use strings instead, which we've conveniently also not put in the core language. More typing for you! Awesome!

Each time in C++ the easiest way to do something turns out to be the wrong way to do something. Why? Because that's how our grandfathers did it, and if it was good enough for them, it's good enough for us. Ok, ok, I know, that's not entirely fair, backwards compatibility is important. But some of these constructs have been outdated for almost half a century now, and they are still around. That's just overdoing it.

It's important that these primitives constructs exist, to give C++ its full power even as a low level language. I get that. But they shouldn't be the default. Instead of a raw array being x[] and a vector being std::vector x, it should be the other way around. Let x[] automatically give you a vector while a raw array is made with std:rawarray x; or something like that. The same with casting.

The example I gave in my previous code was artificial. And it's ok for there to exist methods to remove const-ness. If you declare stuff mutable, or use a const_cast, then it's explicit, you won't do that by accident. But with C-style casts it is very easy to do it accidentally. So the solution is to not use C-style casting at all. So again we're forced to ignore all the easy methods of doing something, and use complicated and hard to remember expressions instead.

I do love C++ as a language. But it's time they gave up C compatibility and just did away with all these legacy constructs (keep them as options, but move 'em somewhere out of the spotlight).
It's one of those irregular verbs, isn't it? I have an independent mind, you are an eccentric, he is round the twist
- Bernard Woolley in Yes, Prime Minister

User avatar
Jplus
Posts: 1709
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Coding: Fleeting Thoughts

Postby Jplus » Wed Feb 12, 2014 10:43 pm UTC

Thesh wrote:Where C gets annoying with const is with this:

Code: Select all

#include <stdio.h>

int foo (const int a[][3]) {
   return a[0][0];
}

int main() {
   int a[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}};
   printf("%d\n",foo(a)); //AHHH!!!! MAKE THE WARNINGS GO AWAY!
}

Never declare non-reference non-pointer function arguments const.

Diadem wrote:It's important that these primitives constructs exist, to give C++ its full power even as a low level language. I get that. But they shouldn't be the default. Instead of a raw array being x[] and a vector being std::vector x, it should be the other way around. Let x[] automatically give you a vector while a raw array is made with std:rawarray x; or something like that. The same with casting.

C++ is not only designed to be backwards-compatible (which I agree is a problem), but also to be extensible and to provide functionalities through libraries rather than core language features whenever possible. I can see how you may find that inconvenient, but it boils down to taste.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

User avatar
Xeio
Friends, Faidites, Countrymen
Posts: 5092
Joined: Wed Jul 25, 2007 11:12 am UTC
Location: C:\Users\Xeio\
Contact:

Re: Coding: Fleeting Thoughts

Postby Xeio » Wed Feb 12, 2014 11:06 pm UTC

Yakk wrote:Why wouldn't you just write:

Code: Select all

Y GetOrDefault( Dictionary<X, Y>& dict1, X key, Y(*)() default )

well, in the C# syntax. (Y(*)() is a nullary function returning Y, Dictionary<X,Y>& is a read/write parameter of type Dictionary<X,Y>
So I was playing around with this as an extension method:

Code: Select all

public static T GetOrDefault<T, U>(this U dictionary, string key)
    where U : IDictionary<string, T>
    where T : IDictionary, new()
{
    T value;
    if (dictionary.TryGetValue(key, out value))
        return value;
    return (dictionary[key] = new T());
}

Problem being apparently this is a bit too clever for the type inferer. Becase this gives me an error about matching overloads:

Code: Select all

var dict1 = dict.GetOrDefault(slot);

It works if I manually fill in the generics on the call, but that's unbelievably hideous given the nested dictionaries.

EDIT: I suppose the lambda version works:
Spoiler:

Code: Select all

public static T GetOrDefault<T, U>(this U dictionary, string key, Func<T> defaultor)
    where U : IDictionary<string, T>
{
    T value;
    if (dictionary.TryGetValue(key, out value))
        return value;
    return (dictionary[key] = defaultor());
}

var dict1 = dict.GetOrDefault(slot, () => new Dictionary<string, Dictionary<string, Dictionary<string, int>>>());
var dict2 = dict1.GetOrDefault(level, () => new Dictionary<string, Dictionary<string, int>>());
var dict3 = dict2.GetOrDefault(glyph, () => new Dictionary<string, int>());
dict3[glyphCount] = value;

I just wanted to be able to write:

Code: Select all

dict.GetOrDefault(slot).GetOrDefault(level).GetOrDefault(glyph)[glyphCount] = value;

User avatar
Xanthir
My HERO!!!
Posts: 5281
Joined: Tue Feb 20, 2007 12:49 am UTC
Location: The Googleplex
Contact:

Re: Coding: Fleeting Thoughts

Postby Xanthir » Thu Feb 13, 2014 5:52 am UTC

Ubik wrote:Operator overloading to allow shell syntax in a program.

Code: Select all

// Using >> just because
// Also, common programs are already defined, otherwise a string should be used or maybe program(string)
shell >> grep("pattern", "file") | sort | uniq > "somefile.txt";

The same, in Python.

This one overloads __ror__ (right or), so that you can start with any iterable and define classes that represent the shell functions.
(defun fibs (n &optional (a 1) (b 1)) (take n (unfold '+ a b)))

korona
Posts: 495
Joined: Sun Jul 04, 2010 8:40 pm UTC

Re: Coding: Fleeting Thoughts

Postby korona » Thu Feb 13, 2014 11:45 am UTC

lgw wrote:There's a lot of myth around this, though. STL containers, when used expertly, give the same performance as C arrays and char*s (sometimes producing the same object code under optimization).

That is true for std::vector but not for other containers like std::map.

lgw wrote:I'm not sure that the new operator really matters either (depends on how slow your malloc is underneath, I guess), though a constructor that does a lot of work is of course a different story.

One problem is that constructors have to be called on every element of an array when that array is allocated. Often there are much better approaches (e.g. hand-written garbage collection) when initializing arrays with millions of elements.

lgw wrote:Virtual function pointers are a waste unless the class is polymorphic, of course, but are usually faster than a tagged union.

That is just plain wrong, tagged unions are orders of magnitude faster because of cache misses and code locality.

lgw wrote:Of course, all of those things can be slower than the C approach, if done casually, but then neither language is particularly friendly to junior coders.

Sure. It was not my intention to say that C++ is a bad language. I love C++. But sometimes it makes sense to use C-style coding in C++ to improve performance.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11077
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Thu Feb 13, 2014 1:08 pm UTC

lgw wrote:
EvanED wrote:
lgw wrote:
EvanED wrote:To be honest, I have a weak preference for pointers, rather than references, as output parameters. I like the extra explicitness at call sites. I don't insist it's The Right Way to do things, but it's my current position anyway.

I think that's just a habit a lot of people still have - and it does make the semantics obvious, which never hurts. But once you get in the habit of using const references for all your input parameters, the missing "const" on output parameters starts to jump out at you. The lack of const on input references is actually my biggest problem with Java and C#.
At call sites, not function definition.

Yes, I did read carefully. Do people really still code in editors that don't show the function definition while typing out a call? How very strange.

The primary purpose of code is to make what it is doing clear to someone reading it.

So what appears when you write a method is of little importance. In fact if that information is key to understanding what the line does, that is a bad sign. Tools that make it easy to write hard to read code are counter productive.

Writing code is generally an easy task. Maintaining it is most of the lifetime of the code,
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11077
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Thu Feb 13, 2014 3:24 pm UTC

lgw wrote:
Yakk wrote:
Xenomortis wrote:That's static though.
Yes. There are no first class pointers to dynamically sized arrays in C++.

You can have a pointer to the first element.


The whole idea in C++ is that dynamically sized arrays are called vectors. Stroustrup has ranted about this in the past.

First, those aren't first class.

Second, that is very C++11 of you. C++1y (well, a TS/TR) will be adding std::dynarray possibly, which is an actual dynamic array (no ability to resize, which saves a pointer-size).
The biggest weakness IMO of C++ is that people write C-style code in it. C is a fine language to itself, but the C++ standard libraries are quite important to writing maintainable C++ code. It used to be a real problem that students were taught C, then taught a little C++, as if it were "C with classes" (which it was in the early 80s, to be fair). Now of course it's rare to see C++ in school, and really moving from Java to C++ probably makes for a better approach than moving from C to C++.

Except then you have people writing Java in C++, which is just as bad as writing C in C++.

I've seen people take the address of a reference variable and check if it is a nullptr. I have seen ships on fire off the shoulder of orion. Time to die.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Diadem
Posts: 5653
Joined: Wed Jun 11, 2008 11:03 am UTC
Location: The Netherlands

Re: Coding: Fleeting Thoughts

Postby Diadem » Thu Feb 13, 2014 4:10 pm UTC

Yakk wrote:I've seen people take the address of a reference variable and check if it is a nullptr. I have seen ships on fire off the shoulder of orion. Time to die.

Huh? Does that even do anything? The address of a reference is just the address of whatever it is referencing, which is never null. You could make a reference to a pointer (if you wanted to be perverse) and check if that is null, but the address of the pointer would still be not null.

Or was that your point? That the check is meaningless?
It's one of those irregular verbs, isn't it? I have an independent mind, you are an eccentric, he is round the twist
- Bernard Woolley in Yes, Prime Minister

EvanED
Posts: 4330
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Thu Feb 13, 2014 4:34 pm UTC

Diadem wrote:
Yakk wrote:I've seen people take the address of a reference variable and check if it is a nullptr. I have seen ships on fire off the shoulder of orion. Time to die.

Huh? Does that even do anything? The address of a reference is just the address of whatever it is referencing, which is never null. You could make a reference to a pointer (if you wanted to be perverse) and check if that is null, but the address of the pointer would still be not null.
The following, while undefined behavior, is unlikely to produce a crash or have other ill effects under any compiler I know of until execution reaches a use of foo()'s parameter within that function:

Code: Select all

// foo(int & x)
int * p = NULL;
foo(*p);
Hypothetically the optimizer could do something, but I doubt it will.

The result is that if you have

Code: Select all

#include <iostream>

void foo(int const & x) {
  if (&x == NULL) {
    std::cout << "Reference is null\n";
  }
  else {
    std::cout << "Reference is not null\n";
  }
}

int main(int argc, char ** argv) {
        int * p = NULL;
        if (argc > 1)
                p = &argc;
        foo(*p);
        return NULL;
}
then it will almost certainly print "reference is null" when run with no arguments. (You'll have to ignore a GCC warning, but you can certainly imagine that control flow and such could be complicated so that GCC isn't smart enough to figure out that will happen.)

It's like how you occasionally see checks whether this == NULL. It's "guaranteed" to not happen, and yet some "programmers" take advantage of the fact that the following is also not going to crash under real implementations:

Code: Select all

struct C { int foo(); /* does not access member variables or make calls to virtual funcs (or use typeid or ...) */ };
C * p = NULL;
p->foo();


I'm not sure that Yakk was really meaning this sort of abuse of non-language features, but taking advantage of the compiler's interpretation of such undefined behavior is something you'll see in poorly-written code once in a blue moon.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11077
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Thu Feb 13, 2014 8:50 pm UTC

Yep, it was that kind of abuse. A null pointer was *'d, passed to a reference parameter, which would then take the address of it and check if it was null.

Because the programmer was used to java, and wanted reference parameters (which used . not ->) that could be nulled.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

lgw
Posts: 435
Joined: Mon Apr 12, 2010 10:52 pm UTC

Re: Coding: Fleeting Thoughts

Postby lgw » Fri Feb 14, 2014 9:37 pm UTC

Yakk wrote:
lgw wrote:
EvanED wrote:
lgw wrote:
EvanED wrote:To be honest, I have a weak preference for pointers, rather than references, as output parameters. I like the extra explicitness at call sites. I don't insist it's The Right Way to do things, but it's my current position anyway.

I think that's just a habit a lot of people still have - and it does make the semantics obvious, which never hurts. But once you get in the habit of using const references for all your input parameters, the missing "const" on output parameters starts to jump out at you. The lack of const on input references is actually my biggest problem with Java and C#.
At call sites, not function definition.

Yes, I did read carefully. Do people really still code in editors that don't show the function definition while typing out a call? How very strange.

The primary purpose of code is to make what it is doing clear to someone reading it.

So what appears when you write a method is of little importance. In fact if that information is key to understanding what the line does, that is a bad sign. Tools that make it easy to write hard to read code are counter productive.

Writing code is generally an easy task. Maintaining it is most of the lifetime of the code,


Yes, my point was that const vs nonconst references as a means of indicating output semantics is perfectly clear with modern tools. I do realize that some people still use notepad or butterflies or whatever, and in that case I could see the point of pointers, but I personally find using poor tools unprofessional (I could rant for pages about people stuck in the 80s, tools-wise, but that belongs in the holy wars forum).
"In no set of physics laws do you get two cats." - doogly

User avatar
Dopefish
Posts: 854
Joined: Sun Sep 20, 2009 5:46 am UTC
Location: The Well of Wishes

Re: Coding: Fleeting Thoughts

Postby Dopefish » Sun Feb 16, 2014 4:54 am UTC

Is *_ some sort of indicator or part of syntax for any languages?

I saw someone on the interwebs use *_ in a similar manner as I would use $ in $example in casual text, but it turns out that it's really hard to search for *_ and get potentially relevant results instead of emoticon things. Might just be their own little creation but they do have a coding background so perhaps it's just something new to me.

User avatar
Jplus
Posts: 1709
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Coding: Fleeting Thoughts

Postby Jplus » Sun Feb 16, 2014 9:30 am UTC

In certain C++ coding styles, private data members of a class have names starting with _. If such a private data member is a pointer, * will dereference it. From what I can tell, that might have been what you were looking at. That, or the person in question was using a concatenative language like Forth. You can basically invent any syntax you want in concatenative languages.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

User avatar
chridd
Has a vermicelli title
Posts: 808
Joined: Tue Aug 19, 2008 10:07 am UTC
Location: ...Earth, I guess?
Contact:

Re: Coding: Fleeting Thoughts

Postby chridd » Sun Feb 16, 2014 9:42 am UTC

It could be an attempt at bold, underline, or italic. I think some software interprets _this_ and *this* as underline or italic and bold, so they might have forgotten the ending _*, or used it in a program that didn't support that, or something.
~ chri d. d. /tʃɹɪ.di.di/ (Phonotactics, schmphonotactics) · she(?)(?(?)(?))(?(?(?))(?))(?) · Forum game scores
mittfh wrote:I wish this post was very quotable...
flicky1991 wrote:In both cases the quote is "I'm being quoted too much!"

User avatar
Negrebskoh
Posts: 139
Joined: Fri Mar 01, 2013 11:49 pm UTC
Location: The Netherlands

Re: Coding: Fleeting Thoughts

Postby Negrebskoh » Sun Feb 16, 2014 12:58 pm UTC

Dopefish wrote:Is *_ some sort of indicator or part of syntax for any languages?

I saw someone on the interwebs use *_ in a similar manner as I would use $ in $example in casual text, but it turns out that it's really hard to search for *_ and get potentially relevant results instead of emoticon things. Might just be their own little creation but they do have a coding background so perhaps it's just something new to me.

Maybe SymbolHound helps? It appears people can use it in Perl in some way, at least. (I wouldn't know how, though. Still got to learn me some Perl.)

User avatar
Diadem
Posts: 5653
Joined: Wed Jun 11, 2008 11:03 am UTC
Location: The Netherlands

Re: Coding: Fleeting Thoughts

Postby Diadem » Sun Feb 16, 2014 2:12 pm UTC

In the Elder Days, when the Internet was young, most text was not marked up. Chatting was done via IRC, which is plain text. Forums, if they even existed, didn't have BBCode tags, they were plaintext too. HTML email? Nope. In those days, it was quite common to add emphasis like _this_ or *this*. The former denotes underlying, the latter bolding. There's also /italics/.

Some people still use that on occasion.

In that case there should generally also be a closing _* though.

Alternatively it could have been some obscure emoticon. Those too used to be plain text ;-)
It's one of those irregular verbs, isn't it? I have an independent mind, you are an eccentric, he is round the twist
- Bernard Woolley in Yes, Prime Minister

User avatar
headprogrammingczar
Posts: 3072
Joined: Mon Oct 22, 2007 5:28 pm UTC
Location: Beaming you up

Re: Coding: Fleeting Thoughts

Postby headprogrammingczar » Sun Feb 16, 2014 2:15 pm UTC

Dopefish wrote:Is *_ some sort of indicator or part of syntax for any languages?

I saw someone on the interwebs use *_ in a similar manner as I would use $ in $example in casual text, but it turns out that it's really hard to search for *_ and get potentially relevant results instead of emoticon things. Might just be their own little creation but they do have a coding background so perhaps it's just something new to me.


They're clearly using typeglobs. :)
<quintopia> You're not crazy. you're the goddamn headprogrammingspock!
<Weeks> You're the goddamn headprogrammingspock!
<Cheese> I love you

User avatar
chridd
Has a vermicelli title
Posts: 808
Joined: Tue Aug 19, 2008 10:07 am UTC
Location: ...Earth, I guess?
Contact:

Re: Coding: Fleeting Thoughts

Postby chridd » Sun Feb 16, 2014 4:37 pm UTC

*_example could be "underscore-separated phrases ending in the word 'example'" (like in bash, etc.).
~ chri d. d. /tʃɹɪ.di.di/ (Phonotactics, schmphonotactics) · she(?)(?(?)(?))(?(?(?))(?))(?) · Forum game scores
mittfh wrote:I wish this post was very quotable...
flicky1991 wrote:In both cases the quote is "I'm being quoted too much!"

User avatar
Dopefish
Posts: 854
Joined: Sun Sep 20, 2009 5:46 am UTC
Location: The Well of Wishes

Re: Coding: Fleeting Thoughts

Postby Dopefish » Sun Feb 16, 2014 5:26 pm UTC

It was being used as part of a normal english sentence along the lines of "Do I play *_game here" on a few scattered occasions so I doubt it's related to pointer shenanigans (and with multiples things following the *_ though, so there's not some game called "*_game" or anything). The Perl thing is new to me and might be related, although I don't know why the _ would be used too from what I can tell from reading the linked explanations.

The absence of closing stuff made it seem odd to me too if they were going for some kind of emphasis, but eh. I think I'll conclude there were using *_ to indicate "make the replacement I'm about to tell you ahead" in a similar way as I'd use $ or even <> as in <insert whatever here>, but without a closing thing, and it seems like it's just their own way of indicating that.

Ah well, doesn't actually matter, just figured I'd check with you lot in case I was missing something clever. Thanks.

User avatar
Diadem
Posts: 5653
Joined: Wed Jun 11, 2008 11:03 am UTC
Location: The Netherlands

Re: Coding: Fleeting Thoughts

Postby Diadem » Mon Feb 17, 2014 5:11 pm UTC

So today I wanted to copy the contents of some array of data, after processing, into a vector.

Straightforward:

Code: Select all

vector<int> convert(ArrayObject& arr) {
    std::vector<int> vec;
    for (auto it = arr.begin(); it != arr.end(); ++it)
        vec.push_back(it->as_int());
    return vec;
}


Then I thought, no wait, that can't be very efficient, because push_back will continuously resize the vector. So I changed it to:

Code: Select all

vector<int> convert(ArrayObject& arr) {
    std::vector<int> vec;
    vec.reserve(arr.size());
    for (auto it = arr.begin(); it != arr.end(); ++it)
        vec.push_back(it->as_int());
    return vec;
}

To my very great surprise, this not only failed to speed up my program, but in fact slowed it down. So I figured perhaps I should avoid push_back altogether:

Code: Select all


vector<int> convert(ArrayObject& arr) {
    std::vector<int> vec(arr.size());
    for (size_t i = 0; i < arr.size(); i++)
        vec[i] = arr[i].as_int();
    return vec;
}

Turns out, that is even slower. Huh. What is going on here?

Then later on I realized I wanted an overloaded version of convert: 'void convert(ArrayObject& arr, vector<int>& vec)'. So I made that, and it that was also slower than my original.

I just don't understand why the first approach would be faster. I can see it being equally fast, if your compiler is optimizing all the inefficiencies away. But how can it be faster?
It's one of those irregular verbs, isn't it? I have an independent mind, you are an eccentric, he is round the twist
- Bernard Woolley in Yes, Prime Minister

User avatar
Yakk
Poster with most posts but no title.
Posts: 11077
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Mon Feb 17, 2014 7:09 pm UTC

How did you determine which was faster?

Is there anything else going on at the same time?

What is your memory architecture like? Does allocating small blocks somehow cause work to happen in the background to "bring up" big blocks for later use? How big is arr.size()?

What is arr, and how expensive is size? What does [] do on arr? Is arr a list structure?!

If arr was basically a pre-C++11 `std::list` with O(n) counting size, your observations would be consistent with how I would expect things to go. Pre-iterating (via size()) requires iterating over the list twice, which is way more expensive than allocating the vector's buffer ~lg(n) total times with total size O(2n) and iterating once.
Last edited by Yakk on Mon Feb 17, 2014 7:11 pm UTC, edited 1 time in total.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Xenomortis
Not actually a special flower.
Posts: 1412
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Mon Feb 17, 2014 7:11 pm UTC

How do the loops look after the compiler's had its way with them?
Image

User avatar
Negrebskoh
Posts: 139
Joined: Fri Mar 01, 2013 11:49 pm UTC
Location: The Netherlands

Re: Coding: Fleeting Thoughts

Postby Negrebskoh » Mon Feb 17, 2014 9:10 pm UTC

Xenomortis wrote:How do the loops look after the compiler's had its way with them?

That's the most important question, I think. The first thought that entered my mind after reading what you (Diadem) wrote was "Huh, seems like you're accidentally interfering with the compiler's optimization heuristics."

User avatar
Yakk
Poster with most posts but no title.
Posts: 11077
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Mon Feb 17, 2014 10:10 pm UTC

Nobody but me is spooked by a non-const "ArrayObject" named type? "as_int"? These aren't huge red flags to you people?

I know the performance characteristics of std::vector and what Diadem is doing to it.

I have no idea what ArrayObject is, but if things are wonky performance-wise, it is the obvious thing to blame.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 5 guests