Re: How to check if an array is a manifest constant?

2011-04-04 Thread simendsjo
 What use case do you have for wanting to know whether a variable is an enum 
 or not?

The same reason I'd like to check if it's const/immutable; if an algorithm 
requires a
modifiable array.

void sortInPlace(int[] array) {
array.sort;
}

void main() {
int[] a = [3,2,1];
sortInPlace(a);
assert(a == [1,2,3]);

auto i = [3,2,1].idup;
//sortInPlace(i); // Fails at compile time

enum e = [3,2,1];
sortInPlace(e);
assert(e == [1,2,3]); // fails at runtime
}

I can check the type for const or immutable with template constraits or static 
if's, but I
cannot check for enum.
I can use ref int[] as a parameter to get a compile time error, but that's 
misleading as I
often don't want to reassign the parameter.

Cannot the type of enum e = [1] be immutable(int[])? Or is that wrong?
Or am I missing something crucial because of CTFE or other stuff? I've just 
started looking
into D2, so theres a good possibility my reasoning is wrong.


Static array size limit

2011-04-02 Thread simendsjo
http://digitalmars.com/d/2.0/arrays.html says static arrays are
limited to 16mb, but I can only allocate 1mb.
My fault, or bug?

enum size = (16 * 1024 * 1024) / int.sizeof;
//int[size] a;   // Error: index 4194304 overflow for static
array
enum size2 = (16 * 1000 * 1000) / int.sizeof;
//int[size2] b; // Stack Overflow
//int[250_001] c; // Stack Overflow
int[250_000] d; // ok


Re: Static array size limit

2011-04-02 Thread simendsjo
This is using dmd 2.052 on windows by the way.


Re: Static array size limit

2011-04-02 Thread simendsjo
I think you missed my /int.sizeof at the end.

enum size = (16*1024*1024)/int.sizeof;
int[size] a; // Error index overflow for static as expected
int[size-1] b; // stack overflow
int[250_001] c; // stack overflow
int[250_000] d; // ok


Where does the template parameter E come from?

2011-03-28 Thread simendsjo
When running compose with two arguments, the implementation uses the 
template parameter E. I don't understand what's going on here as E isn't 
submitted to the template - what type is E?

I've also seen this in unary/binaryFun using ElementType.


template compose(fun...) { alias composeImpl!(fun).doIt compose; }

// Implementation of compose
template composeImpl(fun...)
{
static if (fun.length == 1)
{
static if (is(typeof(fun[0]) : string))
alias unaryFun!(fun[0]) doIt;
else
alias fun[0] doIt;
}
else static if (fun.length == 2)
{
// starch
static if (is(typeof(fun[0]) : string))
alias unaryFun!(fun[0]) fun0;
else
alias fun[0] fun0;
static if (is(typeof(fun[1]) : string))
alias unaryFun!(fun[1]) fun1;
else
alias fun[1] fun1;
// protein: the core composition operation
typeof({ E a; return fun0(fun1(a)); }()) doIt(E)(E a)
{
return fun0(fun1(a));
}
}
else
{
// protein: assembling operations
alias composeImpl!(fun[0], composeImpl!(fun[1 .. $]).doIt).doIt 
doIt;

}
}


Re: Where does the template parameter E come from?

2011-03-28 Thread simendsjo

On 28.03.2011 16:54, simendsjo wrote:

When running compose with two arguments, the implementation uses the
template parameter E. I don't understand what's going on here as E isn't
submitted to the template - what type is E?
I've also seen this in unary/binaryFun using ElementType.


template compose(fun...) { alias composeImpl!(fun).doIt compose; }

// Implementation of compose
template composeImpl(fun...)
{
static if (fun.length == 1)
{
static if (is(typeof(fun[0]) : string))
alias unaryFun!(fun[0]) doIt;
else
alias fun[0] doIt;
}
else static if (fun.length == 2)
{
// starch
static if (is(typeof(fun[0]) : string))
alias unaryFun!(fun[0]) fun0;
else
alias fun[0] fun0;
static if (is(typeof(fun[1]) : string))
alias unaryFun!(fun[1]) fun1;
else
alias fun[1] fun1;
// protein: the core composition operation
typeof({ E a; return fun0(fun1(a)); }()) doIt(E)(E a)
{
return fun0(fun1(a));
}
}
else
{
// protein: assembling operations
alias composeImpl!(fun[0], composeImpl!(fun[1 .. $]).doIt).doIt doIt;
}
}


I think I get it.

doIt becomes the function being called. So E is the type of the 
parameter being used when calling compose.


Re: Where does the template parameter E come from?

2011-03-28 Thread simendsjo

On 28.03.2011 17:07, David Nadlinger wrote:

On 3/28/11 4:54 PM, simendsjo wrote:

When running compose with two arguments, the implementation uses the
template parameter E. I don't understand what's going on here as E isn't
submitted to the template - what type is E?
[…]
typeof({ E a; return fun0(fun1(a)); }()) doIt(E)(E a)
{ […] }


doIt is a function template, so E will be deduced to be whatever type
the passed argument is – you won't notice the extra »template layer« as
E is automatically inferred from the argument.

For better understanding, you might want to look at the definition like
this:

---
template composeImpl(fun...) {
[…]
template doIt(E) {
typeof({ E a; return fun0(fun1(a)); }()) doIt(E a) {
[…]
}
}
}
---

David


Thanks. That seems like a good way of mentally mapping template usage 
until it comes more naturally.


Error in Template Alias Parameter example in the documentation

2011-03-17 Thread simendsjo
This example comes from http://digitalmars.com/d/2.0/template.html

int x;

template Foo(alias X)
{
static int* p = X;
}

void test()
{
alias Foo!(x) bar;
*bar.p = 3; // set x to 3
static int y;
alias Foo!(y) abc;
*abc.p = 3; // set y to 3
}

Compiling this gives the following compiler errors on the line inside Foo:
t.d(5): Error: non-constant expression  x
t.d(5): Error: non-constant expression  y

Changing static int* to enum int* fixes the compiler errors.

Are these pages written using DDoc? Is it possible to extract and compile the 
examples to
ensure they are correct? And perhaps use asserts instead of/in addition to 
comments where
possible (Asserts are used many places already)?
Executable and verifiable examples could be a useful feature as plain text 
documentation and
examples have a tendency to rot.


TemplateParameterList in is expression

2011-03-16 Thread simendsjo
I'm having some problems understanding the (complex) is expression.

 // Example from the documentation
 static if (is(int[10] X : X[Y], int Y : 5))
 {
assert(0);  // should not match, Y should be 10
 }

 // but this doesn't match either.. Shouldn't it?
 static if (is(int[10] X : X[Y], int Y : 10))
 {
assert(0);
 }


Expression tuples

2011-03-16 Thread simendsjo
http://www.digitalmars.com/d/2.0/tuple.html

// this example fails
Tuple!(3, 7, 'c')

typecons.d(298): Error: static assert Attempted to instantiate Tuple
with an invalid argument: 3

Even this fails:
alias Tuple!(0) T;

Is Tuple only meant to store types or named types?


Re: Mocking framework

2011-03-09 Thread simendsjo
I gave this some thought, and I'm probably just a bit braindamaged by C#.
Consider you wish to unittest a class that fetches data from a database and 
sends an
email.
The common scenario here is to use IoC and mock the objects so you can check 
that
FetchData was called and SendEmail is called using the data from your 
FetchData.

So this is the scenario:

interface SomeBigInterface {
void doStuff();
// And many more methods here
}

class SomeClassImplementingInterface : SomeBigInterface {
void doStuff() {}
// And many more methods here
}

class SomeClass {
SomeBigInterface _i;
this(SomeBigInterface i) {
_i = i;
}

void someComplexStuff() {
_i.doStuff();
}
}

And how can I mock the entire SomeBigInterface containing 20 methods just to 
make sure
doStuff is called? And what if it didn't take an interface, but an SmtpClient?

But then I thought I might be forcing D into the limitations of C# and other 
pure oo
langauges.
Then I created this instead:

// Now I'm only depending on the methods I use, not an entire interface or a 
specific
class/struct
class SomeClass2(T)
if( is(typeof({ return T.init.doStuff(); })) )
{
T _i;
this(T i) {
_i = i;
}

void someComplexStuff() {
_i.doStuff();
}
}

Then I can mock it up a lot easier:

class MyMock {
int called;
void doStuff() { ++called; }
}

auto mock = new MyMock();

auto a = new SomeClass2!MyMock(mock);
assert(mock.called == 0);
a.someComplexStuff();
assert(mock.called == 1);
a.someComplexStuff();
assert(mock.called == 2);


And voila.. It's simpler to create the mock object by hand than through a 
library.
The question is, is this good practice? Should I often just create templates 
like
isSomeInterface (like the range api does) checking for methods and properties 
instead of
using interfaces directly?


Re: Some weird crashes

2011-03-08 Thread simendsjo

On 08.03.2011 01:32, Andrej Mitrovic wrote:

Sorry for not seeing this sooner. I think you might have set the wrong
calling convention in the translated header file. See my answer on SO.
I hope it works for you now.


Thanks. Just to get the solution here too:

* Use the vs2005 library (to get COFF?)
* coffimplib
* wrap __stdcall in extern(Windows)

One more thing..
Function pointers in structs.. Should they use extern(Windows) too?


Re: Wrapping C that uses compiler extensions

2011-03-05 Thread simendsjo

On 05.03.2011 08:58, Jérôme M. Berger wrote:

simendsjo wrote:

On 04.03.2011 22:42, Jérôme M. Berger wrote:

int main(string[] args) {
 auto s1 =(); // MH MH
 auto s2 =(); // OK
 s2.c =ull; // OK
 return 0;
}


Is part of your message gone?


Uh, I did not write that.


Checked the web newsinterface, and I see your post. In thunderbird I got 
another post from Tom with the subject Struct reference returning 
function and const members in your post...



You can safely ignore the “ATTRIBUTE_FORMAT_FPTR(printf, 4, 5)”.


That I understood :) Thanks!


Then if the issue is with the rest of the definition, it is more or
less equivalent to (you will need to translate the argument
declaration too):

alias size_t function (struct charset_info_st *, char *to, size_t n,
const char *fmt,
...) snprintf;

Jerome


The definition is inside a struct. I shouldn't use an alias then..?

