Re: template alias parameters
enuhtac Wrote: > Hi, > > I'm playing around with template alias parameters. At the moment I'm > considering the following simple code: > > struct A > {}; > > struct B( T ) > { > T t; > }; > > struct C( alias T ) > { > T t; > }; > > void main() > { > B!A a; > C!A b; > } > > What exactly is the difference between a and b? Both seem to do the same No difference. > thing but obviously there is a difference as I cannot instanciate C with > buildin types as template parameter ("C!int c" results in "Error: > template instance C!(int) does not match template declaration C(alias T)"). I'm going to take a guess at the issue here. alias parameters are supposed to bind to a symbol. Types aren't symbols, they aren't things that will have an address during runtime. I'm not exactly sure why the struct is excepted. > The other question is: is there a possibility to distinguinish between > different "things" passed to a template alias paramter? - Like "isType", > "isVariable", "isLiteral", "isTemplate" ... > > enuhtac There isn't a distinction for literal vs variable. I'm pretty sure. As mentioned you don't pass types to alias. And you probably wouldn't write a template that accepts a template or a variable. As it is a symbol you do get to use typeof() and the likes on it.
Re: char[][] join ==> string
On 04/06/2011 05:13 PM, bearophile wrote: > Given an array of strings std.string.join() returns a single string: > > import std.string; > void main() { > string[] a1 = ["hello", "red"]; > string j1 = join(a1, " "); // OK > } > > > But in a program I need an array of mutable arrays of chars. If I join the arrays I get a mutable array of chars. But I need a string: Tangentially off-topic: This does not apply to your case, but I think we should think twice before deciding that we need a string. For example, functions parameters should be const(char[]) (or const(char)[]) instead of string as that type accepts both mutable and immutable strings. > > import std.string; > void main() { > char[][] a2 = ["hello".dup, "red".dup]; > string j2 = join(a2, " "); // error If possible, this might work: const(char[]) j2 = join(a2, " "); There is also std.exception.assumeUnique, but it's too eager to be safe and tries to null its parameter and this fails: string j2 = assumeUnique(join(a2, " ")); // error Finally, casting ourselves works: string j2 = cast(string)join(a2, " "); > } > > Error: cannot implicitly convert expression (join(a," ")) of type char[] to string > > ..idup avoids the error: > > string j3 = join(a2, " ").idup; // OK > > Given the low efficiency of the D GC it's better to reduce memory allocations as much as possible. > Here join() creates a brand new array, so idup performs a useless copy. To avoid this extra copy do I have to write another joinString() function? > > Bye, > bearophile Ali
char[][] join ==> string
Given an array of strings std.string.join() returns a single string: import std.string; void main() { string[] a1 = ["hello", "red"]; string j1 = join(a1, " "); // OK } But in a program I need an array of mutable arrays of chars. If I join the arrays I get a mutable array of chars. But I need a string: import std.string; void main() { char[][] a2 = ["hello".dup, "red".dup]; string j2 = join(a2, " "); // error } Error: cannot implicitly convert expression (join(a," ")) of type char[] to string .idup avoids the error: string j3 = join(a2, " ").idup; // OK Given the low efficiency of the D GC it's better to reduce memory allocations as much as possible. Here join() creates a brand new array, so idup performs a useless copy. To avoid this extra copy do I have to write another joinString() function? Bye, bearophile
Re: Why doesn't curry work with multiple arguments?
Well this still hasn't solved my problem. Because I shouldn't bind from left to right, but arbitrarily. So ideally I would want this: void foo(string str, int x, int y, string str2) { } alias bind!(foo, null, 1, 2, null) twoStrings; twoStrings("abc", "def"); -> foo("abc", 1, 2, "def"); I'm pretty sure I could do this with D's templates.
Re: Why doesn't curry work with multiple arguments?
Andrej Mitrovic: > Maybe "bind" should be a better name. I'm not sure.. In Python there is something similar that's named "partial": http://docs.python.org/library/functools.html#functools.partial Bye, bearophile
Re: Why doesn't curry work with multiple arguments?
On 4/6/11, bearophile wrote: > - Currying and partial function application are not exactly the same thing. > So I am not sure the "curry" in std.functional is named correctly; Maybe "bind" should be a better name. I'm not sure..
Re: Why doesn't curry work with multiple arguments?
Wow, talk about enlightement. I think I've done it now: import std.stdio; import std.traits; import std.metastrings; template count(T...) { enum count = T.length; } template myCurry(alias fun, args...) { static if (args.length > (ParameterTypeTuple!fun).length) { static assert(0, Format!("Tried to pass %s arguments, max is %s.", count!args, (ParameterTypeTuple!fun).length)); } ReturnType!fun myCurry(T...)(T t) { return fun(args, t); } } void foo(string x, int y, int z) { writeln(x, y, z); } alias myCurry!(foo, "bar") oneCurry; alias myCurry!(foo, "bar", 1)twoCurry; alias myCurry!(foo, "bar", 1, 2) threeCurry; void main() { oneCurry(1, 2); twoCurry(2); threeCurry(); }
Re: Why doesn't curry work with multiple arguments?
Andrej Mitrovic: > Here's a basic implementation: I have some general comments: - Currying and partial function application are not exactly the same thing. So I am not sure the "curry" in std.functional is named correctly; - Partial application is important in a language that wants to support functional idioms a little. This means that if D doesn't currently supports Partial application well, then it's worth improving; - A good function application must be able to solve this little rosettacode task too: http://rosettacode.org/wiki/Partial_function_application Bye, bearophile
Re: Why doesn't curry work with multiple arguments?
It's still wrong, the tuple is backwards. Haha, that's what I get for not unittesting.
Re: Why doesn't curry work with multiple arguments?
Ok, enjoy this monstrosity: template count(T...) { enum count = T.length; } template myCurry(alias fun, args...) { static if (args.length > (ParameterTypeTuple!fun).length) { static assert(0, Format!("Tried to pass %s arguments, max is %s.", count!args, (ParameterTypeTuple!fun).length)); } static if (is(typeof(fun) == delegate) || is(typeof(fun) == function)) { static if ((ParameterTypeTuple!fun).length - count!args) { ReturnType!fun myCurry(ParameterTypeTuple!fun[0 .. (ParameterTypeTuple!fun).length - count!args] myarg) { return fun(args, myarg); } } else { ReturnType!fun myCurry() { return fun(args); } } } }
Re: Why doesn't curry work with multiple arguments?
Crap, that is a horrible implementation, I didn't take into account not binding all arguments. Be right back..
Re: Why doesn't curry work with multiple arguments?
Here's a basic implementation: import std.stdio; import std.traits; import std.metastrings; template count(T...) { enum count = T.length; } template curry(alias fun, args...) { static if (args.length > (ParameterTypeTuple!fun).length) { static assert(0, Format!("Tried to pass %s arguments, max is %s.", count!args, (ParameterTypeTuple!fun).length)); } static if (is(typeof(fun) == delegate) || is(typeof(fun) == function)) { ReturnType!fun curry() { return fun(args); } } } void foo(int x, int y) { writeln(x, y); } alias curry!(foo, 1, 2) bar; void main() { bar(); } It will complain if you try to pass it more arguments than a function can take. I didn't implement curry's original else clause because I have no idea what's going on there (some comments would be useful in Phobos implementations, people!..) There is some wacky error if I didn't use the count template workaround. If I try to use args.length twice, like so: static if (args.length > (ParameterTypeTuple!fun).length) { static assert(0, Format!("Tried to pass %s arguments, max is %s.", args.length, (ParameterTypeTuple!fun).length)); } Then I get back: identifier 'length' of 'args.length' is not defined But it only errors out in the static assert, and yet it can check args.length in the static if. Really weird.
Re: Why doesn't curry work with multiple arguments?
Andrej Mitrovic Wrote: > Yes, I write a whole new function, but why do that when curry is there. Or so > I thought.. Oops: *Yes, I _can_ write a whole new function
Why doesn't curry work with multiple arguments?
import std.functional; void foo(int x, int y, int z) { } alias curry!(foo, 1, 2, 3) bar; Error: template instance curry!(foo,1,2,3) does not match template declaration curry(alias fun,alias arg) Shouldn't curry take a variable number of arguments and then check the length of the arguments passed in against `fun`s length of parameters, and do its work from there? I'm trying to translate a C header file from the following to a D equivalent: #define txmOpenFile(hwndTV, szFile) \ SendMessage((hwndTV), TXM_OPENFILE, 0, (LPARAM)(szFile)) Yes, I write a whole new function, but why do that when curry is there. Or so I thought..
Re: incompatible types!
On 06.04.2011 02:15, Steven Schveighoffer wrote: On Tue, 05 Apr 2011 19:37:15 -0400, Caligo wrote: It's just frustrating, that's all. Writing thousands of lines of code and having everything stop because of a compiler bug is just frustrating. I completely understand. It's why I have to periodically stop using D. Dcollections sat idle for over a year while I waited for a compiler bug to be fixed. I know progress is being made, and all that is appreciated. But, I don't remember ever hearing anything about D2 being in beta. If anything, I remember months ago where D2 was recommended for new projects. So, now I'm not sure what I'm supposed to do. Start all over again from scratch? I really like my design, so I guess I'll have to wait till it gets fixed. Sorry you got that impression. The fact is, as long as you are using the non-broken features, D2 is pretty useful, even downright awesome :) The issue is, if you hit one of those broken ones. Unfortunately, the release of TDPL didn't make all those features magically appear fully implemented. So since TDPL is promoted as the offical language spec, D2 suddenly jumped way back in the release cycle, since many of its unimplemented/not-fully-implemented features became "official". I'd highly recommend *NOT* to use D2 for new projects unless you are willing to redesign your code to work around those issues, or wait for them to be fixed. I truly wish this wasn't the case, but I don't see how anyone can confidently recommend D2 for professional or non-toy projects. This may sound like an anti-endorsement, but I assure you it is not. I think D2 is going to be absolutely killer when it's finished. I just would not use it for professional development *right now*, where deadlines and budgets are under consideration. If you can afford to put it down when it breaks and wait for a fix, then I think it will be worth the wait. -Steve Both the d1 and d2 homepage states the following: There are two versions of the language: 1. D version 1 which is in maintenance mode. 2. D version 2 which is recommended for new projects. Should it mention that d2 is beta and phobos alpha? Or are you alone in thinking that?
template alias parameters
Hi, I'm playing around with template alias parameters. At the moment I'm considering the following simple code: struct A {}; struct B( T ) { T t; }; struct C( alias T ) { T t; }; void main() { B!A a; C!A b; } What exactly is the difference between a and b? Both seem to do the same thing but obviously there is a difference as I cannot instanciate C with buildin types as template parameter ("C!int c" results in "Error: template instance C!(int) does not match template declaration C(alias T)"). The other question is: is there a possibility to distinguinish between different "things" passed to a template alias paramter? - Like "isType", "isVariable", "isLiteral", "isTemplate" ... enuhtac
[SOLVED] [BUG?] Re: error "Not the start of the UTF-8 sequence"
On 04/06/2011 11:53 AM, Kagamin wrote: spir Wrote: Hello, I get this error message: Not the start of the UTF-8 sequence without any other comment module name or whatnot. This happens when I just added toString to the following struct, and used it: struct Node { // Note: level is equal to the number of chars up to this node. // Note: a 'path' node without entry has key="". char ch; uint level; Key key; Value value; ... string toString() { if (this.key != "") return format("<%s %s:%s>", this.ch, this.key, this.value); else return format("<%s>", this.ch); } } Hints? I'm blocked :-( struct Node { // Note: level is equal to the number of chars up to this node. // Note: a 'path' node without entry has key="". dchar ch; Sorry, no, nothing to do with the type. The error came from a special case where ch='\0'. Seems some routine in dmd does not like that; but no idea where the error comes from. There are two points to solve, I guess: * The error message should tell where it happens. * '\0' is a valid code point, should pass through without error. Denis -- _ vita es estrany spir.wikidot.com
Re: error "Not the start of the UTF-8 sequence"
spir Wrote: > Hello, > > I get this error message: > Not the start of the UTF-8 sequence > without any other comment module name or whatnot. > > This happens when I just added toString to the following struct, and used it: > > struct Node { > // Note: level is equal to the number of chars up to this node. > // Note: a 'path' node without entry has key="". > char ch; > uint level; > Key key; > Value value; > ... > string toString() { > if (this.key != "") > return format("<%s %s:%s>", this.ch, this.key, this.value); > else > return format("<%s>", this.ch); > } > } > > Hints? I'm blocked :-( > > Denis > -- > _ > vita es estrany > spir.wikidot.com > struct Node { // Note: level is equal to the number of chars up to this node. // Note: a 'path' node without entry has key="". dchar ch;
error "Not the start of the UTF-8 sequence"
Hello, I get this error message: Not the start of the UTF-8 sequence without any other comment module name or whatnot. This happens when I just added toString to the following struct, and used it: struct Node { // Note: level is equal to the number of chars up to this node. // Note: a 'path' node without entry has key="". char ch; uint level; Key key; Value value; ... string toString() { if (this.key != "") return format("<%s %s:%s>", this.ch, this.key, this.value); else return format("<%s>", this.ch); } } Hints? I'm blocked :-( Denis -- _ vita es estrany spir.wikidot.com
Re: ElementType!(Range) problem
--Philippe wrote:: >ElementType acts on types. It takes a type and 'returns' (compiles to, >actually) another type. You need to give it typeof(listR). >Then, as ElementType!(typeof(listR)) is a type, you cannot pass it to >writeln. Use .stringof to go from the type to a string representation >of its name. > >So: > >writefln("%s", ElementType!(typeof(listR)).stringof); > >ElementType!(typeof(listR)) is a type like any other. You can create a >variable with it: > >ElementType!(typeof(listR)) elem; > Got it!. Thanks. I faced this confusion because of the description for "ElementType" which is available in http://d-programming-language.org/phobos/std_range.html. It says, " template ElementType(R): The element type of R. R does not have to be a range. The element type is determined as the type yielded by r.front for an object r or type R. For example, ElementType!(T[]) is T. If R is not a range, ElementType!R is void. " So I thought that just passing ElementType!listR was adequate. :s