Jump to page: 1 2
Thread overview
Chain two different struct specialization
Mar 01, 2013
Andrea Fontana
Mar 01, 2013
Andrea Fontana
Mar 01, 2013
bearophile
Mar 01, 2013
Andrea Fontana
Mar 01, 2013
bearophile
Mar 01, 2013
bearophile
Mar 01, 2013
Andrea Fontana
Mar 01, 2013
bearophile
Mar 01, 2013
Andrea Fontana
Mar 01, 2013
bearophile
Mar 01, 2013
Era Scarecrow
Mar 01, 2013
Andrea Fontana
March 01, 2013
I'm trying to do something like this. I don't know whether or not it's a good idea, i'm open to solutions and suggestions

struct MyStruct(WEIGHTS)
{
   string ...
   string ...

   alias WEIGHTS weights;
}

double likeness(T,T1)(ref in T1, ref in T2)
{
    // Here i do some complex calculus using struct fields
    // and using weights consts
}

enum FirstWeights : double
{

}
March 01, 2013
On Friday, 1 March 2013 at 14:27:40 UTC, Andrea Fontana wrote:
> I'm trying to do something like this. I don't know whether or not it's a good idea, i'm open to solutions and suggestions
>
> struct MyStruct(WEIGHTS)
> {
>    string ...
>    string ...
>
>    alias WEIGHTS weights;
> }
>
> double likeness(T,T1)(ref in T1, ref in T2)
> {
>     // Here i do some complex calculus using struct fields
>     // and using weights consts
> }
>
> enum FirstWeights : double
> {
>
> }

Ops. Here the complete message:

I'm trying to do something like this. I don't know whether or not it's a good idea, i'm open to solutions and suggestions

struct MyStruct(WEIGHTS)
{
   string ...
   string ...

   alias WEIGHTS weights;
}

double likeness(T,T1)(ref in T1, ref in T2)
{
    // Here i do some complex calculus using struct fields
    // and using weights consts
}

enum FirstWeights : double
{
    double foo = 0.3,
    double bar = 0.4
}

enum SecondWeights : double
{
    double foo = 0.3,
    double bar = 0.4
}

so:
auto s1 = MyStruct!FirstWeights ...
auto s2 = MyStruct!SecondWeights ...

likeness(s1,s2); // works

But I can't mix different type (s1,s2) on a single range or array, to check for likeness, is there a way? (or should I avoid template init a double[] weights field)
March 01, 2013
Andrea Fontana:

> double likeness(T,T1)(ref in T1, ref in T2)

==>

double likeness(T1, T2)(in ref T1, in ref T2)

Bye,
bearophile
March 01, 2013
On Friday, 1 March 2013 at 14:39:53 UTC, bearophile wrote:
> Andrea Fontana:
>
>> double likeness(T,T1)(ref in T1, ref in T2)
>
> ==>
>
> double likeness(T1, T2)(in ref T1, in ref T2)
>
> Bye,
> bearophile


Sure not the only error. I was writing "pseudo code". Real code it's quite complex.

Try this one (is a really reduced working example):

struct MyStruct(WEIGHTS)
{
	this (int p, int p2) { prop = p; prop2 = p2; }
	int prop;
	int prop2;
	
	alias WEIGHTS weights;
}

double likeness(T1,T2)(ref in T1 first, ref in T2 second)
{
	double v = (first.prop - second.prop) * first.weights.foo * second.weights.foo;
	v += (first.prop2 - second.prop2) * first.weights.bar * second.weights.bar;
	return v;
}

enum FirstWeights : double
{
	foo = 0.3,
	bar = 0.4
}

enum SecondWeights : double
{
	foo = 0.5,
	bar = 0.2
}

void main(string[] args)
{


	auto s1 = MyStruct!FirstWeights(10,8);
	auto s2 = MyStruct!FirstWeights(9, 10);
	auto s3 = MyStruct!SecondWeights(9,10);

	writeln(likeness(s1,s2)); // works
	writeln(likeness(s1,s3)); // works


}

How to put s1,s2,3... in a range/array or something similar/iterable? Probably there's no way (inside variant?)...
March 01, 2013
Andrea Fontana:

> How to put s1,s2,3... in a range/array or something similar/iterable? Probably there's no way (inside variant?)...

One solution is to not use templates:



immutable struct Weights {
     double foo, bar;
}

enum Weights firstWeights  = { foo: 0.3, bar: 0.4 },
              secondWeights = { foo: 0.5, bar: 0.2 };

struct MyStruct {
	int prop, prop2;
     immutable Weights weights;

	this ( Weights weights_, in int p, in int p2) pure nothrow {
         prop = p;
         prop2 = p2;
     }
}

double likeness(in ref MyStruct first, in ref MyStruct second) {
	double v = (first.prop - second.prop) * first.weights.foo *
second.weights.foo;
	return v + (first.prop2 - second.prop2) * first.weights.bar *
second.weights.bar;
}

void main() {
	immutable s1 = MyStruct(firstWeights,  10,  8);
	immutable s2 = MyStruct(firstWeights,   9, 10);
	immutable s3 = MyStruct(secondWeights,  9, 10);

     import std.stdio;
	writeln(likeness(s1, s2));
	writeln(likeness(s1, s3));

     const r = [s1, s2, s3];
}


