Re: Ranges

2011-03-12 Thread Jonas Drewsen

Hi Jonathan,

   Thank you very much your in depth answer!

   It should indeed goto a faq somewhere it think. I did now about the 
codepoint/unit stuff but had no idea that ranges of char are handled 
using dchar internally. This makes sense but is an easy pitfall for 
newcomers trying to use std.{algoritm,array,ranges} for char[].


Thanks
Jonas

On 13/03/11 01.05, Jonathan M Davis wrote:

On Saturday 12 March 2011 14:02:00 Jonas Drewsen wrote:

Hi,

 I'm working a bit with ranges atm. but there are definitely some
things that are not clear to me yet. Can anyone tell me why the char
arrays cannot be copied but the int arrays can?

import std.stdio;
import std.algorithm;

void main(string[] args) {

// This works
int[]   a1 = [1,2,3,4];
int[] a2 = [5,6,7,8];
copy(a1, a2);

// This does not!
char[] a3 = ['1','2','3','4'];
char[] a4 = ['5','6','7','8'];
copy(a3, a4);

}

Error message:

test2.d(13): Error: template std.algorithm.copy(Range1,Range2) if
(isInputRange!(Range1)&&  isOutputRange!(Range2,ElementType!(Range1)))
does not match any function template declaration

test2.d(13): Error: template std.algorithm.copy(Range1,Range2) if
(isInputRange!(Range1)&&  isOutputRange!(Range2,ElementType!(Range1)))
cannot deduce template function from argument types !()(char[],char[])


Character arrays / strings are not exactly normal. And there's a very good
reason for it: unicode.

