Re: Sorting a zipped range

2014-02-27 Thread Timon Gehr

On 02/27/2014 10:09 PM, Ben Jones wrote:


My question is:  which features of the D range abstraction allow zip to
work the way we expect?


Assignable elements of a range do not need to be addressable.


What C++isms were left behind to make this work?


In C++, iterators should implement operator-> which must return a 
pointer to  data, and unary operator*, which should return a reference 
if it is to be assignable. This makes the iterator abstraction less 
flexible.


I.e. it is a consequence of

- desire to use pointer-like syntax for iterators
- weak support for hooking into the corresponding syntactic constructs

Phobos eg. allows retrieval of and assignment to a range's front element 
to be implemented in distinct methods that can execute arbitrary code. 
Zip uses such facilities to distribute assignments to its range elements 
back to each source range.


Re: DMD Source Guidance: Unused Return Values of Strictly Pure Function Calls

2014-02-27 Thread Timon Gehr

On 02/28/2014 12:38 AM, "Nordlöw" wrote:

Does anybody know where in the DMD source I can figure out if the return
value of a function call is used or not?


I'm not familiar with the DMD source code, but a good way to proceed is 
usually to grep for existing error messages that are somehow related. In 
this case, DMD already complains about some cases of unused values:


$ grep "no effect" *.c
declaration.c:   error("storage class 'auto' has no effect if type 
is not inferred, did you mean 'scope'?");
expression.c:e = new CastExp(loc, e, Type::tvoid);   // 
avoid "has no effect" error

mtype.c:// substitution has no effect on function pointer type.
sideeffect.c: * Don't complain about an expression 
with no effect if it was cast to void
sideeffect.c:/* Don't complain about calling functions 
with no effect,

sideeffect.c:error("%s has no effect", toChars());
sideeffect.c:error("%s has no effect in expression (%s)",

This leads directly to sideeffect.c: Expression::discardValue(), which 
seems to be the place where you want to insert your detection code.


Re: Function to print a diamond shape

2014-03-20 Thread Timon Gehr

On 03/20/2014 10:25 PM, Ali Çehreli wrote:

This is a somewhat common little exercise: Write a function that takes
the size of a diamond and produces a diamond of that size.

When printed, here is the output for size 11:

  *
 ***
*
   ***
  *
 ***
  *
   ***
*
 ***
  *

What interesting, boring, efficient, slow, etc. ways are there?

Ali


import std.stdio, std.range, std.algorithm, std.math;

enum s=11;
writef("%(%s\n%)", (i=>i.map!(a=>i.map!(b=>"* "[a+b>s/2])))
   (iota(-s/2,s/2+1).map!abs));



Re: Choice ranges?

2014-03-29 Thread Timon Gehr

On 03/28/2014 08:00 PM, H. S. Teoh wrote:

Today I ran into an interesting situation where I have a function f that
needs to return ranges of different types (but identical element types):

auto f(A...)(A args) {
...
if (someCondition)
return cartesianProduct(x, y)
.joiner;
else
return cartesianProduct(x, y)
.joiner
.filter!someFilter;
}

This obviously can't compile, because the return types are not the same.
(Note that someCondition is only known at runtime.) But abstractly
speaking, it *should* work, because the element type of the returned
range is identical.

So how would I implement something like this?


T



The following is as close as I got. I think the definite initialization 
checks DMD implements are horribly broken for union fields.


import std.range, std.algorithm, std.typetuple, std.traits;

template CommonElementType(T...)if(allSatisfy!(isInputRange,T)){
alias CommonElementType = CommonType!(staticMap!(ElementType,T));
}

private template Neg(alias a){
enum Neg(T...)=!a!T;
}

struct 
SumRange(T...)if(allSatisfy!(isInputRange,T)&&!is(void==CommonElementType!T)&&allSatisfy!(Neg!hasElaborateDestructor,T)&&allSatisfy!(Neg!hasElaborateCopyConstructor,T)){

size_t tag;
private union{ T rs=void; }
// private this();
@property front()@trusted{
switch(tag){
foreach(i,_;T) case i: return rs[i].front;
default: assert(0);
}
}
@property bool empty()@trusted{
switch(tag){
foreach(i,_;T) case i: return rs[i].empty;
default: assert(0);
}
}
void popFront()@trusted{
switch(tag){
foreach(i,_;T) case i: return rs[i].popFront();
default: assert(0);
}
}
}

private T buildSum(T, size_t tag,S)(S arg)@trusted{
T r;
r.tag=tag;
r.rs[tag]=arg;
return r;
}

auto inl(T,S)(S 
arg)if(!hasElaborateDestructor!S&&!hasElaborateDestructor!T&&!hasElaborateCopyConstructor!S&&!hasElaborateCopyConstructor!T){

return buildSum!(SumRange!(S,T),0)(arg);
}
auto inr(S,T)(T 
arg)if(!hasElaborateDestructor!S&&!hasElaborateDestructor!T&&!hasElaborateCopyConstructor!S&&!hasElaborateCopyConstructor!T){

return buildSum!(SumRange!(S,T),1)(arg);
}

auto f(R,S)(bool condition,R x,S y){
auto r1(){
return cartesianProduct(x, y).map!(a=>[a.expand])
.joiner;
}
auto r2(){
return cartesianProduct(x, y).map!(a=>[a.expand])
.joiner
.filter!(a=>a>2);
}
if(condition) return r1().inl!(typeof(r2()));
else return r2().inr!(typeof(r1()));
}

void main(){
import std.stdio;
writeln(f(true, [1,2,3], [4,5,6]));
writeln(f(false, [1,2,3], [4,5,6]));
}



Re: Choice ranges?

2014-03-29 Thread Timon Gehr

On 03/29/2014 01:37 AM, Artur Skawina wrote:

You can wrap the range in a common one. When the above approach isn't
enough, there's always the next level:


(Note that your code does not actually compile.)


Re: Choice ranges?

2014-03-29 Thread Timon Gehr

On 03/29/2014 06:19 PM, Artur Skawina wrote:

Of course it compiles -- with the compiler version I happen to use...

The compiler situation is one of the main reasons I gave up on D
about a year ago. Every release introduces a new dialect. This may
not be such a big problem for trivial toy programs, but for anything
else it means that the only practical approach is locking the toolchain
down and never looking forward.
Sometimes this means that the examples I post won't work -- I don't
have any newer D compiler to check with, sorry.


I'm stuck with 2.060 myself, but there's always http://dpaste.dzfl.pl/.


Re: They are not the same

2014-04-05 Thread Timon Gehr

On 04/05/2014 11:53 AM, bearophile wrote:

John Colvin:


I think there's an argument that this should work, on the grounds that
the context pointer is just another argument and therefore the lambda
can be weakly pure.


Was this discussed in the forum?


I've been bringing this up time and time again, but it is usually ignored.


Do you think you can ask for an enhancement in Bugzilla?
...


It's a plain bug. In fact, you have commented on it:

https://d.puremagic.com/issues/show_bug.cgi?id=9148


Re: They are not the same

2014-04-05 Thread Timon Gehr

On 04/05/2014 10:33 PM, Artur Skawina wrote:

On 04/05/14 21:51, Timon Gehr wrote:

On 04/05/2014 11:53 AM, bearophile wrote:

John Colvin:


I think there's an argument that this should work, on the grounds that
the context pointer is just another argument and therefore the lambda
can be weakly pure.


Was this discussed in the forum?


I've been bringing this up time and time again, but it is usually ignored.


Do you think you can ask for an enhancement in Bugzilla?
...


It's a plain bug. In fact, you have commented on it:

https://d.puremagic.com/issues/show_bug.cgi?id=9148


You're asking for bypassing immutability there (The first 'bar'.


Good point, presumably this was a copy-and-paste error.


That second 'bar' does not make sense w/o properly typed delegates;


The issue asks for delegates to be typed properly, unless I 
misunderstand what 'properly' means here.



the second 'foo' should indeed work).

artur





Re: Empty array and AA literals

2014-04-06 Thread Timon Gehr

On 04/06/2014 05:28 AM, dnspies wrote:


int[][] nested;

nested ~= null;

~ is overloaded, so how does it know what type I intend null to be?  How
can I specify it?


(int[]).init


Re: They are not the same

2014-04-09 Thread Timon Gehr

On 04/09/2014 07:27 PM, Kagamin wrote:

On Saturday, 5 April 2014 at 21:33:30 UTC, Timon Gehr wrote:

The issue asks for delegates to be typed properly, unless I
misunderstand what 'properly' means here.


Isn't the issue in pure nested functions treated as strongly pure?
What does it have to do with delegates?


The issue is that pure nested functions and delegate literals are not 
allowed mutable access to data reachable using context pointers.


However, this may also be exactly what is wanted in certain 
circumstances. 'Delegates are typed properly', I interpreted as meaning 
for one thing (besides fixing the unsoundness issues) that the 
'immutable'/'const' qualifiers can be used on nested functions/delegate 
literals, which then restores the current behaviour in the case of 
immutable (i.e. only immutable state can be accessed through context 
pointers thus annotated.), and would prevent updates to data in the 
context in the case of const.


Re: Understanding switch + foreach

2014-04-17 Thread Timon Gehr

On 04/08/2014 05:14 PM, Steven Schveighoffer wrote:

On Mon, 07 Apr 2014 18:30:30 -0400, Matej Nanut 
wrote:


Hello,

I don't understand why so many break statements are needed in this
construct:

immutable key = 3;
switch (key)
{
foreach (c; TypeTuple!(1, 2, 3, 4, 5))
{
case c: "Found %s!".writefln(c);
break;
}
break; // Default always gets executed without this break.
default:
"Not found %s :(".writefln(key);
break;
}

One after each case and another one after the foreach.


First, let me say this is a cool usage of compile-time foreach, I had
never thought of that.
...


I do this quite often.


Second, I think the issue is likely a bug with the break exiting the
wrong scope.


No, this is expected behaviour. break and continue work in any foreach 
statement. break always breaks the innermost breakable statement. (In 
particular, it does not pair up with case statements.)



You may be able to fix it by labeling the switch scope.

For example:

theswitch:
switch(key)
{

   ...
   break theswitch; // should exit the switch.
}

I have not tested it.

-Steve


Yes, this works.


Re: Understanding switch + foreach

2014-04-17 Thread Timon Gehr

On 04/17/2014 03:15 PM, Steven Schveighoffer wrote:




But should a foreach over a tuple a breakable statement?


Well, it is a foreach statement.

It is on the other hand not too clear what to do about 'static foreach', 
but I am leaning towards banning non-labelled break and continue inside it.



Basically, the above seems to me it should be equivalent to:

case 1:
writefln("Found %s!", 1);
break;
case 2:
writefln("Found %s!", 2);
break;
...

The foreach should be gone once the foreach is executed at compile-time.
...


So are the break statements. The lowering is more along the lines of:

{
case 1:
writefln("Found %s!", 1);
goto Lbreakforeach;
case 2:
writefln("Found %s!", 2);
goto Lbreakforeach;
}
Lbreakforeach:;


If the break breaks the foreach, why isn't just case 1 produced? That
would be an actual break in the foreach, no?

-Steve


No. You don't know the dynamic behaviour of the code at runtime just by 
unrolling the foreach body.


import std.stdio;
alias Seq(T...)=T;

void main(){
int x,y,z;
readf("%d %d %d",&x,&y,&z);
alias a=Seq!(x,y,z);
auto b=[x,y,z];
foreach(v;a){
if(v==2) break;
writeln(v);
}
foreach(v;b){
if(v==2) break;
writeln(v);
}
}



Re: alias this with template class?

2012-06-03 Thread Timon Gehr

On 06/03/2012 08:43 PM, Namespace wrote:

I think this should work:

[code]
import std.stdio;

class Foo(T) {
public:
 T Num;

 @property
 Foo!(U) ConvertTo(U)() inout {
 return cast(Foo!(U)) this;
 }

 alias ConvertTo this;
}

void Call(const Foo!(float) FFoo) {

}

void main() {
 Foo!(ubyte) UbFoo = new Foo!(ubyte)();

 Call(UbFoo);

 readln();
}
[/code]

Why it doesn't?


Making this generally work as you expect would be too hard.
The compiler would have to reverse-engineer the 'ConvertTo' template
which is an undecidable problem in general. Some clever heuristics
might suffice for most practical instances though, but those are
very open-ended and therefore it is hard to incorporate them into the
language definition. If you think it should be done you could file a
suggestion (enhancement request) into the bug tracker.


Re: Multi-Dimensional Associative Arrays ".get" and "in"

2012-06-08 Thread Timon Gehr

On 06/06/2012 04:17 PM, Paul wrote:

I've seen examples using .get and "in" to test for keys:
aa.get("hello", "salute") == "ciao"
"hello" in aa

Can I use this .get function or "in" operator with multi-D arrays?

string[string][string][string] aa;

if (["hello"][][] in aa) ?



Well, no. string[string][string][string] is an associative array mapping 
strings to associative arrays mapping strings to associative arrays 
mapping strings to strings. The indexes are more or less unrelated as 
far as the AA interface is concerned.


You can implement such functionality yourself, or use an approach like

string[Tuple!(string, string, string)] aa;

if(tuple("hello","salute","ciao") in aa)

if it is compatible with your usage patterns. this maps 3 key strings to 
the value string in one go.


Re: Is it possible to force CTFE?

2012-06-10 Thread Timon Gehr

On 06/10/2012 09:04 AM, Tommi wrote:

Three related questions:

1) Is there a way to force a function to be always executed at compile
time (when it's possible to do so) no matter what context it's called in?



No there is not. You could use a template that calls a private function 
at compile time instead. What is your use case?



2) Is it possible to specialize a function based on whether or not the
parameter that was passed in is a compile time constant?



This has been discussed before, but there is not.


1-2) could be introduced later when D gets AST macros.


3) Does any D compiler currently optimize out a conditional branch which
_can_ be evaluated at compile time (but which isn't forced into CTFE)?
Like:

int getValue(bool b)
{
 return b ? 123 : 456;
}

//...
auto value = getValue(true);


Yes, DMD/GDC/LDC should be able to do this to different extents.


Re: Auto-conversion in array literals?

2012-06-11 Thread Timon Gehr

On 06/12/2012 12:55 AM, bearophile wrote:

This is valid Scala code:

object Main {
 def main(args: Array[String]): Unit = {
 val a: List[BigInt] = List(1, BigInt(2))
 }
}


Is it possible/meaningful to support/allow D code like this?

import std.bigint;
void main() {
 BigInt[] a = [1, BigInt(2)];
}

Bye,
bearophile


Making it work would require a way to specify an implicit conversion 
from int to BigInt.


Re: Package and virtual functions

2012-06-13 Thread Timon Gehr

On 06/14/2012 01:34 AM, BLM768 wrote:




override will eventually be required when overriding a function. It is
already
if you compile with -w but not yet all of the time - though since
protected
isn't virtual and isn't really overriding anything, the compiler doesn't
complain if you don't use override with it (though it will if you do,
since
it's not overriding anything). So, eventually (or now if you use -w),
you will
_always_ know whether a function is overiding another or not, because
it will
have to have override if it is and can't have it if it isn't.

- Jonathan M Davis


That's good to know. I'll start using -w from now on.
However, the problem still exists that if a function is meant to
override a virtual method, but the method is not actually virtual, and
the programmer forgets to type "override," the compiler won't complain
and the error will slip through.




True, but it will be explicit in the derived class code:
No 'override', no function that is overridden.


Re: Package and virtual functions

2012-06-13 Thread Timon Gehr

On 06/14/2012 01:57 AM, BLM768 wrote:

I guess that another solution to this whole mess is to just start
requiring the use of override; then everyone would be educated and it
would be obvious where the bug is in the code I posted. Since we don't
want to break code, though, maybe there should be a message prominently
displayed on the D homepage telling people to use the -w switch until
the requirement is actually enforced for all code. If that requirement
is going to be enforced, though, I can't think of a better time than
now; otherwise, people are going to write code without "override" and
eventually end up making the same mistakes that I did.




Yes, this is the plan.


Re: Constraining template's function parameter signature

2012-06-14 Thread Timon Gehr

On 06/14/2012 02:57 PM, Tommi wrote:

I'm trying to constrain a struct template based on a parameter that's
supposed be a function with a certain signature. Difficult to explain,
easier just to show the problem:

module pseudorange;

struct PseudoInputRange(T, alias advance)
//The next line doesn't compile
//if (is(typeof(advance(T.init)) == void))
...
alias PseudoInputRange!(int, (ref int x) {++x;}) MyRange;
static assert(isInputRange!MyRange);



'T.init' is not an lvalue and can therefore not be passed by ref.
You can fix the problem with the fewest keystrokes like this:
if (is(typeof(advance([T.init][0])) == void))


Re: How to specialize templates for l-value and non-l-value arguments?

2012-06-14 Thread Timon Gehr

You can overload based on 'ref'.

auto just(ref immutable(T) data) { return Maybe!T(&data); }
auto just(immutable(T) data) { return Maybe!T([data].ptr); }


Re: Switch Statement case '0': .. case '9'

2012-06-14 Thread Timon Gehr

On 06/14/2012 05:59 PM, Paul wrote:

The book in section 3.5 gives these valid case examples:

case ’0’: .. case ’9’:
case ’A’: .. case ’Z’: case ’a’: .. case ’z’:
case ’.’, ’,’, ’:’, ’;’, ’!’, ’?’:

In my code:

case "STEP01": ...compiles and works correct
case "STEP01", "STEP02": ...compiles and works correct
case "STEP01": .. case "STEP50": ...compiler reports:

iccstats.d(27): Error: Integer constant expression expected instead of
"STEP01"
iccstats.d(27): Error: Integer constant expression expected instead of
"STEP50"
iccstats.d(27): Error: integral constant must be scalar type, not
const(char[])

Help please.


case-range expressions don't work with strings. (because there is no 
general way to meaningfully fill in the gap.)


You could automatically generate the case statements via a string mixin 
(untested):


mixin({
string r;
foreach(i;1..51) r~=`case "STEP`~(i<10?"0":"")~to!string(i)~`":`;
return r;
}());

But that is probably overkill, why not just parse the string with an if 
statement?


If you need fallthrough, you can use a goto statement

if(...) goto Lstepn;
switch(...){
case ...:
...
break;
Lstepn:
case ...:
...
break;
}


Re: How to specialize templates for l-value and non-l-value arguments?

2012-06-14 Thread Timon Gehr

On 06/14/2012 06:20 PM, Roman D. Boiko wrote:

On Thursday, 14 June 2012 at 16:08:54 UTC, Roman D. Boiko wrote:

On Thursday, 14 June 2012 at 16:05:52 UTC, Timon Gehr wrote:

You can overload based on 'ref'.

auto just(ref immutable(T) data) { return Maybe!T(&data); }
auto just(immutable(T) data) { return Maybe!T([data].ptr); }

Great! Thanks

Hmm... seems to fail for immutable:

immutable a = 2.0f;
#line 121
auto y0 = Maybe!float.just(a);
assert(!y0.empty);
assert(y0.front == a);

Compiler output:
fds/persistent.d(121): Error: 2 is not an lvalue
dmd: glue.c:1114: virtual unsigned int Type::totym(): Assertion `0' failed.
Aborted (core dumped)
make: *** [build/client] Error 134



You have found a compiler bug.


Re: Immutability and other attributes, please review

2012-06-14 Thread Timon Gehr

On 06/14/2012 06:42 PM, Jonathan M Davis wrote:

I wish that you could do

auto f = new float(2.1);

and therefore

auto f = new immutable(float)(2.1);

but you can't.


This seems to be an arbitrary limitation.
Imho it should be fixed. Probably it was missed because allocating a
primitive type on the heap is not a very common operation.


Re: Using consistently auto as function return type

2012-06-16 Thread Timon Gehr

On 06/16/2012 11:31 AM, Tommi wrote:

Do you consider it to be good or bad style of programming to use
consistently auto as function return type?

One of the pros is that it saves some redundant typing when the function
returns some complex templated type:

auto getValue()
{
 return MyType!(int, "asdf", 64).init;
}

But one of the cons is that you don't see what the function returns just
by looking at the signature.

Are there some more severe issues that I'm missing?


auto return types make functions semantically dependent on each other,
eg. the following is illegal code:

auto foo(){bar(); return 0; }
auto bar(){foo(); return 1; }

In order to resolve the return type of foo, the body of foo needs to be
analyzed, which involves resolving the return type of bar, therefore
the body of bar needs to be analyzed, which involves resolving the
return type of foo, therefore the body of foo needs to be analyzed, ...


The current implementation is very conservative, and rejects every
dependency cycle of auto return functions, even if the return types
could be resolved in theory.


Other than that, there are no more severe issues, I see these major
applications for auto return types:

- The body is very short and spells out the type explicitly, auto saves 
redundancy.


- The implementer does not know the exact return type himself, because
  it depends on template arguments.

- The user of the function does not need to know the return type. eg if
  it is a type local to the function.


Re: sorting associative array's keys by values

2012-06-16 Thread Timon Gehr

On 06/16/2012 06:34 PM, maarten van damme wrote:

Right now I have an associative array "int[string] aa" and stored the
keys in "string[] keys".
Now I want to sort keys[] so that "aa[keys[0]]>aa[keys[1]]"
I remember someone gave the answer to that question on stackoverflow
but after some googling I couldn't find the right answer.

maarten


schwartzSort!(k=>aa[k])(keys);


Re: sorting associative array's keys by values

2012-06-16 Thread Timon Gehr

On 06/16/2012 06:41 PM, Timon Gehr wrote:

On 06/16/2012 06:34 PM, maarten van damme wrote:

Right now I have an associative array "int[string] aa" and stored the
keys in "string[] keys".
Now I want to sort keys[] so that "aa[keys[0]]>aa[keys[1]]"
I remember someone gave the answer to that question on stackoverflow
but after some googling I couldn't find the right answer.

maarten


schwartzSort!(k=>aa[k])(keys);


oops.

Seems like you actually want

schwartzSort!(k=>aa[k],"a > b")(keys);


Re: sorting associative array's keys by values

2012-06-16 Thread Timon Gehr

On 06/16/2012 07:51 PM, maarten van damme wrote:

For some crazy reason my program now crashes on seemingly random
locations when parsing content of the form:

randomname
I want to extract randomname but an xml parser would be overkill so I
extract it using
curLine=curLine[curLine.countUntil(">")+1..$];
curLine=curLine[0..curLine.countUntil("

Possibly memory corruption. Do you use any unsafe constructs?


Re: Swap furthest element type of an array

2012-06-18 Thread Timon Gehr

On 06/18/2012 06:29 PM, Andrej Mitrovic wrote:

I just had a need for this but couldn't find it in Phobos:

import std.stdio;
import std.traits;
import std.range;

template SwapElem(Arr, Type)
{
 static if (isArray!(ElementType!Arr))
 {
 static if (isDynamicArray!Arr)
 alias SwapElem!(ElementType!Arr, Type)[] SwapElem;
 else
 alias SwapElem!(ElementType!Arr, Type)[Arr.length] SwapElem;
 }
 else
 {
 static if (isDynamicArray!Arr)
 alias Type[] SwapElem;
 else
 alias Type[Arr.length] SwapElem;
 }
}

void main()
{
 alias int[2][1] IntArr;
 alias SwapElem!(IntArr, float) FloatArr;
 writeln(typeid(FloatArr));  // float[2][1]
}

It doesn't handle complex declarations like "int[2]*[1]". It seems
hard to do since I can't pass a naked pointer as a type to a template.
Some other clever tricks would have to be used here. But it's a worthy
start. If you can improve it feel free to do so. :)


template SwapElem(A, E){
static if(is(A X:X[N],size_t N)) alias SwapElem!(X,E)[N] R;
else static if(is(A X:X[])) alias SwapElem!(X,E)[] R;
else static if(is(A X:X*)) alias SwapElem!(X,E)* R;
else alias E R;
alias R SwapElem;
}

pragma(msg, SwapElem!(int[]*[3][]*[2][]*[1][], float));


Re: Formatted input from text file

2012-06-18 Thread Timon Gehr

On 06/18/2012 05:11 PM, IK wrote:

Hmm does your code generate a 1D `array` as a grid, bearophile?
Anyway thanks, I'll compile it shortly.

My own code evolved to what's below and gives a Range violation.
Also I don't understand why formattedRead can't just accept a casted
`opSlice.dup`, is it a bug?


Yes.



void main()
{
uint[20][20] grid;
auto input_file = new MmFile("p011_input.txt");
string temp = cast(string)input_file.opSlice;

formattedRead(temp, "%(%(%s %)\n%)",&grid);
}


IIRC formattedRead would require input similar to

"[[1,2,3,4,5],[1,2,3,4,5],[1,2,3,4,5],[1,2,3,4,5],[1,2,3,4,5]]"

This works:

void main()
{
auto input_file = new MmFile("p011_input.txt");
auto text = cast(string)input_file[];
auto grid = text.splitLines.map!(_=>_.split.to!(uint[])).array;
}


Re: Swap furthest element type of an array

2012-06-18 Thread Timon Gehr

On 06/19/2012 12:01 AM, Andrej Mitrovic wrote:

On 6/18/12, Timon Gehr  wrote:

template SwapElem(A, E){
  static if(is(A X:X[N],size_t N)) alias SwapElem!(X,E)[N] R;
  else static if(is(A X:X[])) alias SwapElem!(X,E)[] R;
  else static if(is(A X:X*)) alias SwapElem!(X,E)* R;
  else alias E R;
  alias R SwapElem;
}

pragma(msg, SwapElem!(int[]*[3][]*[2][]*[1][], float));



Nce! Did you just come up with this right now? :D


Indeed. If you are interested, I'll make it work with qualified types as 
well. =)


Re: D: Unexpected output when using a delegate and EnumMembers

2012-06-19 Thread Timon Gehr

On 06/19/2012 04:44 PM, Travis Gockel wrote:


I am clearly doing something wrong,


You are not.


but I have no idea what and would
appreciate some insight.



You have found a bug in DMD.

Reduced test case that should compile:

template Seq(T...){alias T Seq;}
auto exec(alias a)(){return a();}
void main(){
foreach(e; Seq!(0, 1))
static assert(exec!(()=>e)()==e);
}

You can report the bug here: http://d.puremagic.com/issues/

The 'exec' template is instantiated only once instead of two times.


Re: D: Unexpected output when using a delegate and EnumMembers

2012-06-19 Thread Timon Gehr

On 06/19/2012 05:08 PM, Artur Skawina wrote:


Yes, it can be surprising, but I'm not convinced it's actually wrong
behavior (the bug is http://d.puremagic.com/issues/show_bug.cgi?id=2043)



It is not this bug. (And what is listed there is clearly wrong
behaviour, because it can be used to break the type system.)


Just do this:

size_t c = count!(function(x, e) { return x.e == e;} )(source, e);

and it will work. [1]

artur

[1] I don't do that new kinky lambda syntax, sorry. ;)


Your embarrassment about this issue is justifiable.


Re: Does the 'with' statement affect object lifetime?

2012-06-19 Thread Timon Gehr

On 06/19/2012 07:51 PM, Ali Çehreli wrote:


Bug?



Bug.


Re: what is the difference between static method of the class, module method and static method of the module?

2012-06-20 Thread Timon Gehr

On 06/20/2012 09:52 PM, bearophile wrote:

Alex Rønne Petersen:


The static keyword has no effect on module functions, so 2 and 3 are
equivalent.


This problem is caused by DMD sloppyness regarding its management of
attributes. A serious language  doesn't accept a keyword like "static"
where it has no meaning.


What is a 'serious language'?

interface I{ static int x=2; } // java


It just causes confusion to newbies, and makes
it harder to port D code across future D compilers...

Bye,
bearophile


To be fair, it does not have no meaning. It is simply redundant, because 
all module scope declarations are implicitly 'static'.


Re: Allocate an Array!T on the heap?

2012-06-22 Thread Timon Gehr

On 06/22/2012 08:45 AM, Tobias Pankrath wrote:

import std.container;

struct A {};

void main()
{
Array!(A)* arr = new Array!(A);
}

yields


bug.d(7): Error: template std.container.Array!(A).Array.__ctor does not
match any function template declaration
/usr/include/d/std/container.d(1625): Error: template
std.container.Array!(A).Array.__ctor(U) if
(isImplicitlyConvertible!(U,T)) cannot deduce template function from
argument types !()()



This seems to work:

import std.container;

struct A {};

void main() {
auto arr = new Array!A(A.init);
}


Re: const behaviour

2012-06-22 Thread Timon Gehr

On 06/22/2012 11:21 AM, Namespace wrote:

Based to the current const discussions (once again) I wanted to appease
my curiosity and want to ask why the following code works as described
in the comments:

[code]

import std.stdio;

class Bar { }

class Foo {
private:
 string _text;

 Bar _b;

public:
 this(string text, Bar b) {
 this._text = text;
 this._b = b;
 }

 // const_behaviour.d(18): Error: cannot implicitly convert
expression (this._b) of type const(Bar) to const_behaviour.Bar
 Bar GetB() const pure nothrow { /// <- must be const(Bar) instead
of Bar
 return this._b;
 }

 string GetText() const pure nothrow { /// <- no const(string) is
neccessary. Why?
 return this._text;
 }
}

void main() {
 Bar b = new Bar();

 Foo f = new Foo("foobar", b);
}

[/code]


string is immutable(char)[] and const(immutable(char)[]) implicitly
converts to immutable(char)[]. Or put differently, a string doesn't
have to be const-qualified because it cannot be changed anyway.


Re: Stack overflow

2012-06-22 Thread Timon Gehr

On 06/22/2012 12:22 PM, Namespace wrote:

I have this code:
http://codepad.org/vz17iZrm

And as long as i comment out the assert's in the constructor on line 10
and the assert in the invariant on line 16 it works as i want.
But otherwise the compiler prints stackoverflow and that's all.

Why and how is the stack overflowed with an simple assert?!


On my machine it is the compiler that crashes => compiler bug.
Presumably it is having trouble with the circular alias this.
(BTW, what is 'obj' in the invariant supposed to refer to?)


Re: const behaviour

2012-06-22 Thread Timon Gehr

On 06/22/2012 12:25 PM, Namespace wrote:

As far as i know "int" is not immutable or const by default.
So, why work this code:

[code]
import std.stdio;

class Bar {

}

class Foo {
private:
 int _id;

 Bar _b;

public:
 this(int id, Bar b) {
 this._id = id;

 this._b = b;
 }

 // const_behaviour.d(18): Error: cannot implicitly convert
expression (this._b) of type const(Bar) to const_behaviour.Bar
 const(Bar) GetB() const pure nothrow { /// <- must be const(Bar)
instead of Bar
 return this._b;
 }

 int GetId() const pure nothrow { /// <- no const(int) is
neccessary. Why?!
 return this._id;
 }
}

void main() {
 Bar b = new Bar();

 Foo f = new Foo(42, b);
}
[/code]


The same reason, because const(int) implicitly converts to int. If the
data is copied, the qualifiers can be changed in any way that is
desired. As string, int has no mutable indirections.


Re: Address of TLS variables

2012-06-23 Thread Timon Gehr

On 06/23/2012 09:51 PM, Alex Rønne Petersen wrote:

Hi,

Does taking the address of a TLS variable and passing it to other
threads have defined semantics? I would assume it results in a pointer
to the thread's instance of the TLS variable (which makes sense),



I'd assume that it results in a pointer to the original thread's TLS 
variable, because threads usually share the physical address space.



but is passing it to other threads OK?


I think you could pass a T* function() thunk that takes the respective 
TLS variable's address instead, if that makes sense.



Does the language guarantee this?



No, it is probably implementation/architecture dependent.


Re: Stack overflow

2012-06-24 Thread Timon Gehr

On 06/24/2012 12:37 PM, David wrote:

Am 24.06.2012 11:35, schrieb Namespace:

A non-nullable type _will_ be added to Phobos at some point.


As struct or class or as built-in type?

And can me explain somebody why
[code]
@disable
this(typeof(null));
[/code]
print "Stack overflow"?



What should typeof(null) return you? void*, int*


typeof(null) gives typeof(null).


Re: Stack overflow

2012-06-25 Thread Timon Gehr

On 06/25/2012 02:48 AM, Jonathan M Davis wrote:

On Sunday, June 24, 2012 19:03:17 Namespace wrote:

This might work:

this(U)(U obj)

 if(is(U : T)&&  !is(U == typeof(null)))

{
}


- Jonathan M Davis


Interesting. With or wihtout that, if i add a method to Foo it
prints "Stack overflow" also.

http://dpaste.dzfl.pl/91dad66c

Can you explain that?


Wait, you have a template mixin inside of Foo which passes Foo to it? I don't
know if you can get away with that or not, since you're trying to pass a type
to a template while you're adding stuff to it via that template. So, the type
is incomplete. I'm willing to be that that's your problem, but I don't know.

- Jonathan M Davis


This is fine. I am doing it all the time.
Why are we discussing this compiler bug on the main newsgroup though?


Re: front doesn't compile for arrays of immutable data

2012-06-25 Thread Timon Gehr

On 06/25/2012 04:27 PM, Roman D. Boiko wrote:

@property ref T front(T)(T[] a)
if (!isNarrowString!(T[]) && !is(T[] == void[]))
{
assert(a.length, "Attempting to fetch the front of an empty array of " ~
typeof(a[0]).stringof);
return a[0];
}

Why is front returned by ref even when it is not possible to do so?


It should always be possible to do so. What you are experiencing seems 
to be a compiler bug.


Re: Stack overflow

2012-06-25 Thread Timon Gehr

On 06/25/2012 02:18 PM, Namespace wrote:

Fine. But nothing of them explain the Stack overflow if i add an
additional method or disable/add an additional ctor.


It does not have to be explained: it is a compiler bug.


Re: Stack overflow

2012-06-25 Thread Timon Gehr

On 06/25/2012 05:52 PM, Namespace wrote:

On Monday, 25 June 2012 at 15:39:19 UTC, Timon Gehr wrote:

On 06/25/2012 02:18 PM, Namespace wrote:

Fine. But nothing of them explain the Stack overflow if i add an
additional method or disable/add an additional ctor.


It does not have to be explained: it is a compiler bug.


Then it will take months or years until it is fixed ... too bad.



Many of them get fixed quite fast if they are reported properly.


And that Ref!(Foo) rf = new Foo(); ends even with "Stack overflow" and
Ref!(Foo) rf2 = new Ref!(Foo)(new Foo()); not has the same explanation
"Compiler Bug", hm?



It is always a compiler bug if compilation crashes.


Re: Circle Calculator Help

2012-06-26 Thread Timon Gehr

On 06/26/2012 09:43 PM, Steven Schveighoffer wrote:

On Tue, 26 Jun 2012 10:40:18 -0400, Alexander
 wrote:
...

//Wait
void wait()
{
writefln ("Type A to continue!");
exittest();
}

//Exit tester
void exittest()
{
char[] a;
stdin.readln(a);
if (a == "A")
{
exit();
}
else
{
wait();
}
}


Hm... interesting code here :)

This is not horrible, just... weird.



It is functional style. ;)


You probably want to avoid recursion in this case:

void wait()
{
char[] a;
while(a != "A")
{
writeln("Type A to continue!");
stdin.readln(a);
}
}

-Steve


I want the two examples to generate comparable code.


Re: Circle Calculator Help

2012-06-26 Thread Timon Gehr

On 06/27/2012 01:40 AM, Steven Schveighoffer wrote:

On Tue, 26 Jun 2012 19:10:25 -0400, bearophile
 wrote:


Steven Schveighoffer:


I agree with Andrei, there is no outlet for errors in the to!T
function, exception is the logical choice.


Maybe I was not clear enough, so let me explain a bit better.

What I don't like is to!int("15\n") to be seen as an error in the
first place.
I'd like it to ignore leading and trailing whitespace, as in Python
(stripping it automatically):


Right, but what if it's an error in your code if whitespace is present?
Then you have to check for whitespace and throw your own error.

I admit, that would likely be a rare occasion. But having both behaviors
should be possible.
...


I think the default behaviour should be the behaviour that is wanted in 
the majority of cases.


Re: Bug in Auto Functions and Template? Or Am I Just Crazy...

2012-06-27 Thread Timon Gehr

On 06/27/2012 11:07 AM, Michael wrote:

Hello all,
   I came across some weird behaviors yesterday and I can't figure out
what it's about.

(1)
auto factorial(int n) {
 if (n < 2) return 1;
 return n * factorial(n-1);
}

The compiler complained about "forward declaration of factorial". If I
change the return type to int, the problem goes away. I can understand
that with the recursion, it might be impossible for the compiler to
deduce the type of factorial and so it compile errors, but I don't see
anything about that on the Language Reference. Is this the intended
behavior?



Apparently the compiler attempts to type combine the types of the
return statements. This does not match the language documentation. I
think it should just use the type of the first return statement.


(2)
auto stuff(T)(T[] arr) {
 auto inner(T[] s) {
 s[0] = 0;
 }
 arr.inner();
}
This time the compiler complained about 'inner' not being defined. This
time I have no idea what is wrong.

Thanks for your help!
Michael



This is expected behaviour. UFCS only works with module scope functions.


Re: Bug in Auto Functions and Template? Or Am I Just Crazy...

2012-06-27 Thread Timon Gehr

On 06/27/2012 01:24 PM, Timon Gehr wrote:

On 06/27/2012 11:07 AM, Michael wrote:

Hello all,
   I came across some weird behaviors yesterday and I can't figure out
what it's about.

(1)
auto factorial(int n) {
 if (n < 2) return 1;
 return n * factorial(n-1);
}

The compiler complained about "forward declaration of factorial". If I
change the return type to int, the problem goes away. I can understand
that with the recursion, it might be impossible for the compiler to
deduce the type of factorial and so it compile errors, but I don't see
anything about that on the Language Reference. Is this the intended
behavior?



Apparently the compiler attempts to type combine the types of the
return statements. This does not match the language documentation. I
think it should just use the type of the first return statement.
...


http://d.puremagic.com/issues/show_bug.cgi?id=8307


Re: Removing from SList (std.container)...

2012-06-27 Thread Timon Gehr

On 06/27/2012 08:46 PM, Roman D. Boiko wrote:

On Wednesday, 27 June 2012 at 18:26:46 UTC, Steven Schveighoffer wrote:

The thing that makes SList useless is the O(n) removal. Nobody will
ever use SList when they can write a replacement that has O(1) removal
in 10 minutes.

Do you mean something like indexed/sorted dictionary? It doesn't seem to
be that easy to implement. Or some other data structure with O(1) removal?


O(1) removal works quite ok for a singly linked list. eg:

1.
- Add a sentinel node to the start of your list.
- Represent an iterator into the list as a pointer to the predecessor
  of the respective node.
- Removal: trivial. rebind the 'next' reference of the pointed-to node.

2.
- Represent the empty list as a sentinel node with null 'next' field.
- For removal of a node you own a pointer to:
 -- case 1: the successor is an empty list:
- destroy the value, set the 'next' reference to null.
 -- case 2: else:
- move the successor's value into the node that holds the value to
  be removed, bind the 'next' reference to the successor of the
  successor.


Re: foreach syntax

2012-06-29 Thread Timon Gehr

On 06/29/2012 12:47 PM, Namespace wrote:

A friend of mine ask me why D's foreach isn't like C#

Means, why is it like
int[] arr = [1, 2, 3];

foreach (int val; arr) {



foreach(val; arr) {


and not
foreach (int val in arr) {

which it is more intuitive.



To someone coming from C#, yes.


I could give him no clever answer to, so maybe someone here knows the
reasons.


Just because. This does not matter.


Re: foreach syntax

2012-06-29 Thread Timon Gehr

On 06/29/2012 01:01 PM, bearophile wrote:

Namespace:

A friend of mine ask me why D's foreach isn't like C#


In D you often omit the type:

foreach (val; arr) {

Using "in" is better for the human programmers.


Certainly not. (except if 'human' means 'python' or 'C#'.)
It is just as good as ';'.


But D is largely
designed to make D compilers too happy. I think Walter said that the
semicolon was preferred because it simplifies the compiler/compilation a
little.


It does not. Parsing the statements just about the same. In fact, only
2 lines in the DMD parser implementation need to be changed (slightly!)
to implement the 'in' syntax instead.


Re: foreach syntax

2012-06-29 Thread Timon Gehr

On 06/29/2012 04:16 PM, bearophile wrote:

Timon Gehr:


Just because. This does not matter.


Now and then I write foreach(x;y;data)


error: found ';' when expecting ')'


or foreach(x,y,data) or


error: found ')' when expecting ';'


foreach(x;y,data).


error: undefined identifier y


"in" avoids some of those little mistakes.



foreach(x in y,data)


Re: foreach syntax

2012-06-29 Thread Timon Gehr

On 06/29/2012 04:23 PM, Timon Gehr wrote:

...

foreach(x;y,data).


error: undefined identifier y



BTW, it would certainly be better if this didn't actually pass the parser.


Re: foreach syntax

2012-06-29 Thread Timon Gehr

On 06/29/2012 04:34 PM, bearophile wrote:

Timon Gehr:


foreach(x in y,data)


There is no way to avoid all possible mistakes, but it's easier to
mistake a ";" for a ",", than mistake a "in" for a ",".



I don't think optimizing the grammar for error cases that are not even
compilable code is worthwhile at all.


"in" is used for this purpose in Python, C#, and probably other
languages because it's more readable


Probably it is used in those languages because it resembles
mathematical notation, or let var in exp. I doubt there is anything
deep behind it.


than an arbitrary symbol like ";".



Probably, but when I read code, I don't read the ';', it is just a
separator and helps orientation. Making separators 'readable' is imho a
non-goal. But YMMV. Patching the parser so that it accepts both forms
takes 20 seconds.


Re: foreach syntax

2012-06-29 Thread Timon Gehr

On 06/29/2012 06:09 PM, Namespace wrote:

It wasn't my intention to start a syntax war. :D
But i must agree, that "in" is a lot more readable as ";". Event ":" ist
more readable as ";". But i just would know the real reason to this
decision. Tanks to all. :)
But why correct a few guys here my code?


It was more of a suggestion than a correction.


foreach (int val; is the same as foreach(val; except that i like to
write which type "val" is. Is that against the D nature or what?



It is redundant.


P.S.: Which line must be changed to allow the "in2 syntax?
Just out of pure interest. Thanks.


Search for TOKforeach in parse.c and change the TOKsemicolon's around 
there to TOKin's. If you want to allow both, that should be

straightforward as well.


Re: foreach syntax

2012-06-29 Thread Timon Gehr

On 06/29/2012 06:27 PM, Namespace wrote:

You mean just change line 3817 to
if (t->value == TOKcomma || t->value == TOKsemicolon || t->value ==
TOKin) ?
But know i have to rebuild dmd (i use windows), and i never did this
before. :/


You'll also have to change the line that says expect(TOKsemicolon);


Re: foreach syntax

2012-06-29 Thread Timon Gehr

On 06/29/2012 07:47 PM, Namespace wrote:

On Friday, 29 June 2012 at 17:08:36 UTC, Namespace wrote:

Which is easy.


Even on Windows? :O


I tried with win32.mak in src/dmd and i get a dmd.exe. But the compiler
still says
"found 'in' when expecting ';'!" if i try to write foreach (val in vals) {.
Have i edit the wrong line in paste.c or fails my build?


You have to edit both relevant lines.


Re: foreach syntax

2012-06-29 Thread Timon Gehr

On 06/29/2012 07:50 PM, Namespace wrote:

You'll also have to change the line that says expect(TOKsemicolon);


In what? comment out?


Looking at some other parts of the parse.c source reveals that

if(token.value == TOKin) nextToken(); else expect(TOKsemicolon);

might get you going.


Re: How would I sort an associative array by value?

2012-06-29 Thread Timon Gehr

On 06/29/2012 07:52 PM, ixid wrote:

Or more generally does D have a library function so I can sort one array
based on sorting the contents of another?


sort!"a[0]

Re: foreach syntax

2012-06-29 Thread Timon Gehr

On 06/29/2012 08:04 PM, Namespace wrote:

On Friday, 29 June 2012 at 17:55:57 UTC, Timon Gehr wrote:

On 06/29/2012 07:50 PM, Namespace wrote:

You'll also have to change the line that says expect(TOKsemicolon);


In what? comment out?


Looking at some other parts of the parse.c source reveals that

if(token.value == TOKin) nextToken(); else expect(TOKsemicolon);

might get you going.


I think i'm to stupid for that, sry.


My bad:

Replacing the line with the following, together with the other change 
you made, works:


if(token.value == TOKin) nextToken(); else check(TOKsemicolon);


Re: foreach syntax

2012-06-29 Thread Timon Gehr

On 06/29/2012 08:18 PM, Namespace wrote:

My bad:

Replacing the line with the following, together with the other change
you made, works:

if(token.value == TOKin) nextToken(); else check(TOKsemicolon);


Impressive, thanks a lot, sometimes I'm a bit stupid. :)

Last question: It works fine, but i'm getting now "DMD v2.059 DEBUG" if
i compile. Do I need a special flag by recompiling?


I don't have a windows system handy, but you could try the following:

make -fwin32.mak release


Re: foreach syntax

2012-06-29 Thread Timon Gehr

On 06/29/2012 09:51 PM, Namespace wrote:

But there is no overhead or something else _if_ i put the type, or?


There is a slight typing and compilation overhead. Nothing significant.


Re: foreach syntax

2012-06-29 Thread Timon Gehr

On 06/29/2012 10:02 PM, Roman D. Boiko wrote:

On Friday, 29 June 2012 at 19:52:33 UTC, Timon Gehr wrote:

On 06/29/2012 09:51 PM, Namespace wrote:

But there is no overhead or something else _if_ i put the type, or?


There is a slight typing and compilation overhead. Nothing significant.


You missed a slight reading overhead.


Good catch.


Re: Debugging compiler crashes?

2012-07-02 Thread Timon Gehr

On 07/02/2012 08:38 PM, Wouter Verhelst wrote:


Hi,

I have a body of code which makes the compiler frontend segfault.

Is there some automated tool which will help me produce a minimal
testcase so I can file a bugreport? The body in question is fairly
large, just posting that to a bugreport doesn't sound like a good idea
to me.

Thanks,



https://github.com/CyberShadow/DustMite


Re: Parser generator?

2012-07-04 Thread Timon Gehr

On 07/04/2012 11:41 PM, Jonathan M Davis wrote:

On Wednesday, July 04, 2012 15:32:16 Wouter Verhelst wrote:

Jonathan M Davis  writes:

On Wednesday, July 04, 2012 14:53:02 Wouter Verhelst wrote:

Hi folks,

Does someone know of a parser generator for D?

If it doesn't exist, I can write a parser by hand, but having it
generated (at least for my initial permutation) seems like a better
idea...

Thanks,


https://github.com/PhilippeSigaud/Pegged
https://github.com/PhilippeSigaud/Pegged/wiki


Whoa. That's so perfect, it makes me drool.


Yeah. It's pretty cool. It really shows up D's metaprogramming capabilities.
The one thing to watch out for though is that such metaprogramming tends to
eat up a lot of memory when compiling at this point (primarily because the
compiler doesn't manage memory very well at this point - it's approach is very
simplistic). So, that may or may not cause you problems. It should be fixed
eventually, but it does sometimes cause problems with this sort of thing.
std.regex has similar issues.

- Jonathan M Davis


https://github.com/PhilippeSigaud/Pegged/wiki/Grammars-as-D-Modules


Re: why is string not implicit convertable to const(char*) ?

2012-07-05 Thread Timon Gehr

On 07/05/2012 09:32 PM, dcoder wrote:


Thanks for the thorough explanation, but it begs the question why not
make strings be array of chars that have \0 at the end of it?


Because that is inefficient. It disables string slicing and is 
completely redundant.


BTW: String literals are guaranteed to be zero-terminated.


Since, lots of D programmers were/are probably C/C++ programmers, why should D
be different here?


Because it is a superior model.


Wouldn't it facilitate more C/C++ programmers to come to D?



Why would that matter?


Re: why is string not implicit convertable to const(char*) ?

2012-07-05 Thread Timon Gehr

On 07/06/2012 02:57 AM, Wouter Verhelst wrote:

Jonathan M Davis  writes:


On Thursday, July 05, 2012 21:32:11 dcoder wrote:

Thanks for the thorough explanation, but it begs the question why
not make strings be array of chars that have \0 at the end of it?
   Since, lots of D programmers were/are probably C/C++
programmers, why should D be different here?  Wouldn't it
facilitate more C/C++ programmers to come to D?

Just curious.


Are you serious? I'm shocked to hear anyone suggest that. Zero-terminated
strings are one of the largest mistakes in programming history. They're
insanely inefficient. In fact, IIRC Walter Bright has stated that he thinks that
having arrays without a length property was C's greatest mistake (and if
they'd had that, they wouldn't have created zero-terminated strings).

C++ tried to fix it with std::string, but C compatability bites you everywhere
with that, so it only halfway works. C++ programmers in general would probably
have thought that the designers of D were idiots if they had gone with zero-
terminated strings.

You don't do what another language did just to match. You do it because what
they did works and you have no reason to change it. Zero-terminated strings
were a horrible idea, and we're not about to copy it.


To be fair, there are a _few_ areas in which zero-terminated strings may
possibly outperform zero-terminated strings (appending data in the case
where you know the memory block is large enough, for instance).


It is impossible to know that the memory block is large enough unless
the length of the string is known. But it isn't.



But they're far and few between, and it would indeed be silly to switch to
zero-terminated strings.



There is no string manipulation that is significantly faster with
zero-terminated strings.


Re: why is string not implicit convertable to const(char*) ?

2012-07-05 Thread Timon Gehr

On 07/06/2012 03:40 AM, Wouter Verhelst wrote:

Timon Gehr  writes:


On 07/06/2012 02:57 AM, Wouter Verhelst wrote:

To be fair, there are a _few_ areas in which zero-terminated strings may
possibly outperform zero-terminated strings (appending data in the case
where you know the memory block is large enough, for instance).


It is impossible to know that the memory block is large enough unless
the length of the string is known. But it isn't.


Sure it is, but not by looking at the string itself.

Say you have a string that contains some data you need, and some other
data you don't. I.e., you want to throw out parts of the string.

You could allocate a memory block that's as large as the original string
(so you're sure you've got enough space), and then start memcpy'ing
stuff into the new memory block from the old string.



This incurs the cost of determining the original string's length, which 
is higher than computing the new string length for the data&length

representation.


This way you're sure you won't overrun your zero-terminated string, and
you'll be a slight bit faster than you would be with a bounded string.



Are you talking about differences of a few operations that are
completely hidden on a modern out-of-order CPU? I don't think the
zero-terminated string method will even perform less operations.


I'll readily admit I haven't don't this all that often, though :-)


But they're far and few between, and it would indeed be silly to switch to
zero-terminated strings.


There is no string manipulation that is significantly faster with
zero-terminated strings.


Correct -- but only because you said "significantly".



I meant to say, 'measurably'.


Re: Garbage Collection Pitfall in C++ but not in D?

2012-07-06 Thread Timon Gehr

On 07/06/2012 05:39 PM, Alex Rønne Petersen wrote:

On 06-07-2012 16:07, Denis Shelomovskij wrote:

06.07.2012 17:43, akaz пишет:

Hi,

Reading about the C++11, I stumbled upon this:

http://www2.research.att.com/~bs/C++0xFAQ.html#gc-abi

Specifically (quote):

int* p = new int;
p+=10;
// ... collector may run here ...
p-=10;
*p = 10; // can we be sure that the int is still there?

How does the D garbage collector solves (answers) that?

Thank you.


If you are interested in D read this first:
http://dlang.org/garbage.html

You can find there e.g.:
> Do not add or subtract an offset to a pointer such that the result
points outside of the bounds of the garbage collected object originally
allocated.

So `p+=10;` is already "undefined behavior".



I'll just add: Handling this case is basically impossible to do sanely.
You can't really know what some pointer off the bounds of a managed
memory region is based on. It could literally be based on any memory
region in the entire program. You could do heuristics of course, but . . .



You could run the program in a dedicated VM. :)


Re: multiple inheritance

2012-07-08 Thread Timon Gehr

On 07/08/2012 07:31 PM, Namespace wrote:

How can i implement C++ behaviour like this:

class Shape : Drawable, Transformable {
class Sprite : Drawable {
class Image : Transformable {
?

One way is to declare Transformable or Drawable as interface.
But what if i have more then one class which implements
Transformable/Drawable and i wouldn't rewrite the implementation of
Transformable/Drawable in every class again?


Depending on what exactly your use case is, this might get you going:

class Shape : Drawable {
protected class MyTransformable : Transformable{
// ...
// (can reference all fields of the enclosing class object)
}

Transformable transformable;
alias transformable this;

this() { transformable = new MyTransformable(); }
// ...
}


Re: multiple inheritance

2012-07-08 Thread Timon Gehr

On 07/08/2012 07:47 PM, Namespace wrote:

Smart idea.
Why the inner class and not direct Transformable _t; ?



If it should be true multiple inheritance, the class must be able to
override the virtual methods of each superclass and each overridden
method must be given access to the fields of the class.


Re: Portable way to obtain member function pointer (and invoke it)?

2012-07-08 Thread Timon Gehr

On 07/08/2012 09:57 PM, Alex Rønne Petersen wrote:

Hi,

Is there a portable way to obtain a pointer to a member function and
invoke it with the this reference? I seem to recall some discussion
about this on the NG in the past, but can't find the thread now.



auto mptr = function(Base o,Args args)=>o.member(args);
mptr(this, args);


Re: Return type inference on template

2012-07-10 Thread Timon Gehr

On 07/10/2012 04:14 PM, Andrea Fontana wrote:

Simple template:

T test(T)() { return T.init; }

This code give error:

int myVar;
myVar = test();

Why? Can't compiler guess T == int?



Type deduction only proceeds in the direction the data flows.

Reversing this process would in principle work in a few cases, such as
the one you present here.

I think it would be neat to have more powerful IFTI. An even more
important improvement would be to allow parameters to cross-talk, eg:

auto map(R,S,T...)(R range, S delegate(ElementType!R) dg) { ... }

[1,2,3].map(x=>2*x); // currently an error, but could be made to work

Note that full type inference cannot be achieved in D, because the type
system is Turing complete.


Re: Compilation failure

2012-07-10 Thread Timon Gehr

On 07/08/2012 11:47 PM, Lemonfiend wrote:

Hi,

I seem to have run into a strange error..
When I put tmp1 outside the main loop, it compiles fine and gives the
expected output.
When tmp1 is put inside the main loop, the compiler seems to get stuck
in a loop?

I've tested it on: http://dlang.org/index.html

See error on bottom (lol)


#!/usr/bin/rdmd

import std.stdio;

//immutable int[] tmp1 = [1, 2]; // compiles

void main()
{
immutable int[] tmp1 = [1, 2]; // does not compile

int[tmp1.length] tmp2 = tmp1;

tmp2[] += 1;

writeln(tmp1);
writeln(tmp2);
}





I'd argue that this is a bug. The length of an immutable variable with
a constant initializer should be a constant expression.

Presumably this is caused by the compiler rewriting the array literal
into an allocation.


Re: readonly?

2012-07-10 Thread Timon Gehr

On 07/11/2012 12:58 AM, Ali Çehreli wrote:

On 07/10/2012 03:53 PM, Namespace wrote:

const(T)* ?


Example?


class Bar
{}

class Foo
{
 const(Bar) * _b;

 void SetBar(const(Bar) * b) {
 _b = b;
 }
}

void main()
{
 auto b = new Bar();
 auto f = new Foo();
 f.SetBar(&b);
}

Ali


This escapes a stack reference.


Re: Compilation failure

2012-07-10 Thread Timon Gehr

On 07/11/2012 04:25 AM, ixid wrote:

in some way it sees global immutables almost as enums


This seems like a bad idea. Consistency of behaviour would seem to be a
good principle to expect of a language.


You are right; this is a bug.


Re: (a,b,c) syntax

2012-07-11 Thread Timon Gehr

On 07/11/2012 02:44 PM, Andrea Fontana wrote:

Why this code print "five" ?

writeln(("One", 10, "Five"));

What does ( ... , ... , ...) means?



, is the comma operator inherited from C.

a,b means: execute a first, then b, and the result is b.


Re: caller trouble

2012-07-14 Thread Timon Gehr

On 07/14/2012 08:53 AM, captaindet wrote:

i need a discreet handle on the calling/instantiating source file
(module). using __FILE__, it is surprisingly easy for functions (via
argument) and templated functions (via template parameter) but i cannot
get it working for templated classes. how can i make them aware of the
calling module?

thx, det


module other;

string fun(string infile = __FILE__){ return infile; }
string tfun(string infile = __FILE__)(){ return infile; }
class tclass(string infile = __FILE__){ string from = infile; }

//...//

module main;
import other;

void main(){
 auto _fun = fun();//_fun == "main.d"
 auto _tfun = tfun();//_tfun == "main.d"
 auto _tclass = new tclass!();//_tclass.from == "other.d" !!!

 //this works but i do not want to provide __FILE__ explicitly:
 auto _tclassx = new tclass!(__FILE__)();//_tclass.from == "main.d"
 //and why do i get 2 different results for the last 2 cases?
}


This is a bug.

dlang.org agrees: http://dlang.org/template.html#TemplateValueParameter


Re: ufcs and integer params

2012-07-15 Thread Timon Gehr

On 07/15/2012 05:40 AM, Jonathan M Davis wrote:

On Sunday, July 15, 2012 05:30:55 Jay Norwood wrote:

I see from this other discussions that it looks like 2.059 ( or
maybe 2.060) does support something like 3.cm().   Not sure from
the discussion if it would also accept 3.cm as in the xtext/xtend
example.

http://forum.dlang.org/thread/smoniukqfxerutqrj...@forum.dlang.org


UFCS (universal function call syntax) was added in 2.059. If cm is a function,
then 3.cm() will work. If it's a property function, then 3.cm will work. If
you don't compile with -property, then 3.cm will still work with cm being a
non-property function, but -property will become the normal behavior
eventually,  so you shouldn't expect that 3.cm will work long term unless cm is
a property function.



I expect it to stay.

Another reason why @property-'enforcement' is flawed:

@property auto cm(int arg){ .. }

cm=2;   // ok
2.cm;   // ok

The two code snippets would in fact be equivalent.
What is enforced here? Why would it matter if anything is 'enforced'?


Re: ufcs and integer params

2012-07-15 Thread Timon Gehr

On 07/15/2012 09:41 PM, Jonathan M Davis wrote:

On Sunday, July 15, 2012 11:56:57 Jonathan M Davis wrote:

What is enforced here? Why would it matter if anything is 'enforced'?


If you marked it as a property, then it's supposed to be abstracting a
variable and should be treated as one, just like if it's a normal function,
it should be invoked as a function, just like ++ shouldn't suddenly do --,
and / shouldn't *.


And on a purely objective note, if you don't have property enforcement, you
can't turn a property function into a variable, because even though it's
supposed to be used as one, you can't guarantee that everyone's using it that
way,  and if they're using it as a function, changing the property into a
variable will break their code.  And part of the point of properties is to be
able to switch between variables and property functions depending on whether
additional protections or calculations or whatnot are required for that
variable/property. Property enforcement is required in order to allow that.

- Jonathan M Davis


No it is not, assuming that property enforcement is supposed to mean
that function 'foo' cannot be called like 'foo' if it is not annotated
@property.

There is no objective argument for banning this, except that the syntax
would be made free for alternative use.

@property means: always implicitly call if it can be called without
arguments. If it cannot, disallow calls that are not of the form fun = 
argument; (After the op= operators have been properly rewritten.)


And that is completely sufficient for transparently switching between
variable/property. Stuff that is *not* annotated @property has no
relevance.


Re: ufcs and integer params

2012-07-15 Thread Timon Gehr

On 07/15/2012 08:56 PM, Jonathan M Davis wrote:

On Sunday, July 15, 2012 19:50:18 Timon Gehr wrote:

On 07/15/2012 05:40 AM, Jonathan M Davis wrote:

On Sunday, July 15, 2012 05:30:55 Jay Norwood wrote:

I see from this other discussions that it looks like 2.059 ( or
maybe 2.060) does support something like 3.cm().   Not sure from
the discussion if it would also accept 3.cm as in the xtext/xtend
example.

http://forum.dlang.org/thread/smoniukqfxerutqrj...@forum.dlang.org


UFCS (universal function call syntax) was added in 2.059. If cm is a
function, then 3.cm() will work. If it's a property function, then 3.cm
will work. If you don't compile with -property, then 3.cm will still work
with cm being a non-property function, but -property will become the
normal behavior eventually,  so you shouldn't expect that 3.cm will work
long term unless cm is a property function.


I expect it to stay.

Another reason why @property-'enforcement' is flawed:

@property auto cm(int arg){ .. }

cm=2;   // ok
2.cm;   // ok

The two code snippets would in fact be equivalent.


@property isn't perfect, and I admit that the fact that both cm = 2 and 2.cm
works here is undesirable, given what's trying to be done here, but it makes
sense given that it's abstracting a variable. It's just undesirable that you
can't make it so that it functions only as a getter.


cm=2 is in fact a getter call. I don't mind this, because I don't need 
to write that code if I don't want to. The 'puritanical' view is simply

incompatible with how the whole thing is laid out.


But the overall situation
is still a whale of a lot better than the laxity of letting just any function
be called with or without parens depending no what each particular programmer
feels like doing with it. If it's a property, it should be treated as such,
and if it isn't, it shouldn't.


What is enforced here? Why would it matter if anything is 'enforced'?


If you marked it as a property, then it's supposed to be abstracting a
variable and should be treated as one, just like if it's a normal function, it
should be invoked as a function,


This seems to be tautological. But what this statement presumably
really meant to say was 'it should be invoked as a function using the
notation present in eg. C or Java'.


just like ++ shouldn't suddenly do --, and / shouldn't *.



That depends entirely on the domain of these functions.


I don't want to get into this argument again.


Yah, we have gone through this before.


The current plan is (and has been for some time)
that -property will become the normal behavior,


It is obvious that -property is broken and will not become the normal 
behaviour.


Re: ufcs and integer params

2012-07-15 Thread Timon Gehr

On 07/15/2012 11:11 PM, Jonathan M Davis wrote:


There are two levels to enforcement. Neither exist without -property. The
absolutely minimal level is that anything marked with @property must be used
as a property.  Without this, you can't swap out a property function for a
variable without breaking code.



If it means what I think it means then that should be done and this is
where -property fails.


The second level - i.e. strict property enforcement - also requires that non-
property functions be called as functions.



Exactly. This part is useless.

(The 'Without this, you can't...' part is notably missing.)






Re: ufcs and integer params

2012-07-15 Thread Timon Gehr

On 07/15/2012 11:43 PM, Jonathan M Davis wrote:

On Sunday, July 15, 2012 23:35:12 Timon Gehr wrote:

The second level - i.e. strict property enforcement - also requires that
non- property functions be called as functions.


Exactly. This part is useless.


And there, we will forever disagree.



If it is a matter of personal preference, then it shouldn't be in the 
compiler.


Re: ufcs and integer params

2012-07-15 Thread Timon Gehr

On 07/15/2012 11:35 PM, Jonathan M Davis wrote:

On Sunday, July 15, 2012 23:29:04 Timon Gehr wrote:

The current plan is (and has been for some time)
that -property will become the normal behavior,


It is obvious that -property is broken and will not become the normal
behaviour.


It is obvious that -property needs to be fixed before it becomes the normal
behavior. It is _not_ obvious that it will not become the normal behavior. The
-property flag was created explicitly so that its implementation could be fixed
_before_ making it the normal behavior and so that programmers had time to fix
their code before it become enforced.

- Jonathan M Davis


I'd say the -property switch is there to make the fruitless
bikeshedding discussions about @property disappear. Nothing else makes
sense. Its inclusion obviously has been rushed (the error message does 
not even follow English grammar) and it _only_ implements the one

restriction that does not objectively matter.


Re: ufcs and integer params

2012-07-15 Thread Timon Gehr

On 07/15/2012 11:56 PM, Jonathan M Davis wrote:

On Sunday, July 15, 2012 23:47:58 Timon Gehr wrote:

On 07/15/2012 11:43 PM, Jonathan M Davis wrote:

On Sunday, July 15, 2012 23:35:12 Timon Gehr wrote:

The second level - i.e. strict property enforcement - also requires that
non- property functions be called as functions.


Exactly. This part is useless.


And there, we will forever disagree.


If it is a matter of personal preference, then it shouldn't be in the
compiler.


It's a matter of enforcing the correct syntax,


This post seems to attempt to distract from the fact that the topic of 
the discussion is which syntax is correct.



which the compiler does all the
time. It's just that you don't think that the compiler should care in this
particular case, since it hasn't cared in the past.



The compiler does not and has never 'not cared'. It has to do slightly 
more work. This is a designed language feature, although it's a trivial

one. eg. Eiffel and Scala have the same thing.

The prime reason why I think it is beneficial if no more restrictions
than necessary are applied is UFCS:

array(map!(x=>2*x)(range));   // should be fine

range.map!(x=>2*x).array; // so should this

range.map!(x=>2*x)().array(); // who needs this?



Re: Can't create immutable type in template

2012-07-16 Thread Timon Gehr

On 07/16/2012 01:38 AM, Nick Gurrola wrote:

import std.stdio;

void main()
{
writeln(typeid(Test!int));
}

template Test(T...)
{
alias immutable(T[0]) Test;
}


This prints "int" instead of "immutable(int)" like I would expect. Is
this a bug, or is that what is supposed to happen?


This is a known issue.
http://d.puremagic.com/issues/show_bug.cgi?id=6966
The bug report also contains a simple workaround.


Re: ufcs and integer params

2012-07-16 Thread Timon Gehr

On 07/16/2012 10:55 AM, Chris NS wrote:

Having been around long enough to remember when the ability to call
"foo()" as "foo" first appeared, I feel it necessary to point out that
this was *not* in fact a deliberate design, but rather a sort of
"accident" that arose out of D's first attempt at properties.


Afaik this first attempt was implemented roughly as designed. It is my
understanding that @property was added later in order to fix the
introduced ambiguities.


It was the same "accident" loaded compiler release that gave us pseudo-members 
--
the precursors to UFCS.



I still wonder how that could possibly happen.


The community discovered that these things were accepted by the compiler
-- which was actually against the language spec at the time -- and
further that the resulting code did the intuitively correct thing.
Response to the "accidents" being generally positive, it was decided to
work toward making them legitimate language features. Some flavor of
@property (or of a certain other proposal which was a mimicry of C#
properties... I was in that camp)


That would certainly be more pretty -- OTOH it is hard to think of a
way to extend this to UFCS that is as natural as what happens if
everything is conflated in functions.


has been in the plan ever since.

I find the ongoing debate/discussion of @property and -property to be...
well, moot. But hey, I'm just one crazy among an army of crazies.



Well, this newsgroup has the property that the stuff that is actually
important is usually unilaterally agreed upon rather quickly. :o)


Re: Is this actually supposed to be legal?

2012-07-17 Thread Timon Gehr

On 07/17/2012 07:23 PM, Jonathan M Davis wrote:

On Tuesday, July 17, 2012 14:48:32 David Nadlinger wrote:

On Tuesday, 17 July 2012 at 05:24:26 UTC, Jonathan M Davis wrote:

This code strikes me as being a bug:


class MyBase(T)
{}

class MySubA : MyBase!MySubA
{}

class MySubB : MyBase!MySubB
{}

void main()
{}



This pattern is actually quite common in C++ code, and referred
to as CRTP (curiously recurring template pattern). If you propose
to kill it, Andrei is going to get mad at you. ;)


Well, it certainly seems insane to me at first glance - particularly when you
take compile time reflection into account, since the derived classes'
definitions are now effectively recursive (so I suspect that the situation is
worse in D, since C++ doesn't have conditional compliation like D does).


The fact that it is allowed does not make the compiler's job
significantly more complicated. It is not important if the type is
passed as a template argument or referred to directly from inside the
template -- the issues are the same.


Re: Is this actually supposed to be legal?

2012-07-17 Thread Timon Gehr

On 07/17/2012 10:50 PM, Jonathan M Davis wrote:

On Tuesday, July 17, 2012 22:36:10 Timon Gehr wrote:

On 07/17/2012 07:23 PM, Jonathan M Davis wrote:

On Tuesday, July 17, 2012 14:48:32 David Nadlinger wrote:

On Tuesday, 17 July 2012 at 05:24:26 UTC, Jonathan M Davis wrote:

This code strikes me as being a bug:


class MyBase(T)
{}

class MySubA : MyBase!MySubA
{}

class MySubB : MyBase!MySubB
{}

void main()
{}



This pattern is actually quite common in C++ code, and referred
to as CRTP (curiously recurring template pattern). If you propose
to kill it, Andrei is going to get mad at you. ;)


Well, it certainly seems insane to me at first glance - particularly when
you take compile time reflection into account, since the derived classes'
definitions are now effectively recursive (so I suspect that the
situation is worse in D, since C++ doesn't have conditional compliation
like D does).

The fact that it is allowed does not make the compiler's job
significantly more complicated. It is not important if the type is
passed as a template argument or referred to directly from inside the
template -- the issues are the same.


The problem is that if you have static ifs and the like in the base class
which depends on compile time reflection of the derived class, you effectively
have a recursive template definition. e.g.

class MyBase(T)
{
  static if(is(typeof(T.func(
  {
  int func() { return 42; }
  }
}

- Jonathan M Davis


This issue is unrelated to CRTP. (also, you probably want to negate
that static if condition, otherwise the code is valid and poses no
challenge to a compiler.)

class MyBase{
  static if(!is(typeof(T.func(
int func() { return 42; }
}

class T : MyBase { }




Re: Is this actually supposed to be legal?

2012-07-18 Thread Timon Gehr

On 07/18/2012 11:08 PM, monarch_dodra wrote:

On Tuesday, 17 July 2012 at 23:38:04 UTC, Jonathan M Davis wrote:

It's not that it makes the compiler's life hard. It's the fact that
conditional compilation relies on state that doesn't exist yet. It's
messed up
to be checking whether an object defines something when you're in the
middle of
defining that object.

[snip]

- Jonathan M Davis


Well, while you "can" do it in C++ as the "Curiously Recursive Template
Pattern" (particularly popular way of implementing the singleton pattern
BTW), you can't just do anything you feel like doing with it.

If I remember correctly, in C++, you can't access any of T's members, or
create any (stack) instances of T, or (I think) call T's any of T's
static members, because "T is not correctly formed yet".

Did you try anything more advanced? For example, this outright _crashes_
my (r)dmd:


class MyBase(T)
{
int a = T.hello();
}

class MySubA : MyBase!MySubA
{
static int hello(){return 0;}
}



Well, that is a bug.


I'm not entirely sure how valid the comparison with C++'s CRTP is,
because D's classes are actually pointer to implementation,  but I think
it is a safe bet that what C++ can't do, neither can D.


Careful there. D allows forward references. This is all supposed to work 
in D. (but DMD is poor when it comes to tricky symbol lookup tasks.)


Re: Is this actually supposed to be legal?

2012-07-18 Thread Timon Gehr

On 07/18/2012 01:37 AM, Jonathan M Davis wrote:

On Tuesday, July 17, 2012 23:11:43 Timon Gehr wrote:

This issue is unrelated to CRTP. (also, you probably want to negate
that static if condition, otherwise the code is valid and poses no
challenge to a compiler.)


It's not that it makes the compiler's life hard. It's the fact that
conditional compilation relies on state that doesn't exist yet. It's messed up
to be checking whether an object defines something when you're in the middle of
defining that object.
...


Declarations in D are declarative. There is no notion of state.



Re: Compilation failure

2012-07-18 Thread Timon Gehr

On 07/19/2012 12:42 AM, bearophile wrote:

Timon Gehr:


You are right; this is a bug.


This discussion is not about an obscure language detail, it's a common
situation.


FWIW, I have never run across it before.


So if you think this is a bug, then please Timon file it in
Bugzilla.



Usually bugs are reported by the guy who finds them, but here you go:
http://d.puremagic.com/issues/show_bug.cgi?id=8400


Re: ~= call copy ctor?

2012-07-19 Thread Timon Gehr

Use std.algorithm.move if you want to avoid the copy ctor call.


Re: Compilation failure

2012-07-20 Thread Timon Gehr

On 07/20/2012 01:53 PM, bearophile wrote:

Timon Gehr:


Usually bugs are reported by the guy who finds them, but here you go:
http://d.puremagic.com/issues/show_bug.cgi?id=8400


Thank you, already fixed, it seems. Even if the fix is the opposite of
what I have thought (I was thinking about forbidding global immutables
too to be used as compile-time constants, while this fix turns local
immutables too into enums. I hope this change doesn't cause a large mess).



They are not enums. They are interpretable at compile time if their
initializer is interpretable at compile time. This makes sense. This is
a bug fix. Similar code already works.


Re: Is "delete" really going away?

2012-07-29 Thread Timon Gehr

On 07/29/2012 03:03 PM, Minas Mina wrote:


Having a destructor and that you know when is going to be called is VERY
useful!
So by removing the "delete" keyword, what happens? We won't have a way
to destroy objects in a predictable way anymore? (I'm not talking about
structs in any way).

Thanks


import std.stdio;
void main(){
auto c = new class{ ~this(){writeln("destroyed!");} };
version(future) destroy(c);
else clear(c);
}

clear is being renamed to destroy starting from the next release IIRC.


Re: template with more than one tuple parameter

2012-07-29 Thread Timon Gehr

On 07/28/2012 06:17 PM, Zhenya wrote:

Why do not D allow templates with more than one tuple
parameters,at the same time that C++11 support it:



This is a gratuitous restriction. They will be supported at some point.


Re: template with more than one tuple parameter

2012-07-29 Thread Timon Gehr

On 07/28/2012 06:47 PM, Simen Kjaeraas wrote:

On Sat, 28 Jul 2012 18:17:14 +0200, Zhenya  wrote:


Why do not D allow templates with more than one tuple
parameters,at the
same time that C++11 support it:


Well, Walter implemented type tuples with automatic flattening,


The lack of multiple tuple parameters is not caused by automatic
flattening.

However, if they are introduced, the respective templates may only
ever be instantiated by IFTI.

To fix this, there would maybe need to be a special syntax to separate
the tuple parameters in an explicit instantiation, eg.

template Seq(T...){ alias T Seq; }

template Test(T..., S...){ alias T A; alias S B; }

with(Test!(int,double,float)){
static assert(is(A==Seq!(int,double,float)));
static assert(is(B==Seq!()));
}

with(Test!(int,double,,float)){
static assert(is(A==Seq!(int,double)));
static assert(is(B==Seq!(float)));
}

with(Test!(,int,double,float)){
static assert(is(A==Seq!()));
static assert(is(B==Seq!(int,double,float)));
}

Of course, that feels a little bolt-on. The alternative would be to
accept that templates with multiple tuple parameters cannot be
instantiated explicitly.


( If we want arbitrary tuple nesting, the notation could be
generalized, eg like this:

Seq!(Seq!(int,double)); // flattened 2-element tuple
Seq!(int,double,,); // 1-element tuple of 2-element tuple
Seq!(int,double,,,); // 1-element tuple of 1-element tuple of 2-element 
tuple

Seq!(int,double,,int,double); // 2-element tuple of 2-element tuples
 )


Re: A few questions

2012-07-29 Thread Timon Gehr

On 07/27/2012 04:35 PM, bearophile wrote:


But implementing good non-null types in library code is hard


It is closer to impossible than to hard.


(rather harder than implementing vector ops in library code on library defined
vectors). I think @disable isn't enough to cover what Spec# shows good
non-null types are meant to be.



Non-null types in Spec# are unsound.


Re: A few questions

2012-07-29 Thread Timon Gehr

On 07/29/2012 06:24 PM, bearophile wrote:

Timon Gehr:


Non-null types in Spec# are unsound.


Really? I didn't know it. Surely its non-null design looks quite refined
and thought-out. But maybe as say it's not enough still. Do you have a
link where it shows it's unsound?



Google for "freedom before commitment". The example is in the paper.
Apparently the unsoundness was recently fixed though -- the faulty
assignment in question is now correctly rejected by the online Spec#
compiler.



Re: Ranges and backward iteration

2012-07-29 Thread Timon Gehr

On 07/30/2012 01:26 AM, Andrew wrote:

I have a use case where I would like to be able to pass both a
forward and backward iteration of an array to a function:

void foo(InputR, OutputR)(InputR i, OutputR j)
if (isInputRange!InputR && isOutputRange!(OutputR, InputR))
{
...
}

main()
{
//forward:
foo(a[1..n], b[1..n]);
//backward:
foo(retro(a[n..$]), retro(b[n..$]));

//do stuff with b as it has been constructed now...
}

This doesn't work


Works for me.

This is how I test:

void foo(InputR, OutputR)(InputR i, OutputR j) if (isInputRange!InputR 
&& isOutputRange!(OutputR, InputR)){

j.put(i);
}

void main() {
int[] a=[2,0,0,3], b=[1,2,3,4];
int n=2;
foo(a[0..n], b[0..n]);
assert(b==[2,0,3,4]);
foo(retro(a[n..$]), retro(b[n..$]));
assert(b==[2,0,0,3]);
}


(retro doesn't appear to return a Range, but
rather an object of type "Result", which I don't understand)


'Result' implements the range interface and is a local struct of the 
'retro' function.



, but the intent should be clear.

How do I do this? What am I missing? There doesn't seem to be a
"backward iterator" equivalent in std.range.


retro should do the job.


<    1   2   3   4   5   6   7   8   9   10   >