Random Access I/O

2016-03-25 Thread Chris Williams via Digitalmars-d-learn
I need to be able to perform random access I/O against a file, 
creating a new file if it doesn't exist, or opening as-is (no 
truncation) if it already exists.


None of the access modes for std.stdio.File seem to allow that. 
Any usage of the "w" mode causes my code to consider the file 
empty if it pre-exists (though, it doesn't always actually 
truncate the disk on file?)


If I was coding in C, I would use open() as it gives more options 
for access:


http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html

However, I don't see this exposed in phobos anywhere?


Static convertability testing?

2015-02-12 Thread Chris Williams via Digitalmars-d-learn
I have a template function that gets values out of a tree of 
variant types. My goal is to be able to write code like;


node.get!string("path", "to", "leaf");

Inside get(), I would like to use std.conv to dynamically convert 
(where able) to the target type (T) or, if that is not possible, 
to return T.init.


If I wanted to force the user to request the correct type as is 
stored in the structure, I could write code like:


switch (leafType) {
case STRING:
   static if (is(T : string)) {
  return leftValue;
   }
   else {
  return T.init
   }
break;
...

But since I want to allow all possiblities that std.conv 
supports, I want something like:


static if (isConvertible!(T, string)) {
   return leftValue.to!T;
}
else {
   return T.init;
}

Is there something like isConvertible() in the library somewhere?


Re: Time from timestamp?

2015-01-30 Thread Chris Williams via Digitalmars-d-learn
On Saturday, 31 January 2015 at 00:14:37 UTC, Steven 
Schveighoffer wrote:

On 1/30/15 5:18 PM, Chris Williams wrote:
I'm attempting to print a human-readable version of a 
timestamp. The
timestamp is coming from an external service, via JSON. An 
example is:


1421865781342

Which I know to be:

2015-01-21T18:43:01.342Z



http://dlang.org/phobos/std_datetime.html#.unixTimeToStdTime

It's kind of convoluted because there is no epoch, but you can 
make one:


import std.datetime;
import std.stdio;

void main(string[] args)
{
// can't make this enum because of time zone...
auto epoch = SysTime(unixTimeToStdTime(0), UTC());
writeln(epoch + 1_421_865_781_342.msecs);
}

output:
2015-Jan-21 18:43:01.342Z

Note the reason your code didn't work is because SysTime uses 
1/1/1 as the epoch.


-Steve


D'oh, I missed that in the description:

"and convert it to hnsecs in UTC since midnight, January 1st, 1 
A.D. UTC"


That does explain it. I also didn't spot the declaration of 
unixTimeToStdTime(), which assuredly helps.


Thank you!


Re: Time from timestamp?

2015-01-30 Thread Chris Williams via Digitalmars-d-learn

On Saturday, 31 January 2015 at 00:20:07 UTC, ketmar wrote:

On Sat, 31 Jan 2015 00:03:43 +, Chris Williams wrote:


since most database software probably
stores birthdates (many of which are pre-1970) in this format

O_O
a perfectly broken software.


And stdc:

http://h50146.www5.hp.com/products/software/oe/tru64unix/manual/v51a_ref/HTML/MAN/MAN3/3955.HTM

And UNIX:

http://www.lehman.cuny.edu/cgi-bin/man-cgi?mktime+3


Re: Time from timestamp?

2015-01-30 Thread Chris Williams via Digitalmars-d-learn

On Friday, 30 January 2015 at 23:50:53 UTC, ketmar wrote:

On Fri, 30 Jan 2015 23:42:04 +, Chris Williams wrote:

On Friday, 30 January 2015 at 22:38:21 UTC, Chris Williams 
wrote:
On Friday, 30 January 2015 at 22:22:27 UTC, Rikki Cattermole 
wrote:
On a slightly related note, I have code for UTC+0 to unix 
time stamp.

https://github.com/Devisualization/util/blob/

b9ab5758e755c4e33832ac4aed0a5d7f2c728faf/source/core/devisualization/util/
core/time.d


Unix timestamps can be negative, so you should probably be 
using longs

instead of ulongs.


Yup, there was a world before January 1st, 1970.


not for unix timestamps. please, stop that, unix timestamp was 
not
designed to present any dates before 1970. "negative timestamp" 
is a bug

in code.


Unless you know something I don't, everything I've ever read says 
that a negative unix timestamp is meant to refer to a time before 
1970. It may not have been intentional, but since most database 
software probably stores birthdates (many of which are pre-1970) 
in this format, having a library be unable to support them just 
makes the library useless for many situations.


Re: Time from timestamp?

2015-01-30 Thread Chris Williams via Digitalmars-d-learn

On Friday, 30 January 2015 at 22:38:21 UTC, Chris Williams wrote:
On Friday, 30 January 2015 at 22:22:27 UTC, Rikki Cattermole 
wrote:
On a slightly related note, I have code for UTC+0 to unix time 
stamp.

https://github.com/Devisualization/util/blob/b9ab5758e755c4e33832ac4aed0a5d7f2c728faf/source/core/devisualization/util/core/time.d


Unix timestamps can be negative, so you should probably be 
using longs instead of ulongs.


Yup, there was a world before January 1st, 1970.


Re: Time from timestamp?

2015-01-30 Thread Chris Williams via Digitalmars-d-learn
On Friday, 30 January 2015 at 22:22:27 UTC, Rikki Cattermole 
wrote:
On a slightly related note, I have code for UTC+0 to unix time 
stamp.

https://github.com/Devisualization/util/blob/b9ab5758e755c4e33832ac4aed0a5d7f2c728faf/source/core/devisualization/util/core/time.d


Unix timestamps can be negative, so you should probably be using 
longs instead of ulongs.


Time from timestamp?

2015-01-30 Thread Chris Williams via Digitalmars-d-learn
I'm attempting to print a human-readable version of a timestamp. 
The timestamp is coming from an external service, via JSON. An 
example is:


1421865781342

Which I know to be:

2015-01-21T18:43:01.342Z

The only method I see which takes an epoch-style timestamp, so 
that I can convert it to something printable, is the SysTime 
constructor:


pure nothrow @safe this(long stdTime, immutable TimeZone tz = 
null);


According to the reference, this seems to take the value in 
hnsecs. My expectation would be that this means multiplying my 
initial value by 1_000_000. But if I do that, I get a random date 
2500 years in the future.


I created this sample code:

void main() {
long time = 1421865781342L;
writefln("%s", SysTime(time));
writefln("%s", SysTime(time * 10L));
writefln("%s", SysTime(time * 100L));
writefln("%s", SysTime(time * 1_000L));
writefln("%s", SysTime(time * 10_000L));
writefln("%s", SysTime(time * 100_000L));
writefln("%s", SysTime(time * 1_000_000L));

writefln("%s", Clock.currTime.stdTime);
}

Outputs:

0001-Jan-02 07:36:48.5781342
0001-Jan-17 03:04:47.781342
0001-Jun-14 05:44:39.81342
0005-Jul-04 08:23:20.1342
0046-Jan-21 10:50:03.342
0451-Jul-28 11:17:15.42
4506-Sep-18 16:42:14.2
635582516

My expectation would be that the final line would be something 
beginning with "14" at least. Playing around with possible 
multipliers, there doesn't even seem to be any integer value that 
would allow conversion between the timestamp I received and 
whatever SysTime expects.


I'm using:

DMD64 D Compiler v2.066.1
Ubuntu from .deb package

Is this a bug, or am I doing something wrong?


Re: Using std.net.curl to stream data

2015-01-28 Thread Chris Williams via Digitalmars-d-learn

On Wednesday, 28 January 2015 at 14:18:38 UTC, Trollgeir wrote:
I'm having some trouble trying to stream data to my plot.ly 
graph:

https://plot.ly/62/~Trollgeir/

The API:  https://plot.ly/streaming/

I am able to post messages that get recorded into the stream 
live, although right after curl uploads it, it just seems to 
wait for a response it's not getting, and eventually timeouts. 
Does anyone have any advice?


auto client = HTTP("stream.plot.ly");
client.addRequestHeader("plotly-streamtoken","e8bg6omat6");
client.verbose = true;

string msg = "{ \"x\": 500, \"y\": 500 } \n";
client.postData(msg);
client.perform; 


You have to define a handler for HTTP.onReceive before calling 
HTTP.perform. It will receive ubyte arrays for each packet that 
comes in. For most purposes, you just copy that onto the end of a 
string in an external scope. But if you're streaming content, 
you'll need to do something more fancy.


Re: How to copy object of class A to another object of class B?

2015-01-28 Thread Chris Williams via Digitalmars-d-learn

On Wednesday, 28 January 2015 at 09:44:29 UTC, zhmt wrote:

Sometime , I need to copy them:

thrift.Card tc;

db.Card dc;

dc.id = tc.id;
dc.pwd = tc.pwd;
...


It is boring coding, I want a solution to copy them 
automatically:

void copyObj(SRC,DEST)(SRC src,DEST dest)
{
foreach (i, type; typeof(SRC.tupleof)) {
auto name = SRC.tupleof[i].stringof;
		__traits(getMember, dest, name) =  __traits(getMember, src, 
name);

writeln(name);
}
}

Unfortunitely, it doesnt work,  how to improve it?


Assuming that the hibernated class isn't auto-generated and you 
can redefine its contents freely, the following style may be an 
alternative that works for you:


struct Foo {
public:
string a;
int b;
}

class FooClass {
public:
union {
struct {
string a;
int b;
};
Foo foo;
}

}

void main() {
Foo f = Foo("a", 10);
FooClass c = new FooClass();
c.foo = f;

writefln("%s %s", c.a, c.b);
}

Probably the anonymous struct will break the UDAs, but it should 
be worth testing.


Re: how convert the range to slice ?

2015-01-28 Thread Chris Williams via Digitalmars-d-learn

On Wednesday, 28 January 2015 at 22:43:36 UTC, bearophile wrote:

Nordlöw:

Is there any chance we could add logic to dmd+phobos that 
hints user about this?


It's such a fundamental part of D+Phobos that newbies are 
forced to learn this quickly. On the other hand an informative 
error message could be useful...


What error message do you suggest?

Bye,
bearophile


Range is not castable to array. See std.array.array to generate 
an array from a Range.


Re: Russian translation of the "range" term?

2014-11-12 Thread Chris Williams via Digitalmars-d-learn

On Wednesday, 12 November 2014 at 11:38:52 UTC, thedeemon wrote:
On Tuesday, 11 November 2014 at 11:50:18 UTC, Ivan Kazmenko 
wrote:

Hi!

I'm unsure what is the Russian equivalent for the term 
"range", as in "D range", the generalization of a pair of 
iterators.


I think "последовательность" (sequence) is the most 
appropriate, because the defining characteristic of an input 
range (most common one) is ability to provide data 
sequentially. Also, afaik, some languages like F# and Clojure 
use this term (often shortened to 'seq') for the same thing 
that D calls ranges.


While sequence makes more sense for how std.range thinks of 
ranges, I think the history of the term is closer to how we use 
slices. So another (English) alternative to try might be a 
"view". It's a fairly common term in SQL databases, so presumably 
there's a translation for it in Russian.


Re: Why do some language-defined attributes have @ and some not?

2014-10-24 Thread Chris Williams via Digitalmars-d-learn

On Thursday, 23 October 2014 at 07:39:21 UTC, Gary Willoughby
wrote:
On Thursday, 23 October 2014 at 00:59:26 UTC, Shriramana Sharma 
via Digitalmars-d-
I submit that the syntax for attributes should be streamlined. 
Shall I

go and open a Bugzilla item?


No need: http://wiki.dlang.org/DIP64


Besides the @ symbols, isn't there also some inconsistency on
whether attributes go before or after the declaration?

@property public static void foo() const @safe pure nothrow

I've never bothered to ascertain how much of the positioning is
optional, but definitely none of it makes sense.


Re: Search Engine

2014-10-08 Thread Chris Williams via Digitalmars-d-learn

On Wednesday, 8 October 2014 at 18:15:08 UTC, ANtlord wrote:
It would be stable? I mean program, that will use C++ extern 
interface.


Trying to link to C++ code will cause some work to solve build 
issues, but there shouldn't be any stability impacts other than 
recognizing that C++ won't be using memory management.


Re: Momentary Eh?! for a Dynamic Language Programmmer. Tuples vs Arrays. Just rambling.

2014-06-25 Thread Chris Williams via Digitalmars-d-learn

On Monday, 23 June 2014 at 22:08:59 UTC, John Carter wrote:

On Monday, 23 June 2014 at 21:26:19 UTC, Chris Williams wrote:


More likely what you want are variants:


Hmm. Interesting.

Yes, Variant and VariantArray are much closer to the dynamic 
language semantics...


But the interesting thing is Tuple is much closer to "What I 
Mean" when I create these things.


I probably should used Rubies
   http://ruby-doc.org/core-2.0/Struct.html
but apart from naming the elements it gives me nothing beyond 
more keystrokes to enter.


Tuple is very similar, but also grants type safety.


D has structs. If you have any problem working with Tuples, you 
might consider moving over.


Re: Momentary Eh?! for a Dynamic Language Programmmer. Tuples vs Arrays. Just rambling.

2014-06-23 Thread Chris Williams via Digitalmars-d-learn

On Monday, 23 June 2014 at 21:18:39 UTC, John Carter wrote:
I guess between perl and Ruby and Scheme etc. I got used to 
creating hybrid containers


Want a pair of [string, fileList]? Just make an Array with two 
items, one a string, one and array of strings. Done.


D barfed... leaving me momentarily stunned... then Oh Yes, type 
safety, Tuple's are the answer where Tuples where Tuples...


Eventually found http://dlang.org/tuple.html and more 
specifically the somewhat unexpectedly named 
http://dlang.org/phobos/std_typecons.html and off I went...


I do have a personal design guideline of when you adding too 
much behaviour to a heterocontainer, refactor into a class.


But I guess I have never realised how often I do casually 
create heterogenous containers


Just rambling and musing.


More likely what you want are variants:

http://dlang.org/library/std/variant/variantArray.html
http://dlang.org/library/std/variant.html

Tuples can hold multiple types, but they're only available during 
compile time.


Re: Separate allocation and construction?

2014-06-05 Thread Chris Williams via Digitalmars-d-learn

On Thursday, 5 June 2014 at 22:25:03 UTC, Adam D. Ruppe wrote:

On Thursday, 5 June 2014 at 22:22:16 UTC, Chris Williams wrote:
If I wanted to allocate memory for a class and then call its 
constructor as two separate steps, while still having the 
object be managed by the garbage collector, is there any way 
to do that?



Check out std.conv.emplace
http://dlang.org/phobos/std_conv.html#emplace

First, allocate the memory block for the class. The size is 
__traits(classInstanceSize, Yourclass). Then slice it:


enum size = __traits(classInstanceSize, YourClass);
auto memory = GC.malloc(size)[0 .. size];


Why slice? There seems to be a version of emplace that accepts a 
pointer, which is what GC.malloc() seems to return.


Separate allocation and construction?

2014-06-05 Thread Chris Williams via Digitalmars-d-learn
If I wanted to allocate memory for a class and then call its 
constructor as two separate steps, while still having the object 
be managed by the garbage collector, is there any way to do that?


I believe that I've figured out a way to accomplish the first 
step, but not the second.


import std.stdio;

class Foo {
this(string bar) {
writeln(bar);
}
}

void main() {
Foo f = (new Foo[1])[0];
f("Hello"); // doesn't compile
}


Re: two questions on enums

2014-04-04 Thread Chris Williams

On Thursday, 3 April 2014 at 23:16:14 UTC, Eric wrote:
Okay - I'm new to D, and I'm comming from a java background.  
Suppose
you are designing an API, and you want the user to supply 
arguments
as an enum.  But the user needs to define the enum, so how can 
the API
know in advance what enum to require?  The solution is to 
require an
enum that implements a known interface.  This is easy to do in 
java,
but I haven't yet tried it in D.  I suspect it could be done 
with CTFE
or something.  An example where I use this is for electronics 
software.
If I need the user to supply a set of pins, the pins are 
supplied as an
enum which implements an interface.  By using the interface, it 
also
forces the user to include all of the attributes of each pin 
such as
direction, max load, DC current, etc.  Since class type enums 
are references,
they are light, - and they should be immutable - so they are 
thread safe aslo.


I'm not sure how you're using your enum. In Java, the only way to 
perform a switch over an enum is if you know all the values 
during compile time. Passing a type Enum into a function (i.e. as 
opposed to "enum MyEnumType') requires using introspection to 
pull the actual values out, and then a loop to scan through them 
for your target value.


But if you've programmed a switch for a known enum type, then 
that means the enum has already been implemented and there is no 
chance for more than one type to be passed in.


So I'm confused.


Re: Musings on infinite loops and not reachable returns

2014-03-25 Thread Chris Williams

On Tuesday, 25 March 2014 at 20:49:57 UTC, bearophile wrote:
Note how the opApply() of Foo should not end with a return, 
while the opApply() of Bar is required by the D compiler to end 
with a return.


Yet, Foo is contains an infinite loop, so the result of Bar 
will not be reached. But the type system of D is not strong 
enough to see that.


I'm not seeing it. "while (true)" is no more an infinite loop 
than "for (i = 0; i < x; i++)", if the body of the while has a 
break or return statement.


int i = 0;
while (true) {
if (i < x) break;
i++;
}


Re: Alias template param - Undefined Identifier

2014-03-21 Thread Chris Williams

On Wednesday, 19 March 2014 at 00:07:04 UTC, Chris Williams wrote:
  ...probably something 
along the lines of making all of my functions a static function 
in a struct, which I then pass into a template which processes 
UDAs to generate functions at the top with the same names as 
the originals in the struct, which call the struct variants. 
It's also a longer to write and debug.


Here's a simple (unsafe and inflexible) implementation, should 
anyone want to build it out into something that can accept 
multiple arguments and return types.



import std.stdio;

string wrap(string wrapperName, string structName, string 
innerName) {
return "void " ~ innerName ~ "() {" ~wrapperName~ "( 
&"~structName~"."~innerName~" );}";

}

