Coding: Fleeting Thoughts

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

Moderators: phlip, Moderators General, Prelates

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

Re: Coding: Fleeting Thoughts

Postby Xeio » Wed Sep 10, 2014 3:39 pm UTC

I wonder if the compiler optimizes "if x is Foo ... x as Foo" into a single cast...

EDIT: It seems... not (both built in release for reference)?

Is then As:
Spoiler:

Code: Select all

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       31 (0x1f)
  .maxstack  1
  .locals init ([0] class CastOptimizeTest.Foo x)
  IL_0000:  ldstr      "bar"
  IL_0005:  call       class CastOptimizeTest.Foo CastOptimizeTest.Program::FooBarFactory(string)
  IL_000a:  stloc.0
  IL_000b:  ldloc.0
  IL_000c:  isinst     CastOptimizeTest.Bar
  IL_0011:  brfalse.s  IL_001e
  IL_0013:  ldloc.0
  IL_0014:  castclass  CastOptimizeTest.Bar
  IL_0019:  callvirt   instance void CastOptimizeTest.Bar::Baz()
  IL_001e:  ret
} // end of method Program::Main


As then null check:
Spoiler:

Code: Select all

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       28 (0x1c)
  .maxstack  1
  .locals init ([0] class CastOptimizeTest.Foo x,
           [1] class CastOptimizeTest.Bar bar)
  IL_0000:  ldstr      "bar"
  IL_0005:  call       class CastOptimizeTest.Foo CastOptimizeTest.Program::FooBarFactory(string)
  IL_000a:  stloc.0
  IL_000b:  ldloc.0
  IL_000c:  isinst     CastOptimizeTest.Bar
  IL_0011:  stloc.1
  IL_0012:  ldloc.1
  IL_0013:  brfalse.s  IL_001b
  IL_0015:  ldloc.1
  IL_0016:  callvirt   instance void CastOptimizeTest.Bar::Baz()
  IL_001b:  ret
} // end of method Program::Main


The is->as has an extra castclass call. Granted, it's possible this is optimized when the IL is compiled...

Breakfast
Posts: 117
Joined: Tue Jun 16, 2009 7:34 pm UTC
Location: Coming to a table near you

Re: Coding: Fleeting Thoughts

Postby Breakfast » Wed Sep 10, 2014 5:46 pm UTC

Xeio wrote:The is->as has an extra castclass call. Granted, it's possible this is optimized when the IL is compiled...

In C# the typical guidance is to prefer as / null check over is / as specifically because of the extra castclass call. Because of this I would doubt, or at least not rely on, the IL compiler optimizing it away.

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

Re: Coding: Fleeting Thoughts

Postby Thesh » Wed Sep 10, 2014 5:52 pm UTC

Xeio wrote:
Thesh wrote:

Code: Select all

if (x is DerivedType)
{
    x@DerivedType.baz();
}
Well, in C# 6.0 you can do

Code: Select all

(x as DerivedType)?.baz();

So... marginally less code anyway.

Well, we are still using VS 2010 at work.

Robert'); DROP TABLE *; wrote:

Code: Select all

void forward<T, U>(U u, Action<T> f) where T : class
{
   if (u is T)
   {
      var t = u as T;
      f(t);
   }
}
forward<DerivedType,Base>(foo, foo => foo.baz());


I'm not sure why that would be any better. Also, in many cases I'm accessing the value of a property.
Summum ius, summa iniuria.

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

Re: Coding: Fleeting Thoughts

Postby Yakk » Wed Sep 10, 2014 7:06 pm UTC

Robert'); DROP TABLE *; wrote:

Code: Select all

void forward<T, U>(U u, Action<T> f) where T : class
{
   if (u is T)
   {
      var t = u as T;
      f(t);
   }
}
forward<DerivedType,Base>(foo, foo => foo.baz());

Wait, it won't deduce U for you?
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
Robert'); DROP TABLE *;
Posts: 730
Joined: Mon Sep 08, 2008 6:46 pm UTC
Location: in ur fieldz