This is the C struct:
typedef struct my_charset_handler_st
{
  // snip
  size_t (*snprintf)(struct charset_info_st *, char *to, size_t n,
 const char *fmt,
 ...) ATTRIBUTE_FORMAT_FPTR(printf, 4, 5);
  // snip
}

And this is my D struct:
struct my_charset_handler_st
{
  // snip
  size_t  function(charset_info_st*, char* to, size_t n,
const char* fmt,
...) snprintf;
  // snip
}


Re: Some weird crashes

2011-03-05 Thread simendsjo

On 28.02.2011 18:52, simendsjo wrote:

I'm trying to wrap the newest mysql c connector, but I get some weird
bugs. I don't know any assembly, so I don't even know if I've included
enough info.. I hope this is a small enough test case so someone can
understand the issue.
I've used implib on the included dll and rdmd and dmd 2.051 to compile.



Asked on SO too: 
http://stackoverflow.com/questions/5204460/problems-convering-a-c-header-to-d


Re: htod and system files

2011-03-05 Thread simendsjo

On 05.03.2011 20:04, Bekenn wrote:

On 3/4/2011 3:31 PM, simendsjo wrote:

The htod page, http://www.digitalmars.com/d/2.0/htod.html, says that
system files will be included using the -hs option.

htod mysql.h -hs
Fatal error: unable to open input file 'sys/types.h'

Does it try to find these files through an environment variable?


htod is compatible with the -I and -D compiler switches from dmc. Use -I
to reference to the directory containing the system headers you want to
use.


Ah, thanks.

Doesn't seem dmc is a supported compiler though..

htod -hs -Ic:\d\dm\include mysql.h

  my_socket fd; /* For Perl DBI/dbd */
 ^
mysql_com.h(268) : Error: ';' expected following declaration of struct 
member

my_bool net_realloc(NET *net, size_t length);
   ^
mysql_com.h(422) : Error: ')' expected
my_bool my_net_write(NET *net,const unsigned char *packet, size_t len);
^
mysql_com.h(424) : Error: ')' expected
  const unsigned char *header, size_t head_len,
^
mysql_com.h(426) : Error: ')' expected
int net_real_write(NET *net,const unsigned char *packet, size_t len);
  ^
mysql_com.h(428) : Error: ')' expected
Fatal error: too many errors


C const

2011-03-04 Thread simendsjo
I'm not quite sure how to wrap c's const. This page, 
http://www.digitalmars.com/d/2.0/htomodule.html, says:


D has const as a type modifier.
void foo(const int *p, char *const q);
becomes:
void foo(const int* p, const char* q);
But D's const is transitive - there are no const pointers to mutable 
types in D. When encountering such in C code, simply drop the const.



So const on basic types should be const in D too. It also says char 
const* q. Is const char* the same thing in C?


But this page, http://www.digitalmars.com/d/2.0/interfaceToC.html, says:

There are no const or volatile type modifiers in D. To declare a C 
function that uses those type modifiers, just drop those keywords from 
the declaration.


So all const modifiers should be dropped everywhere..?

And should the const be dropped here?
struct somestruct {
  const struct otherstruct;
}


Wrapping C that uses compiler extensions

2011-03-04 Thread simendsjo


This code confuses me... It's from the c mysql windows dll, libmysql.dll.

  size_t (*snprintf)(struct charset_info_st *, char *to, size_t n,
 const char *fmt,
 ...) ATTRIBUTE_FORMAT_FPTR(printf, 4, 5);

#ifndef _my_attribute_h
#define _my_attribute_h

/*
  Disable __attribute__() on gcc  2.7, g++  3.4, and non-gcc compilers.
  Some forms of __attribute__ are actually supported in earlier versions of
  g++, but we just disable them all because we only use them to generate
  compilation warnings.
*/
#ifndef __attribute__
# if !defined(__GNUC__)
#  define __attribute__(A)
# elif GCC_VERSION  2008
#  define __attribute__(A)
# elif defined(__cplusplus)  GCC_VERSION  3004
#  define __attribute__(A)
# endif
#endif

/*
  __attribute__((format(...))) is only supported in gcc = 2.8 and g++ 
= 3.4

  But that's already covered by the __attribute__ tests above, so this is
  just a convenience macro.
*/
#ifndef ATTRIBUTE_FORMAT
# define ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n)))
#endif

/*

   __attribute__((format(...))) on a function pointer is not supported
   until  gcc 3.1
*/
#ifndef ATTRIBUTE_FORMAT_FPTR
# if (GCC_VERSION = 3001)
#  define ATTRIBUTE_FORMAT_FPTR(style, m, n) ATTRIBUTE_FORMAT(style, m, n)
# else
#  define ATTRIBUTE_FORMAT_FPTR(style, m, n)
# endif /* GNUC = 3.1 */
#endif


#endif


Re: Wrapping C that uses compiler extensions

2011-03-04 Thread simendsjo

On 04.03.2011 22:42, Jérôme M. Berger wrote:

int main(string[] args) {
auto s1 =(); // MH MH
auto s2 =(); // OK
s2.c =ull; // OK
return 0;
}


Is part of your message gone?

 You can safely ignore the “ATTRIBUTE_FORMAT_FPTR(printf, 4, 5)”.

That I understood :) Thanks!


Re: C const

2011-03-04 Thread simendsjo

On 04.03.2011 23:10, Jesse Phillips wrote:

simendsjo Wrote:


So all const modifiers should be dropped everywhere..?

And should the const be dropped here?
struct somestruct {
const struct otherstruct;
}


All in all the real answer comes down to, is the data modified. Since C makes 
no guarantees you must only declare things const if you know the library will 
abide by it. In the case above I think you have to drop it.

Remember that const/immutable, and other attributes/properties aren't going to 
change the ABI so dropping them will be safer then leaving them.


Thanks. Does this apply to all uses of const, or just complex members?


Re: Some weird crashes

2011-03-03 Thread simendsjo
Thanks! I couldn't find it on the web page.
coffimplib is missing to option to prepend _ to the types as implib
does with /system. Any way around this (without changing all my code)?


Re: Some weird crashes

2011-03-03 Thread simendsjo

On 02.03.2011 18:24, Denis Koroskin wrote:

On Tue, 01 Mar 2011 23:01:21 +0300, simendsjo
simen.end...@pandavre.com wrote:


On 28.02.2011 20:24, Denis Koroskin wrote:

On Mon, 28 Feb 2011 22:04:44 +0300, simendsjo
simen.end...@pandavre.com wrote:


On 28.02.2011 18:52, simendsjo wrote:


// ERROR
auto res = mysql_library_init(0, null, null);

auto cn = mysql_init(null);
auto oldcn = cn;

writeln(mysql_errno(cn));
assert(cn == oldcn); // when the last assert is active, the above line
changes cn and thus fails.

auto err = mysql_errno(cn);
assert(cn == oldcn);


Btw, if I don't use writeln it doesn't fail..


I think you have a bug at line 42.

On a serious note, it might have helped if you'd attached source code,
or at least binaries.


Hmmm.. Seems my post last night didn't get through..
Here's the code and necessary libraries: http://share1t.com/4xgt2l


What appears to be an error here is in fact an Access Violation at
mysql_close.

Here is a reduced test-case:

import mysql;

void main()
{
auto res = mysql_library_init(0, null, null);
auto cn = mysql_init(null);
mysql_close(cn);
}


Then I decided to check whether it is D's fault or not by porting this
short program to C. Here is what I got:

// mysql.c
int mysql_server_init(int argc, char **argv, char **groups);
struct MYSQL* mysql_init(struct MYSQL*);
void mysql_close(struct MYSQL*);

#define mysql_library_init mysql_server_init

#define NULL 0

#include stdio.h

int main()
{
int res = mysql_library_init(0, NULL, NULL);
struct MYSQL* cn = mysql_init(NULL);
printf(here);
mysql_close(cn);
return 0;
}

This program works fine, BUT try commenting out the printf call and it
crashes, too. That said, it is unlikely to be DMD fault here. Are you
sure those prototypes and/or .lib/.dll files are fine?


I've gone through the entire file and fixed ever wrong definition I 
found. I added the C declarations as a comment before each type.

The same error exists, and I cannot understand why...

The code is pasted here: http://pastebin.com/KwacZ0MY

Does anyone have a clue where to start looking?



Re: Some weird crashes

2011-03-02 Thread simendsjo

On 02.03.2011 18:24, Denis Koroskin wrote:

On Tue, 01 Mar 2011 23:01:21 +0300, simendsjo
simen.end...@pandavre.com wrote:


On 28.02.2011 20:24, Denis Koroskin wrote:

On Mon, 28 Feb 2011 22:04:44 +0300, simendsjo
simen.end...@pandavre.com wrote:


On 28.02.2011 18:52, simendsjo wrote:


// ERROR
auto res = mysql_library_init(0, null, null);

auto cn = mysql_init(null);
auto oldcn = cn;

writeln(mysql_errno(cn));
assert(cn == oldcn); // when the last assert is active, the above line
changes cn and thus fails.

auto err = mysql_errno(cn);
assert(cn == oldcn);


Btw, if I don't use writeln it doesn't fail..


I think you have a bug at line 42.

On a serious note, it might have helped if you'd attached source code,
or at least binaries.


Hmmm.. Seems my post last night didn't get through..
Here's the code and necessary libraries: http://share1t.com/4xgt2l


What appears to be an error here is in fact an Access Violation at
mysql_close.

Here is a reduced test-case:

import mysql;

void main()
{
auto res = mysql_library_init(0, null, null);
auto cn = mysql_init(null);
mysql_close(cn);
}


Then I decided to check whether it is D's fault or not by porting this
short program to C. Here is what I got:

// mysql.c
int mysql_server_init(int argc, char **argv, char **groups);
struct MYSQL* mysql_init(struct MYSQL*);
void mysql_close(struct MYSQL*);

#define mysql_library_init mysql_server_init

#define NULL 0

#include stdio.h

int main()
{
int res = mysql_library_init(0, NULL, NULL);
struct MYSQL* cn = mysql_init(NULL);
printf(here);
mysql_close(cn);
return 0;
}

This program works fine, BUT try commenting out the printf call and it
crashes, too. That said, it is unlikely to be DMD fault here. Are you
sure those prototypes and/or .lib/.dll files are fine?



The prototypes might be wrong. I'm in the process of checking everything.

