Re: Synchronized const methods

2010-06-11 Thread Daniel Keep

immutable means "no one can modify this."

const means "someone might be able to modify this, but not you can't."


Re: Yet more OPTLINK woes

2010-05-13 Thread Daniel Keep

Some general replies:

There have been three responses along the lines of "are you sure OPTLINK
is running?".  Quoting myself:

"Invoking OPTLINK directly changes nothing."

Or to be more specific:

> link AstTest,AstTest,,user32+kernel32/noi+tango.lib;
(zero-byte .map file pops into existence)

Yes, I'm sure.  I'm also sure it's the DigitalMars link.exe and in the
correct directory.

> I've had problems before with DMD silently exiting without an error
> message and with error success and leaving behind a corrupt .obj.

I had a look at the .obj file (I actually used lib to stuff it into a
.lib file and then dump the symbols), and it looked fine.

Well, except for this:

_D11TokenStream<80><8d><8d>5_ctorMFC6SourceP<80><90><91>
  DFS8Location<80><89><89>AaYvJS6<80><85>s5Zb<80>
  <99>ZC<81><9a><87>

(broken across 3 lines;  are bytes in hex since several of them were
non-printable.)

The same had happened to a number of symbols from tango.io.stream.Format.

In the case of the first one, the appropriate declarations (with
fully-qualified module name commented) are:

> final class /*TokenStream.*/TokenStream
> {
> alias bool function(Source, LocErr, out Token) NextToken;
> this(Source src, NextToken next, LocErr err) { ... }
> }
>
> final class /*Source.*/Source { ... }
>
> alias void delegate(Location, char[], ...) /*Location.*/LocErr;
>
> struct /*Location.*/Location { ... }

As far as I understand D's name mangling, that symbol name is corrupt.

> CTFE recursion is the only reported unfixed bug that does that ...

There is exactly one CTFE function that calls itself.  However, it
cannot recurse more than once (it does so to change types) *and* this
function is used in the LexerTest program which does compile.

AstTest uses an additional CTFE function, but this just concatenates
some strings together.

> Try and remove stuff until it starts working

I've gutted the changes between LexerTest and AstTest to the point that
I get an .exe.  This involved stripping out more or less every global
and member function that was added and every derived class.

What tipped it over into compiling was removing the reference to
StructuredOutput from AstDumpVisitor.  Which is odd, because
StructuredOutput is still being used in AstTest.

StructuredOutput, once gutted, is this:

> module StructuredOutput;
>
> import tango.io.model.IConduit : OutputStream;
> import tango.io.stream.Format : FormatOutput;
>
> final class StructuredOutput
> {
> alias StructuredOutput This;
> this(OutputStream os)
> {
> }
> }

I honestly can't see what it could be upset about.

> Post the source and I'll try to help. I like debugging weird problems.
> :)

Attached both regular and decaffeinated^Hgutted versions.


matheval.7z
Description: Binary data


matheval-gutted.7z
Description: Binary data


Yet more OPTLINK woes

2010-05-12 Thread Daniel Keep

That's right, it's time for everyone's favourite [1] game: guess why
OPTLINK's not working! [2]

*sigh*  I'm writing a math eval library.  There are two test
applications.  LexerTest only touches part of the code.  AstTest touches
everything.

Now, the following works and creates an executable:

dmd -ofLexerTest (appropriate .d files)

So far, so good.  I get LexerTest.map, LexerTest.obj and LexerTest.exe.
 Let's try the other one...

dmd -ofAstTest (more .d files)

This creates a legitimate-looking AstTest.obj and a completely empty
AstTest.map file.

That's it.

No executable, no error message, no register dump, nothing.

Adding or removing -g, -debug, -unittest, -release, -inline, -O does
nothing.  Changing the target filename does nothing useful.

There are no spurious link.exe or dmd.exe processes running.  Invoking
OPTLINK directly changes nothing.

Does anyone have any idea, any idea at all, on what could be causing
this?  I've tried everything myself and several others on #d could think of.

*miserable sob*

After over five years of this sort of shit, I am so, so completely and
utterly sick to death of OPTLINK.



[1] I am, of course, being sarcastic.

[2] It is, of course, entirely possible that it's not OPTLINK's fault.
Frankly though, I find that hard to believe.


Re: metaprogramming question

2010-04-18 Thread Daniel Keep

http://while-nan.blogspot.com/2007/06/wrapping-functions-for-fun-and-profit.html

It shouldn't be too difficult to inject an extra parameter; just add it
to the end of the call to the wrapped function after args.


Re: gdc and Make

2010-04-10 Thread Daniel Keep

bud, rebuild and xfbuild were designed so we wouldn't NEED Makefiles in
the first place.

Unless you've got a good reason, just use a recent dmd and xfbuild.


Re: enum values without initializer

2010-04-06 Thread Daniel Keep


bearophile wrote:
> Nick Sabalausky:
> 
>>> If you don't want that doplication you can also write:
>>> enum auto f = Foo();
>> Can't you do:
>> enum f = Foo();
>> ?
> 
> In my opinion that's a semantic mess, I don't write that. auto is for 
> automatic local type inference and enum is to ask for a compile time constant.

No it isn't.  'auto' is a storage class, it has NOTHING to do with type
inference.

Type inference is triggered when the type is omitted from a declaration.
 It just turns out that in the majority of cases (variables), the
easiest way to do this is to use the default storage class which is used
if you don't otherwise specify one: auto.

This is why 'const blah = 42;' works: const is used as a storage class
and the type is omitted.


Re: tango and unicode

2010-03-31 Thread Daniel Keep

Ellery Newcomer wrote:
> Is there an equivalent of std.utf.stride anywhere in tango?

decode in tango.text.convert.Utf.

Returns the code point at the start of the string and passes the length
in code units out of the second parameter by ref.


Re: D1: Overloading across modules

2010-03-23 Thread Daniel Keep


Nick Sabalausky wrote:
> In D1, is there any reason I should be getting an error on this?:
>
> // module A:
> enum FooA { fooA };
> void bar(FooA x) {}
> 
> // module B:
> import A;
> enum FooB { fooB };

alias A.bar bar;

> void bar(FooB x) {}
> 
> bar(FooB.fooB); // Error: A.bar conflicts with B.bar
> 
> Is overloading across modules not allowed? Is overloading on two different 
> enum types not allowed? Is it a DMD bug? Or does this all work fine and I 
> probably just have some other problem elsewhere? 

The compiler assumes that, unless you specifically tell it otherwise,
symbols pulled in from another module conflict with local ones.

This might also work: import A : bar;


Re: is pointer

2010-03-20 Thread Daniel Keep

bearophile wrote:
> (I am looking for rough corners in D, or in my knowledge of D.)
> 
> In this page:
> http://www.digitalmars.com/d/2.0/templates-revisited.html
> 
> In the section "Template Parameters" there is written:
> 
> P:P*, // P must be a pointer type
> 
> -
> 
> So I have written this D2 program:
> 
> 
> template IsPointer1(T) {
> enum bool IsPointer1 = is(T : T*);
> }
> void main() {
> int* ptr;
> static assert(IsPointer1!(typeof(ptr))); // Err
> }
> 
> 
> But it asserts, do you know why?

You do realise that "Template Parameters" are a completely different
thing to "is expressions", right?


Re: exceptions

2010-02-24 Thread Daniel Keep


Ellery Newcomer wrote:
> On 02/24/2010 03:10 AM, bearophile wrote:
>> Ellery Newcomer:
>>> Okay, does anyone know a good way to figure out where something like
>>> this is coming from:
>>> object.Exception: lengths don't match for array copy
>>
>> void main() {
>>  auto a1 = new int[5];
>>  auto a2 = new int[4];
>>  a1[] = a2;
>> }
>>
>> Bye,
>> bearophile
> 
> I want line numbers

You could use Tango and enable stack tracing.  That or hook up a debugger.


Re: When is array-to-array cast legal, and what does actually happen?

2010-02-22 Thread Daniel Keep

> ...
>
> I see that neither the constructor nor the postblit is called.
> Apparently the bit representation is used. This has the risk of
> violating struct invariants.
> 
> Is it legal?
> 
> Thank you,
> Ali

cast is to value conversions what a tactical nuclear strike is to
peaceful negotiations.  cast is specifically *designed* to circumvent
the type system's protections [1].

If you want to do a value conversion, *do a value conversion*.  Allocate
a new array and convert each member.  cast doesn't call the constructor
or the postblit because it's doing a pointer conversion.

Your code is basically equivalent to this:

void main()
{
auto tmp = "hello"d;
auto mine = cast(MyChar*)(tmp.ptr)
[0..(tmp.length*typeof(tmp[0]).sizeof)/MyChar.sizeof)];
}

That is, it's doing an unsafe, unchecked pointer cast, then re-slicing
the array.

To answer your question: yes, it's legal.  Not what you wanted, but legal.



[1] Except for int<->float.  Oh, and objects.  Really, this is one thing
I could just about strangle K&R for: conflating value-preserving,
non-value-preserving *AND* unsafe conversions all into a single
construct.  Walter, gets slapped with a fish for not putting a bullet in
cast's head when he had the chance.  Argh!


Re: Commmandline arguments and UTF8 error

2010-02-22 Thread Daniel Keep


Jacob Carlborg wrote:
> On 2010-02-22 15.39, Nils Hensel wrote:
>> Daniel Keep schrieb:
>>> If you look at the real main function in src\phobos\internal\dmain2.d,
>>> you'll see this somewhere around line 109 (I'm using 1.051, but it's
>>> unlikely to be much different in an earlier version):
>>>
>>>> for (size_t i = 0; i<  argc; i++)
>>>> {
>>>>  auto len = strlen(argv[i]);
>>>>  am[i] = argv[i][0 .. len];
>>>> }
>>>>
>>>> args = am[0 .. argc];
>>>>
>>>> result = main(args);
>>>
>>> In other words, Phobos never bothers to actually convert the arguments
>>> to UTF-8.
>>
>> Hmm, I really can't see any benefit. Did Walter ever comment on this
>> matter? Surely, I can't be the only one who is unable to use D for
>> something as mundane as a command line tool that takes file names for
>> arguments?
>>
>>> Tango does (tango\core\rt\compiler\dmd\rt\dmain2.d:238 for a recent-ish
>>> trunk).
>>
>> Actually I was trying to avoid Tango. For one I'm not too fond of the
>> interface [Stdout.format(...).newline just seems awkward und
>> unnecessarily complicated compared to writef(...)].

It *is* more verbose.  It's one of the few things I've never liked about
Tango.

That said, the justification for it is that Stdout.format /
Stdout.formatln is significantly clearer.  Plus, you also get an Stderr
version as well.

>> Also, I use derelict
>> which I don't believe supports Tango yet.

I'm fairly certain it should.  I'm positive I've used them together in
the past.

>> And I liked the
>> out-of-the-box-feeling of Phobos which is supposedly the standard.

That's a bit like not using Boost because there's the C standard library.

Whilst Tango is not a strict superset of Phobos, it generally does more
and does it better.  For example, it actually makes the effort to decode
command line arguments.  :P

> You can use derelict with tango. I can agree you about Stdout.format,
> You can create wrappers like this:
> 
> void writeln (ARGS...) (ARGS args)
> {
> foreach (arg ; args)
> Stdout(arg);
> 
> Stdout().newline;
> }
> 
> void writefln (ARGS...) (char[] str, ARGS args)
> {
> foreach (arg ; args)
> Stdout.format(str, arg);
> 
> Stdout().newline;
> }

Shouldn't that be

void writefln(Args...)(char[] str, Args args)
{
Stdout.formatln(str, args);
}

Incidentally, you don't need the `()`s before `.newline`.

>> Guess I have to make up my mind if all the extra hassle of installing
>> and learning (and updating) another and utterly different "standard"
>> library outweighs the benefits of developing in D.

Having written projects using both Phobos and Tango (not in the same
project, mind you), I'd say Tango is very much worth the effort.

Just... just don't use the Zip module.  It's complete and utter crap.


Re: Commmandline arguments and UTF8 error

2010-02-21 Thread Daniel Keep