Re: Coding: Fleeting Thoughts

Postby Robert'); DROP TABLE *; » Wed Sep 10, 2014 7:11 pm UTC

Unfortunately, the usefulness is rather shot by the compiler wanting either both or neither of the type arguments. (And if you give neither, it can't deduce T) However, if it didn't, then the second argument is actually an arbitary function of a DerivedType, so you could read/change any properties in there.

EDIT: Actually, I just realized that you can leave out both so long as the lambda/function specifies its parameter's type, but that also looks rather ugly.

Breakfast wrote:
Xeio wrote:The is->as has an extra castclass call. Granted, it's possible this is optimized when the IL is compiled...

In C# the typical guidance is to prefer as / null check over is / as specifically because of the extra castclass call. Because of this I would doubt, or at least not rely on, the IL compiler optimizing it away.

I didn't actually realize there was a difference, so thanks for pointing that out.
Last edited by Robert'); DROP TABLE *; on Wed Sep 10, 2014 7:14 pm UTC, edited 1 time in total.
...And that is how we know the Earth to be banana-shaped.

Breakfast
Posts: 117
Joined: Tue Jun 16, 2009 7:34 pm UTC
Location: Coming to a table near you

Re: Coding: Fleeting Thoughts

Postby Breakfast » Wed Sep 10, 2014 7:13 pm UTC

Yakk wrote:
Robert'); DROP TABLE *; wrote:

Code: Select all

void forward<T, U>(U u, Action<T> f) where T : class
{
   if (u is T)
   {
      var t = u as T;
      f(t);
   }
}
forward<DerivedType,Base>(foo, foo => foo.baz());

Wait, it won't deduce U for you?

Do you mean in the call to forward or in the function definition? Because in the call, no. C# is kind of dumb like that in that it needs to be able to know all of the types of a generic function at compile time. I'm somewhat confident that you might be able to do something if you put a constraint on the U parameter but I can't say for sure without testing it.

User avatar
Robert'); DROP TABLE *;
Posts: 730
Joined: Mon Sep 08, 2008 6:46 pm UTC
Location: in ur fieldz

Re: Coding: Fleeting Thoughts

Postby Robert'); DROP TABLE *; » Wed Sep 10, 2014 7:27 pm UTC

It technically can deduce U, but there's no syntax for providing only some type arguments, so you've got to either specify both of them, replace U with "object" and specify just T, or not specify either, the last of which looks like:

Code: Select all

forward(foo, (DerivedType bar) => bar.baz());

(OK, that's not as ugly as I thought it was. Maybe I misremebered typed lambda syntax.)
...And that is how we know the Earth to be banana-shaped.

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

Re: Coding: Fleeting Thoughts

Postby Xeio » Wed Sep 10, 2014 7:40 pm UTC

Robert'); DROP TABLE *; wrote:It technically can deduce U, but there's no syntax for providing only some type arguments, so you've got to either specify both of them, replace U with "object" and specify just T, or not specify either, the last of which looks like:

Code: Select all

forward(foo, (DerivedType bar) => bar.baz());

(OK, that's not as ugly as I thought it was. Maybe I misremebered typed lambda syntax.)
Well, since you're casting anyway, you could just do:

Code: Select all

void Forward<T>(object o, Action<T> f) where T : class
{
   var t = o as T;
   if (t != null)
   {
      f(t);
   }
}
And only have one generic type.

The upside to two type constraints is you could change the constraints to "where T : class, U" and get a compile error if you try to pass a type that can't ever forward correctly.
Last edited by Xeio on Wed Sep 10, 2014 7:45 pm UTC, edited 1 time in total.

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

Re: Coding: Fleeting Thoughts

Postby Yakk » Wed Sep 10, 2014 7:44 pm UTC

So C# lacks partial type deduction, where you pass in some types, and let the rest be deduced? Huh, that must suck.
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
Xeio
Friends, Faidites, Countrymen
Posts: 5101
Joined: Wed Jul 25, 2007 11:12 am UTC
Location: C:\Users\Xeio\
Contact:

Re: Coding: Fleeting Thoughts

Postby Xeio » Wed Sep 10, 2014 7:47 pm UTC

Yakk wrote:So C# lacks partial type deduction, where you pass in some types, and let the rest be deduced? Huh, that must suck.
How could the compier deduce the subtype in the lambda?

I mean, it could make a haphazard guess of any type with a "baz()" method match... but that's about it?

EDIT: Or wait, you mean as part of the method call? I think the issue there then is C# doesn't have named parameter passing as part of generics, so you can't do:

Code: Select all

Forward<T = DerivedType>(foo, foo => foo.baz());

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

Re: Coding: Fleeting Thoughts

Postby Yakk » Wed Sep 10, 2014 7:58 pm UTC

No, like this:

Code: Select all

    void forward<T, U>(U u, Action<T> f) where T : class
    {
       if (u is T)
       {
          var t = u as T;
          f(t);
       }
    }
    forward<DerivedType>(foo, foo => foo.baz());

Pass T explicitly, and let U be deduced from the function call types.

The C++(14) equivalent:

Code: Select all

template<class T, class U>
void forward(U* u, std::function<void(T*)> f) {
  if (T* t = dynamic_cast<T*>(u))
    f(t);
}

forward<Derived>( base, [&](auto* base){ base->baz(); } );

of course, we could also strip the std::function:

Code: Select all

template<class T, class U, class F>
void forward(U* u, F f) {
  if (T* t = dynamic_cast<T*>(u))
    f(t);
}

forward<Derived>( base, [&](auto* base){ base->baz(); } );

which would be slightly faster at runtime. Both U and F get deduced, while T is passed in as Derived.
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.

Breakfast
Posts: 117
Joined: Tue Jun 16, 2009 7:34 pm UTC
Location: Coming to a table near you

Re: Coding: Fleeting Thoughts

Postby Breakfast » Wed Sep 10, 2014 8:05 pm UTC

Xeio wrote:
Yakk wrote:So C# lacks partial type deduction, where you pass in some types, and let the rest be deduced? Huh, that must suck.
How could the compier deduce the subtype in the lambda?

I mean, it could make a haphazard guess of any type with a "baz()" method match... but that's about it?

EDIT: Or wait, you mean as part of the method call? I think the issue there then is C# doesn't have named parameter passing as part of generics, so you can't do:

Code: Select all

Forward<T = DerivedType>(foo, foo => foo.baz());

C# does indeed lack partial type deduction. However, F# has it so it may make its way into the C# language at some point. It's not incredibly apparent in this example but it becomes a real problem when you're writing generic functions that take one type as input but can return several different output types...

Despite lacking partial type deduction, I'd still prefer the two generic parameter version with a constraint that T has to implement U like Xeio suggested.

yakk wrote:No, like this:

Code: Select all

    void forward<T, U>(U u, Action<T> f) where T : class
    {
       if (u is T)
       {
          var t = u as T;
          f(t);
       }
    }
    forward<DerivedType>(foo, foo => foo.baz());

Pass T explicitly, and let U be deduced from the function call types.

It's against good practice in C# to do is / as. You should do what Xeio suggested with the as / null check.

*Edit*
Just to provide a sample for easier reference
Spoiler:

Code: Select all

void Forward<T, U>(U u, Action<T> f) where T : class, U, new()
{
   var t = u as T;
   if (t != null)
   {
      f(t);
   }
}

User avatar
Robert'); DROP TABLE *;
Posts: 730
Joined: Mon Sep 08, 2008 6:46 pm UTC
Location: in ur fieldz

Re: Coding: Fleeting Thoughts

Postby Robert'); DROP TABLE *; » Wed Sep 10, 2014 8:47 pm UTC

Breakfast wrote:C# does indeed lack partial type deduction. However, F# has it so it may make its way into the C# language at some point. It's not incredibly apparent in this example but it becomes a real problem when you're writing generic functions that take one type as input but can return several different output types...

Given that C# doesn't support algebraic types, how would that even hypothetically work? Would the function just return the deepest common ancestor of the different options?
...And that is how we know the Earth to be banana-shaped.

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

Re: Coding: Fleeting Thoughts

Postby Yakk » Wed Sep 10, 2014 9:00 pm UTC

Oh wait -- I'm thinking of the C# code as templates, but it is generics isn't it? So a bunch of type-safe casting auto fluff over a single function implementation, not instructions on how to write a function for each set of types passed?
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
Xeio
Friends, Faidites, Countrymen
Posts: 5101
Joined: Wed Jul 25, 2007 11:12 am UTC
Location: C:\Users\Xeio\
Contact:

Re: Coding: Fleeting Thoughts

Postby Xeio » Wed Sep 10, 2014 9:52 pm UTC

Yes, it's generics.

Technically speaking, generics in C# generate one instance for each value type that's used, and a shared instance for any reference type that's passed. But that's all waaaaay down the line at runtime.

Breakfast
Posts: 117
Joined: Tue Jun 16, 2009 7:34 pm UTC
Location: Coming to a table near you

Re: Coding: Fleeting Thoughts

Postby Breakfast » Wed Sep 10, 2014 9:58 pm UTC

Yakk wrote:Oh wait -- I'm thinking of the C# code as templates, but it is generics isn't it? So a bunch of type-safe casting auto fluff over a single function implementation, not instructions on how to write a function for each set of types passed?

Yeah, something like that in so many words. It's like Java generics but without type erasure so you can still get at the generic metadata at runtime.

Robert'); DROP TABLE *; wrote:
Breakfast wrote:C# does indeed lack partial type deduction. However, F# has it so it may make its way into the C# language at some point. It's not incredibly apparent in this example but it becomes a real problem when you're writing generic functions that take one type as input but can return several different output types...

Given that C# doesn't support algebraic types, how would that even hypothetically work? Would the function just return the deepest common ancestor of the different options?

Are you asking me to clarify what I'm talking about or are you saying that it's something the language just couldn't ever have?
*Edit to provide a code sample*
Spoiler:
So the code I've got here is not friendly and shows the problems that C# has because of its weak type inference and deduction.

Code: Select all

// These two definitions are for functions that take a predicate p and return a result after applying that
// predicate over the _oas collection. The first function, _any, returns a bool while the second function,
// _select, returns an object of type A. I'm using dynamic as the return type for both of these functions
// because the next function wouldn't be able to deduce the resulting type if I had used a static one.
Func<Func<OA, bool>, dynamic> _any = p => _oas.Any(oa => p(oa));
Func<Func<OA, bool>, dynamic> _select = p => _oas.Where(oa => p(oa)).Select(oa => oa.As).First();

// This function, f, is essentially like Haskell's flip. I'm defining a function that takes in a predicate,
// creates a closure over it, and waits to be given one of the above two selectors. Once again, I'm
// using the dynamic type keyword because the compiler can't figure out the resultant type even
// though that information should be available to it.
Func<Func<OA, bool>, Func<Func<Func<OA, bool>, dynamic>, dynamic>> f = p => s => s(p);

// These two definitions are just the predicates that I'm going to be using in my queries.
// I'm using var here because the compiler can infer the type of calling f with a predicate.
// It wouldn't be able to do this if I wasn't using the dynamic keyword though.
var _isO = f(oa => !oa.ExpirationDate.HasValue && oa.ATypeID == (short)AType.O);
var _isOM = f(oa => !oa.ExpirationDate.HasValue && (oa.ATypeID == (short)AType.M || oa.ATypeID == (short)AType.OM));

// Here's the query where I use each predicate with each selector.
// Notice all of the required casting caused by the use of the dynamic keyword and wanting to return a type safe result.
return (_isO(_any) as Nullable<bool>).Value
   ? _isO(_select) as A
   : (_isOM(_any) as Nullable<bool>).Value
      ? _isOM(_select) as A
      : null;

User avatar
ahammel
My Little Cabbage
Posts: 2135
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC
Contact:

Re: Coding: Fleeting Thoughts

Postby ahammel » Thu Sep 11, 2014 9:35 pm UTC

The standard for file type Fox says that field Bar is indexed from one, with zero indicating a null value.

So of course, in the PyFoo module, the field is indexed from zero. And a null value is apparently a secret?

RAAAAAAAAAAAAAAGE!
He/Him/His/Alex
God damn these electric sex pants!

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

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Fri Sep 12, 2014 10:07 pm UTC

Code: Select all

bool foundValues[3000] = {false};
for ( int i = 0; i < 64; i++ ) {
  value = someCoolFunction( arguments[i] );
  foundValues[value] = true;
  value = someOtherCoolFunction( arguments[i] );
  foundValues[value] = true;
}

Was terminating after 18 iterations instead of 64.
Turns out I neglected to check for negative values being returned from my super cool functions.

Serves me right for not using std::array I guess...
Image

User avatar
The Great Hippo
Swans ARE SHARP
Posts: 7368
Joined: Fri Dec 14, 2007 4:43 am UTC
Location: behind you

Re: Coding: Fleeting Thoughts

Postby The Great Hippo » Sat Sep 13, 2014 10:30 pm UTC

I've made a type of class that helps with equality tests, and I wanted to know if something similar exists that I could read about to help me understand what I'm doing.

The class (called Signal) accepts another class and keyword arguments to pass to that other class as its parameters. This produces a Signal instance, which holds the passed class and generates an instance of this class (using the keyword arguments passed to it -- or, if insufficient arguments are supplied, passing dummy values to the instance). Now, the Signal instance will test equal to any instance of the passed class, so long as 1) The tested instance inherits from the class stored in the signal, 2) the instance stored in the signal has all the attributes, and those attributes either equal the tested instance's attributes or are dummy values.

Additionally, calling the signal instance with new keyword arguments will return a new signal instance based on the initially passed class, but with the new keyword arguments passed to it instead of the original ones (if any).

The point of this process (as convoluted as it might be!) to be that I wanted to test if a message has arrived, but I wanted a method that allowed me to test for all messages of a certain type, and also all messages of a certain type with certain attribute values.

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

Re: Coding: Fleeting Thoughts

Postby Thesh » Sun Sep 14, 2014 8:10 pm UTC

Me: Hey, when I pass a wildcard character like an asterisk as a parameter, I want it to do a wildcard search for files in the current directory and give me a list of filenames. Just like how every other shell does automatically without you having to code for it.

WIndows API: Oh? What's that? A list? HA HA! Nope, you have to do two different function calls, you call one to get the first file and you have to check that return value, and then you have to call a second function once for each additional file. What's that? You wanted one function so you can just put it in a nice, clean loop? Jackass! Oh, I'm also going to throw in a "typedef char TCHAR" because fuck you, that's why.


At least, that's how the Windows API sounds in my head.
Summum ius, summa iniuria.

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

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Mon Sep 15, 2014 12:37 pm UTC

What's that Visual Studio? My trial edition of VS Express has expired and now I need to register?
How about "fuck you".

At least cl.exe still works.
Image

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

Re: Coding: Fleeting Thoughts

Postby Yakk » Mon Sep 15, 2014 1:46 pm UTC

Thesh wrote:Me: Hey, when I pass a wildcard character like an asterisk as a parameter, I want it to do a wildcard search for files in the current directory and give me a list of filenames. Just like how every other shell does automatically without you having to code for it.

I actually find such globbing annoying when I'm talking to shells. Lots of escaping. And dog help you if you want to pass a command line with stdin and stdout redirects to a command line which contains a command line as an argument and have your command not blow up.
WIndows API: Oh? What's that? A list? HA HA! Nope, you have to do two different function calls, you call one to get the first file and you have to check that return value, and then you have to call a second function once for each additional file. What's that? You wanted one function so you can just put it in a nice, clean loop? Jackass! Oh, I'm also going to throw in a "typedef char TCHAR" because fuck you, that's why.

Which works reasonably well with a for loop. for (HANDLE blah = init(...); test(blah); blah = next(blah)) sort of thing.

Of course, what I do nowadays is wrap such legacy APIs in a C++ range, which is pretty easy. And I get:
for( auto value : magic )
or even
std::vector< whatever > v = as_vector( magic )
if I feel like having concrete data around.

The TCHAR mess is because they wanted you to be able to compile the same code for 8 bit and 16 bit characters, because reasons.

But you probably knew all that.
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.

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

Re: Coding: Fleeting Thoughts

Postby EvanED » Mon Sep 15, 2014 2:18 pm UTC

Yakk wrote:Which works reasonably well with a for loop. for (HANDLE blah = init(...); test(blah); blah = next(blah)) sort of thing.
Exactly. IMO, the "first first", "find next" pattern actually works a little better than something like opendir(3)/readdir(3) for that reason. Well, the FindFirstFile pair is a bit uglier than that pattern often is, but with a better API it works a bit better. :-) (For those following along at home, init and next return different types and different indicators of success, so it looks like you can't follow that pattern. So now I'm back to agreeing with Thesh about it being a poorly-designed API.) Or even glob(3), if all you're going to wind up doing is a single forward pass over the matches. And glob(3) has the disadvantage that -- usually -- you don't have control over the number of matches, which means glob could allocate an arbitrarily-large amount of memory.

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