template decorate(T) {
template ForeachMember(Mbr...) {
static if (__traits(getAttributes, __traits(getMember, T, 
Mbr[0])).length > 0) {

static if (Mbr.length > 1) {
enum ForeachMember =
wrap(
__traits(identifier, 
__traits(getAttributes, __traits(getMember, T, Mbr[0]))[0]),

__traits(identifier, T),
Mbr[0]
)
~ ForeachMember!(Mbr[1..$])
;
}
else {
enum ForeachMember =
wrap(
__traits(identifier, 
__traits(getAttributes, __traits(getMember, T, Mbr[0]))[0]),

__traits(identifier, T),
Mbr[0]
)
;
}
}
else {
static if (Mbr.length > 1) {
enum ForeachMember = "" ~ 
ForeachMember!(Mbr[1..$]);

}
else {
enum ForeachMember = "";
}
}
}

enum decorate = ForeachMember!(__traits(allMembers, T));
}

void BeforeAfter(void function() fun) {
writeln("Before");
write("\t"); fun();
writeln("After");
}

void Llama(void function() fun) {
writeln("Llama");
write("\t"); fun();
writeln("Llama");
}

struct Foo {
@BeforeAfter
static void hello() {
writeln("Hello");
}

@Llama
static void and() {
writeln("and");
}

@BeforeAfter
static void goodbye() {
writeln("Goodbye");
}
}