The dll is the one included in the download. The lib is made with implib 
/system


But your c program fails..? Could the problem be with the implib library..?

I couldn't find a free download for coff2omf, that's why I don't use the 
supplied .lib.


Re: Some weird crashes

2011-03-01 Thread simendsjo

On 28.02.2011 20:24, Denis Koroskin wrote:

On Mon, 28 Feb 2011 22:04:44 +0300, simendsjo
simen.end...@pandavre.com wrote:


On 28.02.2011 18:52, simendsjo wrote:


// ERROR
auto res = mysql_library_init(0, null, null);

auto cn = mysql_init(null);
auto oldcn = cn;

writeln(mysql_errno(cn));
assert(cn == oldcn); // when the last assert is active, the above line
changes cn and thus fails.

auto err = mysql_errno(cn);
assert(cn == oldcn);


Btw, if I don't use writeln it doesn't fail..


I think you have a bug at line 42.

On a serious note, it might have helped if you'd attached source code,
or at least binaries.


Hmmm.. Seems my post last night didn't get through..
Here's the code and necessary libraries: http://share1t.com/4xgt2l


Some weird crashes

2011-02-28 Thread simendsjo
I'm trying to wrap the newest mysql c connector, but I get some weird 
bugs. I don't know any assembly, so I don't even know if I've included 
enough info.. I hope this is a small enough test case so someone can 
understand the issue.

I've used implib on the included dll and rdmd and dmd 2.051 to compile.

// CORRECT
auto res = mysql_library_init(0, null, null);

auto cn = mysql_init(null);
auto oldcn = cn;

writeln(mysql_errno(cn));
assert(cn == oldcn);

auto err = mysql_errno(cn);
//assert(cn == oldcn); // notice this is commented out

mysql_close(cn);
mysql_library_end();


0040201A  |. E8 F5B30300CALL JMP.libmysql.mysql_server_init
0040201F  |. 6A 00  PUSH 0
00402021  |. E8 E8B30300CALL JMP.libmysql.mysql_init
00402026  |. 8945 F8MOV DWORD PTR SS:[EBP-8],EAX
00402029  |. 8945 FCMOV DWORD PTR SS:[EBP-4],EAX
0040202C  |. FF75 F8PUSH DWORD PTR SS:[EBP-8]
0040202F  |. E8 D4B30300CALL JMP.libmysql.mysql_errno
00402034  |. 83C4 04ADD ESP,4
00402037  |. E8 4C00CALL mytest_w.00402088
0040203C  |. 8B45 F8MOV EAX,DWORD PTR SS:[EBP-8]
0040203F  |. 3B45 FCCMP EAX,DWORD PTR SS:[EBP-4]
00402042  |. B9 0100MOV ECX,1
00402047  |. 74 02  JE SHORT mytest_w.0040204B
00402049  |. 8ACD   MOV CL,CH
0040204B  | 894D F4MOV DWORD PTR SS:[EBP-C],ECX
0040204E  |. 74 0A  JE SHORT mytest_w.0040205A
00402050  |. B8 1A00MOV EAX,1A
00402055  |. E8 662ACALL mytest_w.00404AC0
0040205A  | FF75 F8PUSH DWORD PTR SS:[EBP-8]
0040205D  |. E8 A6B30300CALL JMP.libmysql.mysql_errno
00402062  |. 807D F4 00 CMP BYTE PTR SS:[EBP-C],0
00402066  |. 75 0A  JNZ SHORT mytest_w.00402072
00402068  |. B8 1D00MOV EAX,1D
0040206D  |. E8 4E2ACALL mytest_w.00404AC0
00402072  | FF75 F8PUSH DWORD PTR SS:[EBP-8]
00402075  |. E8 88B30300CALL JMP.libmysql.mysql_close
0040207A  |. E8 7DB30300CALL JMP.libmysql.mysql_server_end
0040207F  |. 31C0   XOR EAX,EAX
00402081  |. 83C4 18ADD ESP,18
00402084  |. C9 LEAVE
00402085  \. C3 RETN



// ERROR
auto res = mysql_library_init(0, null, null);

auto cn = mysql_init(null);
auto oldcn = cn;

writeln(mysql_errno(cn));
assert(cn == oldcn); // when the last assert is active, the above line 
changes cn and thus fails.


auto err = mysql_errno(cn);
assert(cn == oldcn);

mysql_close(cn);
mysql_library_end();
0040201A  |. E8 D5B30300CALL JMP.libmysql.mysql_server_init
0040201F  |. 6A 00  PUSH 0
00402021  |. E8 C8B30300CALL JMP.libmysql.mysql_init
00402026  |. 8945 F8MOV DWORD PTR SS:[EBP-8],EAX
00402029  |. 8945 FCMOV DWORD PTR SS:[EBP-4],EAX
0040202C  |. FF75 F8PUSH DWORD PTR SS:[EBP-8]
0040202F  |. E8 B4B30300CALL JMP.libmysql.mysql_errno
00402034  |. 83C4 04ADD ESP,4
00402037  |. E8 3000CALL mytest_f.0040206C
0040203C  |. 8B45 F8MOV EAX,DWORD PTR SS:[EBP-8]
0040203F  |. 3B45 FCCMP EAX,DWORD PTR SS:[EBP-4]
00402042  |. 74 0A  JE SHORT mytest_f.0040204E
00402044  |. B8 1A00MOV EAX,1A
00402049  |. E8 562ACALL mytest_f.00404AA4
0040204E  | FF75 F8PUSH DWORD PTR SS:[EBP-8]
00402051  |. E8 92B30300CALL JMP.libmysql.mysql_errno
00402056  |. FF75 F8PUSH DWORD PTR SS:[EBP-8]
00402059  |. E8 84B30300CALL JMP.libmysql.mysql_close
0040205E  |. E8 79B30300CALL JMP.libmysql.mysql_server_end
00402063  |. 31C0   XOR EAX,EAX
00402065  |. 83C4 18ADD ESP,18
00402068  |. C9 LEAVE
00402069  \. C3 RETN



Re: Some weird crashes

2011-02-28 Thread simendsjo

On 28.02.2011 18:52, simendsjo wrote:


// ERROR
auto res = mysql_library_init(0, null, null);

auto cn = mysql_init(null);
auto oldcn = cn;

writeln(mysql_errno(cn));
assert(cn == oldcn); // when the last assert is active, the above line
changes cn and thus fails.

auto err = mysql_errno(cn);
assert(cn == oldcn);


Btw, if I don't use writeln it doesn't fail..


Re: Some weird crashes

2011-02-28 Thread simendsjo

On 28.02.2011 20:24, Denis Koroskin wrote:

I think you have a bug at line 42.

On a serious note, it might have helped if you'd attached source code,
or at least binaries.


The file was too large to be attached. Here's a link to a public hosting 
service: http://share1t.com/4xgt2l. Everything (including mysql 
libraries) is included.


Not sure what line you are referring to though.


Re: Interfacing with c and platform dependent sizes

2011-02-27 Thread simendsjo

On 27.02.2011 11:43, Jacob Carlborg wrote:

On 2011-02-26 17:58, simendsjo wrote:

On 26.02.2011 17:06, Mike Wey wrote:

On 02/26/2011 11:49 AM, Jacob Carlborg wrote:

On 2011-02-26 01:28, simendsjo wrote:

C is not my strong side, so I'm having some problems wrapping some
code.

I found a couple of sources on this:
1) http://www.digitalmars.com/d/2.0/htomodule.html
2) http://www.digitalmars.com/d/2.0/interfaceToC.html

1)
C's long is the same as D's int.
long long is long

2)
C 32bit's long long is D's long, C 64 bits long is D's long.

So.. A long in C is the same as the platform size? And long long
doesn't
exist in 64 bit?


In general you can follow the table at
http://www.digitalmars.com/d/2.0/htomodule.html

But when it comes to long in C you have to be careful. On 32bit
platforms a C long will be 32bit long. But on 64bit platforms it
depends of what data model is used. To simplify things:

* On Windows 64bit a C long will be 32bit long
* On Posix 64bit a C long will be 64bit long.

What you can do is to create an alias called c_long and c_ulong,
something like this:

version (D_LP64)
{
version (Windows)
{
alias int c_long;
alias uint c_ulong;
}

else
{
alias long c_long;
alias ulong c_ulong;
}
}

else
{
alias int c_long;
alias uint c_ulong;
}

To read more about data models:
http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models



You can also import core.stdc.config witch defines both c_long and
c_ulong.


Thanks for all the answers. Is something like this correct?

version(X86_64)
{
version(Windows)
{
version = LLP64;
}
else version(Posix)
{
version = LP64;
}
else
{
static assert(0);
}

version(LLP64)
{
alias short c_short;
alias ushort c_ushort;
alias int c_int;
alias uint c_uint;
alias int c_long;
alias uint c_ulong;
alias long c_longlong;
alias ulong c_ulonglong;
alias ulong c_size_t;
}
else version(LP64)
{
alias short c_short;
alias ushort c_ushort;
alias int c_int;
alias uint c_uint;
alias long c_long;
alias ulong c_ulong;
alias long c_longlong;
alias ulong c_ulonglong;
alias ulong c_size_t;
}
else version(ILP64)
{
alias short c_short;
alias ushort c_ushort;
alias long c_int;
alias ulong c_uint;
alias long c_long;
alias ulong c_ulong;
alias long c_longlong;
alias ulong c_ulonglong;
alias ulong c_size_t;
}
else version(SILP64)
{
alias long c_short;
alias ulong c_ushort;
alias long c_int;
alias ulong c_uint;
alias long c_long;
alias ulong c_ulong;
alias long c_longlong;
alias ulong c_ulonglong;
alias ulong c_size_t;
}
else
{
static assert(0);
}
}
else version(X86)
{
alias short c_short;
alias ushort c_ushort;
alias int c_int;
alias uint c_uint;
alias int c_long;
alias uint c_ulong;
alias long c_longlong;
alias ulong c_ulonglong;
alias uint c_size_t;
}
else
{
static assert(0);
}



I suggest you use core.stdc.config instead, I forgot it existed. BTW
size_t already exists in D (defined in the object module) and it will be
the same as size_t in C.



Ok. Thanks.


Version very simple?

2011-02-27 Thread simendsjo

I'm having some problems grokking version.

How would I translate this simple C macro?
#if !defined(IDENT) || !defined(IDENT2)