Re: Coding: Fleeting Thoughts

Postby Yakk » Mon Sep 15, 2014 2:39 pm UTC

Oh ya, that is horrid: Well, it works with while loops.

Code: Select all

FindFirst
if (handle is valid) {
  do {
  } while (next);
  FindClose
}

Anyhow, I dress it up with:

Code: Select all

struct find_files_t {
  find_files_t( pattern_whatever_args );
  struct iterator {
    bool is_end = false;
    windows_data_stuff; // here, or a pointer to the stuff in the range.
    file_state state;
    iterator& operator++() { is_end = !find_next(&windows_data_stuff, &state); return *this; }
    // etc
  };
  bool empty() const;
  iterator begin() const;
  iterator end() const;
  ~find_files_t();
};
find_files_t find_files( pattern_whatever_args );

for( file_state f : find_files( arguments ) ) {
  // ...
}

which is admittedly more evidence of the ability for C++ to wrap ugly stuff than anything else.

However, you really really want to iterate over stuff like "all matches" or "all files", because expanding to "all" might be ridiculously expensive. They threw together some API to let you iterate, and it stuck. It isn't so crappy that you can't make it pretty in C++.
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
Thesh
Made to Fuck Dinosaurs
Posts: 6598
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Mon Sep 15, 2014 6:19 pm UTC