mixin(decorate!(Foo));

void main() {
   hello();
   and();
   goodbye();
}


Re: Function to print a diamond shape

2014-03-20 Thread Chris Williams

On Thursday, 20 March 2014 at 21:25:03 UTC, Ali Çehreli wrote:

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

Ali


Well one of the more convoluted methods that I can think of would 
be to define a square as a set of four vectors, rotate 45 
degrees, and then create a rasterizer that checks for the 
presence of the rect at sequential points, and plots those to the 
console.


Re: bool Associative Array Synchronized

2014-03-20 Thread Chris Williams

On Thursday, 20 March 2014 at 18:06:18 UTC, Etienne wrote:
Right, I was assuming it was always ordered, but modern 
processor pipelines are different I guess.


Even without rearranging the order of your code, your bit exists 
in RAM but all the logic takes place in a CPU register, meaning 
that any time you operate with the bit, there's at least two 
copies. When the CPU switches threads (which could be at any 
point), it empties the CPU into RAM. If the thread it's switching 
to then tries to interact with the bit, it's going to create a 
third copy. Now whichever of the two threads is slower to write 
back to the original location is going to smash the other's.


Re: Alias template param - Undefined Identifier

2014-03-18 Thread Chris Williams

On Tuesday, 18 March 2014 at 23:33:12 UTC, bearophile wrote:

Chris Williams:

But I also like to know how most-effectively to write a 
C-style macro in D, so it seemed worth checking what the state 
of the art is.


This is an antipattern :-)

Bye,
bearophile


As are goto, pointers, and conditional compilation. That doesn't 
mean that there aren't cases where those are the best solution, 
because other solutions would be longer and more convoluted or 
too inefficient.


In Python, I could write a wrapping function that I could apply 
(using decorators) to each function with this behavior, based on 
the presence of a UDA.


I could roughly build something like that for D, but the whole 
framework for it would be far more convoluted and harder to 
maintain than a simple three line macro. ...probably something 
along the lines of making all of my functions a static function 
in a struct, which I then pass into a template which processes 
UDAs to generate functions at the top with the same names as the 
originals in the struct, which call the struct variants. It's 
also a longer to write and debug.


Unfortunately, at the moment, I don't believe that there's any 
way to use UDAs to process a file and generate interceptors -- 
which would be the sort of pattern that we'd like.


Re: Alias template param - Undefined Identifier

2014-03-18 Thread Chris Williams

On Tuesday, 18 March 2014 at 23:05:51 UTC, bearophile wrote:

Chris Williams:

I could put a wrapper around the calls to these functions that 
performs this action, but I figured a little macro would be 
sufficient for my needs (it's just a little script.)


I suggest to keep the code simpler.

Bye,
bearophile


I could. I could simply allow the current working directory to 
drift as the application performs operations, but I prefer the 
consistency of knowing that methods I call restore state before I 
continue to the next method. I sense that in the long run it will 
make life easier.


But I also like to know how most-effectively to write a C-style 
macro in D, so it seemed worth checking what the state of the art 
is.


Re: Alias template param - Undefined Identifier

2014-03-18 Thread Chris Williams

On Tuesday, 18 March 2014 at 22:42:20 UTC, anonymous wrote:

You can pass the variable name as a string:
Or you can get the variable name from the alias parameter:

 import std.string: format;
 template gotoPath(alias path) {
 enum gotoPath = format(q{
 ...
 fs.chdir(%s);
 }, path.stringof);
 }

I think I've read that .stringof shouldn't be used for code
generation, but I can't think of anything better.


Your memory seems to be correct:

http://forum.dlang.org/thread/bug-1103...@http.d.puremagic.com/issues/

It looks like the issue is that .stringOf is something generated 
according to AST information and is thus intrinsically 
compiler-specific. The ticket it links to suggest using 
__traits(identifier, X) or 'one of the Phobos helper functions 
such as "fullyQualifiedName".'


Annoying that formatting the string is required. I think you're 
right that it's ignoring my alias parameter because I'm not using 
it. Formatting doesn't accomplish anything except to use the 
parameter. But in exchange, you have to relate your format 
arguments to the %s entries, instead of the q{} contents just 
being code.



import fs = std.file;
import std.stdio;
import std.string: format;

template gotoPath(alias path) {
enum gotoPath = format(q{
string currPath = fs.getcwd();
scope (exit) fs.chdir(currPath);
fs.chdir(%s);
}, __traits(identifier, path));
}

void doStuff(string targetDirectory) {
mixin(gotoPath!(targetDirectory));
writefln("b %s", fs.getcwd());
}

void main() {
writefln("a %s", fs.getcwd());
doStuff("/etc");
writefln("c %s", fs.getcwd());
}


Alias template param - Undefined Identifier

2014-03-18 Thread Chris Williams
I have a series of functions that each needs to change directory, 
perform an action, and then revert to the original working 
directory.


I could put a wrapper around the calls to these functions that 
performs this action, but I figured a little macro would be 
sufficient for my needs (it's just a little script.)



import fs = std.file;
import std.stdio;

template gotoPath(alias path) {
enum gotoPath = q{
string currPath = fs.getcwd();
scope (exit) fs.chdir(currPath);
fs.chdir(path);
};
}

void doStuff(string targetDirectory) {
mixin(gotoPath!(targetDirectory));
writefln("b %s", fs.getcwd());
}

void main() {
writefln("a %s", fs.getcwd());
doStuff("/etc");
writefln("c %s", fs.getcwd());
}


When I try to compile (DMD 2.064), I get the following error:

test.d(16): Error: undefined identifier path

I can fix the issue by removing the alias parameter and 
hardcoding the name of the variable in the template:



import fs = std.file;
import std.stdio;

template gotoPath() {
enum gotoPath = q{
string currPath = fs.getcwd();
scope (exit) fs.chdir(currPath);
fs.chdir(targetDirectory);
};
}

void doStuff(string targetDirectory) {
mixin(gotoPath!());
writefln("b %s", fs.getcwd());
}

void main() {
writefln("a %s", fs.getcwd());
doStuff("/etc");
writefln("c %s", fs.getcwd());
}


However, it seems like that shouldn't be necessary. The alias 
parameter should create a local alias for the external variable 
which can be utilized by the generated code. Is there something 
wrong with my syntax?


Re: Get Compile Errors - Command Line

2014-03-14 Thread Chris Williams

On Friday, 14 March 2014 at 17:10:46 UTC, Bauss wrote:

I'm using dmd.exe and not cmd.exe


dmd.exe doesn't have a GUI. You're probably running dmd.exe 
inside cmd.exe.


dmd foo.d > mylog.txt


Re: Regarding fixed size arrays

2014-03-14 Thread Chris Williams

On Saturday, 15 March 2014 at 00:11:22 UTC, bearophile wrote:

Do you think it's useful/worth supporting code like that?


My expectation would be that your code is implicitly the same as:

int[5] foo(int[2] a, int[3] b) {
   int[5] staticArray;
   int[] dynamicArray = a ~ b;
   staticArray = dynamicArray;
   return staticArray;
}

Based on the information at http://dlang.org/arrays.html, my 
expectation would be that a copy requires the slice operator, 
which isn't in your code. Thus it's trying to initialize 
staticArray as a new dynamic array -- which obviously wouldn't 
work.


Since your code doesn't have access to the hidden staticArray 
variable, there's no way to write the correct code:


staticArray[] = dynamicArray;

Short of changing the standard to consider "a = b" to be 
equivalent to "a[] = b" when both a and b are arrays, I don't 
think your code should be handled. And I think such a change 
would be dangerous.


The following works, and I think is probably acceptable.

int[5] foo(int[2] a, int[3] b) {
int[5] ret;
ret[] = a ~ b;
return ret;
}



Re: to! converting 1D to 2D array

2014-03-14 Thread Chris Williams

On Friday, 14 March 2014 at 04:36:27 UTC, ed wrote:

As to whether or not this should work:

int[4] a=[1,2,3,4];
int[2][2] b;
b=a;

is up to the D language gurus. I think it should... but I'm no 
language developer, there may be other side-effects I haven't 
thought about.


Cheers,
ed


In C, any array is just a starting address in memory. Accessing 
indexes is accomplished during compile time, where the compiler 
does some math based on the size of the objects in the array and 
how many dimensions the array has, then more-or-less hardcodes an 
offset to add to the starting address. All arrays are mutually 
exchangeable because they're just a pointer.


In D, an array is a struct (struct Array), with an address and a 
length value. A multi-dimensional array is an Array with an 
address pointing to an array of Arrays. So with an int[2][2] 
array, you have a layout like:


@1000 Array(address=1016, length=2)
@1016 [Array(address=1048, length=2),Array(address=1056, 
length=2)]

@1048 [1,2]
@1056 [3,4]

In this particular case, the data at 1056 is directly following 
the data at 1048. There's no gap between them, so considering the 
buffer at 1048 to be a single array of 4 or two arrays of two is 
inconsequential. But that's no guarantee. Those two arrays could 
be off in entirely separate chunks of RAM. In that case, setting 
a=b would force a copy to occur, since a requires the items to be 
continguous, where b=a results in both variables pointing to the 
same underlying data (changing one changes the other).


Now that's assuming that the compiler is actually trying to 
convert one into the other.


There's the other option of considering a and b to both be of 
type Array. As such, you can simply copy the values in one over 
to the other.


a=b; // equivalent to a.address=b.address; a.length=b.length;
b=a; // equivalent to b.address=a.address; b.length=a.length;

This makes complete sense, other than it trashes the settee's 
type. What was int[2][2] effectively becomes int[4] (or 
vise-versa), which should then make an access to b[0][1] fail, 
since the value at entry [0] isn't an Array struct.


Personally, I don't like the inconsistency of the former 
strategy. People should be forced to implement their own strategy 
for converting array types (whether to create a copy or point to 
the same underlying data). For the latter strategy, changing an 
lvalue's type by setting into it seems like it should only be 
allowed if you cast. Though since it's the lvalue changing, it 
would be the lvalue that you would have to cast, and usually a 
cast only lasts for that line not the rest of time, which 
wouldn't be the case here so


cast(int[4])b = a; // ???

Overall, I don't think the compiler should allow the original 
code. Even if the specification specifies what should happen, the 
minutiae of it seems prone to creating bugs.


Re: to! converting 1D to 2D array

2014-03-13 Thread Chris Williams

On Thursday, 13 March 2014 at 03:31:09 UTC, ed wrote:
On Thursday, 13 March 2014 at 00:15:19 UTC, Chris Williams 
wrote:

[snip]

It shouldn't and probably isn't working.


It is working and in fact it is in a "const pure @safe" 
function. So I will trust it  :-)


Well it's like a broken watch being correct twice a day. The 
correct result doesn't mean that something is working.


I'm glad you've found a solution though.


Re: to! converting 1D to 2D array

2014-03-12 Thread Chris Williams

On Wednesday, 12 March 2014 at 03:37:49 UTC, ed wrote:

My understanding of your explanation is that it shouldn't work.


It shouldn't and probably isn't working. If nothing else, when 
you use to!(x)(y), "x" should be the type that you're trying to 
convert into. So I would expect your code to be 
to!(int[2][2])(a). I would still be impressed if that worked, 
since std.conv is intended more for parsing strings into ints and 
stuff, not for splitting and grouping arrays.


Your assertion probably succeeds because in memory a two 
dimensional array is arranged with the first row followed by the 
second row. So a flat array of four items and a 2-D array of two 
arrays of two items end up laying out the same in memory. Some 
how it's going straight to memory and comparing them that way 
(maybe).


Re: Any way to print compile-time generated code?

2014-03-10 Thread Chris Williams

On Monday, 10 March 2014 at 18:25:10 UTC, Adam D. Ruppe wrote:
Change the mixin(x) line to pragma(msg, x);. It will then print 
out the generated string at compile time instead of mixing it 
in so you can take a look at it.


That just gives me an error:

source/app.d(29): Error: Cannot interpret 
ProtocolBufferFromString!"\x0amessage Person {\x0a  
required string name = 1;\x0a  required int32 id = 2;\x0a 
 optional string email = 3;\x0a\x0a  enum PhoneType {\x0a 
   MOBILE = 0;\x0aHOME = 1;\x0aWORK = 2;\x0a  
}\x0a\x0a  message PhoneNumber {\x0arequired string 
number = 1;\x0aoptional PhoneType type = 2 [default = 
HOME];\x0a  }\x0a\x0a  repeated PhoneNumber phone = 
4;\x0a}\x0a" at compile time