I've tried the following:
version(!IDENT)
 identifier or integer expected, not !

!version(IDENT)
 Declaration expected, not '!'

version(IDENT || IDENT2)
 found '||' when expecting ')'

version(IDENT) || version(IDENT2)
 Declaration expected, not '||'


This is just plain ugly:
version(IDENT) {
} else {
  version = NOT_IDENT_OR_IDENT2;
}

version(IDENT2) {
} else {
  version = NOT_IDENT_OR_IDENT2;
}

version(NOT_IDENT_OR_IDENT2) {
  // Finally
}


Re: Version very simple?

2011-02-27 Thread simendsjo

On 27.02.2011 16:18, David Nadlinger wrote:

On 2/27/11 3:52 PM, simendsjo wrote:

I'm having some problems grokking version.

How would I translate this simple C macro?
#if !defined(IDENT) || !defined(IDENT2)


You are facing a quite common question, with the answer being that there
is no simpler way to do this, at least that I know of.

This has to do with both the stage at which version blocks are parsed
internally, and with Walter taking a defensive stance on the power of
version statements because he feels that the typical C preprocessor
constructs are often a source for confusion (sorry if I misquoted you
there).

If you need more complex version conditions, however, you could consider
mapping versions to manifest constants and using static ifs like this:

version (foo) {
enum version_foo = true;
} else {
enum version_foo = false;
}

static if (version_foo || (version_bar  !version_baz) ) {
…
} else {
…
}


David


Thanks. A nice idea, and it makes the code prettier.
I can even use the same identifier names:

version(IDENT)
enum IDENT = true;
else
enum IDENT = false;

version(IDENT2)
enum IDENT2 = true;
else
enum IDENT2 = false;

static if(IDENT || IDENT2) {
}



Re: Version very simple?

2011-02-27 Thread simendsjo

On 27.02.2011 17:27, Lars T. Kyllingstad wrote:

On Sun, 27 Feb 2011 15:52:01 +0100, simendsjo wrote:


I'm having some problems grokking version.

How would I translate this simple C macro? #if !defined(IDENT) ||
!defined(IDENT2)

I've tried the following:
version(!IDENT)
identifier or integer expected, not !

!version(IDENT)
Declaration expected, not '!'

version(IDENT || IDENT2)
found '||' when expecting ')'

version(IDENT) || version(IDENT2)
Declaration expected, not '||'


This is just plain ugly:
version(IDENT) {
} else {
version = NOT_IDENT_OR_IDENT2;
}

version(IDENT2) {
} else {
version = NOT_IDENT_OR_IDENT2;
}

version(NOT_IDENT_OR_IDENT2) {
// Finally
}


Here's one nice solution to your problem:

http://www.digitalmars.com/d/archives/digitalmars/D/
Improving_version_..._119799.html#N119846

Basically, he defines an isVersion() template which is true if the
current version is enabled, and false if not.

-Lars



Pretty nice, but I don't like magic strings. I'd rather use my more 
clunky version.


Re: Interfacing with c and platform dependent sizes

2011-02-26 Thread simendsjo

On 26.02.2011 17:06, Mike Wey wrote:

On 02/26/2011 11:49 AM, Jacob Carlborg wrote:

On 2011-02-26 01:28, simendsjo wrote:

C is not my strong side, so I'm having some problems wrapping some code.

I found a couple of sources on this:
1) http://www.digitalmars.com/d/2.0/htomodule.html
2) http://www.digitalmars.com/d/2.0/interfaceToC.html

1)
C's long is the same as D's int.
long long is long

2)
C 32bit's long long is D's long, C 64 bits long is D's long.

So.. A long in C is the same as the platform size? And long long doesn't
exist in 64 bit?


In general you can follow the table at
http://www.digitalmars.com/d/2.0/htomodule.html

But when it comes to long in C you have to be careful. On 32bit
platforms a C long will be 32bit long. But on 64bit platforms it
depends of what data model is used. To simplify things:

* On Windows 64bit a C long will be 32bit long
* On Posix 64bit a C long will be 64bit long.

What you can do is to create an alias called c_long and c_ulong,
something like this:

version (D_LP64)
{
version (Windows)
{
alias int c_long;
alias uint c_ulong;
}

else
{
alias long c_long;
alias ulong c_ulong;
}
}

else
{
alias int c_long;
alias uint c_ulong;
}

To read more about data models:
http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models



You can also import core.stdc.config witch defines both c_long and c_ulong.


Thanks for all the answers. Is something like this correct?

version(X86_64)
{
version(Windows)
{
version = LLP64;
}
else version(Posix)
{
version = LP64;
}
else
{
static assert(0);
}

version(LLP64)
{
alias short c_short;
alias ushort c_ushort;
alias int c_int;
alias uint c_uint;
alias int c_long;
alias uint c_ulong;
alias long c_longlong;
alias ulong c_ulonglong;
alias ulong c_size_t;
}
else version(LP64)
{
alias short c_short;
alias ushort c_ushort;
alias int c_int;
alias uint c_uint;
alias long c_long;
alias ulong c_ulong;
alias long c_longlong;
alias ulong c_ulonglong;
alias ulong c_size_t;
}
else version(ILP64)
{
alias short c_short;
alias ushort c_ushort;
alias long c_int;
alias ulong c_uint;
alias long c_long;
alias ulong c_ulong;
alias long c_longlong;
alias ulong c_ulonglong;
alias ulong c_size_t;
}
else version(SILP64)
{
alias long c_short;
alias ulong c_ushort;
alias long c_int;
alias ulong c_uint;
alias long c_long;
alias ulong c_ulong;
alias long c_longlong;
alias ulong c_ulonglong;
alias ulong c_size_t;
}
else
{
static assert(0);
}
}
else version(X86)
{
alias short c_short;
alias ushort c_ushort;
alias int c_int;
alias uint c_uint;
alias int c_long;
alias uint c_ulong;
alias long c_longlong;
alias ulong c_ulonglong;
alias uint c_size_t;
}
else
{
static assert(0);
}



Interfacing with c and platform dependent sizes

2011-02-25 Thread simendsjo

C is not my strong side, so I'm having some problems wrapping some code.

I found a couple of sources on this:
1) http://www.digitalmars.com/d/2.0/htomodule.html
2) http://www.digitalmars.com/d/2.0/interfaceToC.html

1)
C's long is the same as D's int.
long long is long

2)
C 32bit's long long is D's long, C 64 bits long is D's long.

So.. A long in C is the same as the platform size? And long long doesn't 
exist in 64 bit?


Re: Multiple assignment

2011-02-25 Thread simendsjo

On 26.02.2011 01:56, bearophile wrote:

Is this program showing a bug in multiple assignments (DMD 2.052)?


void main() {
 int i;
 int[2] x;
 i, x[i] = 1;
 assert(x == [1, 0]); // OK

 int j;
 int[2] y;
 y[j], j = 1;
 assert(y == [0, 0]); // Not OK
}


At the end of the program I expect y to be [1,0] instead of [0,0].

Yet this C program with GCC:

#include stdio.h
int main() {
 int i = 0;
 int x[2] = {0, 0};
 i, x[i] = 1;
 printf(%d %d\n, x[0], x[1]);

 int j = 0;
 int y[2] = {0, 0};
 y[j], j = 1;
 printf(%d %d\n, y[0], y[1]);

 return 0;
}


has the same output as DMD:
1 0
0 0

Bye,
bearophile


I couldn't find any info on the comma expression in the language 
reference, but this was my first google hit:


A comma expression contains two operands of any type separated by a 
comma and has *left-to-right* associativity. The left operand is fully 
evaluated, possibly producing side effects, and its value, if there is 
one, is *discarded*. The right operand is then evaluated. The type and 
value of the result of a comma expression are those of its right 
operand, after the usual unary conversions




Re: Interfacing with c and platform dependent sizes

2011-02-25 Thread simendsjo

On 26.02.2011 02:06, bearophile wrote:

simendsjo:


So.. A long in C is the same as the platform size? And long long doesn't
exist in 64 bit?


In D the size of int/uint is 32 bits and long/ulong is 64 bits.

In C the size of int, unsigned int, long, long long int, unsigned long long int, etc 
are not fixed, the change according to the CPU. sizeof(int)= sizeof(long)= 
sizeof(long long).

A help:
http://www.digitalmars.com/d/2.0/phobos/std_stdint.html

Bye,
bearophile


Ouch.. Any tips on porting C code that would work nicely with a 
transition to 64 bit?

Should I change all long and int to int_atleast_32_t and long long to 64?


Phobos roadmap?

2011-02-16 Thread simendsjo
I've seen discussions on buffered ranges, std.parallelism, replacement 
of std.xml, std.process and std.stream and probably several other things 
I've already forgotten.


DMD seems to have a quite updated roadmap in the wiki:
http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel#Roadmap

Does something like this exist for Phobos too?
The page above mentions Phobos, but only that it's a moving target.


Re: SO rotate question

2010-09-03 Thread simendsjo

Pelle wrote:

On 09/02/2010 10:24 PM, bearophile wrote:

simendsjo:

Suggestions for D-ifying the code is welcome.


Your unit tests are not good enough, they miss some important corner 
cases.

This my first version in D2:

import std.string: indexOf;

/// return True if s1 is a rotated version of s2
bool isRotated(T)(T[] s1, T[] s2) {
 return (s1.length + s2.length == 0) ||
(s1.length == s2.length  indexOf(s1 ~ s1, s2) != -1);
}

unittest { // of isRotated
 assert(isRotated(, ));
 assert(!isRotated(, x));
 assert(!isRotated(x, ));
 assert(isRotated(x, x));

 string s = rotato;
 assert(isRotated(s, rotato));
 assert(isRotated(s, otator));
 assert(isRotated(s, tatoro));
 assert(isRotated(s, atorot));
 assert(isRotated(s, torota));
 assert(isRotated(s, orotat));

 assert(!isRotated(s, rotator));
 assert(!isRotated(s, rotat));
 assert(!isRotated(s, rotata));
}

void main() {}

Bye,
bearophile


This is what I wrote:

bool isRotated(T)(T[] a, T[] b) {
return a.length == b.length  (a.length == 0 || canFind(chain(a,a), 
b));

}

Use chain to avoid allocation.

canFind isn't really the best possible name, is it?


Sweet! Thats what I was looking for!


SO rotate question