For what it's worth, I wrote a wrapper in C that is fairly clean, although the annoying thing is that "*" matches "." and ".." which I have to discard. It's really ugly when put together, since it has to be wrapped in the "#ifdef _WIN32"

TODO:Refactor
Summum ius, summa iniuria.

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

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Tue Sep 16, 2014 11:51 am UTC

Code: Select all

void DoThing( long timeout ) {
  if ( timeout <= 0 ) {
    DoThingWithoutTimeout();
  } else {
    long timeToWait = /*calculation to get time based on timeout and some other stuff*/
    if ( timeToWait < 0 ) throw someException(...);
    DoThingWithTimeout( timeToWait );
  }
}

...

DoThing( 42 * age of the universe );

Wait... what?
Image

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

Re: Coding: Fleeting Thoughts

Postby Xeio » Tue Sep 16, 2014 5:27 pm UTC

You know, every time I venture back into the command line, the more I absolutely loathe the thing.

Trying to figure out how to configure a new diff tool in git... no fucking idea.

git difftool says "git config option diff.tool set to unknown tool" ... blah blah blah ... see git difftool --tool-help

git difftool --tool-help lists all the valid tools... well fucking thanks, that sure helps me configure a new tool or tell me what's missing with the tool I'm trying to configure

It was easier for me to create a junction point from "C:\Program Files (x86)\Beyond Compare 3" to "C:\Program Files (x86)\Beyond Compare 4" because it's already configured as bc3/bc4.