Any way to print compile-time generated code?

2014-03-10 Thread Chris Williams
I'm toying with the dproto library and have encountered an issue 
where I can't remove items from a "repeated" list of items. I'd 
like to see what the mixins are producing in terms of actual D 
code, so that I can figure out how I can correctly try to delete 
an entry or find the code that's generating the array and add 
whatever corrections are necessary to expose this ability.


Is there any way to push a mixin into a string, instead of into 
the code, or otherwise to view the output of the "preprocessor"?


Re: convert int[][] to int**

2014-02-21 Thread Chris Williams

On Friday, 21 February 2014 at 19:13:13 UTC, Chris Williams wrote:

On Thursday, 20 February 2014 at 17:02:15 UTC, Dicebot wrote:
You can't do it without allocation because memory layout is 
different for int** and int[][] in D - are.ptr in latter 
points to slice struct (pointer+length) as opposed to raw 
pointer in former.


You should only have to copy the top list, though.

int*[] temp = new int*[ arr.length ];
for (size_t i = 0; i < arr.length; i++) {
temp[i] = arr[i].ptr;
}
int** output = temp.ptr;

Untested.


Addendum: Note that bearophile's code probably works out to the 
same thing.


Re: convert int[][] to int**

2014-02-21 Thread Chris Williams