2010-09-02 Thread simendsjo

http://stackoverflow.com/questions/2553522/interview-question-check-if-one-string-is-a-rotation-of-other-string

I created a solution, but I don't want D to look bad, so I won't post 
it. It's a bit for loop heavy...
At least it's shorter than the c example, but I don't know about speed 
or readability..


Suggestions for D-ifying the code is welcome.

import std.range;

bool isRotated(T)(T[] s, T[] d) {
if( s.length != d.length )
return false;

auto cycled = cycle(s);
	for(int loopIdx, matchIdx; loopIdx  d.length || matchIdx  0; 
++loopIdx  cycled.popFront()) {

if( cycled.front == d[matchIdx] )
++matchIdx;
else
matchIdx = 0;

if( matchIdx == d.length )
return true;
}

return false;
}
unittest
{
auto a = rotato;
assert(isRotated(a, rotato));
assert(isRotated(a, otator));
assert(isRotated(a, tatoro));
assert(isRotated(a, atorot));
assert(isRotated(a, torota));
assert(isRotated(a, orotat));

assert(!isRotated(a, rotator));
assert(!isRotated(a, rotat));
assert(!isRotated(a, rotata));
}


Compiler bug? Functions as Array Properties doesn't work with nested functions

2010-08-15 Thread simendsjo

The spec doesn't mention anything about nested functions here.

This works

void foo(int[] a, int x) { };

void main()
{
int[] array;
foo(array, 3);
array.foo(3);
}


But this gives undefined identifier module t.foo

void main()
{
void foo(int[] a, int x) { };
int[] array;
foo(array, 3);
array.foo(3);
}


std.range design part of the language..?

2010-08-15 Thread simendsjo
From http://digitalmars.com/d/2.0/statement.html#ForeachStatement, 
Foreach over Structs and Classes with Ranges.


I read this as the Range design is a part of the language now. Is this 
correct?


And is the spec a bit out of date in the examples?
It says foreach-/reverse translates to

for( auto __r = range; !__r.empty; __r.next /* or __r.retreat */)
auto e = __r.head; // or __r.toe

Should this be the following?
for( auto __r = range; !__r.empty; __r.popFront /* or __r.popBack */)
auto e = __r.front; // or __r.back


Re: std.range design part of the language..?

2010-08-15 Thread simendsjo

On 15.08.2010 23:58, Jonathan M Davis wrote:

On Sunday 15 August 2010 10:12:06 simendsjo wrote:

   From http://digitalmars.com/d/2.0/statement.html#ForeachStatement,
Foreach over Structs and Classes with Ranges.

I read this as the Range design is a part of the language now. Is this
correct?

And is the spec a bit out of date in the examples?
It says foreach-/reverse translates to

for( auto __r = range; !__r.empty; __r.next /* or __r.retreat */)
auto e = __r.head; // or __r.toe

Should this be the following?
for( auto __r = range; !__r.empty; __r.popFront /* or __r.popBack */)
auto e = __r.front; // or __r.back


Those names are indeed out of date. It's another thing that needs to be fixed in
the docs.

- Jonathan M Davis


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


rdmd only works with files in current directory on Windows?

2010-08-14 Thread simendsjo

c:\temp\src\test.d

c:\temprdmd src\test
The system cannot find the path specified.

c:\temprdmd src/test
std.file.FileException: (...)\.rdmd\rdmd-src/test.d-(...): The system 
cannot find the path specified.


Using rdmd 20090902, dmd 2.048 and 64 bit win7


Duck typing and safety.

2010-08-13 Thread simendsjo
While reading std.range, I though that a ducktyping design without 
language/library support can be quite fragile.


Consider the following example:

import std.stdio;

struct S
{
void shittyNameThatProbablyGetsRefactored() { };
}

void process(T)(T s)
{
static if( __traits(hasMember, T, 
shittyNameThatProbablyGetsRefactored))
{
writeln(normal processing);
}
else
{
writeln(Start nuclear war!);
}
}


void main()
{
S s;
process(s);
}


If you rename S's method, process() does something completely different 
without a compile time error. By using interfaces this is avoided as the 
rename would break the interface.


Is there any idoms you can use to avoid stuff like this? Relying on 
documentation doesn't seem like a good solution.


Re: Duck typing and safety.

2010-08-13 Thread simendsjo

On 13.08.2010 19:17, Steven Schveighoffer wrote:

On Fri, 13 Aug 2010 13:01:47 -0400, simendsjo
simen.end...@pandavre.com wrote:


While reading std.range, I though that a ducktyping design without
language/library support can be quite fragile.

Consider the following example:

import std.stdio;

struct S
{
void shittyNameThatProbablyGetsRefactored() { };
}

void process(T)(T s)
{
static if( __traits(hasMember, T,
shittyNameThatProbablyGetsRefactored))
{
writeln(normal processing);
}
else
{
writeln(Start nuclear war!);
}
}


void main()
{
S s;
process(s);
}


If you rename S's method, process() does something completely
different without a compile time error. By using interfaces this is
avoided as the rename would break the interface.

Is there any idoms you can use to avoid stuff like this? Relying on
documentation doesn't seem like a good solution.


You have somewhat missed the point of duck typing. It would look more
like this:

void process(T)(T s)
{
s.shittyNameThatProbabyGetsRefactored();
}


Basically, the point is, you compile *expecting* that you can call the
function, and then when the type doesn't have the function, it simply
fails.

Of course, the error you get is not what you want, because to the
compiler, it's not the call of the function that is the error, it's the
compiling of the function that is the error.

To remedy this, you use template constraints:

void process(T)(T s) if(__traits(hasMember, T,
shittyNameThatProbabyGetsRefactored)
{
...
}

And then the compiler won't even try to compile the function, it just
fails at the call site.

-Steve


Ok, point taken. But take a look at
void put(R, E)(ref R r, E e)
in std.range for instance. This function uses a member put if it exists, 
then front/popfront if it's an input range or opCall as a last instance.


It's easy to imagine such a design for other types where suddenly the 
program behaves differently because of a rename.


Is put a bad design?


typeof and block statements

2010-08-12 Thread simendsjo
The spec doesn't mention anything about block statements in typeof 
declarations.


//typeof({1}) a; // found } expecting ;
//typeof({1}()) b; // same as a
typeof(1) c; // int

I'm asking because isInputRange from std.range the idom from the b test:

template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r; // can define a range object
if (r.empty) {}  // can test for empty
r.popFront;  // can invoke next
auto h = r.front; // can get the front of the range
}()));
}


Also... The unittest contains
static assert(isInputRange!(int[]));
static assert(isInputRange!(char[]));

But arrays doesn't include these methods.. I don't understand a thing :(


Re: typeof and block statements

2010-08-12 Thread simendsjo

On 12.08.2010 15:30, Steven Schveighoffer wrote:

On Thu, 12 Aug 2010 09:13:54 -0400, simendsjo
simen.end...@pandavre.com wrote:


The spec doesn't mention anything about block statements in typeof
declarations.

//typeof({1}) a; // found } expecting ;
//typeof({1}()) b; // same as a
typeof(1) c; // int


{...} is a function literal, a lambda function if you will.


I thought parameterless delegates were written () {}..


Your lambda function contains a syntax error, the single line in it does
not end in a semicolon.

Of course, if you made it:

{1;}

I think it might fail anyways, because 1; is not a statement.


Why doesn't this work then?
typeof({return 1;}()) a; // found 'a' when expecting ';' following statement



I'm asking because isInputRange from std.range the idom from the b test:

template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r; // can define a range object
if (r.empty) {} // can test for empty
r.popFront; // can invoke next
auto h = r.front; // can get the front of the range
}()));
}


is(typeof(...)) is sort of a hack to determine if something compiles or
not. If it does, then there will be a type associated with the
expression, if not, then there will be no type. There is also a
__traits(compiles, ...) which I think really should be used for this
purpose, but the isInputRange may predate that idiom.

Essentially, the isInputRange bool is true if the function literal that
contains those four statements compiles. What it translates to is, Does
R support the functions necessary for input ranges.

I see a syntax error there, r.popFront is not a property, so it should
look like this:

r.popFront();

It only works right now because mandatory () for non-properties is not
implemented in the compiler yet.


So once this is implemented, this template is always false?




Also... The unittest contains
static assert(isInputRange!(int[]));
static assert(isInputRange!(char[]));