Nils Hensel wrote:
> Hello, group!
> 
> I have a problem writing a small console tool that needs to be given
> file names as commandline arguments. Not a difficult task one might
> assume. But everytime a filename contains an Umlaut (ä, ö, ü etc.) I
> receive "Error: 4invalid UTF-8 sequence".
> 
> Here's the sample code:
> 
> import std.stdio;
> 
> int main(string[] argv)
> {
>foreach (arg; argv)
>{
>   writef(arg);
>}
>return 0;
> }
> 
> I use dmd v1.046 by the way.
> 
> How do I make the argument valid? I need to be able to use std.path and
>  std.file methods on the file names.
> 
> Any help would be greatly appreciated.
> 
> Regards,
> Nils Hensel

If you look at the real main function in src\phobos\internal\dmain2.d,
you'll see this somewhere around line 109 (I'm using 1.051, but it's
unlikely to be much different in an earlier version):

> for (size_t i = 0; i < argc; i++)
> {
> auto len = strlen(argv[i]);
> am[i] = argv[i][0 .. len];
> }
>
> args = am[0 .. argc];
>
> result = main(args);

In other words, Phobos never bothers to actually convert the arguments
to UTF-8.

Tango does (tango\core\rt\compiler\dmd\rt\dmain2.d:238 for a recent-ish
trunk).


Re: immutable string literal?

2010-02-21 Thread Daniel Keep

strtr wrote:
> On winXP (D1) I can compile/run this code without a problem.
> Not even a warning.
> 
> void main() {
>   char[] s= "immutable literal?";
>   s[$-1] = '!';
>   writefln(s);
> } 
> Codepad runs into a segmentation fault.
> http://codepad.org/NQfsRoR5
> 
> Why doesn't it result in a compiler error or warning?
> If it did I would have noticed this quirk earlier.

There's no compiler error because D1 doesn't have a const/immutable system.

There's no crash because Windows doesn't write-protect the data segment
which contains the literal.


Re: use variant as associative array

2010-02-11 Thread Daniel Keep


GG wrote:
> Yes I can't use struct and/or enum because I can't know type and number of 
> data that user could pass.
> In this example, we talk about Month, but it could be Minutes, week... So I 
> try to program dynamic not static.

If you're trying to program dynamically, then you're using the wrong
language.  Writing dynamically-typed code in D is like trying to write C
in Python; it's missing the language's strengths.

> In fact I'm learning D thought a little project of graphic chart. I would 
> like to keep a notion that I have found very usefull in AS3 : ArrayCollection.

AS3 is dynamically typed; D is not.  Variant can be used to 'fake'
dynamic typing, but only to a certain degree.  You can't call methods on
Variants, operations on them are kinda flaky, etc.

> I just want to know if it possible in D to have only one BIG collection of 
> any type of data (int,string,bool,double...) ?

Arrays of Variant.