In unicode, a character is generally a single code point (there are also
graphemes which involve combining code points to add accents and superscripts
and whatnot to create a single character, but we'll ignore that in this
discussion - it's complicated enough as it is). Depending on the encoding, that
code point may be made up of one - or more - code units. UTF-8 uses 8 bit code
units. UTF-16 uses 16 bit code units. And UTF-32 uses 32-bit code units. char is
a UTF-8 code unit. wchar is a UTF-16 code unit. dchar is a UTF-32 code unit.
UTF-32 is the _only_ one of those three which _always_ has one code unit per
code point.

With an array of integers you can index it and slice it and be sure that
everything that you're doing is valid. If you look at a single element, you know
that it's a valid int. If you slice it, you know that every int in there is
valid. If you're dealing with a dstring or dchar[], then the same still holds.

A dstring or dchar[] is an array of UTF-32 code units. Every code point is a
single code unit, so every element in the array is a valid code point. You can
take an arbitrary element in that array and know that it's a valid code point.
You can slice it wherever you want and you still have a valid dstrin
g or dchar[]. The same does _not_ hold for char[] and wchar[].

char[] and wchar[] are arrays of UTF-8 and UTF-16 code units respectively. In
both of those encodings, multiple code units are required to create a single
code point. So, for instance, a code point could have 4 code units. That means
that _4_ elements of that char[] make up a _single_ code point. You'd need _all_
4 of those elements to create a single, valid character. So, you _can't_ just
take an arbitrary element in a char[] or wchar[] and expect it to be valid. You
_can't_ just slice it anywhere. The resulting array stands a good chance of
being invalid. You have to slice on code point boundaries - otherwise you could
slice characters in hald and end up with an invalid string. So, unlike other
arrays, it just doesn't work to treat char[] and wchar[] as random access ranges
of their element type. What the programmer cares about is characters - dchars -
not chars or wchars.

So, the way this is handled is that char[], wchar[], and dchar[] are all treated
as ranges of dchar. In the case of dchar[], this is nothing special. You can
index it and slice it as normal. So, it is a random access range.. However, in
the case of char[] and wchar[], that means that when you're iterating over them
that you're not dealing with a single element of the array at a time. front
returns a dchar, and popFront() pops off however many elements made up front.
It's like with foreach. If you iterate a char[] with auto or char, then each
individual element is given

foreach(c; myStr) {}

But if you iterate over with dchar, then each code point is given as a dchar:

foreach(dchar c; myStr) {}

If you were to try and iterate over a char[] by char, then you would be looking
at code units rather than code points which is _rarely_ what you want. If you're
dealing with anything other than pure ASCII, you _will_ have bugs if you do
that. You're supposed to use dchar with foreach and character arrays. That way,
each value you process is a valid character. Ranges do the same, only you don't
give them an iteration type, so they're _always_ iterating over dchar.

So, when you're using a range of char[] or wchar[], you're really using a range
of dchar. These ranges are bi-directional. They can't be sliced, and they can't
be indexed (since doing so wou

Re: .di header imports with DLL symbols fails to link

2011-03-12 Thread Daniel Green

On 3/12/2011 11:39 PM, Bekenn wrote:

On 3/12/2011 7:02 PM, Andrej Mitrovic wrote:

My commands to compile were:
dmd -ofmydll.dll mydll.d
dmd -o- -Hdinclude mydll.d
dmd driver.d mydll.lib -I%cd%\include


Thanks.

I've tried several things, but can't get the _D5mydll12__ModuleInfoZ
symbol to show up at all. The behavior is the same with and without a
.def file (I tried a few versions). I even went back to
http://www.digitalmars.com/d/2.0/dll.html and copied everything
in the "D code calling D code in DLLs" section verbatim. After fixing a
few compilation errors (the web page's version of concat needs its
arguments qualified with "in"), I ended up with the exact same problem
you're experiencing.

I'd definitely call this a bug.


Probably unrelated, but this same issue showed up in the GDC backend. 
Apparently, the compiler tried to be smart about exporting ModuleInfo 
only for those modules that needed it.  The fix was to always export it 
regardless.


Re: .di header imports with DLL symbols fails to link

2011-03-12 Thread Bekenn

On 3/12/2011 7:02 PM, Andrej Mitrovic wrote:

My commands to compile were:
dmd -ofmydll.dll mydll.d
dmd -o- -Hdinclude mydll.d
dmd driver.d mydll.lib -I%cd%\include


Thanks.

I've tried several things, but can't get the _D5mydll12__ModuleInfoZ 
symbol to show up at all.  The behavior is the same with and without a 
.def file (I tried a few versions).  I even went back to 
http://www.digitalmars.com/d/2.0/dll.html and copied everything
in the "D code calling D code in DLLs" section verbatim.  After fixing a 
few compilation errors (the web page's version of concat needs its 
arguments qualified with "in"), I ended up with the exact same problem 
you're experiencing.


I'd definitely call this a bug.


Re: .di header imports with DLL symbols fails to link

2011-03-12 Thread Andrej Mitrovic
My commands to compile were:
dmd -ofmydll.dll mydll.d
dmd -o- -Hdinclude mydll.d
dmd driver.d mydll.lib -I%cd%\include


Re: .di header imports with DLL symbols fails to link

2011-03-12 Thread Andrej Mitrovic
Actually passing that .di file compiles it in statically, and the exe
ends up not needing the DLL.

It's a bit too late for me to thinker with the linker, I'll have a
clearer head tomorrow.


Re: .di header imports with DLL symbols fails to link

2011-03-12 Thread Daniel Green

On 3/12/2011 9:15 PM, Bekenn wrote:

On 3/12/2011 5:24 PM, Andrej Mitrovic wrote:

driver.obj(driver)
Error 42: Symbol Undefined _D5mydll12__ModuleInfoZ
--- errorlevel 1


Your dll is exporting a different symbol: _D5mydll3fooFiZi
Do you have the .def file and the command line used to build the DLL?
I believe _D5mydll12__ModuleInfoZ is supposed to be exported by the 
compiler.


It contains static constructor and unittest information used by the 
runtime to initialize it.


Re: .di header imports with DLL symbols fails to link

2011-03-12 Thread Bekenn

On 3/12/2011 5:24 PM, Andrej Mitrovic wrote:

driver.obj(driver)
  Error 42: Symbol Undefined _D5mydll12__ModuleInfoZ
--- errorlevel 1


Your dll is exporting a different symbol: _D5mydll3fooFiZi
Do you have the .def file and the command line used to build the DLL?


Re: Ranges

2011-03-12 Thread Andrej Mitrovic
What Jonathan said really needs to be put up on the D website, maybe
under the articles section. Heck, I'd just put a link to that recent
UTF thread on the website, it's really informative (the one on UTF and
meaning of glyphs, etc). And UTF will only get more important, just
like multicore.

Speaking of which, a description on ranges should be put up there as
well. There's that article Andrei once wrote, but we should put it on
the D site and discuss D's implementation of ranges in more detail.
And by 'we' I mean someone who's well versed in ranges. :p


.di header imports with DLL symbols fails to link

2011-03-12 Thread Andrej Mitrovic
On Windows, x86.

http://dl.dropbox.com/u/9218759/DLL_Imports.zip

fail_build.bat runs:
dmd driver.d mydll.lib -I%cd%\include\
but linking fails:
driver.obj(driver)
 Error 42: Symbol Undefined _D5mydll12__ModuleInfoZ
--- errorlevel 1

work_build.bat runs:
dmd driver.d mydll.lib %cd%\include\mydll.di
and this succeeds.

So passing the .di file explicitly works, but via the import switch it does not.

Here's a non-DLL example which works fine when using header files and an import 
switch:
http://dl.dropbox.com/u/9218759/importsWorkUsually.zip

So unless I'm missing something this looks like a linker bug?


Re: Ranges

2011-03-12 Thread Jonathan M Davis
On Saturday 12 March 2011 16:11:20 Bekenn wrote:
> On 3/12/2011 2:02 PM, Jonas Drewsen wrote:
> > Error message:
> > 
> > test2.d(13): Error: template std.algorithm.copy(Range1,Range2) if
> > (isInputRange!(Range1) && isOutputRange!(Range2,ElementType!(Range1)))
> > does not match any function template declaration
> > 
> > test2.d(13): Error: template std.algorithm.copy(Range1,Range2) if
> > (isInputRange!(Range1) && isOutputRange!(Range2,ElementType!(Range1)))
> > cannot deduce template function from argument types !()(char[],char[])
> 
> I haven't checked (could be completely off here), but I don't think that
> char[] counts as an input range; you would normally want to use dchar
> instead.

Char[] _does_ count as input range (of dchar). It just doesn't count as an 
_output_ range (since it doesn't really hold dchar).

- Jonathan M Davis


Re: Ranges

2011-03-12 Thread Jonathan M Davis
On Saturday 12 March 2011 16:05:37 Jonathan M Davis wrote:
> You could open an
> enhancement request for copy to treat char[] and wchar[] as arrays if
> _both_ of the arguments are of the same type.

Actually, on reflection, I'd have to say that there's not much point to that. 
If 
you really want to copy on array to another (rather than a range), just use the 
array copy syntax:

void main()
{
auto i = [1, 2, 3, 4];
auto j = [3, 4, 5, 6];
assert(i == [1, 2, 3, 4]);
assert(j == [3, 4, 5, 6]);

i[] = j[];

assert(i == [3, 4, 5, 6]);
assert(j == [3, 4, 5, 6]);
}

copy is of benefit, because it works on generic ranges, not for copying arrays 
(arrays already allow you to do that quite nicely), so if all you're looking at 
copying is arrays, then just use the array copy syntax.

- Jonathan M Davis


Re: Ranges

2011-03-12 Thread Bekenn

Or, better yet, just read Jonathan's post.


Re: Ranges

2011-03-12 Thread Bekenn

On 3/12/2011 2:02 PM, Jonas Drewsen wrote:

Error message:

test2.d(13): Error: template std.algorithm.copy(Range1,Range2) if
(isInputRange!(Range1) && isOutputRange!(Range2,ElementType!(Range1)))
does not match any function template declaration

test2.d(13): Error: template std.algorithm.copy(Range1,Range2) if
(isInputRange!(Range1) && isOutputRange!(Range2,ElementType!(Range1)))
cannot deduce template function from argument types !()(char[],char[])


I haven't checked (could be completely off here), but I don't think that 
char[] counts as an input range; you would normally want to use dchar 
instead.


Re: Points and Vectors in 3D

2011-03-12 Thread Bekenn

On 3/12/2011 2:20 PM, Simon wrote:

I've done lots of 3d over the years and used quite a lot of different
libraries and I've come to prefer code that makes a distinction between
points and vectors.


Agreed.  This has some nice benefits with operator overloading, as well:

vec v = ...;
pt p = ...;
auto p2 = p + v;// p2 is pt
auto p3 = p + p2;   // error
auto v2 = v + v;// v2 is vec

...and with properties:

p.x = 5;// p is pt, sets p._vals[0]
v.dx = 3;   // v is vec, sets v._vals[0]


Re: Ranges

2011-03-12 Thread Jonathan M Davis
On Saturday 12 March 2011 14:02:00 Jonas Drewsen wrote:
> Hi,
> 
> I'm working a bit with ranges atm. but there are definitely some
> things that are not clear to me yet. Can anyone tell me why the char
> arrays cannot be copied but the int arrays can?
> 
> import std.stdio;
> import std.algorithm;
> 
> void main(string[] args) {
> 
>// This works
>int[]  a1 = [1,2,3,4];
>int[] a2 = [5,6,7,8];
>copy(a1, a2);
> 
>// This does not!
>char[] a3 = ['1','2','3','4'];
>char[] a4 = ['5','6','7','8'];
>copy(a3, a4);
> 
> }
> 
> Error message:
> 
> test2.d(13): Error: template std.algorithm.copy(Range1,Range2) if
> (isInputRange!(Range1) && isOutputRange!(Range2,ElementType!(Range1)))
> does not match any function template declaration
> 
> test2.d(13): Error: template std.algorithm.copy(Range1,Range2) if
> (isInputRange!(Range1) && isOutputRange!(Range2,ElementType!(Range1)))
> cannot deduce template function from argument types !()(char[],char[])

Character arrays / strings are not exactly normal. And there's a very good 
reason for it: unicode.

In unicode, a character is generally a single code point (there are also 
graphemes which involve combining code points to add accents and superscripts 
and whatnot to create a single character, but we'll ignore that in this 
discussion - it's complicated enough as it is). Depending on the encoding, that 
code point may be made up of one - or more - code units. UTF-8 uses 8 bit code 
units. UTF-16 uses 16 bit code units. And UTF-32 uses 32-bit code units. char 
is 
a UTF-8 code unit. wchar is a UTF-16 code unit. dchar is a UTF-32 code unit. 
UTF-32 is the _only_ one of those three which _always_ has one code unit per 
code point.

With an array of integers you can index it and slice it and be sure that 
everything that you're doing is valid. If you look at a single element, you 
know 
that it's a valid int. If you slice it, you know that every int in there is 
valid. If you're dealing with a dstring or dchar[], then the same still holds.

A dstring or dchar[] is an array of UTF-32 code units. Every code point is a 
single code unit, so every element in the array is a valid code point. You can 
take an arbitrary element in that array and know that it's a valid code point. 
You can slice it wherever you want and you still have a valid dstrin
g or dchar[]. The same does _not_ hold for char[] and wchar[].

char[] and wchar[] are arrays of UTF-8 and UTF-16 code units respectively. In 
both of those encodings, multiple code units are required to create a single 
code point. So, for instance, a code point could have 4 code units. That means 
that _4_ elements of that char[] make up a _single_ code point. You'd need 
_all_ 
4 of those elements to create a single, valid character. So, you _can't_ just 
take an arbitrary element in a char[] or wchar[] and expect it to be valid. You 
_can't_ just slice it anywhere. The resulting array stands a good chance of 
being invalid. You have to slice on code point boundaries - otherwise you could 
slice characters in hald and end up with an invalid string. So, unlike other 
arrays, it just doesn't work to treat char[] and wchar[] as random access 
ranges 
of their element type. What the programmer cares about is characters - dchars - 
not chars or wchars.

So, the way this is handled is that char[], wchar[], and dchar[] are all 
treated 
as ranges of dchar. In the case of dchar[], this is nothing special. You can 
index it and slice it as normal. So, it is a random access range.. However, in 
the case of char[] and wchar[], that means that when you're iterating over them 
that you're not dealing with a single element of the array at a time. front 
returns a dchar, and popFront() pops off however many elements made up front. 
It's like with foreach. If you iterate a char[] with auto or char, then each 
individual element is given

foreach(c; myStr) {}

But if you iterate over with dchar, then each code point is given as a dchar:

foreach(dchar c; myStr) {}

If you were to try and iterate over a char[] by char, then you would be looking 
at code units rather than code points which is _rarely_ what you want. If 
you're 
dealing with anything other than pure ASCII, you _will_ have bugs if you do 
that. You're supposed to use dchar with foreach and character arrays. That way, 
each value you process is a valid character. Ranges do the same, only you don't 
give them an iteration type, so they're _always_ iterating over dchar.

So, when you're using a range of char[] or wchar[], you're really using a range 
of dchar. These ranges are bi-directional. They can't be sliced, and they can't 
be indexed (since doing so would likely be invalid). This generally works very 
well. It's exactly what you want in most cases. The problem is that that means 
that the range that you're iterating over is effectively of a different type 
than 
the original char[] or wchar[].

You can't just take two ranges of dchar of the same

Re: struct construct with array

2011-03-12 Thread Ali Çehreli

On 03/12/2011 02:52 PM, Ali Çehreli wrote:

On 03/12/2011 10:42 AM, Caligo wrote:

struct Test{

public double[3] ar_;
this(double[3] ar){
this.ar_ = ar;
}
}

void main(){

double[3] v1 = [1.0, 2.0, 3.0];
double[3] v2 = [2.0, 3.0, 4.0];

auto t1 = Test(v1[0..$] + v2[0..$]); // error

}


I want to add those two arrays and call the constructor in one line,
but I'm
getting an error. Any ideas?



Even a simpler code doesn't work:

double[3] v1 = [1.0, 2.0, 3.0];
double[3] v2 = [2.0, 3.0, 4.0];

auto result = v1[0..$] + v2[0..$];

Error: Array operation v1[0LU..__dollar] + v2[0LU..__dollar] not
implemented

The following doesn't work either:

auto result = v1[] + v2[];
auto result = v1 + v2;

dmd does not implement those features yet.

Ali


I see from the other posts that the problem has something to do with 
auto. This works:


double[3] v3 = v1[] + v2[];

Ali



Re: struct construct with array

2011-03-12 Thread Ali Çehreli

On 03/12/2011 10:42 AM, Caligo wrote:

struct Test{

   public double[3] ar_;
   this(double[3] ar){
 this.ar_ = ar;
   }
}

void main(){

   double[3] v1 = [1.0, 2.0, 3.0];
   double[3] v2 = [2.0, 3.0, 4.0];

   auto t1 = Test(v1[0..$] + v2[0..$]); // error

}


I want to add those two arrays and call the constructor in one line, but I'm
getting an error.  Any ideas?



Even a simpler code doesn't work:

double[3] v1 = [1.0, 2.0, 3.0];
double[3] v2 = [2.0, 3.0, 4.0];

auto result = v1[0..$] + v2[0..$];

Error: Array operation v1[0LU..__dollar] + v2[0LU..__dollar] not implemented

The following doesn't work either:

auto result = v1[] + v2[];
auto result = v1 + v2;

dmd does not implement those features yet.

Ali


Re: Points and Vectors in 3D

2011-03-12 Thread Simon

On 12/03/2011 20:51, Caligo wrote:

Given everything that D offers, what would be the best way to implement
a Point and a Vector type?  The same (x, y, z) can be used to represent
vectors, but a point represents a position, whereas a vector represents
a direction.  So, would you define two different structs for each? or
define and implement an interface?  a fixed array or POD members?


I've done lots of 3d over the years and used quite a lot of different 
libraries and I've come to prefer code that makes a distinction between 
points and vectors. Makes code easier to read and more type safe, though 
it's a bit more inconvenient when you need to mix things up.


I use:

struct pt {
  float[3] _vals;
}

struct vec {
  float[3] _vals;
}

Using the float[3] allows you to use vector ops:

pt  p0;
vec v;

p0._vals[] += v._vals[];

You don't want an interface; you don't get anything more value type than 
points & vectors. In a modern 3d models you could be dealing with a 1/2 
million vertices.


--
My enormous talent is exceeded only by my outrageous laziness.
http://www.ssTk.co.uk


Ranges

2011-03-12 Thread Jonas Drewsen

Hi,

   I'm working a bit with ranges atm. but there are definitely some 
things that are not clear to me yet. Can anyone tell me why the char 
arrays cannot be copied but the int arrays can?


import std.stdio;
import std.algorithm;

void main(string[] args) {

  // This works
  int[] a1 = [1,2,3,4];
  int[] a2 = [5,6,7,8];
  copy(a1, a2);

  // This does not!
  char[] a3 = ['1','2','3','4'];
  char[] a4 = ['5','6','7','8'];
  copy(a3, a4);

}

Error message:

test2.d(13): Error: template std.algorithm.copy(Range1,Range2) if 
(isInputRange!(Range1) && isOutputRange!(Range2,ElementType!(Range1))) 
does not match any function template declaration


test2.d(13): Error: template std.algorithm.copy(Range1,Range2) if 
(isInputRange!(Range1) && isOutputRange!(Range2,ElementType!(Range1))) 
cannot deduce template function from argument types !()(char[],char[])


Thanks,
Jonas


Points and Vectors in 3D

2011-03-12 Thread Caligo
Given everything that D offers, what would be the best way to implement a
Point and a Vector type?  The same (x, y, z) can be used to represent
vectors, but a point represents a position, whereas a vector represents a
direction.  So, would you define two different structs for each? or define
and implement an interface?  a fixed array or POD members?


Re: struct construct with array

2011-03-12 Thread Caligo
On Sat, Mar 12, 2011 at 1:02 PM, Andrej Mitrovic  wrote:

> The best thing I can think of is introducing a temp variable:
>
> void main(){
>double[3] v1 = [1.0, 2.0, 3.0];
>double[3] v2 = [2.0, 3.0, 4.0];
>
> double[3] v3 = v1[] + v2[];
>auto t1 = Test(v3);
> }
>


Thanks, but I want to do it in one line, without creating a temporary.


Re: struct construct with array

2011-03-12 Thread Andrej Mitrovic
The best thing I can think of is introducing a temp variable:

void main(){
double[3] v1 = [1.0, 2.0, 3.0];
double[3] v2 = [2.0, 3.0, 4.0];

double[3] v3 = v1[] + v2[];
auto t1 = Test(v3);
}


struct construct with array

2011-03-12 Thread Caligo
struct Test{

  public double[3] ar_;
  this(double[3] ar){
this.ar_ = ar;
  }
}

void main(){

  double[3] v1 = [1.0, 2.0, 3.0];
  double[3] v2 = [2.0, 3.0, 4.0];

  auto t1 = Test(v1[0..$] + v2[0..$]); // error

}


I want to add those two arrays and call the constructor in one line, but I'm
getting an error.  Any ideas?


Re: Fibonacci with ranges

2011-03-12 Thread Jonathan M Davis
On Saturday 12 March 2011 02:48:19 Russel Winder wrote:
> Jonathan,
> 
> On Sat, 2011-03-12 at 10:31 +, Russel Winder wrote:
> [ . . . ]
> 
> > > What's happening is that the parameter that you're passing n to for
> > > recurrence is size_t. And on 32-bit systems, size_t is uint, so
> > > passing n - which is long - to recurrence would be a narrowing
> > > conversion, which requires a cast. The correct thing to do would be
> > > make n a size_t. The other thing that you'd need to do is change
> > > declarative to return auto, since take returns a range, _not_ a long.
> 
> To analyse this a bit more I temporarily deconstructed the expression:
> 
> long declarative ( immutable long n ) {
>   auto r = recurrence ! ( "a[n-1] + a[n-2]" ) ( 0L , 1L ) ;
>   auto t = take ( r , cast ( size_t ) ( n ) ) ;
>   return t [ n ] ;
>   //return ( take ( recurrence ! ( "a[n-1] + a[n-2]" ) ( 0L , 1L )
> , cast ( size_t ) ( n ) ) ) [ n ] ; }
> 
> So with the cast it compiles fine -- though it still seems to me to be
> beyond the point of comprehension as to why an applications programmer
> has to manually cast a long to a size_t.  However the indexing of the
> range fails:

Um. Because it's a narrowing conversion on 32-bit machines. What else should it 
be doing? If it allowed the narrowing conversion without a cast, then you'd run 
into problems where you were losing precision without realizing it which would 
cause plenty of other entertaining bugs. Most newer languages require casts for 
narrowing conversions.

> fibonacci_d2.d(17): Error: no [] operator overload for type
> Take!(Recurrence!(fun,long,2u))
> 
> Which elicits the response:  for f sake, I'm just copying the
> example from the manual.
> 
> OK, so I am grumpy this morning, but that doesn't affect the fact that
> there appears to be a disconnect between documentation and what actually
> works.

take will only return a sliceable range if the range that you give it is 
sliceable. recurrence does not return a sliceable range, so take used an the 
result of recurrence doesn't return a sliceable range. The documentation for 
take is completely correct. It's just that it only has an array in its example, 
not a range which _isn't_ sliceable, so the one example that it does have 
involves a sliceable range.

- Jonathan M Davis


Re: Fibonacci with ranges

2011-03-12 Thread Russel Winder
Jonathan,

On Sat, 2011-03-12 at 10:31 +, Russel Winder wrote:
[ . . . ]
> > What's happening is that the parameter that you're passing n to for 
> > recurrence 
> > is size_t. And on 32-bit systems, size_t is uint, so passing n - which is 
> > long - 
> > to recurrence would be a narrowing conversion, which requires a cast. The 
> > correct thing to do would be make n a size_t. The other thing that you'd 
> > need to 
> > do is change declarative to return auto, since take returns a range, _not_ 
> > a 
> > long.

To analyse this a bit more I temporarily deconstructed the expression:

long declarative ( immutable long n ) {
  auto r = recurrence ! ( "a[n-1] + a[n-2]" ) ( 0L , 1L ) ;
  auto t = take ( r , cast ( size_t ) ( n ) ) ;
  return t [ n ] ;
  //return ( take ( recurrence ! ( "a[n-1] + a[n-2]" ) ( 0L , 1L ) , 
cast ( size_t ) ( n ) ) ) [ n ] ;
}