[/rant]

Maybe GitHub will add diff tool support directly to their app one of these days...

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

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Tue Sep 16, 2014 5:53 pm UTC

Git on Windows kinda sucks.
Or maybe I just mean the Windows command prompt sucks.

(git config diff.tool [tool])
Image

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

Re: Coding: Fleeting Thoughts

Postby Xeio » Tue Sep 16, 2014 6:54 pm UTC

But that doesn't set up a new tool. I think there's a path, and maybe cmd you need to setup too.

diff.tool only works if the tool is already configured.

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

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Tue Sep 16, 2014 7:10 pm UTC

Wait, are you in the repository when you try it?
Git maintains local and global settings, with local ones overriding the global ones (obviously).
git config --global diff.tool [tool] ?
Image

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

Re: Coding: Fleeting Thoughts

Postby Xeio » Wed Sep 17, 2014 6:59 pm UTC

Xenomortis wrote:Wait, are you in the repository when you try it?
Git maintains local and global settings, with local ones overriding the global ones (obviously).
git config --global diff.tool [tool] ?
What are you talking about?

Beyond Compare 4 is not pre-configured as a git tool, or at least not on the GitHub install of git. It has a lot of tools that are available and pre-configured with paths, but this isn't one of them.

Beyond Compare 3 is pre-configured as tool "bc3", there is also a "bc4" but it appears that's still Beyond Compare 3 but in diff mode rather than merge mode (I can only imagine what decisions went into naming those).