> We talk about Variant but it could be other ? Maybe not...
> 
> So I tried this :
> Variant[char[]][int] aa;
> 
>   aa[0]["Month"] = Variant("Jan"); // compile
>   aa[0]["Profit"] = Variant(500); // compile
> 
>   aa[1]["Month"] = Variant("Feb");  // compile
>   aa[1]["Profit"] = Variant(800); // compile
>   
>   for(int i=0;i dmd: mtype.c:3426: StructDeclaration* TypeAArray::getImpl(): Assertion `impl' 
> failed.

AAs don't have a length (as far as I remember).  Besides which, there's
NOTHING that says the keys for aa are sequential.  If you want a
sequence, use an array.

You should probably read the documentation on how to use AAs.

>   {
>   writefln("%s",aa[i]["Month"]); // compile but get at runtime : 
> core.exception.rangeer...@test(25): Range violation
>   }

What you want is probably more along these lines:

foreach( k,v ; aa )
{
writefln("%s", v);
}

> It seems to be a bug...
> 
> Thanks  !


Re: use variant as associative array

2010-02-11 Thread Daniel Keep


Daniel Keep wrote:
> I got the following to work with Tango's Variant (dmd 1.051 + pre-0.99.9
> trunk):
> 
> Variant[char[]][int] aa;
> 
> aa[0] = typeof(aa[0]).init;
> aa[0]["Month"] = Variant("Jan");
> aa[0]["Profit"] = Variant(500);
> 
> aa[1] = typeof(aa[0]).init;
> aa[1]["Month"] = Variant("Feb");
> aa[1]["Profit"] = Variant(800);
> 
> There's actually two problems at work here:
> 
> 1. You can't use a nested associative array without initialising it.

Scratch that; it does work.  Huh.  Fancy that.

> 2. You apparently can't assign to an aa of Variants for some reason.
> 
> Keep in mind that Variants are basically a hack on the language; that
> assigning to a Variant value in an AA doesn't work isn't entirely
> surprising.

Another thing that occurred to me; is there any reason you can't do this:

> struct Record
> {
> char[] month;
> int profit;
> }
>
> Record[int] aa;
>
> aa[0] = Record("Jan", 500);
> aa[1] = Record("Feb", 800);

Or even this:

> Record[] arr;
> arr ~= Record("Jan", 500);
> arr ~= Record("Feb", 800);

Or even even this:

> enum Month { Jan, Feb, Mar, /* and the rest */ }
> struct Record { Month month; int profit }
> Record[] arr;
> arr ~= Record(Month.Jan, 500);
> arr ~= Record(Month.Feb, 800);

?


Re: use variant as associative array

2010-02-11 Thread Daniel Keep

GG wrote:
> I try to use variant as associative array with dmd2.039, 
> 
> Variant[char[]][int] aa;
> aa[0]["Month"] = "Jan";
> aa[0]["Profit"] = 500;
> aa[1]["Month"] = "Feb";
> aa[1]["Profit"] = 800;
> 
> I got core.exception.rangeer...@main(28): Range violation
> I'm doing something wrong ? Or it's same problem as :
> http://digitalmars.com/d/archives/digitalmars/D/Variant_string_associative_array_..._fail_87248.html
> Same problem with dmd2.040
> 
> Thanks !
> GG

I got the following to work with Tango's Variant (dmd 1.051 + pre-0.99.9
trunk):

Variant[char[]][int] aa;

aa[0] = typeof(aa[0]).init;
aa[0]["Month"] = Variant("Jan");
aa[0]["Profit"] = Variant(500);

aa[1] = typeof(aa[0]).init;
aa[1]["Month"] = Variant("Feb");
aa[1]["Profit"] = Variant(800);

There's actually two problems at work here:

1. You can't use a nested associative array without initialising it.

2. You apparently can't assign to an aa of Variants for some reason.

Keep in mind that Variants are basically a hack on the language; that
assigning to a Variant value in an AA doesn't work isn't entirely
surprising.


Re: D memory consumption/runtime speed problem

2010-01-13 Thread Daniel Keep


sybrandy wrote:
> Hello,
> 
> I've been writing a bit of compression code and I noticed some strange
> behavior that's driving me a bit batty.  I don't know if it's a bug with
> D or something I did.  All I know is I can't figure it out.
> 
> ...
> 
> Am I doing something wrong?  I've tried every trick that I could find by
> reading the documentation.  Btw: The last time I tried this was with the
> latest version of D released at the beginning of the month.

I haven't verified this, but I'd be *deeply* suspicious of encodeNumber.
 I don't usually use array literals but, if I remember correctly, every
time it is called you're performing a heap allocation.  Even worse,
those concatentations might be performing separate allocations, too.

You could eliminate the overhead by using a passed-in buffer design like so:

ubyte[] encodeNumber(in uint count, ref ubyte[4] buffer)
{
if (count <= ONE_BYTE_VAL)
{
buffer[0] = cast(ubyte)(ONE_BYTE_MASK | count);
return buffer[0..1];
}
// ...
}

Then, in the calling function:

{
ubyte[4] temp;
foreach( ... )
{
appOutput.put(encodeNumber(count, temp));
}
}

See if that helps.


Re: Getting access to the variables of an imported class

2009-12-05 Thread Daniel Keep

jicman wrote:
> aalm Wrote:
>> import dfl.all;
>> import myform2;
>>  
>> void main()
>> {
>>   //Form d = new MyForm();
>>   //MyForm d = new MyForm();
>>   auto d = new MyForm();
>>   d.text = "Hello...";
>>   d.Name.text = "name";
>>   d.show();
>> }
> 
> thanks.  That worked.  Would you care to explain? :-)  I know what auto does, 
> but I thought that a Form was a form and a Class was a class.  Does auto here 
> would suffice for all other kinds of variables?
> 
> Thanks for the help.
> 
> jos�

Sometimes, I think all compiler errors should be replaced with
"Something went wrong."  No one ever seems to *read* them.  :|

> testDFL.d(8): Error: no property 'Name' for type 'dfl.form.Form'

You were trying to access a 'Name' property for an object of type
'Form'.  But 'Form's do not have a 'Name' property.  Objects of type
'MyForm' do, but you've explicitly told the compiler that 'd' is of type
'Form' not 'MyForm'.


Re: why can't structs implement interfaces?

2009-11-24 Thread Daniel Keep


Bill Baxter wrote:
> On Tue, Nov 24, 2009 at 3:09 PM, Saaa  wrote:
> 
 I wanted to do something like this:

 class C : I {};
 struct S : I {};
 S s;
 I[] i =[new C(), s ];
>>> Yeh, that's never going to work because that's acting as a dynamic
>>> polymorphic interaface.  Referring polymorphically to a struct like
>>> that pretty much makes it not a struct anymore, and requires having
>>> the hidden pointer to a vtable that was mentioned.  That's what
>>> classes are for.
>> Why is a hidden pointer necessary? (Just curious :)
>>
>> My simplistic view was like this:
>> i[1] would just hold the location of s and s would be checked to have
>> all it needs to be an I.
> 
> I think it could be done with a different implementation of interfaces
> from the one D uses, one based on "fat pointers".
> With that design an I referring to an S would be a "fat pointer", one
> pointer pointing to the S and one pointing to S's table of function
> pointers (vtable) for the I interface.
> 
> That's not how D does it AFAIR, but I don't actually recall how D does it.
> 
> --bb

(This is all off the top of my head.)

In D, interfaces are pointers to the vtable which implements the
interface for a particular class.  In order to actually get the "this"
reference, D stores a pointer to the class' InterfaceInfo (or something)
for that interface in the first slot of the vtable.

This InterfaceInfo indicates how far from the start of an instance the
pointer to the vtable is contained.  To get "this", you take the pointer
to the interface vtable and subtract this offset.

This is why interfaces cannot be implemented by structs in D: it would
require structs to grow magical hidden fields, which is explicitly
against the stated purpose of structs: plain old data.

Even then, there's a worse problem.  All interfaces can be cast to
Object, and then upcast to any valid class.  This is done via the use of
the first slot of the object's vtable, which contains the ClassInfo.

But if you allow structs as interfaces, you're suddenly in the position
where you might not actually have an object at all.  If you tried to
cast a struct to an Object, it might not actually fail; if you're lucky,
you'll get a segfault.

The only solution there is to give structs a vtable.  At which point,
congratulations, you've just re-invented classes.

To allow structs to implement interfaces would require redesigning how
interfaces are actually implemented.  You'd probably have to also
redesign RTTI as well, object casting, etc.


Re: Using ANSI codes

2009-11-05 Thread Daniel Keep

funog wrote:
> Stewart Gordon Wrote:
> 
>> Funog wrote:
>>> How can I get a D1 console program to use ANSI codes? Currently it just 
>>> prints the escape character like any other...
>> At first I thought you meant the ANSI character set, but then I realised 
>> you're probably talking about ANSI.SYS.
>>
>> This is an operating system issue, not a D issue.  What OS version are 
>> you using?  Try searching the web for info related to yours.
>>
>> Alternatively, check out disp.h, which comes with DMC, and use that 
>> instead.  I once began writing D bindings for it
>>
>> Stewart.
> 
> You are right. I was using Vista Premium, but it works fine on linux.

http://github.com/DanielKeep/gb/blob/master/src/gb/io/Ansi.d

Should stand on its own, but only works with Tango.

  -- Daniel


Re: The length of strings vs. # of chars vs. sizeof

2009-11-01 Thread Daniel Keep


Rainer Deyke wrote:
> Jesse Phillips wrote:
>> I believe the documentation you are looking for is:
>>
>> http://www.prowiki.org/wiki4d/wiki.cgi?DanielKeep/TextInD
>>
>> It is more about understanding UTF than it is about learning strings.
> 
> One thing that page fails to mention is that D has no awareness of
> anything higher-level than code points.  In particular:
>   - dchar contains a code point, not a logical character.
>   - D has no awareness of canonical forms and precomposed/decomposed
> characters (at the language level).  (Some characters can be represented
> as either one or two code points.  D does not know that these are
> supposed to represent the same character.)
>   - Although D stops you from outputting an incomplete code point, it
> does not stop you from outputting an incomplete logical character.
> 
> Also, some D library functions only work on the ASCII subset of utf-8.

Well, it *is* on a Wiki.


Re: version specific enum members

2009-10-29 Thread Daniel Keep


Phil Deets wrote:
> Hi, is there a way to add members to an enum based on conditional
> compilation symbols. I tried
> 
> enum Tag {
>A, B,
>version (symbol) {
>   C, D,
>}
>E,
> }
> 
> but it doesn't work. I know I could do
> 
> version (symbol) {
>enum Tag { A, B, C, D, E }
> } else {
>enum Tag { A, B, E }
> }
> 
> but I don't want to do that since in my case, there can be quite a few
> elements outside of the version, and I don't want to repeat them all.

template Version(char[] ident)
{
mixin(`version(`~ident~`) const Version = true;
   else const Version = false;`);
}

char[] genEnum(bool flag1, bool flag2)
{
return "A, B, "
 ~ (flag1 ? "C, D, " : "")
 ~ "E, F, "
 ~ (flag2 ? "G, H, " : "")
 ~ "G, ";
}

mixin(genEnum( Version!(`symbol`), Version!(`somethingElse`) ));

... is about the best you can do, I think.


Re: Error: 4invalid UTF-8 sequence :: How can I catch this?? (or otherwise handle it)

2009-10-21 Thread Daniel Keep

Charles Hixson wrote:
> I want to read a bunch of files, and if the aren't UTF, then I want to
> list their names for conversion, or other processing.  How should this
> be handled??
> 
> try..catch..finally blocks just ignore this error.

> type stuff.d
import std.stdio;
import std.utf;

void main()
{
try
{
writefln("A B \xfe C");
}
catch( UtfException e )
{
writefln("I caught a %s!", e);
}
}

> dmd stuff && stuff
A B I caught a 4invalid UTF-8 sequence!

Works for me.


Re: amazing function behavior

2009-10-19 Thread Daniel Keep


Zarathustra wrote:
> Function is never called but why?

It shouldn't even COMPILE.

You can't use member functions as Windows callbacks.  You haven't even
used the correct calling convention on it.

Callbacks for Win API functions have to be, I believe, extern(Windows),
and they have to be free functions or static members.


Re: Sizeof class instance

2009-10-03 Thread Daniel Keep


Daniel Keep wrote:
> ...
> Note: this is VERY old code, but I have no reason to think it won't
> still work.  I may need a little dusting off...

*It* may need a little dusting off.  Argh.


Re: Sizeof class instance

2009-10-03 Thread Daniel Keep


Jarrett Billingsley wrote:
> On Sat, Oct 3, 2009 at 5:50 PM, Justin Johansson  wrote:
>> How does one determine the sizeof (in bytes) of an instance of a class in D?
>>
>> .sizeof works as advertised for structs, but for reference types,
>> .sizeof yields the sizeof the referencing variable (effectively same as size 
>> of a pointer)
>> and not the size of the underlying instance.
>>
>> I did try scanning the NG and read spec_D1.00.pdf.  Perhaps I missed it in 
>> the latter.
>>
>> btw. I was poking under the hood of std.xml and though, wow, instances of 
>> Element
>> class look humongous, and so I'm interested to how exactly how humongous.
>>
>> Thanks for all help.
>> Justin
> 
> There's no way to get it at compile-time in D1. The best you can do is
> Class.classinfo.init.length.

What nonsense, of course there is!

http://gist.github.com/140531

Note: this is VERY old code, but I have no reason to think it won't
still work.  I may need a little dusting off...


Re: Getting started - D meta-program question

2009-10-03 Thread Daniel Keep

Justin Johansson wrote:
> There was mention** on the general discussion group that the D foreach_reverse
> language construct could be replaced (emulated?) with a (D) meta-program.
> 
> ** "Even a novice programmer can write a meta-program to replace
> foreach_reverse without any runtime performance hit."
> 
>
> http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=97362
>   
> As I'm less than a novice with the D meta-programming facilities (at this 
> stage of my journey into D),
> if someone would kindly show me the D meta-program solution to do this,
> I'd really appreciate the enlightenment.
> 
> Thanks again.

Short answer: you can't.

Long answer: you can, provided you aren't trying to reverse an opApply,
which is patently impossible.

As for the "meta-program", I would suspect whoever said that was talking
about writing a templated type or function to handle it.  You would need
to use template specialisation or static ifs to switch on what type
you've been given to reverse.

http://digitalmars.com/d/1.0/template.html

http://digitalmars.com/d/1.0/version.html#staticif


Re: What if gc.disable at all

2009-09-24 Thread Daniel Keep


Sam Hu wrote:
> Ah yes,I once translated most of Tango's tango.util.container.* into D2 
> excluding one or two modules  which heavily depends on Tango other modules.It 
> get compiled.However,the test program crashed with below error message:
> Error 42:Symbol Undefined _D5tango4core6Memory2GC6addrOfFpvZPv 
> ---errorlevel 1 
> 
> I have no clue what this means and where to restart.
> 
> Regards,
> Sam

How about by reading the error message?

Error 42:Symbol Undefined _D5tango4core6Memory2GC6addrOfFpvZPv

-->

Error 42:Symbol Undefined void* tango.core.Memory.GC.addrOf(void*)

Ergo, you didn't link in tango.core.Memory, which it wants.


Re: Linking in an .so on linux with rebuild?

2009-09-23 Thread Daniel Keep


Jarrett Billingsley wrote:
> On Wed, Sep 23, 2009 at 1:11 AM, Daniel Keep
>  wrote:
>> Now I just have to figure out how to fix THIS:
>>
>> ../build/dsss_objs/D/sandbox.minid_repl.o: In function `_Dmain':
>> sandbox/minid_repl.d:(.text._Dmain+0x6f): undefined reference to
>> `_D5minid11commandline45__T3CLITS5minid11commandline14MDConsoleInputZ3CLI11interactiveMFPS5minid5types8MDThreadZv'
>>
>> I *hate* linker errors.  :(
> 
> Oh boy, looks like templates are at it again. I'm not sure what the
> problem is there. Maybe minid.commandline isn't actually being
> compiled somehow, only imported?

Yeah, I got around it by manually adding minid/commandline.d to the
compile line.


Re: Linking in an .so on linux with rebuild?

2009-09-22 Thread Daniel Keep


Jarrett Billingsley wrote:
> On Wed, Sep 23, 2009 at 12:41 AM, Daniel Keep
>  wrote:
>> I found a solution.
>>
>> See
>> http://stackoverflow.com/questions/335928/linux-gcc-linking-ld-cannot-find-a-library-that-exists
>>
>> For me, I needed readline and history, so I did this:
>>
>> $ cd /lib
>> $ sudo ln -s libreadline.so.5 libreadline.so
>> $ sudo ln -s libhistory.so.5 libhistory.so
>>
>> After that, ld didn't complain.
>>
> 
> Oh yay. I was going to suggest that but I had never had that kind of
> problem on Ubuntu when building MiniD before. Maybe we're using
> different versions or something.

Now I just have to figure out how to fix THIS:

../build/dsss_objs/D/sandbox.minid_repl.o: In function `_Dmain':
sandbox/minid_repl.d:(.text._Dmain+0x6f): undefined reference to
`_D5minid11commandline45__T3CLITS5minid11commandline14MDConsoleInputZ3CLI11interactiveMFPS5minid5types8MDThreadZv'

I *hate* linker errors.  :(


Re: Linking in an .so on linux with rebuild?

2009-09-22 Thread Daniel Keep

I found a solution.

See
http://stackoverflow.com/questions/335928/linux-gcc-linking-ld-cannot-find-a-library-that-exists

For me, I needed readline and history, so I did this:

$ cd /lib
$ sudo ln -s libreadline.so.5 libreadline.so
$ sudo ln -s libhistory.so.5 libhistory.so

After that, ld didn't complain.


Re: Linking in an .so on linux with rebuild?

2009-09-22 Thread Daniel Keep


Nick Sabalausky wrote:
> I can't seem to get that to work. Tried all sorts of stuff. Off the top of 
> my head:
> 
> -ll
> -ll.so
> "-L-l "
> "-L-l .so"
> -L-l -L
> -L-l -L.so
> 
> None of them were able to find the file (and, yes, the name+path are right), 
> and I'm not using any links.

I've had exactly the same problem in trying to compile MiniD on Ubuntu
last night.

MiniD wants libhistory, but -llhistory doesn't work.

What's worrying me is that even if I call ld directly and pass
-lhistory, IT says it can't find it, either.  It's in /lib, so I have no
idea what's going on.

Passing the .so directly on the command line, like on Windows, doesn't
appear to work as either rebuild or DMD is chucking a wobbly at the .so
file, complaining it doesn't know what that extension is for.


Re: delegate reference

2009-09-09 Thread Daniel Keep

Saaa wrote:
> Ok, disregard my last comment :D
> How should I do this then? 

class Foo
{
  C* c;

  this(ref C c)
  {
this.c = &c;
  }

  int invoke()
  {
return (*c).method();
  }
}

void main()
{
  // ...
  deleg = &(new Foo(c)).invoke;
}

Or something similar.

This is dangerous.  Do not allow either the Foo instance or the delegate
to survive past the end of c's scope.

It is simpler and safer to just update the delegate.


Re: delegate reference

2009-09-09 Thread Daniel Keep


Saaa wrote:
> "Daniel Keep"  wrote in message 
> news:h88cck$1or...@digitalmars.com...
>>
>> Saaa wrote:
>>> abstract class C
>>> {
>>>  int method();
>>> }
>>> class C2:C
>>> {
>>>  int method() return 2;
>>> }
>>> class C3:C
>>> {
>>>  int method() return 3;
>>> }
>>> int delegate() deleg;
>>> void main()
>>> {
>>>  C c;
>>>  C2 c2 = new C2;
>>>  C3 c3 = new C3;
>>>  c=c2;
>>>  deleg = &c.method;
>>>  writefln(deleg()); // 2
>>>  c=c3;
>>>  writefln(deleg()); // 2
>>>  // I expected this to write 3, why is this not so?
>> Because you didn't reassign deleg.
> but isn't deleg pointing to c's method? 

Yes... just because you change what c points to doesn't magically
rewrite all other references.

You might want to read http://digitalmars.com/d/1.0/type.html#delegates


Re: delegate reference

2009-09-09 Thread Daniel Keep


Saaa wrote:
> abstract class C
> {
>  int method();
> }
> class C2:C
> {
>  int method() return 2;
> }
> class C3:C
> {
>  int method() return 3;
> }
> int delegate() deleg;
> void main()
> {
>  C c;
>  C2 c2 = new C2;
>  C3 c3 = new C3;
>  c=c2;
>  deleg = &c.method;
>  writefln(deleg()); // 2
>  c=c3;
>  writefln(deleg()); // 2
>  // I expected this to write 3, why is this not so?

Because you didn't reassign deleg.


Re: Structs by ref in D2

2009-08-22 Thread Daniel Keep

bearophile wrote:
> Daniel Keep:
>> In my own code, I usually record my intent by using "inout" for
>> variables I intend to modify and "ref" for ones which I don't.
>> Always seemed reasonable to me.
> 
> for the compiler they mean the same thing, but inout is being deprecated.
> 
> Bye,
> bearophile

I realise this.  My point is that the two keywords pretty nicely sum up
a difference in intent.


Re: Structs by ref in D2

2009-08-21 Thread Daniel Keep


Steven Schveighoffer wrote:
> ...
> 
> The issue is possibly with ref.  There are two reasons to use ref, 1 is
> to be able to change the data referenced, 2 is for passing speed.
> 
> 1 is bad for rvalues.  2 should be ok for rvalues.
> 
> If there was a way to signify you only want to use ref for reason 2,
> there would be a good solution.  Most of the time, that's const ref, but
> what you really want is head-const ref, which isn't currently possible. 
> If a struct has references to other values, they might be lvalues, and
> you may want to be able to change them.
> 
> I'm uncertain as to how often you would want to pass an rvalue as a ref
> that had lvalue reference in it, but at the very least, ref const should
> be valid.
> 
> -Steve

In my own code, I usually record my intent by using "inout" for
variables I intend to modify and "ref" for ones which I don't.

Always seemed reasonable to me.


Re: Structs by ref in D2

2009-08-21 Thread Daniel Keep


Lutger wrote:
> By const ref seems reasonable to allow, but by ref is bug prone. Why is it 
> handy? 

struct Vector4
{
float[4] xyzw;
Vector opAdd(ref Vector rhs);
}

Vector code can be made much faster using ref arguments, but if you use
ref arguments, you can't have anything more complex than a single binary
expression.

D's stance at the moment seems to be: "speed, convenience: pick one"

/sadface


Re: deleting items from 2d arrays

2009-08-15 Thread Daniel Keep


Sergey Gromov wrote:
> Fri, 14 Aug 2009 13:55:18 +1000, Daniel Keep wrote:
> 
>> void dropElement(T)(ref T[] arr, size_t i)
>> {
>> assert( i < arr.length );
>> arr[i] = arr[$-1];
>> arr = arr[0..$-1];
>> }
> 
> I think it's important to erase the last element after the move to make
> sure no dangling references to unused data are left in a memory area you
> don't manage anymore:
> 
> | void dropElement(T)(ref T[] arr, size_t i)
> | {
> | assert( i < arr.length );
> | arr[i] = arr[$-1];
> arr[$-1] = T.init;
> | arr = arr[0..$-1];
> | }
> 
> This is a sad consequence of conservative garbage collection.

Excellent point; I forgot about that.


Re: deleting items from 2d arrays

2009-08-13 Thread Daniel Keep


Michael P. wrote:
> Okay, so I'm making a breakout type game in D. Using Derelict.
> I have a 2d array of Block type variables(not important what's in them) 
> declared like this:
> Block[][] level;
> and later load into like this:
> level = loadLevel( "levels.txt", levelNumber );
> Anyways, what I want to do is that when the ball hits one of the blocks in 
> the array, I remove it. When a line no longer has any blocks in it, I remove 
> that line/row. When there are no more lines, I load the next level.
> Any ideas on how I could achieve this?
> 
> foreach( Block[] ba; level )
> {
>   foreach( Block b; ba )
>   {
>   if( checkCollision( ball, b.p ) )
>   {
>   //remove the block??
>   }
>   }
> }
> 
> The level array has 12 lines of 'x' amount of bricks. x can be as great as 10.
> -Michael P.

That depends on what you mean by "remove" and what Block is.

If Block is a class, you can remove instances from the array simply by
setting that slot to null.

foreach( row ; level )
{
  foreach( ref block ; row )
  {
if( checkCollision( ball, block.p ) )
block = null;
  }
}

If you want to actually remove the Block from the array, and their
relative ordering isn't important, you can do this:

void dropElement(T)(ref T[] arr, size_t i)
{
assert( i < arr.length );
arr[i] = arr[$-1];
arr = arr[0..$-1];
}

That moves the last element into the place of the one you don't want,
then drops the last element of the array.

If the relative ordering DOES matter, then you have to copy the later
elements down the array and drop the last element.


Re: Semi Automated Object wrapping

2009-08-13 Thread Daniel Keep


Bill Baxter wrote:
> On Thu, Aug 13, 2009 at 12:43 AM, Rory McGuire wrote:
>> On Wed, 12 Aug 2009 17:03:17 -0700, Bill Baxter wrote:
>>
>>> On Wed, Aug 12, 2009 at 4:52 PM, Rory McGuire
>>> wrote:
 Here is some code I wrote which enables wrapping a proxy around an
 object. I am using it for my serialization library. It works in
 D1(1.046) and D2 (2.031)

 Posting it here for reference by all before I add to much of the stuff
 specific to my use, should make it easier to follow.

 usage: new ProxyClass!(A, cast(string)"getInt setInt getString"); would
 implement the methods getInt setInt and getString from A in the new
 class.

 the code below will fail to compile but not before printing the
 generated code to stdout.

 Shin Fujishiro has made some new templates for D2 which will make it so
 I can get rid of the "setInt getInt getString" part which would make
 the usage for D2: new ProxyClass!A;
 which would be great!

 -Rory

  // author: Rory McGuire,
 rjmcgu...@gmail.com import std.stdio;
 import std.typetuple;
 import std.traits;
 import std.metastrings;

 //import serializer;

 // this CTF from somewhere on news.digitalmars.com string[]
 splitFuncs(string str) {
string[] res;
while (str.length > 0) {
while (str.length > 0 && (' ' == str[0] || ',' == str[0])) {
str = str[1..$];
}
int to = 0;
for (; to < str.length && str[to] != ' ' && str[to] != ',';
++to)
 {}
if (to > 0) {
res ~= str[0..to];
str = str[to..$];
}
}
return res;
 }

 string MethodTypeTuple_mixin(alias a)(string[] methods) {
string ret = "TypeTuple!("~
"typeof(&C.init."~methods[0]~")"; foreach (method;
methods[1..$]) {
ret ~= ",typeof(&C.init."~method~")";
}
ret ~= ")";
return ret;
 }



 // test case

 class A {
int a;
this(int a) {
this.a = a;
}
int getInt(string intname) {
return a;
}

void setInt(int i) {
a = i;
}
string getString(string s) {
return s ~"1234";
}
 }


 string ProxyMethods_mixin(alias C, string methodstr)() {
string ret;
foreach(i, t; mixin(MethodTypeTuple_mixin!(C)(splitFuncs
 (methodstr {
// output function header
ret ~= "\t"~ReturnType!(t).stringof ~" "~
splitFuncs
 (methodstr)[i]~"(";
// output first arg
ret ~= ParameterTypeTuple!(t)[0].stringof~"
arg"; // output remainder of args
foreach (j, t1; ParameterTypeTuple!(t)[1...$]) {
ret ~= ","~t1.stringof~"
 arg"~std.metastrings.ToString!(j);
}
// output body
ret ~= ") {\n";
// output serialization code
// send method name
ret ~= "\t\twritefln(\"serialize docall id\");
// the
 method call byte id\n";
ret ~= "\t\tbuffer ~=
serialize!(string)(\""~splitFuncs
 (methodstr)[i]~"\", s_state); /+ the method name +/\n";
// send args
ret ~= "\t\tbuffer ~= serialize!("~
ParameterTypeTuple!(t)
 [0].stringof~")(arg, s_state); /+ the first argument +/\n";
foreach (j, t1; ParameterTypeTuple!(t)[1...$]) {
ret ~= "\t\tbuffer ~= serialize!("~
t1.stringof
 ~")(arg"~ToString!(j)~", s_state); /+ argument "~ToString!(j)~" +/\n";
}
// receive return type
static if (!is(ReturnType!(t) == void)) {
ret ~= "\t\treturn deserialize!("~
ReturnType!
 (t).stringof ~")(buffer, des_state);\n";
}
ret ~= "\t}\n";
}
return ret;
 }


 class ProxyClass(alias C, string methodstr) {
ubyte[] buffer;
mixin(ProxyMethods_mixin!(C,methodstr)());
pragma(msg, "class ProxyClass!("~C.stringof~",
\""~
 methodstr ~"\") {\n\tubyte[] buffer;\n  SerializerState s_state;\n
 DeserializerState des_state;\n  this() {s_state = new
 SerializerState(); des_state = new DeserializerState(); }\n\n"~
 ProxyMethods_mixin! (C,methodstr)() ~"\n}\n");

Re: calling function templates

2009-08-09 Thread Daniel Keep


Jos van Uden wrote:
> I noticed that I don't always have to use the bang notation for
> function templates. I played around with that a little, but got
> an error when I used a static array. I think it's because of a
> casting problem or wrong type inference... I don't imagine it's
> a bug. Just not possible.
> 
> ...
> 
> int[20] arr4;
> putNumbers(arr4, 0, 3); // ERROR, stat array, regular notation
> 
> }
> 
> test.d(8): Error: cast(int[])r is not an lvalue
> test.d(25): Error: template instance test.putNumbers!(int[20u],int)
> error instantiating

You're instantiating the template as putNumbers!(int[20u],int) because
arr4 is of type int[20u].

This means Range is int[20u].  Here's the code for put:

> void put(T, E)(ref T[] a, E e) {
> assert(a.length);
> a[0] = e; a = a[1 .. $];
> }

r.put(i) is rewritten by the compiler as put(r, i)... except that put
wants an int[], not an int[20u].  So it implicitly casts it to the
correct type, giving put(cast(int[])r, i).

But put ALSO expects its first argument to be passed by reference, and
you cannot pass the result of a cast by-reference.

(There are a LOT of things you can't pass by reference; it's a constant
thorn in my side, and many others' sides.)

The problem here is that put is fundamentally incompatible with
fixed-size arrays.  The solution is to change line 25 to read:

auto arr4_temp = arr4[]; putNumbers(arr4_temp, 0, 3);


Re: how does range.put work

2009-08-08 Thread Daniel Keep


Jos van Uden wrote:
> Oliver wrote:
>>> The source code for the standard library comes with the compiler.
>>> If you look in std\array.d, you find this around line 279 (reflowed for
>>> readability):
 void put(T, E)(ref T[] a, E e) {
 assert(a.length);
 a[0] = e; a = a[1 .. $];
 }
> 
> Would anybody care to explain what this is used for? I find
> the example in array.d rather unhelpful.
> 
> Example:
> 
> void main()
> {
> int[] a = [ 1, 2, 3 ];
> int[] b = a;
> a.put(5);
> assert(a == [ 2, 3 ]);
> assert(b == [ 5, 2, 3 ]);
> }
> 
> You're putting an element in a, but then the first element is moved out
> of a and the new one shows up in b? Weird. I guess I don't understand
> what a range is.
> 
> Jos

No; read the code.  Before the put, a and b are pointing to the same
span of memory.  a.put(5) puts the value 5 into the front (first
element) of the array, then advances the array.

However, put can't "see" b, so it doesn't get updated along with a.  The
end result is that b = [5,2,3] and a = b[1..3] = [2,3].

Why do it like this?  Here's an example:

void putNumbers(Range)(Range r)
{
int i = 0;
while( !r.empty )
{
r.put(i);
++i;
}
}

void main()
{
int[10] ten_numbers;
putNumbers(ten_numbers);
assert( ten_numbers = [0,1,2,3,4,5,6,7,8,9] );
}

Note that putNumbers will work with any type that supports the range
API, not just arrays.


Re: how does range.put work

2009-08-06 Thread Daniel Keep


O.K. wrote:
> Hello,
> could someone plz clearify what the exact semantics of "put"
> are ?
> Put works with an appender, but gives me a runtime exception
> when using an array.
> 
> Best regards,
> Oliver

The source code for the standard library comes with the compiler.

If you look in std\array.d, you find this around line 279 (reflowed for
readability):

> void put(T, E)(ref T[] a, E e) {
> assert(a.length);
> a[0] = e; a = a[1 .. $];
> }


Re: byte to char safe?

2009-07-30 Thread Daniel Keep


Harry wrote:
> D writef not print utf8 control?

I have no idea what you're asking.  To take a blind stab: writef expects
any char[] you give it to be in utf8 format.  Actually, EVERYTHING
assumes that char[] is in utf8.

> \x00 .. \x1f and \x7f .. \x9f safe for data?

Again, I'm not sure what you're asking.  char[] is utf8, which means
that ANY code unit in the range \x80..\xff is invalid by itself.  If
you're storing binary data, use ubyte[].

> where \n \t?

const NEWLINE = "\n";

What's the issue?


Re: byte to char safe?

2009-07-30 Thread Daniel Keep


Harry wrote:
> Again hello, 
> 
> char[6] t = r"again" ~ cast(char)7 ~ r"hello";
> 
> use only own write functions
> is ok?
> 
> thank you!

I think a more significant problem is that "again\x07hello" can't
possibly fit in six characters, unless you're using some crazy numbering
system I'm not familiar with.


Re: How to search for an element in the array. D2 phobos.

2009-07-12 Thread Daniel Keep


bearophile wrote:
> Eldar Insafutdinov:
>> I think I completely misunderstood how to use it.
> 
> Yes, it's too much complex. It tries to do many different things in the most 
> efficient way possible, the result is a high complexity in usage. That's one 
> of the faults of Andrei's code, it's not tested by letting  average coders 
> use it.
> A solution for this problem is to offer simple functions (like you can find 
> in Tango. In my dlibs the situation is intermediate, I think) with a simple 
> API for the most common purposes.
> 
> Bye,
> bearophile

It should work.  Taken from the algorithm docs:

> Example:
>
> > int[] a = [ 1, 4, 2, 3 ];
> > assert(find(a, 4) == [ 4, 2, 3 ]);

That said, find is too complex for his purposes.  Amazingly, Phobos
still appears to lack a basic indexOf function.

Phobos2: can build a working sentient AI that can feel love up from
individual atoms, but can't find the index of an array element.  :P


Re: pass variable names

2009-07-09 Thread Daniel Keep


Saaa wrote:
> Is it possible to get the passed variable name � la:
> --
> void functio(A...)(ref A a)
> {
> writefln(typeof(a[0]));
> }
> int i;
> functio(i); // prints "i"

No.

You should be able to get the name using an alias:

void func(alias var)()
{
writefln(var.stringof);
}

But you can't do it at runtime.

> Also how do I fix this:
> --
> functio(`i`); // Error: "i" is not an lvalue

You have to store the literal in a variable.


Re: Array slice length confusion

2009-07-09 Thread Daniel Keep


Tim Matthews wrote:
> Kagamin wrote:
>> Tim Matthews Wrote:
>>
>>> I thought a slice would behave slighty different due to some sort of
>>> meta data that is a separate area of memory so it doesn't effect D's
>>> abi.
>>>
>> Current plan is to introduce new type - array - into the language.
> 
> Do you know the ng posts or where ever that was posted?

Best bet would be to search for "T[new]".


Re: How to release memory? (D2.0.30)

2009-07-04 Thread Daniel Keep


AxelS wrote:
> @Ary Borenszweig: Good idea but I can't pipe data to a HTTP-server located 
> somewhere in the internet...

I believe he means to read the file in chunks, sending them across the
network as you get them.

> OK, I tried it with C's malloc and free - but everytime I access my array, D 
> puts the memory into its heap...I'm getting crazy because of this!

D doesn't copy data like that; something else must be going on.


Re: How to release memory? (D2.0.30)

2009-07-04 Thread Daniel Keep

BCS wrote:
> ... The good news is that with virtual memory, all of that has almost
> zero cost. What matters is how much ram you are actively using.

You've obviously never used a netbook with no swap file.  :)


Re: why __traits not in trait module and not name it trait

2009-06-24 Thread Daniel Keep


Sam Hu wrote:
> Yes,__traits did not stole my girl friend,but isn't better to name it trait? 
> And I have thought I can find it in trait moudle but I was wrong.

It's not in a module because it's a keyword.  You don't find "function"
defined in any library.

As for being called __traits instead of traits, I suspect that's for at
least one of two reasons:

1. so it won't invalidate existing code that uses the identifier
"traits", and/or

2. because it's not something regular programmers should have to use; it
should be used to build a higher-level API using templates.


Re: D compiler for .NET

2009-06-09 Thread Daniel Keep


Jason House wrote:
> Earlier today, I tried to use the D compiler for .NET from 
> http://dnet.codeplex.com/
> 
> Beyond compilation of the compiler, I found zero instructions on what to do 
> next.  How do I integrate the compiler into the .NET framework/visual 
> studio?  I'd like to be able to add D files to existing solutions (with C# 
> code).  If I can do that, I'll probably push for some small adoption of D at 
> work.  (I'm hoping mixins and templates will inspire the initial use of D)
> 
> Any tips or documentation on how to get started would be appreciated.
> 

"The back-end code is not of production quality, it is intended for
research and educational purposes. The D Programming Language is a
fairly complex language, and non-trivial features such as TLS and
closures make it an interesting case study for generating IL code."

Why do people never read the big red label saying "Warning: not ready
for use!"?

As for VS integration, so far as I know, there isn't any.  I'm also
fairly certain that you can't combine different languages in a single
project period.


Re: legal identifier check

2009-05-31 Thread Daniel Keep


Saaa wrote:
> ...
> 
> I know use this (in the ddata thread above):
> 
> foreach(char c; identifier)
> {
>  if( !inPattern( c, `_a-zA-Z0-9`) )
>  {
>   return false;
>  }
> } 

That's not correct.  http://digitalmars.com/d/1.0/lex.html#identifier


Re: Encoding problems...

2009-05-28 Thread Daniel Keep


Robert Fraser wrote:
> BCS wrote:
>> Reply to Robert,
>>
>>
>>> Hmm... I'd say x.⊆(y) is preferable x.isSubsetOf(y), but it's not a
>>> huge deal.
>>>
>>
>> Only until you have to type it. I think universal alpha includes only
>> the union of things that can be easily typed on standard keyboards. I
>> don't think any keyboard (ok maybe an APL keyboard) has the subset
>> symbol on it.
> 
> I have 10 configurable keys on my keyboard, none of which are in use. I
> could also remap my numpad (cause, seriously, who uses this?) Also, many
> editors can be configured so that a sequence of characters converts to a
> single one.

Which would possibly make D the first language to *require* a
specialised keyboard and/or editor since APL.

Not a good precedent.

Oh, and don't try to argue it isn't mandatory.  If you can overload
those operators, people WILL use them and WILL complain that it's too hard.

> There appears to be no reason that mathematical symbols aren't allowed
> in identifiers... Think of how awesome it would be to write
> assert(x⊇y→∀a∈x∃b∈y(a⊇b)) ... Okay, that would require overloading of
> those operators (and instantiating variables in a new way), but still!

I think that example you gave is an excellent reason not to allow them.  :D

It would be nice, but it's really not feasible without widespread editor
and/or keyboard support for extra symbols, which I just don't see happening.


Re: How many people here use stackoverflow.com?

2009-05-23 Thread Daniel Keep


Tim Matthews wrote:
> On Sat, 23 May 2009 08:36:44 +1200, hasen  wrote:
> 
>> If I have some questions about D, should I ask on stackoverflow
>> instead of here? Are there enough D'ers there?
>>
>> I personally think that asking there would bring more public attention
>> to D, but it all depends on whether there are enough people there who
>> know about D.
>>
>> For instance, I might have a couple of question about gtkD, as I'm
>> trying to play with it right now.
>>
>> So, do you regularly visit http://stackoverflow.com/ or no?
> 
> 
> http://stackoverflow.com/questions/tagged/d
> 
> I remeber seeing a post on annoucements a long time ago about when you
> type d on the tags page here http://stackoverflow.com/tags you dont get
> the d tag. IIRC that guy sent en email to jeff atwood about it but it is
> still not working.

I use the feed at http://stackoverflow.com/feeds/tag/d to keep an eye on
any D questions as they pop up.

  -- Daniel


Re: DMD Modifications

2009-05-21 Thread Daniel Keep

white_man wrote:
> Does it possible to modify DMD and publish it in that form. Of course with 
> full information about authors. Does it legal? 

It depends.  If you ONLY modify the front-end (front-end files are
identified as being licensed under GPL [1]), then you can distribute the
modified front-end.

However, if you modify the back end, you cannot redistribute those
files.  You also cannot distribute a compiled version.

To be safe, it's probably best to just distribute any changes you make
as a patch.

  -- Daniel


[1] There's another license involved, but I forget what it's called.


Re: D1/D2 co-install?

2009-05-17 Thread Daniel Keep


BCS wrote:
> Does anyone have a good solution to installing both D1 and D2 on the
> same system?

I have... (goes to check) 10 different compilers on my system.  There's
\dmd\bin\dmd-default which is the only one on the PATH (and is basically
a stable version of Tango and DMD).  If I want to use the others, I use
the full path to them.

OR, you can use rebuild and configure it with extra compiler profiles,
then use (for example):

> rebuild -dc=dmd-1.035 stuff

  -- Daniel


Re: Who wants to have some fun memory debugging?

2009-05-12 Thread Daniel Keep


Sean Kelly wrote:
> ...
> 
> At this point it's quite possible that you still have a reference to
> newData in a register.  If you want to be sure the collect call below
> works as intended for this test, try adding:
> 
>   newData = new Data;
> 
> here.

Debugging it with ddbg under Win XP, I found that at "data = null",
there is what appears to be a pointer to the newest allocation in EDX,
and a pointer to the previous one in ECX.

>> i = 0;

After this line, the ECX reference hasn't been touched.

>> GC.collect();

Disassembling the code, there's nothing that touches ECX before the call
to GC.collect, so it's quite probable that this is why the memory isn't
being freed in a given iteration, but not necessarily why it isn't being
collected at all.

I modified the code to explicitly zero-out ECX just before the call to
GC.collect, and it didn't appear to help.

I then instrumented the code with calls to gc_stats.  Here is the run of
it reporting the stats AFTER each forced collect (output via printf):

GCStats: poolsize, usedsize, freeblocks, freelistsize, pageblocks
GCStats: 81985536, 640, 16, 7552, 
GCStats: 16384, 640, 3200, 7552, 18399
GCStats: 232652800, 640, 2030, 7552, 27384
GCStats: 306315264, 640, 5948, 7552, 34417
GCStats: 360251392, 640, 6954, 7552, 40498
GCStats: 410517504, 640, 5502, 7552, 47360
GCStats: 469958656, 640, 8498, 7552, 53118

The program also got progressively slower as the size of the heap
increased.  Odd thing is that it would pause at a certain heap size for
many seconds at a time, increase in size, pause, increase, pause... it
was like the allocations were getting slower.

What's also weird is that even though the heap usage should be the same
each iteration, it's clearly creating more and more blocks.  It's like
the GC is freeing those blocks, but the allocator isn't using them.

Then I ran it so that it would compute the difference of gc_stats before
and after the collect.  This one is somewhat depressing:

GCStats: poolsize, usedsize, freeblocks, freelistsize, pageblocks
GCStats: 0, 0, 2, 0, -1
GCStats: 0, 0, 2, 0, -1
GCStats: 0, 0, 2, 0, -1
GCStats: 0, 0, 2, 0, -1
GCStats: 0, 0, 2, 0, -1
GCStats: 0, 0, 2, 0, -1

It appears to free *two* blocks and consume an extra page during a
collection, but doesn't affect the pool or used size at all.

Maybe it's time to put together an instrumented GC...

  -- Daniel


Re: 3 variant questions

2009-05-12 Thread Daniel Keep


Saaa wrote:
> ...
>> var_arg!(T) will convert _argptr into the type you specify and it will
>> also advance _argptr to the next argument.
> What would happen if you'd cast it incorrectly if it wasn't a simple pointer 
> ? :D

Same as would happen if you incorrectly cast anything.

i.e. anything.  Segfault if you're lucky.  If you're unlucky, random
crashes.

  -- Daniel


Re: 3 variant questions

2009-05-12 Thread Daniel Keep


Saaa wrote:
> I just noticed D1 does have std.stdarg.
> I shouldn't just search on the website :(
> (where it is missing on the phobos page)
> 
>> import std.stdarg;
>>
>> assert( _arguments[0] is typeid(int*) );
>> auto arg = va_arg!(int*)(_argptr);
>> *arg = 10;
>>
>> Probably.
> :D
>>  -- Daniel
> 
> So, you make arg point to the same as va_arg.

No, va_arg is a function.

> Why is this extra step necessary and why won't simple casting not work?

You should never directly work with _argptr.  It's not guaranteed to be
a simple pointer.  For example, I believe that GCC will sometimes use
registers (God only knows WHY).

var_arg!(T) will convert _argptr into the type you specify and it will
also advance _argptr to the next argument.

  -- Daniel


Re: 3 variant questions

2009-05-12 Thread Daniel Keep


Saaa wrote:
>> Saaa wrote:
>>> ...
>>> Passing variadic arguments as ref I think is what I am asking for :)
>> You can't.  You have to explicitly take the address of the arguments.
>>
>>  -- Daniel
> 
> Like this ?
> *_argptr = 10;
> :D
> 
> I don't know how to tell the compiler I want to write data there.

import std.stdarg;

assert( _arguments[0] is typeid(int*) );
auto arg = va_arg!(int*)(_argptr);
*arg = 10;

Probably.

  -- Daniel


Re: 3 variant questions

2009-05-12 Thread Daniel Keep


Saaa wrote:
> ...
> Passing variadic arguments as ref I think is what I am asking for :) 

You can't.  You have to explicitly take the address of the arguments.

  -- Daniel


Re: Resource availability: fonts

2009-05-05 Thread Daniel Keep


Tyro[a.c.edwards] wrote:
> One cannot necessarily rely on particular font being available on a system, 
> and for security reasons asminsistrators restrict instalation of fonts (among 
> other things) onto systems in a network. I would like to know if it is 
> possible to embed a font into my code so that I know that it will always be 
> there, or can I provide it with the exe but not have to rely on it being 
> "installed" (i.e. use it from the same folder in which the exe resides)? 
> 
> Thanks,
> Andrew

That depends.  What are you using the font for?

If you're using a library that requires a family name, then probably
not.  If you're using a library that can accept a file name, then
probably yes.

Remember that the system doesn't care if you append crap to the end of
an executable.  One trick you can use is to just append whatever files
you want to the end of the executable, and then have a little 1K block
at the end that tells you where the files are and how big they are; you
can then extract the files at run time and delete them when you terminate.


  -- Daniel


Re: how to initialize an array of typedef-ed type?

2009-05-01 Thread Daniel Keep


Jarrett Billingsley wrote:
> On Sat, May 2, 2009 at 12:21 AM, Daniel Keep
>  wrote:
> 
>> import std.conf;
>> b = to!(long[])(a);
>>
>> That should work, in theory.
> 
> In reality, it's std.conv ;)

Those letters are like RIGHT NEXT to each otter!  Don't judfe ne!

> (or tango.util.Convert, with identical syntax)

Never heard of it.  :)

  -- Daniel


Re: how to initialize an array of typedef-ed type?

2009-05-01 Thread Daniel Keep


Jarrett Billingsley wrote:
> On Fri, May 1, 2009 at 11:34 AM, MLT  wrote:
> 
>> Is there an easy way to convert arrays from one type to another?
>> int[] a=[1,2,3,4] ;
>> long[] b ;
> 
> Not really.  The best you can do is:
> 
> b.length = a.length;
> foreach(i, ref v; b) v = a[i];

import std.conf;
b = to!(long[])(a);

That should work, in theory.

  -- Daniel


Re: How to get the base type of a typedef

2009-05-01 Thread Daniel Keep


bearophile wrote:
> MLT:
>> Is there a way to get the base type of location?
> 
> See the BaseTypedef() template in the "templates" module of my dlibs (they 
> are for Phobos):
> http://www.fantascienza.net/leonardo/so/libs_d.zip
> 
> Bye,
> bearophile

It's probably something along the lines of:

template BaseTypedef(T)
{
static if( is( T U == typedef ) )
alias U BaseTypedef;
else
alias T BaseTypedef;
}

  -- Daniel


Re: enum in template

2009-04-29 Thread Daniel Keep


Sam Hu wrote:
> Hello everybody!
> 
> Convert integral value to string literal:
> 
> template myToString(ulong n,
>   string suffix=n>uint.max?"UL":"U"
> {
>  static if (n<10)
> enum myToString=cast(char)(n+'0')-suffix; //q1
> else
> enum myToString=.myToString!(n/10,"")-  
>   .myToString!(n%10,"")-suffix;//q2
> 
> Here is my questions,sir:

No need to be so formal.  Also keep in mind that "sir" only applies to
men, and is thus excluding any women in this NG.  :P

> q1.what the key word enum here is doing? not key word char[] or 'string' or 
> something else?

enum defines a "manifest constant."  In other words, it defines a
constant that does NOT consume any storage anywhere in the program: it
exists only at compile-time.

> enum blah = 42; // single manifest constant
>
> enum { blah = 42 } // again, but in a block, potentially with others
>
> enum Stuff { blah = 42 } // again, but in a named enumeration

> q2. How does this works?Say n=12,then how can the result be "12"?

Recursion.  I assume you have modified the code from its original since
'-' would be invalid.  It should be '~' which is the concatenation
operator in D.

> Thanks and best regards,
> Sam

  -- Daniel


Re: Get the name of a function and the parameters?

2009-04-28 Thread Daniel Keep


Jarrett Billingsley wrote:
> On Tue, Apr 28, 2009 at 3:07 PM, grauzone  wrote:
>> I'd like to pass several functions at once. Is there a way to make this
>> variadic? The obvious approach (writing "NameOfFunc(alias f...)") fails with
>> a syntax error.
> 
> Sure, you'd just make it NameOfFunc(f...) and then recursively
> instantiate, converting one item at a time to its name until f.length
> == 0.
> 
> Alternatively, you can write a compile-time map and use NameOfFunc as
> the mapping predicate.

That requires f to be a type, which loses you the actual names.  And you
cannot (last time I checked) have aliases in a tuple.

  -- Daniel


Re: Get the name of a function and the parameters?

2009-04-26 Thread Daniel Keep


Daniel Keep wrote:
> 
> Jacob Carlborg wrote:
>> Is it possible to get the name of a function and the names of the
>> function parameters?
> 
> I don't believe so, no.
> 
>   -- Daniel

I should perhaps qualify, in light of Jarrett's response, that I thought
you meant from inside the function ala __FUNCTION__ or somesuch.

  -- Daniel


Re: Get the name of a function and the parameters?

2009-04-26 Thread Daniel Keep


Jacob Carlborg wrote:
> Is it possible to get the name of a function and the names of the
> function parameters?

I don't believe so, no.

  -- Daniel


Re: i need a serialization framework for d

2009-04-23 Thread Daniel Keep


BCS wrote:
> http://stackoverflow.com/questions/783482/i-need-a-serialization-framework-for-d

Put my AU$0.02 in.

> OT: would anyone be interested in a one way stackoverflow->NNTP hookup
> kinda like is used with the bugzilla?

I think that'd be pretty cool; have it post questions to D.learn so they
get better exposure.

  -- Daniel


Re: Documentation on DMD source

2009-04-19 Thread Daniel Keep


Unknown W. Brackets wrote:
> You'll get a lot of use out of defining the debugs for #ifdefs, and/or
> uncommenting printfs and following it.
> 
> If your code may not be running, use a breakpoint or printf to ensure it
> is.
> 
> -[Unknown]

I finally found out why my changes weren't working.

Because typinf.c is the ONE file in the frontend that doesn't get passed
$(XFLAGS) when built.  Guess where I put the -D for my changes?  Go on,
guess.  You'll never get it.

*bangs head repeatedly*

Now I have an entirely DIFFERENT problem; I officially have NO idea what
the code I modified does.  :'(

  -- Daniel


Re: Documentation on DMD source

2009-04-18 Thread Daniel Keep


Daniel Keep wrote:
> Is there any guide to, or documentation for the DMD compiler source?
> 
> I'm currently trying to make TypeInfo_Function not completely useless,
> but I'm not sure my code is actually being run.
> 
>   -- Daniel

Found this page: http://www.prowiki.org/wiki4d/wiki.cgi?DMDSourceGuide
although it's fairly bare-bones.

  -- Daniel


Documentation on DMD source

2009-04-18 Thread Daniel Keep

Is there any guide to, or documentation for the DMD compiler source?

I'm currently trying to make TypeInfo_Function not completely useless,
but I'm not sure my code is actually being run.

  -- Daniel


Re: Widening a type

2009-04-16 Thread Daniel Keep


Doctor J wrote:
> OK, here's one for you that sounds like it ought to be easy, but I don't 
> immediately see how to do it in a pretty way.
> 
> Given a type parameter T of a template:
> If T is an integral type, I want to declare a variable 'widest' of type ulong;
> If T is a floating-point type, I want to declare a variable 'widest' of type 
> double.
> And it has to be prettier than my solution.  :)
> 
> static if (is (T: ulong))
> ulong widest = 0;
> else if (is (T: double))
> double widest = 0.0;
> else
> static assert (false, "Unimplemented type " ~ T.stringof) ;
> 
> Now, I thought this sounds like a great job for a mixin:
>  
> template Widen (T, alias varname)
> {
> static if (is (T: ulong))
> ulong varname = 0;
> else if (is (T: double))
> double varname = 0.0;
> else
> static assert (false, "Unimplemented type " ~ T.stringof) ;
> }
> 
> mixin Widen!(T, widest);
> 
> but alas, "Declaration expected, not 'if'".
> 
> Help?

The error tells you everything you need to know if you read it.

Actually, you have two problems: you're trying to use "if" where you
should be using "static if", and you can't alias a symbol name then use
it in a declaration.  Here's a fixed, expanded version.

template Widen (T, char[] varname)
{
static if (is (T: ulong))
{
mixin(`ulong `~varname~` = 0;`);
}
else
{
static if (is (T: double))
{
mixin(`double `~varname~` = 0.0`);
}
else
{
static assert (false, "Unimplmented type " ~ T.stringof);
}
}
}

You can remove those braces, I just wanted to point out that putting
"static" out the front of an "if" doesn't magically make the "else"
branch static as well.

  -- Daniel


Re: static initialization of associative arrays

2009-04-15 Thread Daniel Keep


Tyro[a.c.edwards] wrote:
> Is it yet possible to statically initialize an associative array? If so,
> please point me to the documentation. I am using DMD v2.028.
> 
> Currently I'm able to do this:
> 
> import std.stdio;
> 
> string[string] types;
> static this(){
> types = [ "void":"void", "bool":"bool" ];
> }
> 
> void main(){
> writeln(types);
> }
> 
> Output = [void:void,bool:bool] which is exactly what I want.
> 
> However, removing static this() results in an error.
> 
> string[string] types = [ "void":"void", "bool":"bool" ];
> 
> Result:
> api.d(77): Error: non-constant expression ["void":"void","bool":"bool"]
> 
> How do I make the initialization constant?
> 
> Thanks,
> Andrew

I think Walter said something a while back to the effect that making it
possible to statically initialise AAs isn't feasible because it requires
setting up a complex structure on the heap.  The best you could do would
be to *pretend* to statically initialise them, and actually really
initialise them in a module ctor.

Which is exactly what you currently have to do.

Could be wrong; that's just what I remember from the last time this came up.

  -- Daniel


Re: D1 and read-only views?

2009-04-12 Thread Daniel Keep

As others have stated, your surmise is correct.

On a related note, I recently wrote a very simple cstring struct that
acts like const(char)[] does in D2.  I was using unique interned
strings, and didn't want any surprises.  You can still get a mutable
reference to the string by using .toString, but the struct is really
only there to prevent accidental modifications.

  -- Daniel


Re: Class templates with types determined at runtime

2009-04-07 Thread Daniel Keep

The major problem with this is that you're trying to get into a
situation where you don't know the type of T at compile-time, and you
CANNOT do that.

For example, your newContainer function can't return a "Container"
because "Container" isn't a concrete type; it's just a template.

The only thing I can think of that might help you is std.boxer (or
tango.core.Variant).  Variants and boxes can be passed around however
you'd like so long as you don't try to look inside.

As soon as you look inside, you need to have code specialised for each
supported type.

Something like this:

-
import std.stdio;
import std.math;
import std.boxer;

void dostuff(Box cont)
{
if( unboxable!(float)(cont) )
writefln("%.12f", unbox!(float)(cont));

else if( unboxable!(double)(cont) )
writefln("%.12f", unbox!(double)(cont));
}

int main(string[] args)
{
string precision = "double";
if (args.length > 1 && args[1] == "single")
precision = "single";

auto cont = newContainer(precision);
dostuff(cont);

return 0;
}

Box newContainer(string precision)
{
switch (precision)
{
case "single":
return box( cast(float) PI );
case "double":
return box( cast(double) PI );
default:
/+
// exit?  Eurgh!
writefln("Error: unknown type '%s'.", precision);
exit(1);
+/
throw new Exception("unknown type " ~ precision);
}
}
-

Hope that helps.

  -- Daniel



Re: cast a LinkSeq

2009-04-06 Thread Daniel Keep


Qian Xu wrote:
> Adam Burton wrote:
>> I wouldn't think so, cos LinkSeq!(Apple) does not inherit
>> LinkSeq!(Fruit), they are 2 separate types. However your apples
>> automatically downcast (or up, depending which way you like to draw
>> your diagrams :-) ) so unless you  intend to pass the LinkSeq!(Apple)
>> into a function expecting LinkSeq!(Fruit)  it shouldn't be a problem.
>> If you are passing about LinqSeq!(Fruit) and want  your
>> LinkSeq!(Apple) to fit you might need to write some adapters and make
>> use of the models available to you or something along them lines.
>>
>> That's my understanding anyway.
> 
>>
> 
> yes. I can cast all Apple-object to Fruit-objects one by one. I hope
> there is an one-line-solution :-)

You can't do it.  Imagine you cast your LinkSeq!(Apple) to
LinkSeq!(Fruit).  You can now add a Banana to your LinkSeq!(Fruit), thus
corrupting the original object.

You get a similar problem with arrays.

The most direct way would probably be to create a LinkSeqView!(T) class
which did the cast on the fly and prohibited mutating operations.

  -- Daniel


Re: Wht std.complex is needed?

2009-04-06 Thread Daniel Keep


Steven Schveighoffer wrote:
> On Mon, 06 Apr 2009 08:36:18 -0400, Don  wrote:
> 
>> Sam Hu wrote:
>>> Thank you!
>>> Anothe silly question then:What's the disadvantage to have the
>>> built-in type of i-type?
>>>  Regards,
>>> Sam
>>
>> It's a very nasty type. It supports *, but isn't closed under *.
>> Which is really annoying for generic programming.
>>
>> idouble x = 2i;
>> x *= x; // oops, this isn't imaginary. (BTW this currently compiles :o).
> 
> This may be a dumb question, but aren't all real numbers also
> technically imaginary numbers with a 0i term?  that is, I would expect
> the above to evaluate to:
> 
> -4 + 0i
> 
> Which I would view as an imaginary number.  Am I completely wrong here?

You're thinking of "complex".  -4 is real, 2i is imaginary, -4+2i is
complex.

Regarding Don's example, imaginary*imaginary always yields a real,
real*imaginary always yields an imaginary.  It's the only builtin type I
know of that changes type under multiplication with itself.

  -- Daniel


Re: project euler #10: optimization with primes

2009-04-01 Thread Daniel Keep


Robert Fraser wrote:
> bearophile wrote:
>> import d.func, d.primes, d.string;
>> void main() {
>> const int N = 1_000_000_000;
>> putr( sum(xtakeWhile((int i){ return i < N;}, xprimes(N))) );
>> }
> 
> Yeah that's shorter (vertically; it's almost as long in characters), but
> how much lisp do you have to smoke to understand it?

None.  It's a straightforward stream operation.

  -- Daniel


Re: Universel toString

2009-03-20 Thread Daniel Keep


grauzone wrote:
> Daniel Keep wrote:
>>
>> Qian Xu wrote:
>>> Hi All,
>>>
>>> I want to write an universel toString() method for debugging propose.
>>> However I cannot write in one version. The compiler says error all
>>> the time.
>>> Could someone tell me, how to write an universel one?
>>>
>>> What I want, is to convert primtive types (int, int*, bool, bool*,
>>> etc.) to
>>> string using "tango.text.Convert.to()" and convert object to string by
>>> calling obj.toString.
>>>
>>> ...
>>>
>>> Best regards
>>> --Qian Xu
>>
>> to!(char[]) should call toString.  to!(T) should support all atomic
>> types, strings, structs and classes.
> 
> So to!(char[])(x) almost like format("%s", x)?
> 
>>   -- Daniel

Probably something like
tango.text.convert.Format.Format.convert("{0}",x) for Tango.

Actually, that's not entirely true.  to!(char[]) won't convert pointers
or arrays.

Sorry; the brain switched off as soon as I saw "I have to special-case
to" :P

  -- Daniel


Re: Universel toString

2009-03-20 Thread Daniel Keep


Qian Xu wrote:
> Hi All,
> 
> I want to write an universel toString() method for debugging propose.
> However I cannot write in one version. The compiler says error all the time.
> Could someone tell me, how to write an universel one?
> 
> What I want, is to convert primtive types (int, int*, bool, bool*, etc.) to
> string using "tango.text.Convert.to()" and convert object to string by
> calling obj.toString.
>
> ...
> 
> Best regards
> --Qian Xu

to!(char[]) should call toString.  to!(T) should support all atomic
types, strings, structs and classes.

  -- Daniel


D2: bug in struct postblit/dtor, or am I a burke?

2009-03-17 Thread Daniel Keep

Hi all.

I can't seem to get this to work properly.  I'm trying to write a
copy-on-write proxy type.  I'm using postblit and dtors along with the
usual ctors and opAssign to manage the refcount of the shared memory.
However, testing with dmd-2.026 (and a few previous versions a little
while ago), the attached program gives me the following output:

(NB: ">" means entering, "<" means leaving; these messages are printed
from in- and out-contracts.  Printed values are the array being stored
and the ref count (or zero if the ref count pointer is null.))

> opAssign(T[]);COWArray(0x[0..0]) @ 0
> ~this();  COWArray(0x  12FE88[0..4424652]) @ 1245120
< ~this();  COWArray(0x  12FE88[0..4424652]) @ 1245119
< opAssign(T[]);COWArray(0x  AA2E40[0..4]) @ 1
> this(this);   COWArray(0x  AA2E40[0..4]) @ 1
< this(this);   COWArray(0x  AA2E40[0..4]) @ 2
a: [1,2,3,4]
> ~this();  COWArray(0x  AA2E40[0..4]) @ 2
< ~this();  COWArray(0x  AA2E40[0..4]) @ 1

For the following code:

void main()
{
COWArray!(int) a;
a = [1,2,3,4];

// This shouldn't affect ref counts
auto a_str = a.toString;
writefln("a: %s", a_str);
}

As you can see, it correctly enters opAssign and leaves with the correct
array reference and ref count.  However, it also spuriously calls the
destructor with what appears to be a random pointer.  It then calls the
postblit when it shouldn't be doing so, resulting in the refcount being
one too high.

I've attached the full source (compile with -debug); does anyone know
what I'm doing wrong, or whether this is a compiler bug?

  -- Daniel

module cow_bug;

import std.string : format;
import std.stdio : writefln, writef;

struct COWArray(T)
{
private
{
T[] arr = null;
size_t* ctr = null;
}

/*
 * Returns cowarray definition as a string for debugging
 */
debug private string stat()
{
return format("COWArray(0x%08x[0..%d]) @ %d",
arr.ptr, arr.length,
ctr ? *ctr : 0);
}

/*
 * Post-blit function; increment reference count since we've just been
 * copied.
 */
this(this)
in{debug  writefln("> this(this);   ",stat);}
out{debug writefln("< this(this);   ",stat);}
body
{
++ *(this.ctr);
}

/*
 * Dtor; decrement ref count, destroy memory if the counter is zero.
 */
~this()
in{debug  writefln("> ~this();  ",stat);}
out{debug writefln("< ~this();  ",stat);}
body
{
// Accounts for empty cowarrays.
if( this.ctr )
{
-- *(this.ctr);

if( *(this.ctr) == 0 )
delete this.ctr;
}
}

const size_t length()
{
return arr.length;
}

COWArray opAssign(T[] arr)
in{debug  writefln("> opAssign(T[]);",stat);}
out{debug writefln("< opAssign(T[]);",stat);}
body
{
// If we already have an array, dec ref, destroy if counter == 0.
if( this.ctr !is null )
{
-- *(this.ctr);

if( *(this.ctr) == 0 )
delete this.ctr;
}

// Attach to new array, assume no aliasing.
this.arr = arr;
this.ctr = new size_t;
*(this.ctr) = 1;

return this;
}

string toString()
{
return format("%s", this.arr);
}
}

void main()
{
// New array, no ctor, so it's not pointing at anything, and has zero
// length.
COWArray!(int) a;

// opAssign array; should have a single reference.
a = [1,2,3,4];

// This shouldn't affect ref counts
auto a_str = a.toString;
writefln("a: %s", a_str);

// Should have one reference, zero after the dtor, and the memory should
// be deleted.
}



Re: C-style nested structs convert to D

2009-03-17 Thread Daniel Keep
CodexArcanum wrote:
> Hey all, I'm trying to rewrite a few .h files into D so I can call a C 
> library.  One snag I've hit is this guy:
> 
> struct _tree_t {
>   _tree_t* next;
>   _tree_t* father;
>   _tree_t* sons;
> }
> 
> D won't do the nested struct thing, so I need to convert this into something 
> D will like, but which the library will still take in.  What should I do?

Tested with 1.035; it works just fine.

  -- Daniel


Re: lvalue - opIndexAssign - Tango

2009-03-13 Thread Daniel Keep


The Anh Tran wrote:
> Hi,
> 
> When porting from c++ to D, i encounter this strange discrimination:
> 1. Built-in AA:
> int[int] arr;
> arr[123] += 12345;
> arr[321]++;
> 
> 2. Tango HashMap:
> auto hm = new HashMap!(int, int)();
> hm[123] += 12345; // error not lvalue
> hm[123]++;// error
> 
> D document says current opIndexAssign does not work as lvalue. But why
> can builtin AA can that? How can i copy builtin AA behaviour?

You can't.  This is a hole in the language at the moment, hopefully
solved by the introduction of ref returns (but that's in D 2.0 which you
don't want to use at the moment.)

> Forgive my noob, where is the place to ask question, report bug for Tango?

You could try the Tango IRC channel:

irc://irc.freenode.org/#d.tango

That, or the Tango forums:

http://dsource.org/projects/tango/forums

You can report problems with Tango via the ticket system:

http://dsource.org/projects/tango/report ("New Ticket" is down the
bottom of the page.)

> 1. I can't compile D code using tango hashmap in debug mode:
> 
> import tango.util.container.HashMap;
> void main()
> {
> auto hm = new HashMap!(uint, uint)();
> }
> 
>> dmd -w -g -debug  hello.d // error

When posting problems with compiling something, it helps to mention the
version of the compiler you're using, your platform, the version of
Tango (in this case) and what the error actually is.

> 2. Compile D code using Tango Regex by GDC emit lots of link errors.
> 
> 3. Bug in Tango atomicIncrement, atomicDecrement:
> 
> int task_done = 0;
> atomicIncrement(task_done);
> 
> That function is compiled in asm:
> lock inc byte ptr[task_done];
> Which is wrong. It'll wrap to 0 at 255.
> It should be: lock inc dword ptr[task_done];
> 
> 4. There is no atomicAdd(ref original, int newvalue) family. GCC
> equivalence is __syn_fetch_and_add ...

  -- Daniel


Re: recognizing asciiz, utf ...

2009-03-13 Thread Daniel Keep


newbee wrote:
> Jarrett Billingsley Wrote:
> 
>> On Fri, Mar 13, 2009 at 3:04 PM, newbee  wrote:
>>> Hi all,
>>>
>>> How does one check for asciiz, utf ...?
>>> I do get a buffer with characters as parameter in a function, but i don�t 
>>> know if it is asciiz or utf or wchar. Is it possible to find out in dmd1 
>>> and dmd2?
>>>
>>> Any help is appreciated.
>> How are you getting this buffer?  What type is it, char[]?  D strings
>> are supposed to be Unicode, always.  If you read the data in from a
>> file, there's little to no guarantee as to what encoding it is (unless
>> it started with a Unicode BOM).
>>
>> If you have a zero-terminated char* that a C function gives you, you
>> can turn it into a D string with std.string.toString (Phobos) or
>> tango.stdc.stringz.fromStringz (Tango).
> 
> 
> i get it from a tcp buffer and do not know in advace if it is char[], asciiz 
> or wchar. is it possible to check for that?

If you're getting data from a network connection and you have no idea
what it is, then the language certainly isn't going to help you with that.

Perhaps reading the documentation for the network protocol is in order? :P

  -- Daniel


Re: enum to string

2009-03-13 Thread Daniel Keep


Ary Borenszweig wrote:
> Lionello Lunesu wrote:
>>
>> "Brad Roberts"  wrote in message
>> news:alpine.deb.2.00.0903121755240.4...@bellevue.puremagic.com...
>>> That said, I don't think this really helps the desired usecase much. 
>>> It's
>>> useful, don't get me wrong, but still requires code to build up the
>>> bi-directional translations.  Or am I missing something?  Seems to be
>>> happening to me a lot lately, so I'm very prepared to be wrong here too.
>>> :)
>>
>>
>> You're not wrong :)
>> The problem is that the foreach variable is not evaluatable to a
>> compile-time string. I don't know why, but I'll figure it out tonight.
>>
>> I've also managed to convert an enum to an AssocArrayLiteralExp* (with
>> the name/string as the key and the value/int as the value) but it
>> seems that it cannot be foreached at compile time, even if it's a
>> literal expression. But hell, I've spent about 1 hour browsing through
>> dmd's code, so I'm pretty sure it's possible with a little more research.
> 
> Can you foreach at compile-time? I thought you could only do that in
> CTFE (or templates?). Maybe that's why it's not working. How do you do
> it to pragma msg the members of a struct?
> 
> I remember someone proposed "static foreach" some time ago...

We have a sort-of static foreach.  The trick is that the aggregate HAS
to be a tuple.  When in doubt, you can always fall back on the following
construct:

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

template Range(int n)
{
static if( n <= 0 )
alias Tuple!() Range;
else
alias Tuple!(Range!(n-1), n-1) Range;
}

void blah()
{
// Note that static foreach ONLY works inside a function
foreach( i ; Range!(n) )
{
// do stuff with i, which should be a const int
}
}

There have been times when directly accessing some CT construct would
make the compiler choke, but going via an index worked fine.

-- Daniel


Re: # operator under C implementation in D1

2009-03-12 Thread Daniel Keep


Sam Hu wrote:
> I know a little that in C there is a # operator which under a macro can 
> return any type's value in character format.Just wanna know whether there is 
> an equivelent implementation in D1.Say,in C using a/m macro can easily output 
> enum's character value other than integer.It would be grateful if anybody 
> would like to paste a few lines of code to demostrate such implementation.
> 
> Regards,
> Sam

D doesn't have text substitution macros, so it doesn't have a # operator.

The closest you can get is .stringof, which has strange and mysterious
ways.  For example, int.stringof, (1+2).stringof, etc.

That, or just quote out the thing you want to turn into a string.

  -- Daniel


Re: Newbie question: COM programming and linking to Windows libraries

2009-03-11 Thread Daniel Keep


Patrick Kristiansen wrote:
> ...
> 
> Now, this is probably obvious to some people - but not to me. Why doesn't 
> this work? Why does OPTLINK fail and tell me that the format of the .lib file 
> is wrong? Is it because Digital Mars compilers produce .lib files in a 
> different format? Is it because I have the 64 bit SDK installed, and DMD and 
> optlink only produce and consume 32 bit object files and libraries?
> 
> Please enlighten me ;-)
> 
> Thanks in advance.
> 
> -Patrick

The DM toolchain produces and consumes OMF object files, while I suspect
the SDK uses COFF.  Also, the toolchain is 32-bit, not 64-bit.

There's a tool called implib which can generate a .lib file that
DMD/OPTLINK can use.

Documentation is here: .

You can get it by going to , clicking on
"Download Digital Mars C compiler", accept the agreement, and then
scroll down to "Basic Utilities".

  -- Daniel


Re: enum to string

2009-03-10 Thread Daniel Keep


Nick Sabalausky wrote:
> Is there any way to do this (preferably in D1) with reflection? (ie, without 
> having to manually create a conversion func/lookup for every value of every 
> enum.)
> 
> --
> enum Shape
> {
> Square, Circle
> }
> char[] foo(Shape s)
> {
> // ?
> }
> 
> // Either one of these, I don't really care which
> assert(foo(Shape.Square) == "Shape.Square");
> assert(foo(Shape.Square) == "Square");
> --

The only way that I know of is to generate foo at the same time as
Shape.  Generally, you write a CTFE function that generates the enum and
also generates the toString function.

  -- Daniel


Re: array and pointer

2009-03-05 Thread Daniel Keep


takeshi wrote:
> Hello, I have just started learning D.
> 
> I cannot compile the code in the documentation on array and pointer
> either with dmd (D 2.0) and gdmd (D 1.0).
> 
> Is some compile option or cast required?
> 
> int* p;
> int[3] s;
> p = s;

If that's the example, then it's out of date.  It should be this:

int* p;
int[3] s;
p = s.ptr;

  -- Daniel


Re: Reading and writing Unicode files

2009-02-28 Thread Daniel Keep


jicman wrote:
> Ok, the only reason that I say Unicode is that when I open the file in 
> Notepad and I do a SaveAs, the Encoding says Unicode.  So, when i read this 
> file and I write it back to the another file, the Encoding turns to UTF8.  I 
> want to keep it as Unicode.

There is no such thing as a Unicode file format.  There just isn't.  I
know the option you speak of, and I have no idea what it's supposed to
be; probably UCS-2 or UTF-16.

> I will give the suggestion a try.  I did not try it yet.  Maybe Phobos should 
> think about taking care of the BOM byte and provide support for these 
> encodings.  I am a big fan of Phobos. :-)  I have not tried Tango yet, 
> because I would have to uninstall Phobos and I have just spend two years 
> using Phobos and we already have an application based in Phobos and changing 
> back to Tango will slow us down and put us back.  Maybe version 2.0.

There's std.stream.EndianStream, which looks like it can read and write
BOMs.  As for converting between UTF encodings, std.utf.

  -- Daniel


Re: Reading and writing Unicode files

2009-02-28 Thread Daniel Keep


jicman wrote:
> downs Wrote:
> 
>> downs wrote:
>>> jicman wrote:
 Greetings.

 Sorry guys, please be patient with me.  I am having a hard time 
 understanding this Unicode, ANSI, UTF* ideas.  I know how to get an UTF8 
 File and turn it into ANSI. and I know how to take a ANSI file and turn it 
 into an UTF file.  But, now I have a Unicode file and I need to change the 
 content and create a new Unicode file with the changes in the content.  I 
 have read all kind of places, and I found mtext, from Chris Miller's site, 
 by reading,

 http://www.prowiki.org/wiki4d/wiki.cgi?DanielKeep/TextInD

 Anyway, what I need is to read an Unicode file, search the strings inside, 
 make changes to the file and write the changes back to an Unicode file.

 Any help would be greatly appreciate.

 thanks,

 jos�
>>> Wow, you're in luck!
>>>
>>> D is all unicode.
>>>
>>> Just do import std.file; auto text = cast(string) filename.read(); do your 
>>> changes; filename.write(cast(void[]) text);
>>>
>>> and you're done.
>> PS: You may need to do detection for UTF-16. In that case, just cast to a 
>> wstring instead, then (optionally) use std.utf.toUTF8.
> 
> shouldn't auto take care of that?

The compiler doesn't know what format your text files are in.  auto does
type inference.

  -- Daniel


Re: Any way to track memory allocations?

2009-02-24 Thread Daniel Keep


Jarrett Billingsley wrote:
> On Tue, Feb 24, 2009 at 8:23 PM, Daniel Keep
>  wrote:
> 
>> Yup.
>>
>> It's a pity that we don't have, oh I don't know, some sort of efficient
>> iterable interface that doesn't cause a heap allocation that the runtime
>> could use instead *cough*hint*cough*andrei*cough*ranges*cough*.
> 
> You can use "foreach(k; aa)" and "foreach(_, v; aa)".
> 
> The thing is they're not always substitutes for .keys and .values.
> For example, if you want to modify the AA during the foreach loop, you
> have to use something like "foreach(k; aa.keys)" since you need a
> "snapshot" of the keys as they were before you started modifying it.

True; although I'm one of those people who stays up at night, plotting
the gruesome demise of invisible allocations, so I tend to do manually
create and destroy the storage for the keys.

In a perfect world, we'd have extension methods, and then we could just
do this:

RangeType!(T)[] toArray(T)(ref T this) if isRange!(T)
{
  ...
}

foreach( k ; aa.keys.toArray ) ...

My own policy is that if you have to choose between two designs, one
where you always allocate and the other where you can optionally
allocate, go for the second.

  -- Daniel


Re: Dynamic Array Garbage collection

2009-02-24 Thread Daniel Keep


Jarrett Billingsley wrote:
> On Tue, Feb 24, 2009 at 6:45 PM, Daniel Keep
>  wrote:
> 
>>  Maybe it's because I just woke up, but I can't see how that code could
>> compile anyway, since you can't pass a short[] to a function expecting
>> an int[].
> 
> You missed the array literal.

I saw that, but thought that it would be a short[] literal since it's
usually the type of the first argument.

  -- Daniel


Re: Any way to track memory allocations?

2009-02-24 Thread Daniel Keep


wade wrote:
> Thanks again for all the help.  I found what the problem was and it wasn't 
> obvious (at least to me):
> 
> float[uint] arr;
> 
> foreach (uint k; arr.keys)
> {
>  ...
> }
> 
> Changing this to:
> 
> foreach (uint k, float v; arr)
> {
> 
> }
> 
> fixes the leak.  I guess the keys array is constructed on the fly?
> 
> wade

Yup.

It's a pity that we don't have, oh I don't know, some sort of efficient
iterable interface that doesn't cause a heap allocation that the runtime
could use instead *cough*hint*cough*andrei*cough*ranges*cough*.

  -- Daniel


Re: Generic functions to convert to void* and from void*

2009-02-24 Thread Daniel Keep

TSalm wrote:
> In my case, there's also no possibility to get the wrong type, because
> it is managed by the type of the ColumnMem.

You still have to get the code right.  There's a surprising number of
corner cases trying to store arbitrary types.

> And about Object, if I want to store base type like int,double,etc...,
> if I do something like :
> 
>  Object o;
>  int a = 30 ;
>  o = cast(Object) &a ;
> 
> is this syntax is GC safe ?

It's not safe, period.  If the compiler lets you do that, I'd be
tremendously surprised; even more surprised if it doesn't cause major
problems later.  This is what I'm worried about; you're doing dangerous
things with a type system you don't understand.  Don't do this.

Here's the problem: void* isn't going to work for everything.  It'll
work for Object references, other pointers, and that's it.  You can't
store arrays, and you can't store value types like structs or primitive
types.  For that, you need to allocate heap storage, copy the value and
then store the pointer to that.  Oh, and don't forget that fixed-length
arrays have value semantics whereas dynamic arrays and slices have
reference semantics; although you generally solve that issue by having a
special template for your type which rewrites T[n] as T[].  Also,
delegates won't fit, but function pointers will.

This is why I was pointing you at Variant because I already went through
the trouble to solve all this once.  :P

If you still want to do this with void*, build that code in isolation
and test the heck out of it.

  -- Daniel


  1   2   >