So with the cast it compiles fine -- though it still seems to me to be
beyond the point of comprehension as to why an applications programmer
has to manually cast a long to a size_t.  However the indexing of the
range fails:

fibonacci_d2.d(17): Error: no [] operator overload for type 
Take!(Recurrence!(fun,long,2u))

Which elicits the response:  for f sake, I'm just copying the
example from the manual.

OK, so I am grumpy this morning, but that doesn't affect the fact that
there appears to be a disconnect between documentation and what actually
works.
-- 
Russel.
=
Dr Russel Winder  t: +44 20 7585 2200   voip: sip:russel.win...@ekiga.net
41 Buckmaster Roadm: +44 7770 465 077   xmpp: rus...@russel.org.uk
London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder


signature.asc
Description: This is a digitally signed message part


Re: Fibonacci with ranges

2011-03-12 Thread Jonathan M Davis
On Saturday 12 March 2011 02:31:20 Russel Winder wrote:
> Jonathan,
> 
> Thanks for the info, very helpful.  One point though:
> 
> On Sat, 2011-03-12 at 01:56 -0800, Jonathan M Davis wrote:
> [ . . . ]
> 
> > What's happening is that the parameter that you're passing n to for
> > recurrence is size_t. And on 32-bit systems, size_t is uint, so passing
> > n - which is long - to recurrence would be a narrowing conversion, which
> > requires a cast. The correct thing to do would be make n a size_t. The
> > other thing that you'd need to do is change declarative to return auto,
> > since take returns a range, _not_ a long.
> 
> It seems that D is falling into the same bear trap as C++ (and C?)
> descended into long ago.  When a programmer want an int or a long, they
> actually have to decide whether they need a size_t.  To be honest this
> is a simple WTF!!!
> 
> Go really has this right.  int  does not exist, neither does long.
> int32, int64 -- no ambiguity.  Why C++ and D have to continue with the
> pretence of platform independent types when they are far from platform
> independent seems counter-productive.
> 
> 
> 
> Thanks for the pointer about the take, I need to select just the last
> entry in the range and return that.
> 
> > In any case, it _would_ be nice if the compiler gave a more informative
> > message about _why_ the template failed to instantiate - especially
> > since it's _not_ the template constraint which is the problem - but
> > unfortunately, the compiler just isn't that smart about template
> > instantiation errors.
> 
> C++ is bad enough, if D cannot improve on it . . .   :-((

size_t pretty much needs to be platform-dependent unless you want to restrict 
arrays to uint.size as their maximum size. And that really isn't acceptable for 
a systems language  ( there are probably other reasons why size_t is need - 
that's just the most obvious). size_t is used anywhere that an index would be 
used. take is one of those places. Besides indices though, size_t isn't 
something that you're going to run into all that often in Phobos.

Regardless, size_t has _nothing_ to do with your problem here. The problem is 
that you're trying to pass a long to a uint parameter. That problem would exist 
even if uint was used directly instead of size_t. It's a narrowing conversion, 
and those require casts. I expect that Go would have exactly the same problem 
with int32 and int64 - unless Go allows narrowing conversions without casts 
like 
C and C++ do, which causes a whole host of other problems.

So, while you may not like size_t, it really isn't your problem here. Now, the 
error on the failed template instantiation could certainly use some 
improvement, 
but that's completely separate from the type issue. That's just it doing poorly 
at reporting the error caused by the type issue.

D certainly could use further improvement with regards to template errors, but 
on the whole, D's templates are _far_ better than C++'s.

- Jonathan M Davis


Re: Read file/stream

2011-03-12 Thread nrgyzer
== Auszug aus Stewart Gordon (smjg_1...@yahoo.com)'s Artikel
> On 11/03/2011 18:46, Steven Schveighoffer wrote:
> 
> > I am not sure what facilities Phobos provides for reading/writing
integers in network
> > order (i.e. Big Endian), but I'm sure there's something.
> http://www.digitalmars.com/d/1.0/phobos/std_stream.html
> EndianStream
> I haven't experimented with it.  And I don't expect it to handle
structs well.
> Alternatively, you could use some simple code like
> 
> version (BigEndian) {
>  uint bigEndian(uint value) {
>  return value;
>  }
> }
> version (LittleEndian) {
>  uint bigEndian(uint value) {
>  return value << 24
>| (value & 0xFF00) << 8
>| (value & 0x00FF) >> 8
>| value >> 24;
>  }
> }
> 
> though you would have to remember to call it for each file I/O
operation that relies on
> it.  If you use a struct, you could put a method in it to call
bigEndian on the members of
> relevance.
> Stewart.

That's working - thanks for all replies!


Re: Fibonacci with ranges

2011-03-12 Thread Russel Winder
On Sat, 2011-03-12 at 02:15 -0800, Ali Çehreli wrote:
[ . . . ]
> void main()
> {
>  long[] data = [ 0, 1, 1, 2, 3, 5, 8 ];
> 
>  foreach (n; 0 .. data.length) {
>  assert(equal(declarative(n), data[0..n]));
>  }
> }

In fact the driver is:

unittest {
  immutable data = [
[ 0 , 0 ] ,
[ 1 , 1 ] ,
[ 2 , 1 ] ,
[ 3 , 2 ] ,
[ 4 , 3 ] ,
[ 5 , 5 ] ,
[ 6 , 8 ] ,
[ 7 , 13 ] ,
[ 8 , 21 ] ,
[ 9 , 34 ] ,
[ 10 , 55 ] ,
[ 11 , 89 ] ,
[ 12 , 144 ] ,
[ 13 , 233 ] ,
  ] ;
  foreach ( item ; data ) {
assert ( iterative ( item[0] ) == item[1] ) ;
  }
  foreach ( item ; data ) {
assert ( declarative ( item[0] ) == item[1] ) ;
  }
}

so I need to index the take-n list to return the last value.

This of course brings up the question of the signature of any factorial
function.  Without a real use case it is a rhetorical question.  What is
nice though is that there could be a neat way of generating a memoized,
i.e. cached, lazy list.

-- 
Russel.
=
Dr Russel Winder  t: +44 20 7585 2200   voip: sip:russel.win...@ekiga.net
41 Buckmaster Roadm: +44 7770 465 077   xmpp: rus...@russel.org.uk
London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder


signature.asc
Description: This is a digitally signed message part


Re: Fibonacci with ranges

2011-03-12 Thread Russel Winder
Jonathan,

Thanks for the info, very helpful.  One point though:

On Sat, 2011-03-12 at 01:56 -0800, Jonathan M Davis wrote:
[ . . . ]
> What's happening is that the parameter that you're passing n to for 
> recurrence 
> is size_t. And on 32-bit systems, size_t is uint, so passing n - which is 
> long - 
> to recurrence would be a narrowing conversion, which requires a cast. The 
> correct thing to do would be make n a size_t. The other thing that you'd need 
> to 
> do is change declarative to return auto, since take returns a range, _not_ a 
> long.

It seems that D is falling into the same bear trap as C++ (and C?)
descended into long ago.  When a programmer want an int or a long, they
actually have to decide whether they need a size_t.  To be honest this
is a simple WTF!!!

Go really has this right.  int  does not exist, neither does long.
int32, int64 -- no ambiguity.  Why C++ and D have to continue with the
pretence of platform independent types when they are far from platform
independent seems counter-productive.



Thanks for the pointer about the take, I need to select just the last
entry in the range and return that.

> In any case, it _would_ be nice if the compiler gave a more informative 
> message 
> about _why_ the template failed to instantiate - especially since it's _not_ 
> the 
> template constraint which is the problem - but unfortunately, the compiler 
> just 
> isn't that smart about template instantiation errors.

C++ is bad enough, if D cannot improve on it . . .   :-((

-- 
Russel.
=
Dr Russel Winder  t: +44 20 7585 2200   voip: sip:russel.win...@ekiga.net
41 Buckmaster Roadm: +44 7770 465 077   xmpp: rus...@russel.org.uk
London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder


signature.asc
Description: This is a digitally signed message part


Re: Fibonacci with ranges

2011-03-12 Thread Ali Çehreli

On 03/12/2011 01:33 AM, Russel Winder wrote:
> On Fri, 2011-03-11 at 18:46 -0500, Jesse Phillips wrote:
>> Without testing: foreach (f; take(recurrence!("a[n-1] + 
a[n-2]")(0UL, 1UL), 50))

>>
>> teo Wrote:
>>
>>> Just curious: How can I get ulong here?
>>>
>>> foreach (f; take(recurrence!("a[n-1] + a[n-2]")(0, 1), 50))
>>> {
>>>writeln(f);
>>> }
>>
>
> Interestingly, or not, the code:
>
> long declarative ( immutable long n ) {
>return take ( recurrence ! ( "a[n-1] + a[n-2]" ) ( 0L , 1L ) , n ) ;
> }

take returns a lazy range which can't be returned as a single long.

Reading your other post, I think this may be what you wanted to see:

import std.range;
import std.algorithm;

auto declarative(immutable long n)
{
  return take(recurrence!("a[n-1] + a[n-2]")(0L, 1L), n);
}

void main()
{
long[] data = [ 0, 1, 1, 2, 3, 5, 8 ];

foreach (n; 0 .. data.length) {
assert(equal(declarative(n), data[0..n]));
}
}

Ali



Re: Fibonacci with ranges

2011-03-12 Thread Jonathan M Davis
On Saturday 12 March 2011 01:33:34 Russel Winder wrote:
> On Fri, 2011-03-11 at 18:46 -0500, Jesse Phillips wrote:
> > Without testing: foreach (f; take(recurrence!("a[n-1] + a[n-2]")(0UL,
> > 1UL), 50))
> > 
> > teo Wrote:
> > > Just curious: How can I get ulong here?
> > > 
> > > foreach (f; take(recurrence!("a[n-1] + a[n-2]")(0, 1), 50))
> > > {
> > > 
> > >   writeln(f);
> > > 
> > > }
> 
> Interestingly, or not, the code:
> 
> long declarative ( immutable long n ) {
>   return take ( recurrence ! ( "a[n-1] + a[n-2]" ) ( 0L , 1L ) , n ) ;
> }
> 
> results in the return statement delivering:
> 
> rdmd --main -unittest fibonacci_d2.d
> fibonacci_d2.d(15): Error: template std.range.take(R) if
> (isInputRange!(Unqual!(R)) && !isSafelySlicable!(Unqual!(R)) &&
> !is(Unqual!(R) T == Take!(T))) does not match any function template
> declaration fibonacci_d2.d(15): Error: template std.range.take(R) if
> (isInputRange!(Unqual!(R)) && !isSafelySlicable!(Unqual!(R)) &&
> !is(Unqual!(R) T == Take!(T))) cannot deduce template function from
> argument types !()(Recurrence!(fun,long,2u),immutable(long))
> 
> which seems deeply impenetrable for mere mortals.

LOL. Maybe I've been dealing with template code for too long, because that 
seems 
perfectly clear to me. Though I can certainly understand why it wouldn't be. 
Incidentally, isSafelySlicable will be going away (essentially it's checking 
that the range isn't some type of char[] or wchar[], and Andrei's just going to 
make it so that isSliceable is false for them).

All that template constraint is checking for is that the range is an input 
range 
which can't be sliced and isn't already a range returned from take. If a range 
_is_ sliceable, then take just returns the same range type.

However, I don't think that constraint is necessarily all that useful in this 
case. It's just that it's the first version of the template, so that's the way 
that gets displayed when the compiler can't instantiate any of the versions of 
the template with the given arguments.

What's happening is that the parameter that you're passing n to for recurrence 
is size_t. And on 32-bit systems, size_t is uint, so passing n - which is long 
- 
to recurrence would be a narrowing conversion, which requires a cast. The 
correct thing to do would be make n a size_t. The other thing that you'd need 
to 
do is change declarative to return auto, since take returns a range, _not_ a 
long.

In any case, it _would_ be nice if the compiler gave a more informative message 
about _why_ the template failed to instantiate - especially since it's _not_ 
the 
template constraint which is the problem - but unfortunately, the compiler just 
isn't that smart about template instantiation errors.

- Jonathan M Davis


Re: Fibonacci with ranges

2011-03-12 Thread Russel Winder
On Sat, 2011-03-12 at 09:33 +, Russel Winder wrote:
[ . . . ]
> Interestingly, or not, the code:
> 
> long declarative ( immutable long n ) {
>   return take ( recurrence ! ( "a[n-1] + a[n-2]" ) ( 0L , 1L ) , n ) ;
> }
> 
> results in the return statement delivering:
> 
> rdmd --main -unittest fibonacci_d2.d
> fibonacci_d2.d(15): Error: template std.range.take(R) if 
> (isInputRange!(Unqual!(R)) && !isSafelySlicable!(Unqual!(R)) && 
> !is(Unqual!(R) T == Take!(T))) does not match any function template 
> declaration
> fibonacci_d2.d(15): Error: template std.range.take(R) if 
> (isInputRange!(Unqual!(R)) && !isSafelySlicable!(Unqual!(R)) && 
> !is(Unqual!(R) T == Take!(T))) cannot deduce template function from argument 
> types !()(Recurrence!(fun,long,2u),immutable(long))
> 
> which seems deeply impenetrable for mere mortals.

Sorry I needed to add the driver code:

  foreach ( item ; data ) {
assert ( declarative ( item[0] ) == item[1] ) ;
  }

within a unittest block. 
-- 
Russel.
=
Dr Russel Winder  t: +44 20 7585 2200   voip: sip:russel.win...@ekiga.net
41 Buckmaster Roadm: +44 7770 465 077   xmpp: rus...@russel.org.uk
London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder


signature.asc
Description: This is a digitally signed message part


Re: Fibonacci with ranges

2011-03-12 Thread Russel Winder
On Fri, 2011-03-11 at 18:46 -0500, Jesse Phillips wrote:
> Without testing: foreach (f; take(recurrence!("a[n-1] + a[n-2]")(0UL, 1UL), 
> 50))
> 
> teo Wrote:
> 
> > Just curious: How can I get ulong here?
> > 
> > foreach (f; take(recurrence!("a[n-1] + a[n-2]")(0, 1), 50))
> > {
> > writeln(f);
> > }
> 

Interestingly, or not, the code:

long declarative ( immutable long n ) {
  return take ( recurrence ! ( "a[n-1] + a[n-2]" ) ( 0L , 1L ) , n ) ;
}

results in the return statement delivering:

rdmd --main -unittest fibonacci_d2.d
fibonacci_d2.d(15): Error: template std.range.take(R) if 
(isInputRange!(Unqual!(R)) && !isSafelySlicable!(Unqual!(R)) && !is(Unqual!(R) 
T == Take!(T))) does not match any function template declaration
fibonacci_d2.d(15): Error: template std.range.take(R) if 
(isInputRange!(Unqual!(R)) && !isSafelySlicable!(Unqual!(R)) && !is(Unqual!(R) 
T == Take!(T))) cannot deduce template function from argument types 
!()(Recurrence!(fun,long,2u),immutable(long))

which seems deeply impenetrable for mere mortals.

-- 
Russel.
=
Dr Russel Winder  t: +44 20 7585 2200   voip: sip:russel.win...@ekiga.net
41 Buckmaster Roadm: +44 7770 465 077   xmpp: rus...@russel.org.uk
London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder


signature.asc
Description: This is a digitally signed message part