In any case, I found it easier to make my BC4 install masquerade as a BC3 install by creating a junction point, than to actually figure out how to configure git.

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

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Wed Sep 17, 2014 7:49 pm UTC

I completely didn't get what you were talking about...
Yeah, you need to configure it as a tool first...
Image

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

Re: Coding: Fleeting Thoughts

Postby Yakk » Wed Sep 17, 2014 8:20 pm UTC

Thoughts on a cleaner way to do this:
http://coliru.stacked-crooked.com/a/c4dcbe4c72b9832c
the idea is to have a type of std::future return both some data, and optionally a std::future continuation of the same enclosing type.

To do this, I created `next_data`, which is an incomplete type that just inherits and forwards everything to said `std::future`.

The result is a simple function, `stream_start`, which if given a loader (a function that returns vectors of T) streams you the data produced by it in whatever sized chunks the loader provides, while chain running the loader in a chained async. The loader (in this implementation) signals it is done by not returning any more data.

In effect, `streamer<T>` is a `std::future< std::pair< std::vector<T>, std::unique_ptr<X> > >`, where X is the type itself.
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.

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

Re: Coding: Fleeting Thoughts

Postby Ubik » Fri Sep 19, 2014 3:52 pm UTC

Too bad Thesh doesn't have control on the classes in that downcasting problem. It would be such an elegant solution to have them all inherit Exception, and just throwing them and then catching them by the subtype.

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

