Why I get no identifier for declarator .... ?
mixin are useless in this case but that is a minimal example of my problem.
tlvar is type of TL so i do not see where is the problem.
Code also on dpaste, same error with dmd or ldc.
Thanks for your help
import std.stdio;
import std.typecons;
struct Data{
int x;
int y;
}
template getcode(T)
{
mixin(`
alias TL = Tuple!(
int,"x",
int,"y"
);
`);
TL tl;
mixin(`
tl.x = 10;
tl.y = 5;
`);
}
void main()
{
getcode!Data;
writeln( tl.x );
}
Your problem is that templates can only contain declarations, not statements or expressions. This is the offending code:
mixin(`
tl.x = 10;
tl.y = 5;
`);
These are assignments, not declarations. This is why you get the weird error message "Error: no identifier for declarator tl.x". The compiler thinks you are trying to make a declaration of a variable, and it can't find the type "tl.x"... or something like that. The solution is to set the value of the tuple inline, like so:
template getcode(T)
{
mixin(`alias TL = Tuple!(int, "x", int, "y");`);
TL tl = TL(10, 5);
}
Or, to better match your original code:
template getcode(T)
{
mixin(`alias TL = Tuple!(int, "x", int, "y");`);
TL tl = mixin(`TL(10, 5)`);
}
There is now another problem. In main, where you instantiate the template, you will get the error "Error: getcode!(Data) has no effect". This is because a template instantiation on its own is not a declaration. You have to either alias it to a symbol, or mix it in using a mixin statement.
Aliasing it to a symbol will allow you to access the declarations inside the template through that symbol, and mixing it in puts the template's declarations into the scope it's instantiated in. I would recommend the first option, as it's more hygenic. You shouldn't use mixin unless you absolutely have to.
void main()
{
//Error: getcode!(Data) has no effect
//getcode!Data;
//Ok
//mixin getcode!Data;
//writeln( tl.x );
//Ok
alias Code = getcode!Data;
writeln( Code.tl.x );
}
You can see my corrected version of your code here:
http://dpaste.dzfl.pl/f6152a35bfc8
Related
When I want to initialize a red black tree I do as in the documentation.
auto rbt = redBlackTree(1,2,3,4)
but if I want to declare it globally or make an array of red black trees I don't know how to do it and the documentation is not helping. I've tried various things and I frequently get errors similar to: redBlackTree!int is used as a type Can you help me? I could do it if I knew what to put instead of auto, ie, if I knew the type of redBlackTree.
I want to declare a red black tree in global scope or declare an array for which I need to declare the type, I want to do something like this:
type rbt;
void main() {
rbt.insert(3);
}
or this:
void main{
type[2] rbt;
rbt[0].insert(1);
}
You don't need to know the type of redBlackTree. You can query for at compile-time with typeof:
alias RBTree = typeof(redBlackTree(1));
RBTree rbt = redBlackTree(1, 2, 3);
This is a common and an encouraged pattern as many functions in D return Voldemort types (types that cannot be named).
In your example the type is RedBlackTree!int. If you don't use an IDE, an easy way to discover the type is pragma(msg, typeof(<functionCall>(<args>)));.
Furthermore, I should note that declaring an array of RedBlackTree works with auto:
auto arr = [redBlackTree(1, 2), redBlackTree(3, 4)];
For more help, please feel free to post the exact code that failed.
The type (using long instead of int) is RedBlackTree!long, here are some examples. Remember you have to use new to initialize the class.
import std.stdio;
import std.container;
RedBlackTree!long rbtree;
RedBlackTree!long[2] rbarray;
RedBlackTree!long[] rbdynamicarr;
RedBlackTree!long[][] rbmat;
void main() {
rbtree.writeln;
rbtree = new RedBlackTree!long;
rbtree.insert(3);
rbtree.writeln;
rbarray.writeln;
rbarray = new RedBlackTree!long[2];
rbarray.writeln;
rbdynamicarr.writeln;
int n = 3;
rbdynamicarr = new RedBlackTree!long[n];
rbdynamicarr.writeln;
rbmat.writeln;
int m = 2;
rbmat = new RedBlackTree!long[][](n,m);
rbmat.writeln;
alias RBTree = typeof(redBlackTree!long(1L));
RBTree rbalias;
rbalias = new RBTree;
rbalias.writeln;
RBTree[3] crayola;
crayola.writeln;
typeid(redBlackTree(1)).writeln;
RedBlackTree!(long, "a < b", false) hola;
hola = new RedBlackTree!(long, "a < b", false);
hola.writeln;
}
Is it possible to write a template or similar that can be used to automatically curry functions in D? Manually writing out all the nested delegates is killing me.
Basically, for a function f with e.g. 3 arguments, which can usually be called like f(a,b,c), I want it to be callable as f(a)(b)(c).
I know about std.functional.partial, but that's not what I want. I want to translate the function definition side, not the calling side.
I also know this is far from best practice, but I'm generating code, so bear with me.
Well, something along these lines should do the job:
template autocurry(alias what) {
import std.traits;
static if(Parameters!what.length)
auto autocurry(Parameters!what[0] arg) {
alias Remainder = Parameters!what[1 .. $];
auto dg = delegate(Remainder args) {
return what(arg, args);
};
static if(Remainder.length > 1)
return &autocurry!dg;
else
return dg;
}
else
alias autocurry = what;
}
int foo(int a, string b, float c) {
import std.stdio; writeln(a, " ", b, " ", c);
return 42;
}
string test() {
import std.stdio; writeln("called test");
return "no args";
}
void main() {
import std.stdio;
alias lol = autocurry!foo;
writeln(lol(30)("lol")(5.3));
auto partial = lol(20);
partial("wtf")(10.5);
alias t = autocurry!test;
writeln(t());
}
The idea there is pretty simple: generate the helper function based on the remaining arguments - if there are any, return the address of the helper as the delegate, otherwise, just return the delegate that calls the collected arguments. A little recursiveness handles 1+ arg cases, and the static if on the outside handles the 0 arg case by just returning the original function.
Language features to note:
eponymous templates. When a template has a member with the same name as the template (in this case, autocurry), it is automatically referenced when used.
tuple expansion. When I call what(arg, args), the args one, being a built-in tuple, is automatically expanded to create the complete argument list.
the various auto returns here (the explicit auto autocurry and the implicit delegate keyword without specifying a return type) just forward whatever other random type the body happens to return.
In the main function, I did alias lol = autocurry!foo; (I use lol as my placeholder name a lot, lol). You could also overload it at top level:
int foo(int a, string b, float c) {
import std.stdio; writeln(a, " ", b, " ", c);
return 42;
}
alias foo = autocurry!foo; // overloads the auto-curried foo with the original foo
And now you can use it directly, along side the original:
void main() {
foo(30)("lol")(5.3); // overload resolves to curried version
foo(40, "cool", 103.4); // overload resolves to original automatically
}
If you prefer a new name or the overload is up to you, either can work.
Note that each argument is liable to allocate some memory to store it for the next delegate. The GC will be responsible for cleaning that up.
I am trying to use a merit function for my branching in Gecode. In the MPG, the Gecode Manual, an example merit function is stated, and how to pass it to the branching. But I cannot figure out where to put the function. Should it be inside the script or outside? Right now I have put it next to the copy function, etc. I cannot find any example code where someone uses a merit function.
I get the following error:
program.cpp(247): error C2059: syntax error: '}'
program.cpp(247): error C2853: 'm': a non-static data member cannot have a type that contains 'auto'
program.cpp(259): fatal error C1004: unexpected end-of-file found
This is the code I am trying out:
// ...
branch(*this, workers, BOOL_VAR_MERIT_MIN(m), BOOL_VAL_MAX());
}
auto m = [](const Space& home, BoolVar x, int i) {
return i;
}
// ...
I know it is stupid to make a merit function that just returns the index, I am just trying to make the simplest merit function to work before I do what I want to do.
According to the Gecode documentation the merit function should return a double. As suggested by the type definition of BoolBranchMerit:
typedef std::function<double(const Space& home, BoolVar x, int i)> Gecode::BoolBranchMerit
To be safe, you might also want to declare m as being an Gecode::BoolBranchMerit. So I think the following should fix your example:
// ...
branch(*this, workers, BOOL_VAR_MERIT_MIN(m), BOOL_VAL_MAX());
}
BoolBranchMerit m = [](const Space& home, BoolVar x, int i) -> double {
return (double) i;
}
// ...
I would like to use some nss3.dll code in my program. To do this I decided to declare all of the compound datatypes that it needs and call the functions inside the dll file with them.
I am using a file in the firefox source code to see how to properly use the functions I need. In one of the functions it declares one of these compound datatypes (secuPWData) and passes it variables. Here is the definition I pasted into my code without any errors:
typedef struct {
enum {
PW_NONE = 0,
PW_FROMFILE = 1,
PW_PLAINTEXT = 2,
PW_EXTERNAL = 3
} source;
char *data;
} secuPWData;
The declaration of this struct looks like this in the code I'm looking at: secuPWData pwdata = { PW_NONE, NULL };
When I try to use a similar (or even the same) declaration, it complains about the PW_NONE attribute, claiming it is undefined. When I tried to pass in the 0 value in its place, it told me that 'a value of type "int" cannot be used to initialize an entity of type "enum secuPWData::"'. To try to debug the issue, I tried pasting the definition right on top of the declaration, without any change.
What is causing this problem to occur?
Thanks for any help.
just as #n.m. mentioned try using secuPWData::PW_NONE
#include <iostream>
using namespace std;
typedef struct {
enum {
PW_NONE = 0,
PW_FROMFILE = 1,
PW_PLAINTEXT = 2,
PW_EXTERNAL = 3
} source;
char *data;
} secuPWData;
int main() {
secuPWData pwdata = { secuPWData::PW_NONE, NULL };
return 0;
}
worked for me .. ideone - link
I'm trying to send D's sort function as a template argument to the pipe function. When I use sort without template arguments it works:
import std.stdio,std.algorithm,std.functional;
void main()
{
auto arr=pipe!(sort)([1,3,2]);
writeln(arr);
}
However, when I try to use sort with a template argument:
import std.stdio,std.algorithm,std.functional;
void main()
{
auto arr=pipe!(sort!"b<a")([1,3,2]);
writeln(arr);
}
I get an error - main.d(5): Error: template instance sort!("b<a") sort!("b<a") does not match template declaration sort(alias less = "a < b",SwapStrategy ss = SwapStrategy.unstable,Range)
Why does it happen? sort!"b<a" works on it's own, and it has the same arguments and return types as sort, so why does pipe accept sort but not sort!"b<a"? And is there a correct syntax for what I try to do?
UPDATE
OK, I've tried to wrap the sort function. The following code works:
import std.stdio,std.algorithm,std.functional,std.array;
template mysort(string comparer)
{
auto mysort(T)(T source)
{
sort!comparer(source);
return source;
}
}
void main()
{
auto arr=pipe!(mysort!"b<a")([1,3,2]);
writeln(arr);
}
So why doesn't the original version work? is this because of the extra template parameters sort takes?
Yes it's because of the extra template parameters — specifically the Range parameter. The problem can be reduced to
size_t sort2(alias f, Range)(Range range)
{
return 0;
}
alias sort2!"b<a" u;
The instantiation sort!"b<a" will fail because the Range is not determined. The function call sort2!"b<a"([1,2,3]) works because the parameter [1,2,3] can tell the compiler the type Range is int[]. This is known as "implicit function template instantiation (IFTI)". But IFTI only works when it is used as a function. In your use case, sort!"b<a" is instantiated without providing all parameters, thus the error.
This can be fixed by making the input a function literal, which is just similar to your mysort solution:
auto arr = pipe!(x => sort!"b<a"(x))([1,3,2]);
Or you could provide all required template parameters. This makes the code very unreadable though.
auto arr = pipe!(sort!("b<a", SwapStrategy.unstable, int[]))([1,3,2]);