But arrays doesn't include these methods.. I don't understand a thing :(


Arrays support tacking on extra methods to it. Essentially, for arrays
(and arrays only), the compiler will translate this:

arr.foo()

to this:

foo(arr)

See http://www.digitalmars.com/d/2.0/arrays.html#func-as-property


Thanks!


Re: typeof and block statements

2010-08-12 Thread simendsjo

On 12.08.2010 16:19, Steven Schveighoffer wrote:

On Thu, 12 Aug 2010 09:56:07 -0400, simendsjo
simen.end...@pandavre.com wrote:


On 12.08.2010 15:30, Steven Schveighoffer wrote:

On Thu, 12 Aug 2010 09:13:54 -0400, simendsjo
simen.end...@pandavre.com wrote:


The spec doesn't mention anything about block statements in typeof
declarations.

//typeof({1}) a; // found } expecting ;
//typeof({1}()) b; // same as a
typeof(1) c; // int


{...} is a function literal, a lambda function if you will.


I thought parameterless delegates were written () {}..


Your lambda function contains a syntax error, the single line in it does
not end in a semicolon.

Of course, if you made it:

{1;}

I think it might fail anyways, because 1; is not a statement.


Why doesn't this work then?
typeof({return 1;}()) a; // found 'a' when expecting ';' following
statement


First, this compiles for me. Not sure why it doesn't for you.

Second, stringof is your friend. Coupled with pragma(msg, ...) It allows
you to view the type of an expression at compile time:

pragma(msg, typeof({return 1;}()).stringof);

Which when compiled on dmd 2.047 linux, prints:

int



Tested with dmd 2.048 on win7.

pragma(msg, module:~typeof({return 1;}()).stringof);

void main()
{
pragma(msg, main:~typeof({return 1;}()).stringof);
	//typeof({return 1;}()) a; // found 'a' when expecting ';' following 
statement

}

prints
module:int
main:int




I see a syntax error there, r.popFront is not a property, so it should
look like this:

r.popFront();

It only works right now because mandatory () for non-properties is not
implemented in the compiler yet.


So once this is implemented, this template is always false?


Once mandatory parens for non-properties is implemented, the code will
be changed to r.popFront();

-Steve




Re: typeof and block statements

2010-08-12 Thread simendsjo

On 12.08.2010 16:39, Steven Schveighoffer wrote:
(...)


Tested with dmd 2.048 on win7.

pragma(msg, module:~typeof({return 1;}()).stringof);

void main()
{
pragma(msg, main:~typeof({return 1;}()).stringof);
//typeof({return 1;}()) a; // found 'a' when expecting ';' following
statement
}

prints
module:int
main:int



Ahh. It fails on 2.047 also if you put the statement inside main. If you
declare it outside main, it works.

Looks like a bug. Please file http://d.puremagic.com/issues/enter_bug.cgi

-Steve


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


Re: [OT] Is this more readable, or just way too verbose?

2010-08-10 Thread simendsjo

Lutger wrote:

simendsjo wrote:


(...)


The CR and LF constants are a bit too much, probably because they don't really 
abstract over the literals which I can actually parse faster. The isCR and isLF 
are nice however. Taking it a step further:


bool canSplit = inPattern(c,\r\n);
if (canSplit)
{
  ...

You have increased the nesting of ifs to 3 inside a for-loop.Personally I don't 
read deep nesting very well. To go for readability I would use a small function 
for the entire expression: 


if( s[i..$].startsWithCRLF() ) // same as startsWithCRLF(s[i..$])
{
  i++;
  istart++;
}

or use std.algorithm: if ( s[i..$].startsWith(\r\n) )
 

(...)
Nice. I didn't increase the if nesting though.

Something like this then?

S[] mysplitlines(S)(S s)
{
size_t istart;

auto result = Appender!(S[])();

foreach (i; 0 .. s.length)
{
immutable c = s[i];
immutable isEOL = inPattern(c, \r\n);
if (isEOL)
{
auto beforeEOL = s[istart .. i];
result.put(beforeEOL);

auto rest = s[i .. $];
immutable isCRLF = rest.startsWith(\r\n);

istart = i + 1; // consume first EOL character
if (isCRLF) // skip \n too
{
i++;
istart++;
}
}
}

// The last line might not end with EOL
immutable lineNotEmpty = (istart != s.length);
if (lineNotEmpty)
{
auto lastLine = s[istart .. $];
result.put(lastLine);
}

return result.data;
}


Re: AA invalidating pointers and references..?

2010-08-09 Thread simendsjo

bearophile wrote:

simendsjo:

I haven't worked much with AA's, but I find the key in aa returns a 
reference to the value to be handy. I think it's better than the following:


int value;
if( 1 in a )
   value = a[1];

or a[1] in a try/catch or other implementations.


Your examples have shown me that probably the current design can't be made 
safe, and you can't use in SafeD code.
But performing x in AA is a very useful operation that I want to perform in 
SafeD code.

And in my opinion this code:

int value;
auto ptr = 1 in a;
if (ptr)
value = *ptr;


Doesn't look better than:

int value;
if (1 in a)
value = a[1];


2) I don't know what you mean. Does a single lookup often involve 
several under the hood?


If your compiler is naive then code like this:
if (1 in a)
value = a[1];
requires to perform two searches inside the hash, the first to tell if the key 
is present, and the second to find it again and fetch its value.

A bit better compiler (LDC is already able to do this) can recognize that you 
are performing two nearby key searches with the same key, and it can remove the 
second one, essentially replacing that code with this one:

int value;
auto ptr = 1 in a;
if (ptr)
value = *ptr;

Bye,
bearophile


You can always use:
auto value = 1 in a;
if (value) // needs != null? Haven't looked at this in the spec yet.
  //work with *value

But if the compiler can optimize the calls either way, and this is 
unsafe, a safer way sounds nice.


[OT] Is this more readable, or just way too verbose?

2010-08-09 Thread simendsjo

I took splitlines from std.string, which is a simple, short method.

S[] splitlines(S)(S s)
{
size_t istart;
auto result = Appender!(S[])();

foreach (i; 0 .. s.length)
{
immutable c = s[i];
if (c == '\r' || c == '\n')
{
result.put(s[istart .. i]);
istart = i + 1;
if (c == '\r'  i + 1  s.length  s[i + 1] == '\n')
{
i++;
istart++;
}
}
}
if (istart != s.length)
{
result.put(s[istart .. $]);
}

return result.data;
}


I guess it takes less than 30 seconds to fully understand this method. 
Then I rap.. I mean refactored it to this:


S[] mysplitlines(S)(S s)
{
const CR = '\r';
const LF = '\n';

size_t istart;

auto result = Appender!(S[])();

foreach (i; 0 .. s.length)
{
immutable c = s[i];

immutable isCR = (c == CR);
immutable isLF = (c == LF);

if (isCR || isLF)
{
auto line = s[istart .. i];
result.put(line);

istart = i + 1;

// Might be CRLF. In that case we need to consume LF too
if (isCR)
{
immutable hasMoreCharacters = (i + 1  s.length);
immutable nextIsLF = hasMoreCharacters  (s[i + 1] == LF);
immutable isCRLF = isCR  nextIsLF;

if (isCRLF)
{
i++;
istart++;
}
}
}
}

immutable lineNotEmpty = (istart != s.length);
if (lineNotEmpty)
{
auto lastLine = s[istart .. $];
result.put(lastLine);
}

return result.data;
}


Yes, I'm reading some books now and don't have much experience :)

It went from a small 26 line, very readable function to 48 lines (85% 
increase!) with many more temporary variables..


So... Do you think this kind of code is (more) readable, or just way too 
verbose and doing more harm than good?


And will the compiler generate slower code, or should the optimizer be 
able to inline the temporaries?


std.string.chomp error

2010-08-09 Thread simendsjo

The documentation says
/***
 * Returns s[] sans trailing delimiter[], if any.
 * If delimiter[] is null, removes trailing CR, LF, or CRLF, if any.
 */

To adhere to the documentation, chomp must be changed from:

C[] chomp(C, C1)(C[] s, in C1[] delimiter)
{
if (endsWith(s, delimiter))
{
return s[0 .. $ - delimiter.length];
}
return s;
}

to:

C[] chomp(C, C1)(C[] s, in C1[] delimiter)
{
if (delimiter == null)
  return chomp(s);
else if (endsWith(s, delimiter))
  return s[0 .. $ - delimiter.length];
else
  return s;
}




Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 09.08.2010 19:16, Lars T. Kyllingstad wrote:

On Mon, 09 Aug 2010 18:58:36 +0200, simendsjo wrote:


The documentation says
/***
   * Returns s[] sans trailing delimiter[], if any. * If delimiter[] is
   null, removes trailing CR, LF, or CRLF, if any. */

To adhere to the documentation, chomp must be changed from:

C[] chomp(C, C1)(C[] s, in C1[] delimiter) {
  if (endsWith(s, delimiter))
  {
  return s[0 .. $ - delimiter.length];
  }
  return s;
}

to:

C[] chomp(C, C1)(C[] s, in C1[] delimiter) {
  if (delimiter == null)
return chomp(s);
  else if (endsWith(s, delimiter))
return s[0 .. $ - delimiter.length];
  else
return s;
}



Either that, or the documentation for it needs to be changed.  Anyway, it
would be great if you'd report this.

http://d.puremagic.com/issues/

Thanks!

-Lars


Ok; http://d.puremagic.com/issues/show_bug.cgi?id=4608


Justify text

2010-08-09 Thread simendsjo
Phobos assumes that you only want to fill with spaces when justifying 
text. I merged the functions with a user supplied character. Don't think 
it should be much slower.. Just the switch extra switch if the function 
is inlined.. (but don't take my word for it :) )?


enum Alignment { Right, Left, Center }

string justify(string text, Alignment alignment, int width, char symbol)
{
if (text.length = width)
return text;

char[] result = new char[width];
switch(alignment)
{
case Alignment.Right:
result[0 .. width - text.length] = symbol;
result[width - text.length .. width] = text;
break;
case Alignment.Center:
int left = (width - text.length) / 2;
result[0 .. left] = symbol;
result[left .. left + text.length] = text;
result[left + text.length .. width] = symbol;
break;
case Alignment.Left:
result[0 .. text.length] = text;
result[text.length .. width] = symbol;
break;
default:
assert(false);
}

return assumeUnique(result);
}

string ljustify(string s, int width)
{
return justify(s, Alignment.Left, width, ' ');
}

string rjustify(string s, int width)
{
return justify(s, Alignment.Right, width, ' ');
}

string center(string s, int width)
{
return justify(s, Alignment.Center, width, ' ');
}


Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 09.08.2010 23:58, bearophile wrote:

simendsjo:

Ok; http://d.puremagic.com/issues/show_bug.cgi?id=4608


You seem to have missed my answer :-)

Bye,
bearophile


No, but I don't know if it's the documentation or implementation that's 
correct.


Re: Justify text

2010-08-09 Thread simendsjo

On 09.08.2010 23:59, simendsjo wrote:


 return justify(s, Alignment.Right, width, ' ');


Forgot zfill:

string zfill(string s, int width)
{
return justify(s, Alignment.Right, width, '0');
}


Missing test in std.string.replace

2010-08-09 Thread simendsjo

Replacing with  / null is missing.
I first looked at the function and modified it. Quickly noticed that a 
few unit tests were missing:


assert(replace(foo, foo, ) == );
assert(replace(foo, foo, null) == );


Re: Missing test in std.string.replace

2010-08-09 Thread simendsjo

On 10.08.2010 00:29, simendsjo wrote:

Replacing with  / null is missing.
I first looked at the function and modified it. Quickly noticed that a
few unit tests were missing:

assert(replace(foo, foo, ) == );
assert(replace(foo, foo, null) == );


I refactored replace to understand what was going on (related to my post 
is this more readable).
I've seen a couple of functions using Appender, and it's documentation 
says it's faster than ~=. I tried to change char[] result to Appender, 
but dmd crashed...



