View mode: basic / threaded / horizontal-split · Log in · Help
May 07, 2007
Red Code, Green Code (nwcpp video)
I've just noticed a Northwest C++ Users Group presentation
"Red Code, Green Code:  Generalizing const" by Scott Meyers, and found it quite interesting.

So here it is:
http://nwcpp.org/Meetings/2007/04.html


PS./OT: seems Scott do not really enjoying C++ template meta programming =)

-- serg.
May 07, 2007
Re: Red Code, Green Code (nwcpp video)
sergk wrote:
> PS./OT: seems Scott do not really enjoying C++ template meta programming =)

Well, he *is* a pretty smart guy.

--Steve
May 08, 2007
Re: Red Code, Green Code (nwcpp video)
sergk wrote:
> I've just noticed a Northwest C++ Users Group presentation
> "Red Code, Green Code:  Generalizing const" by Scott Meyers, and found it quite interesting.
> 
> So here it is:
> http://nwcpp.org/Meetings/2007/04.html
> 
> 
> PS./OT: seems Scott do not really enjoying C++ template meta programming =)
> 
> -- serg.

The next time some tries to argue library over language, or that 
templates in C++ are perfect, we should point them to that video.

PS - What would be the nicest way to do this in D using current syntax?
May 08, 2007
Re: Red Code, Green Code (nwcpp video)
janderson wrote:
> sergk wrote:
>> I've just noticed a Northwest C++ Users Group presentation
>> "Red Code, Green Code:  Generalizing const" by Scott Meyers, and found 
>> it quite interesting.
>>
>> So here it is:
>> http://nwcpp.org/Meetings/2007/04.html
>>
>>
>> PS./OT: seems Scott do not really enjoying C++ template meta 
>> programming =)
>>
>> -- serg.
> 
> The next time some tries to argue library over language, or that 
> templates in C++ are perfect, we should point them to that video.
> 
> PS - What would be the nicest way to do this in D using current syntax?

Well, we can trans-literate from the C++ code to get the same results.  Here I have an example that replaces the 
functionality from the vector template with tuples, and some additional template namespaces and operations to make it 
all come together.  The actual example is in the bottom third of this snippet.