Re: Coding: Fleeting Thoughts

Postby Thesh » Sat Sep 20, 2014 1:45 am UTC

I came up with a really elegant solution to my globbing problem:

http://msdn.microsoft.com/en-us/library/8bch7bkk.aspx
Summum ius, summa iniuria.

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

Re: Coding: Fleeting Thoughts

Postby Thesh » Tue Sep 30, 2014 1:37 am UTC

You know, in the past I have preferred the Python-style indents for defining blocks of code over other constructs, but now I think I'm switching to the Ada/BASIC style if/end if because I was looking at some C# code at work with three nested using statements, a try/catch, a while loop and some conditions that didn't fit within my window, and it's really annoying trying to match up the braces. With "end if", "end while", "end using" it would be so much easier to figure out.
Summum ius, summa iniuria.

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

Re: Coding: Fleeting Thoughts

Postby Xeio » Tue Sep 30, 2014 1:43 am UTC

Thesh wrote:three nested using statements
Hrmmm, like immediately preceding one another?

I like not indenting those, especially since it's a very common pattern.

Code: Select all

using(Foo foo = new Foo())
using(Bar bar = new Bar(foo)){
     //Something with bar
}

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

Re: Coding: Fleeting Thoughts

Postby Thesh » Tue Sep 30, 2014 1:53 am UTC