Bye,
bearophile
March 01, 2013
> void main() {
> 	immutable s1 = MyStruct(firstWeights,  10,  8);
> 	immutable s2 = MyStruct(firstWeights,   9, 10);
> 	immutable s3 = MyStruct(secondWeights,  9, 10);
>
>      import std.stdio;
> 	writeln(likeness(s1, s2));

Sorry for the mix of tabs and spaces. The crappy editor I have used now has not replaced your tabs with spaces...

Bye,
bearophile
March 01, 2013
On Friday, 1 March 2013 at 15:08:21 UTC, bearophile wrote:
>> void main() {
>> 	immutable s1 = MyStruct(firstWeights,  10,  8);
>> 	immutable s2 = MyStruct(firstWeights,   9, 10);
>> 	immutable s3 = MyStruct(secondWeights,  9, 10);
>>
>>     import std.stdio;
>> 	writeln(likeness(s1, s2));
>
> Sorry for the mix of tabs and spaces. The crappy editor I have used now has not replaced your tabs with spaces...
>
> Bye,
> bearophile

That's right.

I think you missed an initialization on this(): I fixed it.

BTW, compiler can't guess s1 and s2 weights, should it?

if inside likeness() i write:

enum test = first.weights.foo * second.weights.foo;

it said that can't read first and second value at compile time.


Andrea

March 01, 2013
Andrea Fontana:

> BTW, compiler can't guess s1 and s2 weights, should it?
>
> if inside likeness() i write:
>
> enum test = first.weights.foo * second.weights.foo;
>
> it said that can't read first and second value at compile time.

firstWeights and secondWeights are compile-time constants, but the arguments you give to likeness are run-time values, so they are unknown at compile-time inside likeness.

There are ways to solve that problem, but I don't know how much good this is:


immutable struct Weights {
    double foo, bar;
}

enum Weights firstWeights  = { foo: 0.3, bar: 0.4 },
             secondWeights = { foo: 0.5, bar: 0.2 };

struct MyStruct {
    int prop, prop2;
    immutable Weights weights;

    this(Weights weights_, in int p, in int p2) pure nothrow {
        this.weights = weights_;
        this.prop = p;
        this.prop2 = p2;
     }
}

double likeness(alias first, alias second)() {
    enum test = first.weights.foo * second.weights.foo;
    double v = (first.prop - second.prop) *
               first.weights.foo * second.weights.foo;
    return v + (first.prop2 - second.prop2) *
               first.weights.bar * second.weights.bar;
}

void main() {
    enum s1 = MyStruct(firstWeights,  10,  8);
    enum s2 = MyStruct(firstWeights,   9, 10);
    enum s3 = MyStruct(secondWeights,  9, 10);

    import std.stdio;
    writeln(likeness!(s1, s2)());
    writeln(likeness!(s1, s3)());

    const r = [s1, s2, s3];
}

Bye,
bearophile
March 01, 2013
On Friday, 1 March 2013 at 16:03:58 UTC, bearophile wrote:
> Andrea Fontana:
>
>> BTW, compiler can't guess s1 and s2 weights, should it?
>>
>> if inside likeness() i write:
>>
>> enum test = first.weights.foo * second.weights.foo;
>>
>> it said that can't read first and second value at compile time.
>
> firstWeights and secondWeights are compile-time constants, but the arguments you give to likeness are run-time values, so they are unknown at compile-time inside likeness.
>
> There are ways to solve that problem, but I don't know how much good this is:
>
>
> immutable struct Weights {
>     double foo, bar;
> }
>
> enum Weights firstWeights  = { foo: 0.3, bar: 0.4 },
>              secondWeights = { foo: 0.5, bar: 0.2 };
>
> struct MyStruct {
>     int prop, prop2;
>     immutable Weights weights;
>
>     this(Weights weights_, in int p, in int p2) pure nothrow {
>         this.weights = weights_;
>         this.prop = p;
>         this.prop2 = p2;
>      }
> }
>
> double likeness(alias first, alias second)() {
>     enum test = first.weights.foo * second.weights.foo;
>     double v = (first.prop - second.prop) *
>                first.weights.foo * second.weights.foo;
>     return v + (first.prop2 - second.prop2) *
>                first.weights.bar * second.weights.bar;
> }
>
> void main() {
>     enum s1 = MyStruct(firstWeights,  10,  8);
>     enum s2 = MyStruct(firstWeights,   9, 10);
>     enum s3 = MyStruct(secondWeights,  9, 10);
>
>     import std.stdio;
>     writeln(likeness!(s1, s2)());
>     writeln(likeness!(s1, s3)());
>
>     const r = [s1, s2, s3];
> }
>
> Bye,
> bearophile

but:

enum s1 = MyStruct(firstWeights,  10,  8);
enum s2 = MyStruct(firstWeights,   9, 10);

writeln(likeness(s1, s2));

still gives error: and s1 and s2 are known at compile time, aren't them?

Your solution will create code for each item couple, isn't it? Not good in my case :) Other ideas?

March 01, 2013
Andrea Fontana:

> but:
>
> enum s1 = MyStruct(firstWeights,  10,  8);
> enum s2 = MyStruct(firstWeights,   9, 10);
>
> writeln(likeness(s1, s2));
>
> still gives error: and s1 and s2 are known at compile time, aren't them?

Right. But they are known at compile-time only outside likeness().


> Your solution will create code for each item couple, isn't it?

Right.


> Not good in my case :) Other ideas?

Another solution is to use indirection, with classes or unsafe
casts. Or to use variants. No solution is perfect.
Why do you want to perform those computations at compile-time?

Bye,
bearophile
« First   ‹ Prev
1 2