(Mucking with code from http://herbsutter.spaces.live.com/blog/cns!2D4327CC297151BB!207.entry)

// This is placed in the Public Domain

template Tuple(V...){
	alias V Tuple;
}

template InTuple(Item){
	const bool InTuple = false;
}

template InTuple(Item,First,V...){
	static if(is(Item == First)){
		const bool InTuple = true;
	}
	else alias InTuple!(Item,V) InTuple;
}

template TupleRemoveAll(Item){
	alias Tuple!() TupleRemoveAll;
}

template TupleRemoveAll(Item,First,V...){
	static if(is(Item == First)){
		alias TupleRemoveAll!(Item,V) TupleRemoveAll;
	}
	else alias Tuple!(First,TupleRemoveAll!(Item,V)) TupleRemoveAll;
}

// use template 'struct' to prevent tuple flattening when passing constraints around
template Constraints(V...){
	alias V list;
}

template ConstraintRemove(alias Constraints){
	alias Constraints.list list;
}

template ConstraintRemove(alias Constraints,First,V...){
	alias Cosntraints!(TupleRemoveAll!(First,Constraints.list)) newConstraints;
	alias Tuple!(newConstraints,ConstraintRemove!(newConstraints,V)) list;
}

struct IgnoreConstraints {}

template ConstraintCheck(alias Local,Caller:IgnoreConstraints){
	const bool ConstraintCheck = true;
}

// ensure that all local constraints are satisfied by caller
template ConstraintCheck(alias Local,alias Caller){
	static if(Local.list.length > 0){
		static if(Caller.list.length > 0){
			alias Local.list[0] first;
			static if(InTuple!(Local.list[0],Caller.list)){
				alias Constraints!(TupleRemoveAll!(first,Local.list)) newLocalConstraints;
				alias ConstraintCheck!(newLocalConstraints,Caller) ConstraintCheck;
			}
			else{
				const bool ConstraintCheck = false;
			}
		}
		else{ // nothing left to check
			const bool ConstraintCheck = false;
		}		
	}
	else{ // nothing left to check
		const bool ConstraintCheck = true;
	}
}

// Here's the useful part:
struct ExceptionSafe {}
struct LGPLed {}
struct Reviewed {}

void f(alias CallerConstraints)(Params params){
    alias Constraints!(ExceptionSafe) MyConstraints;
    static assert(ConstraintCheck!(MyConstraints,CallerConstraints));
    /* do something */
}

void g(alias CallerConstraints)(){
    alias Constraints!(ExceptionSafe,Reviewed) MyConstraints;
    static assert(ConstraintCheck!(MyConstraints,CallerConstraints));

    // try to call the other function
    f!(MyConstraints)();  // error, trying to call unreviewed code from reviewed code
    f!(ConstraintRemove!(MyConstraints,Reviewed))(); // ok, ignore Reviewed constraint
    f!(IgnoreConstraints)(); // ok, explicitly ignore constraints entirely
}

void main(){
    alias Constraints!(ExceptionSafe,Reviewed) MyConstraints;
    g!(MyConstraints)();
}

This won't compile under DMD 0.012 and later - Bug 1196 keeps operations like InTuple!() from operating correctly.  So 
this is only half-tested.  There are also a few different ways one could implement this.  I opted for this particular 
definition of Constraints!() to allow for the ConstraintCheck!() operation to work for comparing two tuple lists 
(otherwise, they'd collapse into a single tuple).

Aside from the advantages that tuples offer, I'm having a hard time seeing a clear advantage over the C++ version.  We 
still get template bloat, and namespace concerns, plus it's not much more readable.  At a minimum, the lack of a need 
for a heavy amount of compile-time code is a clear advantage and I think (not sure here) the concerns about virtual 
methods are also addressed thanks to D's design.  So I think this edges out the C++ version rather invisibly.

-- 
- EricAnderton at yahoo
May 09, 2007
Re: Red Code, Green Code (nwcpp video)
On Mon, 07 May 2007 10:58:24 -0400, sergk wrote:

> I've just noticed a Northwest C++ Users Group presentation
> "Red Code, Green Code:  Generalizing const" by Scott Meyers, and found it quite interesting.
> 
> So here it is:
> http://nwcpp.org/Meetings/2007/04.html
> 
Very good idea.

I am wondering if it is possible to extend the idea to ensure layering in
code.

I normally use 5 layers.

Interface layer.
Application layer.
Domain layer.
Technical layer.
Platform layer.

The constrain on the code is that it should only make call in it own layer
or the layer below.

I think it could be very useful.

Knud
May 09, 2007
Re: Red Code, Green Code (nwcpp video)
Knud Soerensen wrote:
> 
> The constrain on the code is that it should only make call in it own layer
> or the layer below.
> 
> I think it could be very useful.

I think this is a really interesting idea.

--Steve
May 09, 2007
Re: Red Code, Green Code (nwcpp video)
Pragma wrote:
> janderson wrote:
>> sergk wrote:
>>> I've just noticed a Northwest C++ Users Group presentation
>>> "Red Code, Green Code:  Generalizing const" by Scott Meyers, and 
>>> found it quite interesting.
>>>
>>> So here it is:
>>> http://nwcpp.org/Meetings/2007/04.html
>>>
>>>
>>> PS./OT: seems Scott do not really enjoying C++ template meta 
>>> programming =)
>>>
>>> -- serg.
>>
>> The next time some tries to argue library over language, or that 
>> templates in C++ are perfect, we should point them to that video.
>>
>> PS - What would be the nicest way to do this in D using current syntax?
> 
> Well, we can trans-literate from the C++ code to get the same results.  
> Here I have an example that replaces the functionality from the vector 
> template with tuples, and some additional template namespaces and 
> operations to make it all come together.  The actual example is in the 
> bottom third of this snippet.
> 
> (Mucking with code from 
> http://herbsutter.spaces.live.com/blog/cns!2D4327CC297151BB!207.entry)
> 
> // This is placed in the Public Domain
> 
> template Tuple(V...){
>     alias V Tuple;
> }
> 
> template InTuple(Item){
>     const bool InTuple = false;
> }
> 
> template InTuple(Item,First,V...){
>     static if(is(Item == First)){
>         const bool InTuple = true;
>     }
>     else alias InTuple!(Item,V) InTuple;
> }
> 
> template TupleRemoveAll(Item){
>     alias Tuple!() TupleRemoveAll;
> }
> 
> template TupleRemoveAll(Item,First,V...){
>     static if(is(Item == First)){
>         alias TupleRemoveAll!(Item,V) TupleRemoveAll;
>     }
>     else alias Tuple!(First,TupleRemoveAll!(Item,V)) TupleRemoveAll;
> }
> 
> // use template 'struct' to prevent tuple flattening when passing 
> constraints around
> template Constraints(V...){
>     alias V list;
> }
> 
> template ConstraintRemove(alias Constraints){
>     alias Constraints.list list;
> }
> 
> template ConstraintRemove(alias Constraints,First,V...){
>     alias Cosntraints!(TupleRemoveAll!(First,Constraints.list)) 
> newConstraints;
>     alias Tuple!(newConstraints,ConstraintRemove!(newConstraints,V)) list;
> }
> 
> struct IgnoreConstraints {}
> 
> template ConstraintCheck(alias Local,Caller:IgnoreConstraints){
>     const bool ConstraintCheck = true;
> }
> 
> // ensure that all local constraints are satisfied by caller
> template ConstraintCheck(alias Local,alias Caller){
>     static if(Local.list.length > 0){
>         static if(Caller.list.length > 0){
>             alias Local.list[0] first;
>             static if(InTuple!(Local.list[0],Caller.list)){
>                 alias Constraints!(TupleRemoveAll!(first,Local.list)) 
> newLocalConstraints;
>                 alias ConstraintCheck!(newLocalConstraints,Caller) 
> ConstraintCheck;
>             }
>             else{
>                 const bool ConstraintCheck = false;
>             }
>         }
>         else{ // nothing left to check
>             const bool ConstraintCheck = false;
>         }       
>     }
>     else{ // nothing left to check
>         const bool ConstraintCheck = true;
>     }
> }
> 
> // Here's the useful part:
> struct ExceptionSafe {}
> struct LGPLed {}
> struct Reviewed {}
> 
> void f(alias CallerConstraints)(Params params){
>     alias Constraints!(ExceptionSafe) MyConstraints;
>     static assert(ConstraintCheck!(MyConstraints,CallerConstraints));
>     /* do something */
> }
> 
> void g(alias CallerConstraints)(){
>     alias Constraints!(ExceptionSafe,Reviewed) MyConstraints;
>     static assert(ConstraintCheck!(MyConstraints,CallerConstraints));
> 
>     // try to call the other function
>     f!(MyConstraints)();  // error, trying to call unreviewed code from 
> reviewed code
>     f!(ConstraintRemove!(MyConstraints,Reviewed))(); // ok, ignore 
> Reviewed constraint
>     f!(IgnoreConstraints)(); // ok, explicitly ignore constraints entirely
> }
> 
> void main(){
>     alias Constraints!(ExceptionSafe,Reviewed) MyConstraints;
>     g!(MyConstraints)();
> }
> 
> This won't compile under DMD 0.012 and later - Bug 1196 keeps operations 
> like InTuple!() from operating correctly.  So this is only half-tested.  
> There are also a few different ways one could implement this.  I opted 
> for this particular definition of Constraints!() to allow for the 
> ConstraintCheck!() operation to work for comparing two tuple lists 
> (otherwise, they'd collapse into a single tuple).
> 
> Aside from the advantages that tuples offer, I'm having a hard time 
> seeing a clear advantage over the C++ version.  We still get template 
> bloat, and namespace concerns, plus it's not much more readable.  At a 
> minimum, the lack of a need for a heavy amount of compile-time code is a 
> clear advantage and I think (not sure here) the concerns about virtual 
> methods are also addressed thanks to D's design.  So I think this edges 
> out the C++ version rather invisibly.
> 

Maybe something like C# user-definable attributes would help. (I'm sure 
someone has asked for this before).
May 09, 2007
Re: Red Code, Green Code (nwcpp video)
janderson wrote:
> Pragma wrote:
> 
> Maybe something like C# user-definable attributes would help. (I'm sure 
> someone has asked for this before).

I'm pretty sure I have on a few occasions. ;)

One way I can see this working is to use a custom pragma() - I think I managed to talk Gregor into trying it out in 
Rodin, at some point or another.  The suggestion isn't a personal bias, it's just that they're pretty much the ideal 
construct in D for supporting attributes.

struct ExceptionSafe{
  static ExceptionSafe opCall(){
    ExceptionSafe_this;
    return _this;
  }
}

// attach the ExceptionSafe attribute to the function f()
pragma(attr,ExceptionSafe()) void f(){
  /* do something */
}

But there are a few problems with using reflection to accomplish constraint checks.  The most obvious of which is that 
we're now checking things at runtime rather than at compile-time; so you have to run a full test suite in order to make 
sure you coded things up correctly.  Also, without being able to get the attributes for the current function, or even 
the calling function, there's no way to check the constraints without wrapping the call with a template.

The mess from using templates for this comes from the fact that the constraints can be thrown into a list in any order, 
so it defies the built-in specialization and overloading mechanisms provided by D.  If there were some way to specialize 
function declarations and calls, via an unordered property set (or by compile-time attributes), then it would be very 
easy to do.

-- 
- EricAnderton at yahoo
May 10, 2007
Re: Red Code, Green Code (nwcpp video)
Pragma wrote:
> [...]
> One way I can see this working is to use a custom pragma() - I think I 
> managed to talk Gregor into trying it out in Rodin, at some point or 
> another.  The suggestion isn't a personal bias, it's just that they're 
> pretty much the ideal construct in D for supporting attributes.
> 
> struct ExceptionSafe{
>   static ExceptionSafe opCall(){
>     ExceptionSafe_this;
>     return _this;
>   }
> }
> 
> // attach the ExceptionSafe attribute to the function f()
> pragma(attr,ExceptionSafe()) void f(){
>   /* do something */
> }
> [...]

Interestingly enough, this may well be only the second reasonable 
application of AOP that I've encountered. ;)  The problem here is that 
we want to perform a certain check *on every function*, but we don't 
want to make it *look* like we are performing the check.  Implementing 
these attributes as aspects actually makes a lot of sense.  I wonder 
whether D should try to support AOP somehow...

Dave
May 10, 2007
Re: Red Code, Green Code (nwcpp video)
David B. Held wrote:
> Pragma wrote:
>> [...]
>> One way I can see this working is to use a custom pragma() - I think I 
>> managed to talk Gregor into trying it out in Rodin, at some point or 
>> another.  The suggestion isn't a personal bias, it's just that they're 
>> pretty much the ideal construct in D for supporting attributes.
>>
>> struct ExceptionSafe{
>>   static ExceptionSafe opCall(){
>>     ExceptionSafe_this;
>>     return _this;
>>   }
>> }
>>
>> // attach the ExceptionSafe attribute to the function f()
>> pragma(attr,ExceptionSafe()) void f(){
>>   /* do something */
>> }
>> [...]
> 
> Interestingly enough, this may well be only the second reasonable 
> application of AOP that I've encountered. ;)  The problem here is that 
> we want to perform a certain check *on every function*, but we don't 
> want to make it *look* like we are performing the check.  Implementing 
> these attributes as aspects actually makes a lot of sense.  I wonder 
> whether D should try to support AOP somehow...
> 
> Dave

Well, this example is really more of an attempt to emulate C#'s attribute feature, which is really just to help enrich 
reflection.  I could easily see a pragma being used for AOP, though something like AOP (read: function-wrapping) should 
really be a first-class construct IMO.  I have no clue what that would look like, since there's so many different ways 
developers would expect AOP to work (i.e. explicit meshing of aspects, cross-cutting, etc).

You should drop a message in the "python style decorators thread".  It has morphed into an AOP for D discussion.

-- 
- EricAnderton at yahoo
Top | Discussion index | About this forum | D home