string replace(string s, string from, string to)
{
if (from.length == 0) // Nothing to replace
return s;

char[] result;
for (size_t searchIndex; searchIndex  s.length; )
{
auto rest = s[searchIndex .. s.length];
auto fromIndex = indexOf(rest, from);

bool nothingToReplace = (fromIndex == -1);
if (nothingToReplace)
{
bool firstSearch = (searchIndex == 0);
if (firstSearch)
{
// Never found, so just return s
return s;
}

result ~= rest;
break;
}

auto beforeFrom = s[searchIndex .. searchIndex + fromIndex];
result ~= beforeFrom;
result ~= to;

searchIndex += fromIndex + from.length;
}

return assumeUnique(result);
}


Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 09.08.2010 19:34, bearophile wrote:

Lars T. Kyllingstad:

Either that, or the documentation for it needs to be changed.  Anyway, it
would be great if you'd report this.


A really basic unit testing is able to catch an error like this. This means 
Phobos needs more unit tests.

Stuff that may be added to that unittest:

import std.stdio, std.string;
void main() {
 assert(chomp(hello) == hello);
 assert(chomp(hello\n) == hello);
 assert(chomp(hello\r\n) == hello);
 assert(chomp(hello, ) == hello);
 assert(chomp(hello\n, ) == hello);
 assert(chomp(hello\r\n, ) == hello);
 assert(chomp(hello\r\n, ) == hello);
 assert(chomp(helloxxx, x) == helloxx);
}


But instead of:
if (delimiter == null)
Is better to write:
if (delimiter.length == 0)
Or:
if (delimiter == )

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

Bye,
bearophile


Ahem.. :) Yes, I did miss your answer! How I got fooled by the preview 
pane and never noticed the scrollbar.
I cannot see how your other bug report relates to this though. For 
chomps part it's just an implementation vs. documentation issue.


Cannot use local xxx as parameter to non-global template.

2010-08-09 Thread simendsjo
I'm new, so this is most certainly my fault I guess, but I cannot 
understand the error message...

I wish to slice an array and store the slices in a tuple.

auto partitionArray(T)(T[] array, int offset, int len)
{
auto pre = array[0 .. offset];
auto slice = array[offset .. offset+len];
auto post = array[offset+len .. $];

return Tuple!(pre, slice, post);
}
unittest
{
auto val = partitionArray([1,2,3,4], 1, 2);
}

typecons.d(255): Error: template instance cannot use local 'post' as 
parameter to non-global template A(U...)


Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 10.08.2010 02:09, Jonathan M Davis wrote:

On Monday, August 09, 2010 16:59:07 bearophile wrote:

simendsjo:

Ahem.. :) Yes, I did miss your answer! How I got fooled by the preview
pane and never noticed the scrollbar.


No problem, it happens, don't worry.


I cannot see how your other bug report relates to this though.


My other bug report is about this line in your code:
  if (delimiter == null)
I don't like it :-)

Bye,
bearophile


Why, because it should be

if(delimiter is null)


or just

if(!delimiter)


- Jonathan M Davis


Hehe.. You're a bit beyond my D level right now. At least I now know 
null == false and you can do reference is null :)


[OT] What is more readable?

2010-08-09 Thread simendsjo
Continuing my what is more readable thread (just shut me up, but I 
don't always agree with i, j, k etc...):


std.string.count:

size_t count(string s, string sub)
{
size_t i;
int j;
int count = 0;

for (i = 0; i  s.length; i += j + sub.length)
{
j = indexOf(s[i .. s.length], sub);
if (j == -1)
break;
count++;
}
return count;
}




size_t count(string s, string sub)
{
int result = 0;

int subStart = 0;
for (size_t restStart = 0; restStart  s.length; restStart += 
subStart + sub.length)

{
auto rest = s[restStart .. $];
subStart = indexOf(rest, sub);

bool notFound = (subStart == -1);
if (notFound)
break;

result++;
}

return result;
}


More constants in std.string?

2010-08-09 Thread simendsjo
\r and \n is used many times throughout std.string (and probably other 
modules like file).

I assume defining constants were considered:
const CR = '\r';
const LF = '\n';

So why isn't constants used instead?


std.string.translate using initializing twice?

2010-08-09 Thread simendsjo

translate does this:
bool[256] deltab; // this would make all values of deltab false as 
bool.init == false, right?


deltab[] = false;

Isn't this just initializing all values of deltab to false twice..?

And my Is this more readable?

Original:

string translate(string s, in string transtab, in string delchars)
in
{
assert(transtab.length == 256);
}
body
{
char[] r;
int count;
bool[256] deltab;

deltab[] = false;
foreach (char c; delchars)
{
deltab[c] = true;
}

count = 0;
foreach (char c; s)
{
if (!deltab[c])
count++;
//printf(s[%d] = '%c', count = %d\n, i, s[i], count);
}

r = new char[count];
count = 0;
foreach (char c; s)
{
if (!deltab[c])
{
r[count] = transtab[c];
count++;
}
}

return assumeUnique(r);
}



More readable?:


string translate(string s, in string transtab, in string delchars)
in
{
assert(transtab.length == 256);
}
body
{
// Mark characters to delete
bool[256] deltab;
foreach (char c; delchars)
deltab[c] = true;

// Count characters to translate
int numToTranslate;
foreach (char c; s)
{
if (!deltab[c])
numToTranslate++;
}

char[] result = new char[numToTranslate];

// Translate
int translateIndex = 0;
foreach (char c; s)
{
bool mustTranslate = !deltab[c];
if (mustTranslate)
{
result[translateIndex] = transtab[c];
translateIndex++;
}
}

return assumeUnique(result);
}



Re: [OT] What is more readable?

2010-08-09 Thread simendsjo

On 10.08.2010 02:40, Jonathan M Davis wrote:

On Monday, August 09, 2010 17:20:07 simendsjo wrote:

Continuing my what is more readable thread (just shut me up, but I
don't always agree with i, j, k etc...):


Personally, I think that i is just fine in many cases where it's quite clear 
what
you're doing. e.g. the standard for loop:

for(size_t i = 0; i  a.length; ++i)
   //whatever we do with a[i]...

foreach does reduce how often that sort of thing is necessary though. However,
once you get beyond i, and maybe j, it just gets confusing (not to mention the
fact that i and j look a fair bit alike). So, personally, I avoid going beyond
i, and I don't use i unless it's quite clear what I'm doing. Other than that, I
find clearly named variables make the code much easier to read and understand -
especially if someone else wrote the code, or you haven't read it in a while.

- Jonathan M Davis



I also use i in my for loops. Always!
But I still find it difficult to understand when there are more than one 
index in use.


The thing here is that I couldn't understand the function top to bottom..
j was used both by the incrementer in the for loop, in the indexOf and 
the if statement. I had to get to the indexOf before I could understand 
what j was.


Of course, I'm just pointing out very small areas of potential 
improvement as I've only covered 5% of the spec and 1% of the stdlib :)


Re: More constants in std.string?

2010-08-09 Thread simendsjo

On 10.08.2010 02:46, Jonathan M Davis wrote:

On Monday, August 09, 2010 17:24:47 simendsjo wrote:

\r and \n is used many times throughout std.string (and probably other
modules like file).
I assume defining constants were considered:
const CR = '\r';
const LF = '\n';

So why isn't constants used instead?


Well, what would that really save or help? They're totally unambiguous and
easily typed with the keyboard. Not to mention, if you were going to do that,
you'd probably define them like so

enum CR = \r;
enum LF = \n;

Using enum for manifest constants is the more typical way to do it in D (it also
forces compile-time evaluation of their value), and we want to avoid using
individual chars or wchars, so pretty much all string-related functions take
strings even if you'd think that they'd take a character of some kind (though if
they were to take a character type, it would have to be dchar).

In any case, the values for these constants never change regardless of the
machine - unlike something like path.sep which indicates the path separator for
the machine and changes depending on which machine you compile on. For it to be
worth making \r and \n constants, you have to gain something from it, and I
don't think that there's much to be gained. Not to mention, you can always make
more constants, and you have to stop somewhere, so you're always going to find
something that _could_ be a constant and isn't.

- Jonathan M Davis


I agree. I really don't thing it makes a difference or not.. '\r' is 
always that symbol no matter if it's a iPhone, embedded device or 
supercomputer. It's more that it's more error prone to write it than CR 
(ooops! compiler error!). If I wrote '\e' in a large switch and haven't 
tested all code paths.. Yes, shame on me, but I really meant \r! A 
constant gives me an at once. D is all about removing common, stupid 
programmer errors like I do, right? :)


It's just nitpicking and not a big deal at all. I can only remember once 
I've been bitten by one of these (not in D), but I quickly found the source.


Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 10.08.2010 03:08, bearophile wrote:

Jonathan M Davis:

Why, because it should be

if(delimiter is null)


or just

if(!delimiter)


if (delimiter.length == 0)
Or
if (!delimiter.length)

Bye,
bearophile


Isn't that very different things? You cannot use .length if delimiter is 
null.




AA invalidating pointers and references..?

2010-08-08 Thread simendsjo

unittest
{
auto a = [1:2];
auto p = 1 in a;
// can p be invalidated by rehashing?
	// That is pointing to a different item or a memory location used for 
other things?


auto b = a.rehash;

	// The spec also says it orders in place, but returns the reorganized 
array...

// Is the spec right? That it rehashes in place and returns a reference 
to
// itself?
assert(a is b);
}

unittest
{
auto a = [1:2];
auto p = 1 in a;
a.remove(1);
// the memory for p can be reassigned by the gc,
// so this is undefined behavior.. right?
assert(*p == 2);
}


Re: AA invalidating pointers and references..?

2010-08-08 Thread simendsjo

On 08.08.2010 17:51, bearophile wrote:

simendsjo:


auto a = [1:2];
auto p = 1 in a;
// can p be invalidated by rehashing?


Yes, I presume it can. p is meant for immediate consumption only.



// The spec also says it orders in place, but returns the reorganized
array...
// Is the spec right? That it rehashes in place and returns a reference 
to
// itself?
assert(a is b);


Yes, a and b are meant to be equal, because they are a reference, that doesn't 
change. What changes is the data structures referenced by it (if what I have 
just said turns out to be wrong, then probably it's an implementation bug that 
needs to be added to bugzilla).



Ok, thanks.




auto a = [1:2];
auto p = 1 in a;
a.remove(1);
// the memory for p can be reassigned by the gc,
// so this is undefined behavior.. right?


Right, such things show that it's probably better to change the D AA design 
here:
1) make x in AA return a bool
2) improve dmd so it is able to remove most cases of dual lookups in AAs.

I will think if this needs to become an enhancement request.