On Thursday, 20 February 2014 at 17:02:15 UTC, Dicebot wrote:
You can't do it without allocation because memory layout is 
different for int** and int[][] in D - are.ptr in latter points 
to slice struct (pointer+length) as opposed to raw pointer in 
former.


You should only have to copy the top list, though.

int*[] temp = new int*[ arr.length ];
for (size_t i = 0; i < arr.length; i++) {
temp[i] = arr[i].ptr;
}
int** output = temp.ptr;

Untested.


Re: Why function template 'among' is of complexity O(1) and not O(n)?

2014-02-19 Thread Chris Williams

On Thursday, 20 February 2014 at 02:10:50 UTC, anonymous wrote:

The foreach is definitely always evaluated at compile time.
That's independent of the values being known statically. It
generates a couple of if statements. But optimizing those if
statements away for static values is not guaranteed or expected.


Ah, roger.


Re: Why function template 'among' is of complexity O(1) and not O(n)?

2014-02-19 Thread Chris Williams

On Thursday, 20 February 2014 at 00:36:38 UTC, anonymous wrote:

On Wednesday, 19 February 2014 at 22:46:45 UTC, Chris Williams
wrote:
When the template writes out the definition of the function, 
if the parameters can be interpreted during compile-time, then 
the foreach ( O(n) ) will be run by the compiler to detect the 
correct parameter and the function will be written out as just 
as a return statement in the body, without the loop. So during 
runtime, the function would have an O(1) runtime.


That's an optimization the compiler may do, but it's not
guaranteed. And `among` is not special in this regard.


I think "expected to do" is probably the better phrasing at the 
moment. Traits/annotations would be largely unusable unless 
foreach was able to behave as a static construct. And since there 
is no way for one to declare "static foreach", the only way 
foreach can be used for running over traits, is for the compiler 
to detect constant values in the parameters to the statement.


Re: Why function template 'among' is of complexity O(1) and not O(n)?

2014-02-19 Thread Chris Williams
On Wednesday, 19 February 2014 at 22:05:49 UTC, Peter Alexander 
wrote:
If you want to get even more anal about it, searching an array 
is technically O(1) because an array cannot be bigger than 
size_t.max, and since size_t.max is a constant, O(size_t.max) 
is O(1). Again, completely misleading but technically correct 
in an esoteric, academic way.


That's basically saying that on any linear bouded automaton, all 
algorithms (except an infinite loop) are O(1) - which is silly.


To the OP:

The among() function is defined to template out into multiple 
versions of itself depending on the number of arguments, rather 
than using variadic parameter checking during runtime.


When the template writes out the definition of the function, if 
the parameters can be interpreted during compile-time, then the 
foreach ( O(n) ) will be run by the compiler to detect the 
correct parameter and the function will be written out as just as 
a return statement in the body, without the loop. So during 
runtime, the function would have an O(1) runtime. If the 
parameters can't be determined during compile-time then the 
function will be written out with the contents of the foreach 
copied into the body as many times as there are parameters, 
making the runtime O(n), where n is the number of parameters to 
the function.


Where people are getting a bit technical is that, because the 
function is generated by a template the following two calls:


among("a", "b", "c");
among("a", "b", "c", "d");

end up declaring two separate functions, one which accepts three 
parameters and the other which accepts four. The version which 
accepts three parameters will always run the same speed no matter 
what you call it - since it does the same thing exactly three 
times. The version which accepts four parameters is the same. 
Since they don't have any logic - they just run through a 
constant list of operations with no loop - one can say that they 
are O(1). Technically, it's true, but also a mildly pointless 
distinction to make.


Re: Optimize my code =)

2014-02-17 Thread Chris Williams

On Friday, 14 February 2014 at 16:00:09 UTC, Robin wrote:

this(size_t rows, size_t cols) {
this.dim = Dimension(rows, cols);
this.data = new T[this.dim.size];
enum nil = to!T(0);
foreach(ref T element; this.data) element = nil;
}


Your foreach here is unnecessary. You can zero out an array using 
the syntax:


this.data[] = 0; // probably compiles out as memset()

And while I would expect to!T(0) to compile down to something 
with no particular logic, it still is a function call not a 
macro, so you're better to let the compiler figure out the best 
conversion from 0 for type T than to use a library function for 
it.



I think and hope that this is getting optimized via inlining. =)
This works similar for opIndexAssign.


From complaints that I have seen, very little gets inlined at the 
moment.