At most, you could have gotten rid of one.

Code: Select all

using (SqlConnection Conn = new SQLConnection(ConnString))
{
    Conn.Open();
    using (SqlCommand Comm = new SQLCommand())
    {
        Command.Connection = Conn;
        Command.CommandText = query;
        Command.Parameters.... Blah blah blah, you get the point.
        using (SqlDataReader = Comm.ExecuteReader())
        {
            while (Reader.Read())
            {
                //stuff.
            }
        }       
    }
}
Summum ius, summa iniuria.

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

Re: Coding: Fleeting Thoughts

Postby Xeio » Tue Sep 30, 2014 3:18 pm UTC

So you want to fetch some data from your database, run some things, then set a flag that you processed your data.

So there's a stored procedure to get the list of data to process (sure). In this stored procedure, we run the same query twice, once to actually return the list, and once to insert key-only records into the secondary table that tracks the processed flag.

So, then we have a method that needs to go back and update those records. But rather than say, pass a list, no no, we pass a string of comma-seperated keys to update. (Why? Who knows!)

Then the other stored procedure (to update the flag at the end), does an update, and you guessed it, CAST and CHARINDEX to figure out of the key in the flag table is present in the string list. Hah, try to optimize that SQL Server with your fancy indexes.

But don't worry, we'll never need to insert at least, because our fetch procedure updated the flag table. You know, before we ever needed it.

I guess it's good nobody else uses this service call to update the flag, because it's just nice and silently fails if you didn't arrange to insert the key into the flag table already.

EDIT: Feeling ranty, because I was just going to make it less horribly while doing another change, but now there's this rabbit hole of changes I would need to fill in and I don't even want to touch with a 10 foot pole. So I guess the horribleness is here to stay.

EDIT2: Oh, and more fun I just noticed, the CHARINDEX is of CAST(KEY)+','. So make sure your passed comma separated list includes that trailing comma, or you just forgot to update someone.

That last bit is hilarious, because they use string.Join to add the commas, but have to add a comma at the end anyway! Wheee.

User avatar
raudorn
Posts: 370
Joined: Mon Jun 13, 2011 11:59 am UTC

Re: Coding: Fleeting Thoughts

Postby raudorn » Fri Oct 03, 2014 4:49 pm UTC

I should stop posting rants in here, feel free to ignore this post and let me know if I should stop for good.

Today I met with my old thesis1 supervisor, because he intended to reuse some code2 I wrote for my thesis. He didn't really understand how to use it, so I had to explain it to him. That made me realize something:

Before university I wrote crappy code, because I was young and had no formal training in programming.
At university I wrote crappy code, because I was still in training and all code was only ever used in classes/projects.
At my first job I wrote crappy code, because I was still in training and had no clue about the domain.
For my thesis I wrote crappy code, because I was absolutely out of my depth in the domain and the whole code could be rewritten in three hours anyway.
At my second job I write crappy code, because of heavy time constraints, manpower constraints, access constraints, dependency constraints, responsibility constraints, legacy code and every other contraint under the sun.
For my private projects I write crappy code, because they're either experimental "stuff thrown at the wall" or are written for ridiculous time constraints (game jams).

Does anyone start to see a pattern here? As far as I know, there are a few things about not-crappy code:

  • Well documented, not just with inline comments, but also documentation on how to setup and use the code
  • Easily readable and understandable code style
  • Single-purpose or clearly defined responsibility3
  • Is either independent or has clear communication on which dependencies are not met
  • Stable against change and boundary conditions

But what I feel like is that I can't fulfill half the goals either due to insufficient knowledge or because crappy code is more desirable under the given constraints. Either I don't know the solution and have to implement something and then can't change it or I know of one solution, but it's crappy and I can't change it. However I also feel like those are stupid excuses and I should just start following my own advice.

1 Bachelor thesis
2 That code was really never intended to be used again
3 What the code is used for


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 10 guests