1)
I haven't worked much with AA's, but I find the key in aa returns a 
reference to the value to be handy. I think it's better than the following:


int value;
if( 1 in a )
  value = a[1];

or a[1] in a try/catch or other implementations.

2) I don't know what you mean. Does a single lookup often involve 
several under the hood?


Re: Array Operations and type inference

2010-08-08 Thread simendsjo

On 07.08.2010 14:10, simendsjo wrote:

I'm new to D2, so please.. :)


(...)

Thanks for all answers. Seems array operations is a bit buggy, so I'll 
rather look more into them at a later date.


Re: Slicing to convert pointers to bound arrays

2010-08-08 Thread simendsjo

On 07.08.2010 16:48, bearophile wrote:

simendsjo:

When I do the same with a static array, I get 0. But this is just
actually garbage, right? It might contain other data, and not always 0?


Generally it contains garbage.
In string literals there is one more item that's empty (zero). I don't know if 
normal fixed-sized arrays too have the extra leading zero item (maybe yes), but 
relying on it is surely bad programming practice.

Bye,
bearophile


Ok, thanks. I expected this, but It's good to get it verified.


Re: Static arrays passed by value..?

2010-08-08 Thread simendsjo

On 08.08.2010 01:52, BCS wrote:

What that is saying is that if the type of the function arg is a static
array... not if the value passed to the function is a static array...


Yes, it would help to read the spec a bit closer :)


What on earth is a ref function?

2010-08-08 Thread simendsjo

The spec is very short here, and the example doesn't give me much..

// I thought allows functinos to return by reference meant it could 
return local variables..

ref int* ptr() {
auto p = new int;
*p = 12;
return p; // Error: escaping local variable
}

// So whats the difference between these functions?

ref int val() {
auto p = new int;
assert(*p == 0);
*p = 10;
assert(*p == 10);
return *p;
}

int val2() {
auto p = new int;
*p = 10;
return *p;
}

unittest
{
assert(val() == 10);
assert(val2() == 10);
auto retvalue = val() = 99; // References can be lvalues.. What?
assert(retvalue == 99);
}


Where is function parameter storage classes documented?

2010-08-08 Thread simendsjo
There is very little documentation in the function documentation and 
none in declaration. Or am I just a little blind?


Array Operations and type inference

2010-08-07 Thread simendsjo

I'm new to D2, so please.. :)

The spec on Array Operations, 
http://www.digitalmars.com/d/2./arrays.html says:
A vector operation is indicated by the slice operator appearing as 
the lvalue of an =, +=, -=, *=, /=, %=, ^=, = or |= operator.


The following tests works fine as I expected:


{
double[3] a = [1,1,1];
double[3] b;
b[] = a[] + 3;
assert(a == [1,1,1]);
assert(b == [4,4,4]);
}

{
double[3] a = [1,1,1];
auto b = a;
b[] = a[] + 3;
assert(a == [1,1,1]);
assert(b == [4,4,4]);
}

But from here on I'm having problems...

{
double[] a = [1,1,1];
double[] b;
b[] = a[] + 3;
assert(a == [1,1,1]);
		assert(b == [4,4,4]); // fails as b.length == 0.. Should the compiler 
say something?

}

{
double[] a = [1,1,1];
double[] b;
b.length = a.length;
b[] = a[] + 3;
assert(a == [1,1,1]);
assert(b == [4,4,4]); // Now it's fine
}

{
double[3] a = [1,1,1];
		double[3] b = a[] + 3; // works although lvalue isn't a slice. Static 
arrays? Because it's an initial value?

assert(a == [1,1,1]);
assert(b == [4,4,4]);
}

{
double[3] a = [1,1,1];
auto b = a;
b = a[] + 3; // And so does this.. Something to do with static 
arrays?
assert(a == [1,1,1]);
assert(b == [4,4,4]);
}

{ // Like the previous example, but with dynamic arrays..
double[] a = [1,1,1];
auto b = a;
assert(a is b);
b = a[] + 3;
assert(a == [1,1,1]);
//writeln(b); // access violation. Because of dynamic arrays?
}   

{ // Like above, but using slicing like the spec says.. Works fine
double[] a = [1,1,1];
auto b = a;
assert(a is b);
writeln(typeof(b).stringof); // double[]
b[] = a[] + 3;
assert(a == [4,4,4]); // a also changed. I expected this
assert(b == [4,4,4]);
}

{
double[3] a = [1,1,1];
auto b = a[] + 3; // What happens here?
writeln(typeof(b).stringof); // double[]
assert(b.length == 3);
assert(b.capacity == 0);
//writeln(b); // access violation
}

{ // Same as above?
double[3] a = [1,1,1];
//writeln(a[] + 3); // access violation
}



Slicing to convert pointers to bound arrays

2010-08-07 Thread simendsjo

I understand this is an unsafe operation, I just have a quick question.


Here, b points outside a's memory, so I get garbage.
{
int[] a = [3,3,3];
auto p = a.ptr;
auto b = p[0..3];
assert(b == [3,3,3]);
b = p[0..4]; // b == [3,3,3,?]
}


When I do the same with a static array, I get 0. But this is just 
actually garbage, right? It might contain other data, and not always 0?


{
int[3] a = [3,3,3];
auto p = a.ptr;
auto b = p[0..3];
assert(b == [3,3,3]);
b = p[0..4];
assert(b == [3,3,3,0]);
}


Is is the same as ptr == ptr for arrays?

2010-08-07 Thread simendsjo

Is the following equalent?

int[] a;
int[] b = a;
assert(a is b);
assert(a.ptr == b.ptr);


Re: Is is the same as ptr == ptr for arrays?

2010-08-07 Thread simendsjo

On 07.08.2010 18:04, Peter Alexander wrote:

On 7/08/10 4:33 PM, simendsjo wrote:

Is the following equalent?

int[] a;
int[] b = a;
assert(a is b);
assert(a.ptr == b.ptr);


No.

(a is b) implies (a.ptr == b.ptr)

but

(a.ptr == b.ptr) does not imply (a is b)

For example:

int[] a = [1, 2, 3];
int[] b = a[0..1];

Here, a.ptr == b.ptr, but a !is b.

The ptr property returns a pointer to the first element, which is true
in this case, but it doesn't mean that they both refer to the same range.



Ok, thanks. Does this mean this equivalent then?

int[] a = [1,2,3];
int[] b = a[0..1];
assert(a !is b);
assert(a.ptr == b.ptr  a.length == b.length);


Static arrays passed by value..?

2010-08-07 Thread simendsjo

The spec for array says:
	Static arrays are value types. Unlike in C and D version 1, static 
arrays are passed to functions by value. Static arrays can also be 
returned by functions.


I don't get the static arrays are passed to functions by value part.

Here I am passing in a static and dynamic array. Both are passed by 
value, and the function can modify the array of both


{
void func(int[] arr, void* ptr) {
arr[0] = 9;
assert(arr != ptr);
}

int[3] a = [1,2,3];
func(a, a);
assert(a == [9,2,3]); // changed..

int[] b = [1,2,3];
func(b, b);
assert(b == [9,2,3]);
}


Isn't __traits part of the language?

2010-08-06 Thread simendsjo

Rationale (http://digitalmars.com/d/2.0/rationale.html) says:
Why not use operator names like __add__ and __div__ instead of opAdd, 
opDiv, etc.?


__ keywords should indicate a proprietary language extension, not a 
basic part of the language. 



But traits is explained under the language spec, 
http://digitalmars.com/d/2.0/traits.html.



Can I expect traits to exist for all compiler implementations, or just dmd?


Is it bad practice to alter dynamic arrays that have references to them?

2010-08-05 Thread simendsjo
Just tell me if this is frowned upon... The reason I posted on SO is 
because I think it can help making people aware of D.


http://stackoverflow.com/questions/3416657/is-it-bad-practice-to-alter-dynamic-arrays-that-have-references-to-them

Let me know if it's not accepted to crosspost like this.


Re: Is it bad practice to alter dynamic arrays that have references to them?

2010-08-05 Thread simendsjo

On 05.08.2010 19:35, Steven Schveighoffer wrote:

On Thu, 05 Aug 2010 13:10:44 -0400, simendsjo
simen.end...@pandavre.com wrote:

(...)


One helpful function to note is the capacity function:

http://digitalmars.com/d/2.0/phobos/object.html#capacity

This gives you the capacity of the array, or the largest length it can
be set to without reallocating. If it's 0, that means any append will
reallocate. This can allow deterministic behavior when appending. Or you
can just dup the array if you want to ensure you don't mess up the
original copy.


Ah, that's really good to know! So I can see if it will reallocate using
bool willReallocate = array.capacity  (array.length + 
numberOfItemsToAppend)

?



Let me know if it's not accepted to crosspost like this.


I think there is no problem with that.


Good, then I'll keep on doing that then.

Thanks a lot for your answer!


-Steve




Re: Is it bad practice to alter dynamic arrays that have references to them?

2010-08-05 Thread simendsjo

On 05.08.2010 20:50, Steven Schveighoffer wrote:

On Thu, 05 Aug 2010 14:41:12 -0400, simendsjo
simen.end...@pandavre.com wrote:


On 05.08.2010 19:35, Steven Schveighoffer wrote:

On Thu, 05 Aug 2010 13:10:44 -0400, simendsjo
simen.end...@pandavre.com wrote:

(...)



(...)

Ah, that's really good to know! So I can see if it will reallocate using
bool willReallocate = array.capacity  (array.length +
numberOfItemsToAppend)
?


Yes, except the condition should be =. And that function is
implementation independent (the value returned isn't, but it's
guaranteed that willReallocate should reflect whether the runtime will
reallocate)


bool willReallocate(T)(T[] array, T[] toAppend) {
return array.capacity  (array.length + toAppend.length);
}

int[] a = [0];
auto aOldPtr = a.ptr;
assert(a.capacity == 3);

// a.length == a.capacity, so no reallocation
int[] b = [1,2];
assert(!willReallocate(a, b));
a ~= b;
assert(a.ptr == aOldPtr);

// c.length == 0, so still no
int[] c;
assert(!willReallocate(a, c));
a ~= c;
assert(a.ptr == aOldPtr);

// there, a.length  a.capacity and reallocation
int[] d = [3];
assert(willReallocate(a, d));
a ~= d;
assert(a.ptr != aOldPtr);




<    1   2   3   4   5   6