Matrix opMul(ref const(Matrix) other) {
	if (this.dim.rows != other.dim.cols || this.dim.cols != 
ther.dim.rows) {

// TODO - still have to learn exception handling first ...
}
auto m = new Matrix(this.dim.rows, other.dim.cols);
auto s = new Matrix(other).transposeAssign();


Since you don't return s, it's probably better to not allocate an 
instance. I would also be curious to see your constructor which 
copies one matrix into a new one.


Besides that I can't find a way how to make a use of move 
semantics like in C++. For example a rvalue-move-constructor or 
a move-assign would be a very nice thing for many tasks.


Do you mean something like this?

this.data[] = other.data[]; // probably compiles out as memcpy()
this.data = other.data.dup; // different syntax, but should be 
the same


Another nice thing to know would be if it is possible to 
initialize an array before it is default initialized with 
T.init where T is the type of the array's fields.


I believe so, but I would have to scour about to find the syntax. 
Hopefully, someone else knows.


Re: Is it possible to convert a delegate into a function?

2014-02-06 Thread Chris Williams

On Thursday, 6 February 2014 at 22:15:00 UTC, Dicebot wrote:

assert(!dg.ptr);


Note that Dicebot's version works only because he chose a 
delegate that points to something that doesn't need an external 
state. The below method, Foo.dump(), would fail the assert 
because it requires a reference to an instance of Foo in order to 
grab the state of a.value or b.value.


It does look like one is allowed to write into the delegate .ptr 
and .funcptr variables, so reconstructing a delegate from parts 
is possible. (I'm surprised that the definition of funcptr is 
"void function()" instead of "void function(Foo)"?).



import std.stdio;

class Foo {
private:
int value;

public:
this(int v) {
value = v;
}

void dump() {
writeln(value);
}
}

void doDump(void* obj, void function() func) {
void delegate() dg;
dg.ptr = obj;
dg.funcptr = func;
dg();
}

void main() {
Foo a = new Foo(42);
Foo b = new Foo(255);

auto dgA = &a.dump;
auto dgB = &b.dump;

writefln("%x %x", dgA.funcptr, dgB.funcptr); // Same

void function() func = dgA.funcptr;

doDump(dgA.ptr, func);
doDump(dgB.ptr, func);
}


Re: Is it possible to convert a delegate into a function?

2014-02-06 Thread Chris Williams
On Thursday, 6 February 2014 at 21:26:06 UTC, Gary Willoughby 
wrote:
I know you can convert functions into delegates using: 
http://dlang.org/phobos/std_functional.html#.toDelegate but can 
you do this the other way around?


I have a method that needs a function pointer but it would be 
nice to use a converted delegate pointer instead.


A function is the address of a block of code in memory. A 
delegate also has the address to a block of code (a function) but 
it also has the pointer to an object that is to be passed as the 
first parameter to the function.


It's pretty easy to drop a parameter, so writing a wrapper method 
that passes all the other parameters on to the target function is 
pretty easy.


But unless the function that you're calling can accept a 
reference to the object that the delegate references and use that 
and the function pointer to reconstruct the delegate, you're 
definitely out of luck. Whether there is a means to manually 
construct a delegate or not, I'm not sure.


Re: std.parallelism: How to wait all tasks finished?

2014-02-05 Thread Chris Williams

On Wednesday, 5 February 2014 at 15:38:14 UTC, Cooler wrote:

Will not help. I don't know beforehand what tasks will be
created. procData is recursive and it decides create new task or
not.


You seem to be saying that you want to be able to wait for all 
tasks to complete an indefinite number of times, adding more 
tasks after each one. Why would you want to do that? The queue 
for the pool is infinitely long, so just keep adding tasks till 
you have no more tasks to add. Or if you have a progression of 
types, like all tasks of type A have to be complete before you 
can start running the tasks of type B, then you should be able to 
have a separate thread pool for each type.


Re: Do you have any suggestions for project directory structure?

2014-02-05 Thread Chris Williams

On Wednesday, 5 February 2014 at 21:50:17 UTC, Orfeo wrote:
Suppose I have a project "protocols" that uses DMock and a  
library Foo.
I would like to use a structure dub style..Which solution is 
better:


A.

protocols
 ├── bin
 │   └── protocols.a
 ├── dmocks
 │   └── *.d
 ├── foo
 │   └── *.d
 ├── src
 │   └── protocols
 │   └── *.d

B.

protocols
 ├── bin
 │   └── protocols.a
 ├── src
 │   ├── dmocks
 │   │└── *.d
 │   ├── foo
 │   │└── *.d
 │   └── protocols
 │└── *.d


Or another solution?
Thanks


I would probably advise against having the outside libraries 
inside your project at all. Have them parallel to protocols 
either add a /lib folder to protocols that can hold their 
binaries or pull from the outside (you'll need to point your 
includes outside your own project anyways).


Re: Performant method for reading huge text files

2014-02-04 Thread Chris Williams
Parsing should be faster than I/O. Set up two buffers and have 
one thread reading into buffer A while you parse buffer B with 
a second thread.


...and then flip buffers whenever the slower of the two has 
completed.


Re: Performant method for reading huge text files

2014-02-04 Thread Chris Williams
On Tuesday, 4 February 2014 at 00:04:23 UTC, Rene Zwanenburg 
wrote:

On Monday, 3 February 2014 at 23:50:54 UTC, bearophile wrote:

Rene Zwanenburg:

The problem is speed. I'm using LockingTextReader in 
std.stdio, but it't not nearly fast enough. On my system it 
only reads about 3 MB/s with one core spending all it's time 
in IO calls.


Are you reading the text by lines? In Bugzilla there is a 
byLineFast:

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

Bye,
bearophile


Nope, I'm feeding it to csvReader which uses an input range of 
characters. Come to think of it..


Well this is embarassing, I've been sloppy with my profiling 
:). It appears the time is actually spent converting strings to 
doubles, done by csvReader to read a row into my Record struct. 
No way to speed that up I suppose. Still I find it surprising 
that parsing doubles is so slow.


Parsing should be faster than I/O. Set up two buffers and have 
one thread reading into buffer A while you parse buffer B with a 
second thread.


Re: Enum of functions?

2013-11-25 Thread Chris Williams
On Tuesday, 26 November 2013 at 05:13:00 UTC, Shammah Chancellor 
wrote:

What is the practical purpose of such a thing?

-Shammah


The two cases I can think of are:

1. To define a set of supported handlers which can be passed in 
as a parameter to a call. Rather than writing a switch in your 
method that calls the correct function, based on the supported 
values in the enum, you build the handlers right into the enum. 
It pulls your code into one.


2. If you have a quick and easy method for serializing an enum - 
for example, converting the name to a string and back - then you 
can write can write code that deserializes and calls a function 
in a single line.


But mostly, I was just curious.


Re: Enum of functions?

2013-11-25 Thread Chris Williams

On Tuesday, 26 November 2013 at 00:27:25 UTC, IgorStepanov wrote:

You can write

enum Foo : void function()
{
WOMBAT = function void () {writeln("Wombat");}
}

or

enum Foo
{
WOMBAT = function void () {writeln("Wombat");}
}

`() {writeln("Wombat");}` literal recognized by compiler as 
delegate, not function.


Thank you. It looks like 2.063 only handled the first case (and 
only if there was a single entry), but with 2.064 it works 
perfectly.




Enum of functions?

2013-11-25 Thread Chris Williams

Is there any way to do something like this?

import std.stdio;

enum Foo : void function() {
WOMBAT = () {writeln("Wombat");}
}

void doStuff(Foo f) {
f();
}

int main() {
doStuff( Foo.WOMBAT );

return 0;
}

Currently, I get the errors:

hello.d(4): Error: non-constant nested delegate literal 
expression __lambda1
hello.d(12): Error: delegate hello.Foo.__lambda1 is a nested 
function and cannot be accessed from D main


I can fix it by declaring a function outside of Foo and setting 
WOMBAT = &fname, but it seems like I should be able to create a 
hidden lambda.


Traits and UDAs

2013-06-06 Thread Chris Williams
I decided to write up a little application to test using User 
Defined Attributes and have one question. Here is a working 
application that allows me to mark certain members of a function 
to be dumped:


import std.stdio;

enum Dump = "Dump";
template Dumper(T) {
void dump() {
foreach (mem; __traits(allMembers, T)) {
			auto attributes = __traits(getAttributes, __traits(getMember, 
T, mem));
			static if ( attributes.length > 0 && __traits(getAttributes, 
__traits(getMember, T, mem))[0] == Dump ) {

writeln(mem);
}
}
}
}

class Foo {
@Dump int hello;

@Dump int world;

int bye;

mixin Dumper!(Foo);
}

int main(string[] args) {
Foo f = new Foo();
f.dump();

return 0;
}


The eighth line bothers me, though. It seems like I should be 
able to write:


if (attributes.length > 0 && attributes[0] == Dump)

However, that fails to compile with the message:

test.d(7): Error: variable _attributes_field_0 cannot be read at 
compile time
test.d(8): Error: expression !!(_attributes_field_0 == "Dump") is 
not constant or does not evaluate to a bool
test.d(7): Error: variable _attributes_field_0 cannot be read at 
compile time
test.d(8): Error: expression !!(_attributes_field_0 == "Dump") is 
not constant or does not evaluate to a bool


Any thoughts?


TickDuration = Divide by Zero

2011-10-03 Thread Chris Williams
I have the following code:

import std.datetime;

const TickDuration a;
static this() {
a = TickDuration.from!"msecs"(15_000);
}

int main() {
writefln("Hello world!"); // is never printed

return 0;
}

When I run it, I get the following output:

object.Error: Integer Divide by Zero

I presume that TickDuration is trying to access something that it
doesn't have access to yet, during startup. Is there another way to
make my constant a constant?


Re: Sharing unlocked, unchanging data between threads?

2010-08-10 Thread Chris Williams
== Quote from Jonathan M Davis (jmdavisp...@gmail.com)'s article
> Well, unless it's declared shared, it's going to be thread-local,
and then each
> thread is going to have their own copy. Now, if it were declared
shared and you
> never changed it after initially setting all of its values, then you
shouldn't
> have any problems as far as I'm aware. Just accessing an associative
array
> shouldn't change it.
> - Jonathan M Davis

I'm using D 1.0. I don't believe it has a "shared" keyword. But,
globals are shared as well, I presume.


Sharing unlocked, unchanging data between threads?

2010-08-10 Thread Chris Williams
I'm writing a fairly large, multithreaded application and some part
of it is causing periodic access errors.

Say that I have an associative array like:

uint[ char[] ] nameToId;

If I set all values before I start my threads going and never change
anything after that point -- all access is read only -- is there any
way that having multiple threads access it at the same time would
mess anything up? I'm doing this in several places as locking a
read-only data structure doesn't strike me as something which should
be necessary. I don't know what D's associative arrays look like
internally though, so perhaps it is dangerous to do. It would be a
major hassle to port it all over to locking everything, to test if
it fixes the problem. So, hopefully someone can say whether this is
worth checking.


Shifting values within an array

2010-08-10 Thread Chris Williams
I would like to be able to do something like this:

class A {
int i;
}

int main() {
A[] list;

for (uint L = 0; L < 3; L++) {
for (uint L2 = 0; L2 < 3; L2++) {
uint index = L + L2;

uint copyAmount = list.length - index;
list.length = list.length + 1;
if (copyAmount > 0) {  // Move data after index one 
slot later to make room
A[] sliceFrom = list[index .. (index + 
copyAmount)];
A[] sliceTo = list[(index + 1) .. (index + 1 + 
copyAmount)];
sliceTo[] = sliceFrom[];
}
list[index] = new A();
list[index].i = index;
}
}

return 0;
}

I have a running implementation which uses C's memmove(), but I gather that 
this isn't a safe means to do it as the garbage collector
might run while the references to the object are being manipulated. Is there a 
way to do this outside of a loop?


Re: Multiple Inheritance, Mixins, and Constructors

2009-05-19 Thread Chris Williams
Ary Borenszweig Wrote:

> 
> You can do this:
> 
> template TFoo() {
>   // Never use this variable directly :-P
>   SomeObject _s_o;
> 
>   SomeObject s_o() {
>   if (_s_o is null)
>   _s_o = new SomeObject();
>   return _s_o;
>   }
> 
>   // And if you want to make it assignable too
>   SomeObject s_o(SomeObject x) {
>   _s_o = x;
>   }
>   
>   void bar() {
>   s_o.x = 10;
>   // code
>   // ...
>   }
> }

Well I ended up converting my object to a struct, which solved the issue. Your 
solution would probably work, but for what I'm doing, I'd rather not incur the 
overhead of a branch and (possible) function call for every access of the 
object.

It seems like object initialization outside of a method should be magically 
moved to the top of the constructor. But ah well.

Thank you.


Multiple Inheritance, Mixins, and Constructors

2009-05-18 Thread Chris Williams
Well so I had a case where I needed to do something like multiple inheritance. 
Here's an example solution:

interface IFoo {
   void bar();
}
template TFoo() {
   void bar() {
  // code
  // ...
   }
}

class Base {
   // variables
}

class Thing : Base, IFoo {
   mixin TFoo;
}

Well so that's all well and good. The problem comes if I have an object 
declared in TFoo. For instance:

template TFoo() {
   SomeObject s_o;

   void bar() {
  s_o.x = 10;
  
  // code
  // ...
   }
}

It compiles fine, but when I go to run it, trying to set so.x gets an error 
because s_o hasn't been instantiated. If I try:

template TFoo() {
   SomeObject s_o = new SomeObject();

   void bar() {
  s_o.x = 10;
  
  // code
  // ...
   }
}

Then I get a compile-time error that I can't do that. Now I'd love to define a 
constructor in TFoo that instantiated s_o, but I'm pretty sure that would 
conflict should anyone try to add a constructor to (for instance) class Thing.

My solution was to add an initFoo() definition in IFoo, and say that it needs 
to be called in the constructor of anyone using IFoo/TFoo, but that seems 
pretty wonky. Admittedly the whole interface/mixin thing is already a bit 
wonky, but it seems like there should be a solution to at least the object 
initialization problem.