Re: How to divide by space keeping words with spaces inside quotes?

2021-08-08 Thread cy via Digitalmars-d-learn

On Sunday, 8 August 2021 at 23:04:32 UTC, Marcone wrote:

How to divide by space keeping words with spaces inside quotes?


Well the designers of ASCII were morons who decided that open 
quote and close quote would be the same damn letter, so it's a 
little trickier. Basically what you have to do is process it 
character by character into a finite state machine that switches 
between word mode, space mode, and quoting mode, accounting for 
backslash escapes since morons, etc. so you kinda need them.


I dunno any modules in specific that do it, but something like:

```d
string somestr = "Duck Cat \"Carl Rivers\" Dog";

enum FSM { QUOTING, WORD, SPACE };

struct FSM {
FSM mode;
bool backslash;
Appender!char cur;
Appender!string accum;
}

FSM fsm;
fsm.mode = SPACE;

foreach(char ch: somestr) {
if(fsm.backslash) {
fsm.backslash = false;
cur.add(ch);
continue;
}

switch(fsm.mode) {
case FSM.QUOTING:
switch(ch) {
case '\\':
cur.add('\\');
fsm.backslash = true;
case '"':
fsm.mode = FSM.SPACE;
accum.add(tostring(cur.data));
cur = appender!char;
break;
default:
cur.add(ch);
};
break;
case FSM.WORD:
switch(ch) {
case '\\':
cur.add('\\');
fsm.backslash = true;   
case ' ':
case '\t':
fsm.mode = FSM.SPACE;
if(cur.data.length) {
accum.add(tostring(cur.data));
cur = appender!char;
}
break;
default:
cur.add(ch);
};
break;
case FSM.SPACE:
switch(ch) {
case '\\':
fsm.backslash = true;
fsm.mode = WORD;
cur.add('\\');
break;
case ' ':
case '\t':
case '\n':
break;
case '"':
fsm.mode = FSM.QUOTING;
break;
default:
cur.add(ch);
fsm.mode = FSM.WORD;
break;
};
};
}

string[] result = fsm.data;
print(result);
```

(untested pseudocode that won't work btw)


Re: Invoking the compiler during runtime

2020-08-05 Thread cy via Digitalmars-d-learn

On Wednesday, 5 August 2020 at 06:02:58 UTC, cy wrote:
Some way to import the compiler itself, instead of calling it 
in a subprocess?


Well, I did find this: 
https://dlang.org/blog/2017/08/01/a-dub-case-study-compiling-dmd-as-a-library/


But it's pretty advanced... probably just invoking dmd would be 
good...




Invoking the compiler during runtime

2020-08-05 Thread cy via Digitalmars-d-learn
D's compile-time-execution is fantastic, but there are some times 
when I'd like to examine the generated code, or produce code that 
needs to pass through earlier phases before CTFE, or do AST 
stuff. Sometimes I simply don't want to generate the code with 
every compilation, so saving the generated code in a file some 
would be really neat, if I could then invoke the compiler during 
runtime to build it. Plus backtraces wouldn't just be 
"dlang-mixin-397."


I'm a big supporter of compiling from source and not using third 
party binaries, so I don't mind designing software that only 
works with runtime access to a D compiler. But I'm not sure how 
best to generate the code, or to invoke the compiler, or how to 
use what it compiles. In C I write a utility program in awful C 
to print out C code, have a cmake custom command run that awful C 
as needed, and assume the existence of that generated source in 
my main program.


So is that the best way to do it? Have a side program that writes 
D source to a file, and then the main program simply imports the 
file? Or is there some AST syntax I should be generating instead? 
Some way to import the compiler itself, instead of calling it in 
a subprocess? Is there a way in dub to specify that you run a D 
program contained in X.d during the build process, to build Y.d, 
that Z.d imports?


Re: GDC and DMD incompatability, can both be used?

2020-07-10 Thread cy via Digitalmars-d-learn
And OK yes I see gdc definitely does not support static foreach, 
but instead there's some sort of D compiler written in D compiled 
by GDC? That's just dmd, isn't it?


https://github.com/D-Programming-GDC/GDC/pull/550

He calls it "DDMD."


GDC and DMD incompatability, can both be used?

2020-07-10 Thread cy via Digitalmars-d-learn
hunt/source/hunt/serialization/JsonSerializer.d:125:20: error: 
basic type expected, not foreach
  125 | static foreach (string member; 
FieldNameTuple!T) {


I'm having a little trouble using the hunt library with gdc. Does 
gdc not support static foreach at all? Is there some way to write 
code that it can understand, which does the same thing?


Re: C interface provides a pointer and a length... wrap without copying?

2017-03-11 Thread cy via Digitalmars-d-learn

On Saturday, 11 March 2017 at 23:43:54 UTC, Nicholas Wilson wrote:

A string *is* a pointer length pair, an immutable(char)[].


Yes, but surely there's some silly requirement, like that the 
pointer must only ever point to garbage collected memory, or 
something?


ubyte[] arr; // or byte/char whatever is the pointed to type 
returned by giveMeTheMemory

arr = giveMeTheMemory()[0 .. getMeTheLength()];


...guess not! :D



C interface provides a pointer and a length... wrap without copying?

2017-03-11 Thread cy via Digitalmars-d-learn
So a lovely C library does its own opaque allocation, and 
provides access to the malloc'd memory, and that memory's length. 
Instead of copying the results into garbage collected memory 
(which would probably be smart) I was thinking about creating a 
structure like:


struct WrappedString {
  byte* ptr;
  size_t length;
}

And then implementing opIndex for it, and opEquals for all the 
different string types, and conversions to those types, and then 
it occurred to me that this sounds like a lot of work. Has 
anybody done this already? Made a pointer/length pair, that acts 
like a string?


Re: How to avoid ctRegex (solved)

2016-08-27 Thread cy via Digitalmars-d-learn

On Wednesday, 24 August 2016 at 05:29:57 UTC, ag0aep6g wrote:
The plain regex function doesn't have such a requirement. It 
also works with a pattern that's generated at run time, e.g. 
from user input. But you can use it with a compile time 
constant, too. And it works in CTFE then, but it does not 
"generate optimized native machine code".


It's not using it with a compile time constant that struck me as 
weird. It's using it to assign a global variable that struck me 
as weird.


When I saw `auto a = b;` at the module level, I thought that b 
had to be something you could evaluate at compile time. But I 
guess it can be a runtime calculated value, acting like it was 
assigned in a a static this() clause, and the requirement for it 
to be compile time generated is only for immutable? like 
`immutable auto a = b`?


Re: Is there a d analog of strncmp?

2016-08-23 Thread cy via Digitalmars-d-learn

import std.algorithm.searching: startsWith, commonPrefix;
if(s1.startsWith(s2)) {...}
string prefix = commonPrefix(s1,s2);


Re: How to avoid ctRegex (solved)

2016-08-23 Thread cy via Digitalmars-d-learn

On Tuesday, 23 August 2016 at 04:51:19 UTC, ag0aep6g wrote:

That's true, and apparently `regex("foobar")` can be evaluated 
at compile time.


Then what's ctRegex in there for at all...?



Re: How to avoid ctRegex (solved)

2016-08-22 Thread cy via Digitalmars-d-learn

On Sunday, 21 August 2016 at 21:18:11 UTC, ag0aep6g wrote:

I may be missing the point here, but just putting `auto pattern 
= regex("foobar");` at module level works for me.


Really? I thought global variables could only be initialized with 
static stuff available during compile time, and you needed a 
"static this() {}" block to initialize them otherwise.


How to avoid ctRegex (solved)

2016-08-21 Thread cy via Digitalmars-d-learn
At seconds PER (character range) pattern, ctRegex slows down 
compilation like crazy, but it's not obvious how to avoid using 
it, since Regex(Char) is kind of weird for a type. So, here's 
what I do. I think this is right.


in the module scope, you start with:
auto pattern = ctRegex!"foobar";

and you substitute with:
typeof(regex("")) pattern;
static this() {
  pattern = regex("foobar");
}

That way you don't have to worry about whether to use a 
Regex!char, or a Regex!dchar, or a Regex!ubyte. It gives you the 
same functionality, at the cost a few microseconds slowdown on 
running your program. And once you're done debugging, you can 
always switch back, so...


string defineRegex(string name, string pattern)() {
  import std.string: replace;
  return q{
debug {
pragma(msg, "fast $name");
import std.regex: regex;
typeof(regex("")) $name;
static this() {
$name = regex(`$pattern`);
}
} else {
pragma(msg, "slooow $name");
import std.regex: ctRegex;
auto $name = ctRegex!`$pattern`;
}
}.replace("$pattern",pattern)
.replace("$name",name);
}

mixin(defineRegex!("naword",r"[\W]+"));
mixin(defineRegex!("alnum",r"[a-zA-Z]+"));
mixin(defineRegex!("pattern","foo([a-z]*?)bar"));
mixin(defineRegex!("pattern2","foobar([^0-9z]+)"));

void main() {
}

/*
$ time rdmd -release /tmp/derp.d
slooow naword
slooow alnum
slooow pattern
slooow pattern2
slooow naword
slooow alnum
slooow pattern
slooow pattern2
rdmd -release /tmp/derp.d  17.57s user 1.57s system 82% cpu 
23.210 total


$ time rdmd -debug /tmp/derp.d
fast naword
fast alnum
fast pattern
fast pattern2
fast naword
fast alnum
fast pattern
fast pattern2
rdmd -debug /tmp/derp.d  2.92s user 0.37s system 71% cpu 4.623 
total

*/

...sure would be nice if you could cache precompiled regular 
expressions as files.


Re: When does take modify the underlying iterator?

2016-08-16 Thread cy via Digitalmars-d-learn
On Tuesday, 16 August 2016 at 21:13:38 UTC, Steven Schveighoffer 
wrote:

static if(isForwardRange!(typeof(iter)))


But this may not work for any input range, since any time you 
copy the range, you are copying internal state that may cache 
an element or more.


Yes, that was the problem with SecretlyForwardRange, is that it 
acts like a ForwardRange because it's implicitly copied, but 
doesn't implement .save, so isForwardRange would return false.


What we need is a take function that accepts input ranges by 
reference, so it modifies the original.


What we need is a way to split a range into two sub-ranges, the 
head and the tail.


auto res = a.take(1)
auto head = res.head
a = res.tail

...or something. Like what findSplit does, but with an index 
instead of a delimiter.


When does take modify the underlying iterator?

2016-08-16 Thread cy via Digitalmars-d-learn
InputRanges that are not ForwardRanges seem to lack a possibly 
crucial operation. I want to start with an arbitrary range, take 
1 from it, then process the rest. But there doesn't seem to be 
any way to do that, because there's no way to tell whether "take" 
will advance the range, or whether it will leave the range as-is.


When you know a range implements front, empty, and popFront, and 
you take from that range, there seems to be a secret requirement 
that the iterator supports save() via copy constructor. And if it 
doesn't... your program just breaks silently when you drop 
elements that haven't been processed yet.


Is there some way around that, that I'm not aware of?

struct CertainlyNotAForwardRange(A) {
static int i = 0;
A a;
auto front() {
return a[i];
}
auto empty() {
return i == a.length;
}
auto popFront() {
++i;
}
}

struct SecretlyForwardRange(A) {
A a;
int i = 0;
auto front() {
return a[i];
}
auto empty() {
return i == a.length;
}
auto popFront() {
++i;
}
}

auto failhard(T)(T iter) {
import std.stdio;
import std.range: take, drop;
import std.array: array;

writeln("We have some range:");
writeln(typeid(T));
writeln("We take 1 from it...");
writeln(iter.take(1));
writeln("The rest of the range has:");
writeln(iter.drop(1).array);
writeln("");
}   

void main() {
auto arr = [0, 1, 2, 3];
failhard(arr);
failhard(SecretlyForwardRange!(typeof(arr))(arr));
failhard(CertainlyNotAForwardRange!(typeof(arr))(arr));
}



Re: Passing Structs to function like in C

2016-08-12 Thread cy via Digitalmars-d-learn

On Friday, 12 August 2016 at 15:21:22 UTC, D.Rex wrote:
I was wondering how this is achieved in D, or if D has an 
alternative implementation of this.


It isn't, because C interfaces that require you to pass in 
structures are inherently bad design, and usually both unstable 
and extremely C specific. Nobody wants to bother with that, and 
get stuck maintaining it to boot. You have to re-define the 
struct in D's language in order to comprehend it, but then you 
look in libuv and you see things like:


struct uv_shutdown_s {
  UV_REQ_FIELDS
  uv_stream_t* handle;
  uv_shutdown_cb cb;
  UV_SHUTDOWN_PRIVATE_FIELDS
};

and you let out a slow, agonized groan of disgust, because now 
you have to go searching through the CPP parser output manually 
to determine the nature of the struct. Once you've done that, 
your code is unstable and likely to stop working with even minor 
version changes, because the C programmers used those #define 
statements on the assumption that what substitutes in there won't 
always remain the same. And since C doesn't check the size of a 
structure, you usually get no error when they add another byte in 
the middle, only silent failures and breakage.


But... assuming you're forced to do this, you'd run the header 
file through cpp with all the relevant flags. There is no parser 
for C that works in the general case (and C programmers just LOVE 
using all the horrible edge cases), but you can just manually go 
through and look at the structures you want to use. For instance:


struct uv_shutdown_s {
  void* data; uv_req_type type; void* active_queue[2]; void* 
reserved[4];

  uv_stream_t* handle;
  uv_shutdown_cb cb;

};

cpp doesn't fill in typedefs, so you have to manually go and look 
at what those are (and hope that they don't change depending on 
compilation parameters). Oh, and I should mention cpp erases all 
newlines, so any substitution is all going to be crammed on a 
single line. But once you see that, then you make a uv.d file 
containing:


...

alias ShutdownCallback = void function(shutdown*, int);

struct Shutdown {
  void* data;
  Req type;
  void*[2] active_queue;
  void*[4] reserved;
  Stream* handle;
  ShutdownCallback cb;
}

as well as the same thing done for "req" (uv_req_t) and "stream" 
(uv_stream_t). Then you can just...


extern (C) int uv_shutdown(Shutdown*, Stream*, ShutdownCallback);
extern (C) void* malloc(size_t);
void foo(Stream* something, int delegate() handle) {
  Shutdown* req = cast(Shutdown*)malloc(Shutdown.sizeof);
  req.data = handle; // ?
  uv_shutdown(req, something, unpack_delegate);
}


...and it'll work, until they change something, or you try to 
switch to a 64 bit machine, or something.


...and if instead, libuv used an opaque structure for Shutdown 
and Stream, and functions to access its data, you could do this:


struct Shutdown;
struct Stream;
extern (C) int uv_shutdown(Shutdown*, Stream*, ShutdownCallback);
extern (C) Shutdown* uv_new_shutdown();
void foo(Stream* something, int delegate() handle) {
  Shutdown* req = uv_new_shutdown();
  req.data = handle;
  uv_shutdown(req,stream,unpack_delegate);
}

Much simpler, no? Plus it's stable even when they change the 
structure of their implementation.


When I have to write a C library, I almost always write a C 
interface that doesn't suck, in order to do the things I want 
with that library. Then at least when they change their internal 
structure, my C can recompile, and present a stable and simple 
ABI to the D side of things.


This is actually a problem for every language that's not C, not 
just D. Passing structs as arguments to your interface just 
always makes things harder for language supporters.


Re: std.range pipelike interface, inverting OutputStreams?

2016-08-12 Thread cy via Digitalmars-d-learn
Here's how to do it using context switches. There ought to be a 
way to manually pass specific state around to keep that from 
happening, but probably not since there's no interface to pause 
something writing to an OutputRange.


auto pipe(T, alias oh)()
{
import std.concurrency: Generator, yield;
return new Generator!T({
struct OutputRange {
void put(T item) {
yield(item);
}
}
oh(OutputRange());
});
}



std.range pipelike interface, inverting OutputStreams?

2016-08-12 Thread cy via Digitalmars-d-learn
I was trying to use std.regex, and it takes an output stream to 
pump the result to, which is great, but I wanted to perform TWO 
replacements, one with the output of the previous, with data that 
might be a tricky size to cache redundantly.


So, ideally when you do something like regexp replacing, you'd 
have a function like:
InputRange replaceThingy(InputRange source, someregex, 
somereplacer);


It doesn't do that, unfortunately, so I can't easily chain 
replacements. But couldn't I do a thing like...


InputRange pipe(void delegate(ref OutputRange)) { ? }

and then just...
  auto result = pipe((sink) => replaceAllInto(sink, data, 
firstmatch, firstreplacer));
  auto result2 = pipe((sink) => replaceAllInto(sink, result, 
secondmatch, secondreplacer));

  copy(result2,stdout);

... or something like that? Has that been done before? Can it be 
done?


I'm pretty sure any algorithm that takes an output stream can be 
transformed into an algorithm that provides an input stream, but 
I'm not sure if I'd be reinventing the wheel here, or if my 
assumptions are seriously off.


Hoping to avoid weird stuff like context switches... eh.


Re: UFCS with implicit "this" ?

2016-08-09 Thread cy via Digitalmars-d-learn

On Tuesday, 9 August 2016 at 05:33:09 UTC, Jonathan M Davis wrote:
Personally, I think that you should just make it a member 
function if it's not a generic function, but to each their own,


Well, I use generics for when I have like, optional functionality 
that isn't inherent to the class itself. Since I avoid using 
wildcard imports, I won't import any generics I don't specify by 
name, when I import the class itself.


It's good for extending or adding informal things on the side, 
bells and whistles basically. Sometimes it can be useful for 
third party structures. Or combinations of existing member 
functions, in ways that only have limited applicability (like a 
calculation for graphics, that the database backend won't care 
about).



with(object)
return a && b || c && !d;


And... the feature already exists, I just didn't know about it. 
Thanks!


UFCS with implicit "this" ?

2016-08-08 Thread cy via Digitalmars-d-learn
I really like UFCS, which is to say, defining functions outside 
the class/struct to operate on it, but you can still say 
object.function(...) and it'll get rewritten into 
function(object,...).


Only sticky point is the convenience of "this". Like I can go

struct A {
bool a;
bool b;
bool c;
bool d;
bool foo() {
return a && b || c && !d;
}
}

But if I try do do the same thing with "bool bar(A object)" I end 
up with this:


bool bar(A object) {
return object.a && object.b || object.c && !object.d;
}

My example is a bit contrived, but it occurred to me how neat it 
would be if we could just specify "implicit" objects in our 
current scope. Like I was messing with an RGB and an HSL object, 
and I ended up having things like:


hsl.saturation = (max(rgb.r,rgb.g,rgb.b) - 
min(rgb.r,rgb.g,rgb.b)) / (2 - max(rgb.r,rgb.g,rgb.b) - 
min(rgb.r,rgb.g.rgb.b))


when I wanted something more like this:

saturation = (max(r,g,b) - min(r,g,b)) / (2 - max(r,g,b) - 
min(r,g,b)


Is there any way to do that in D? They don't let you use "alias 
this rgb" for a function scope, only a type's scope, so I guess 
it isn't possible?


I mean, aside from making an inner structure to the function, and 
copying the object by value... that's even more confusing than 
worth the convenience.


build a subpackage in dub?

2016-07-16 Thread cy via Digitalmars-d-learn
Say I have a package called "main" and a sub-package in a 
"complicatedexample" directory, and my dub.json in "main" looks 
sort of like:


"subPackages": [
  "./complicatedexample/"
],

Let's say I do *not* have ":complicatedexample" in my 
dependencies for "main", but "complicatedexample" itself imports 
from /other/ sub-packages in main, like I dunno, "support" 
"coolstuff" "thingies" or whatever.


I can't chdir to complicatedexample and dub -v build, because it 
says "Unknown dependency: complicatedexample:support" since it 
can't know that it's in a subpackage. But I also can't build 
":complicatedexample" from in the main directory, because "dub 
build -v :complicatedexample" gives me "Failed to find a package 
named main:complicatedexample".


I swear I figured out how to do this before, but I honestly 
cannot remember. The example imports a huge C library and 
compiles stubs and does all sorts of stupid stuff that the rest 
of the program doesn't have anything to do with at all, just to 
demonstrate the algorithm. But I don't know how to isolate it. 
Any ideas?


Just... create a totally separate package, and remember to copy 
and paste all the other sub-packages to it, and add all the other 
subpackages to every dub.json manually?


Re: extern (C++) including bodies of member functions?

2016-07-15 Thread cy via Digitalmars-d-learn

On Friday, 15 July 2016 at 19:20:52 UTC, Jacob Carlborg wrote:
Yes. Just as it's possible to call C function from D, it's 
possible to implement functions in D that can be called from C. 
This compatibility applies C++ and Objective-C as well.


So, it applies to member functions too (for C++)? Just as if you 
passed an extern(C++) directive to each one? And only their 
signature/mangling is changed, so that say in gdb for instance, 
they represent Type::member instead of zzTypezdxqdstuffmember?



The front end was only fairly recently converted to D.


Oh, I thought it happened a while ago, like when D2 came out. (Or 
was D2 recent as well?)


extern (C++) including bodies of member functions?

2016-07-15 Thread cy via Digitalmars-d-learn
I would never (ever) do this myself, but trying to understand 
dmd, the code is absolutely packed with things like this:


extern(C++) class Package : ScopeDSymbol
{
...
  override const(char)* kind() const
  {
 return "package";
  }
...
  override final inout(Package) isPackage() inout
  {
 return this;
  }
...etc...
}

How exactly does that... work? Is the body of such a member 
function written in the D Programming Language? Or is it some 
weird hybrid of D and C++ that just has a human programmer brain 
taking into account all the times that differing name mangling 
might produce different code? I mean, Package.resolve for 
instance is a non-trivial function. Can you not use templates 
inside such a function? Can you only use other "extern(C++)" 
types? Can you import from other modules, inside such a function?


The documents say nothing about this, only defining their 
examples as stubs, like

extern(C++) class Foo {
  void bar();
}

The documentation also avoids any memory allocation in D, instead 
assuming C++ routines like createInstance to use malloc to 
allocate the classes. But the code in dmd makes extensive use of 
things like this:

extern(C++) ... {
  final extern(D) this(...) { ... }
}

How would you create new objects of types that are declared 
extern(C++)? Just new, and mark the constructor as extern(D)?


I realize DMD is a horrible program that was Frankensteined from 
C++ code ages ago and is practically still C++ itself, and that 
DMD has to have /full/ control of symbol mangling, but it is also 
sort of important, not just as a D compiler, but as one of the 
only programs left in the world that produces optimized assembly, 
rather than passing it on to gcc or LLVM. So, understanding it is 
kind of an interest of mine.


Re: How to group similar member functions from different classes?

2016-07-15 Thread cy via Digitalmars-d-learn

On Monday, 20 June 2016 at 16:39:54 UTC, Marc Schütz wrote:

Untested:


Seems to only work if A and B are both defined in the same file 
as Foos (defeating the purpose). Putting A and B in a.d and b.d 
respectively gives me these errors:


a.d(2): Error: undefined identifier 'Foos'
a.d(2): Error: mixin a.A.Foos!() is not defined
b.d(2): Error: undefined identifier 'Foos'
b.d(2): Error: mixin b.B.Foos!() is not defined

I also tried switching it around, like
// b.d
import foos Foos;
class B {
  mixin Foos;
}

but that of course gives the error:
foos.d(4): Error: undefined identifier 'A'
b.d(3): Error: mixin b.B.Foos!() error instantiating

since you can't do a static if(typeof(this) == A) without 
importing A from a somehow. (you can do else static 
if(typeof(this) == B) without importing B though, since it does 
the branch for A first)


I think a mixin here is just required, because you can't use an 
identifier before it's defined, even at compile time. Honestly, I 
have yet to find a use for mixin templates.


Re: How to group similar member functions from different classes?

2016-06-18 Thread cy via Digitalmars-d-learn

On Saturday, 18 June 2016 at 07:03:25 UTC, cy wrote:
So how would you do it? Defining A.foo, B.foo, etc in one 
place, and A.bar, B.bar, etc in another?


The only thing I've been able to figure is a horrible hack, where 
your member functions are something like


// off in define_foos.d

template foo_for(T) {
  static if(is(T == A)) {
enum foo_for = q{
  int foo () {
return bar+42;
  }
};
  } else static if(is(T == B)) {
enum foo_for = q{
  int foo () {
return bar+23;
  }
   };
  }
}

// in classes.d

import define_foos: foo_for;

struct A {
int bar;
mixin(foo_for!A);
}

struct B {
int bar;
mixin(foo_for!B);
}

// etc

void main() {
import std.stdio;
A a = A(0);
B b = B(1);
writeln(b.foo());
writeln(a.foo());
}


Re: How to get access to Voldemort / private thingies

2016-06-18 Thread cy via Digitalmars-d-learn

On Saturday, 18 June 2016 at 08:41:30 UTC, Johan Engelen wrote:
Without going in too much detail, the problem is that I am not 
linking to opaque .o files.


The problem is the compiler has to assume you *might* be linking 
to opaque .o files, so it can't provide any introspection 
capabilities. There's no way to tell which "hidden type" that the 
getObject function is returning, since that's decided in the 
(possibly opaque) function body.


You could hack something with debugging, I suppose. (Probably 
not. DWARF/ptrace is ridiculously undocumented.) Perhaps you 
could make an alternate version of the function with the same 
source code, that returns auto instead of an Object type? As in...


Object evil() {
  class Vold {...}
  Vold v = new Vold(...);
  return v;
}


auto notevil() {
  static class Vold {...}
  Vold v = new Vold(...);
  return v;
}

...

auto hack = new typeof(notevil());

That can magically allow you to return type Vold, even though 
it's an error to say


Vold notevil() {
  static class Vold { ... }
  ...
}


Re: vibe.d - asynchronously wait() for process to exit

2016-06-18 Thread cy via Digitalmars-d-learn

On Friday, 17 June 2016 at 13:53:15 UTC, Vladimir Panteleev wrote:

Geod24 on IRC suggested signalfd + createFileDescriptorEvent. I 
think this would work, but isn't it possible to wrap the fd 
returned by signalfd into a Vibe.d stream and read it directly? 
I'm just not sure how.


Well, vibe.d streams are defined as interfaces, so you'd have to 
import vibe.core.stream: InputStream, and create a SignalFdInput 
class that implemented all the required methods. When it requires 
you to "wait" for data available, you save 
core.task.Task.getThis() somewhere, and... basically do what 
you're doing with createFileDescriptorEvent, just resuming the 
task instead of handling the event in a callback.


I should point out that createFileDescriptorEvent is an assert(0) 
for libasync.


How to group similar member functions from different classes?

2016-06-18 Thread cy via Digitalmars-d-learn

When I define functions like:

class A {
  abstract void format(...) {...}
}

class B : A {
  void format(...) {...}
}

class C : A {
  void format(...) {...}
}

and so on, often these different member functions all share a lot 
in common. Maybe they are the only ones that require formatting 
modules, that do I/O, that do string manipulation, that sort of 
thing.


But if I made a second function, say for instance clone() or 
replaceWithDucks(), it too might import a lot of modules, and 
perform a lot of logic. And there may be many, many different 
types of object here.


In C++ I could forward declare the member functions, then put all 
"::format(...)" member functions together in their own source 
file, making everything pretty neat and tidy. How do I do that in 
D? As near as I can tell, you can only define member functions 
inside the class definition itself, and you can't add to that 
definition piece-wise like


// file 1
class A ... {
  void format(...) { ... }
}
...

// file 2
class A ... {
 void doathing() { ... }
}
...

So how would you do it? Defining A.foo, B.foo, etc in one place, 
and A.bar, B.bar, etc in another?


Re: How to get access to Voldemort / private thingies

2016-06-17 Thread cy via Digitalmars-d-learn

On Friday, 17 June 2016 at 19:49:18 UTC, Johan Engelen wrote:

Hi all,
  Is there another way to get access to Voldemort class 
methods, or private class members, other than using


Voldemort data is pretty well protected though. Because unlike 
protection attributes, modularizing stuff in functions actually 
means something.


I mean, D doesn't exactly make it easy. You can't normally define 
a function in a different file it's declared in. But if you use 
extern(C) to avoid mangling getObject, you can pretty much 
provide interface.d and secrets.o and without analyzing the 
binary machine code, there's no way to tell the size or nature of 
what getObject returns, aside from that it (claims) to have 
pointers to functions that match the interface.


interface.d:
interface Object { ... };
extern(C) Object getObject();

secrets.d:
class Vold : Object { ... };
extern(C) Object getObject() { ... return new Vold(...); ... }

secrets.o: 

Because of the guarantee that you can link to opaque .o files, 
there's no general way to introspect into just what a function 
does, because that function might not have any source at all.


(I suppose you could instrument "new" itself in the raw runtime, 
to at least get the size of it. Assuming it wasn't malloc'd, or 
static...)


Re: How to get access to Voldemort / private thingies

2016-06-17 Thread cy via Digitalmars-d-learn

On Friday, 17 June 2016 at 20:12:53 UTC, cy wrote:

  writeln("see ",wow," for any equipment you need.");


Oh, and as you can see it's important to automate that, so you 
don't make any mistakes while copying.


const types can't be specialized non-const, if arrays?

2016-06-16 Thread cy via Digitalmars-d-learn
I don't get it. Do I have to write a separate template for arrays 
specifically or something?


NonConst foo(Constant: const NonConst, NonConst)(Constant bar) {
pragma(msg,"NonConst is ",NonConst);
pragma(msg,"Constant is ",Constant);
NonConst foo = bar;
return foo;
}

void main() {
const int bar = 42;
auto baz = foo(bar);
pragma(msg,typeof(baz));
baz = 23;
const(int[]) barr = [1,2,3];
auto bazz = foo(barr);
pragma(msg,typeof(bazz));
bazz[0] = 4;

}

/*

NonConst is int
Constant is const(int)
int
NonConst is const(int)[]
Constant is const(int)[]
const(int)[]
derp.d(16): Error: cannot modify const expression bazz[0]
Failed: ["dmd", "-v", "-o-", "derp.d", "-I."]

*/



Re: shared Mutex?

2016-06-09 Thread cy via Digitalmars-d-learn

On Thursday, 9 June 2016 at 20:53:38 UTC, tcak wrote:


(cast()mx).lock();


I was told casting away shared when there are still references to 
it is a bad idea. Like, the Mutex object might get corrupted if 
the garbage collector tries to move it while another thread is 
using it.


So thread 1 casts it to unshared, locks it, then allocates 
memory, triggering the GC to move things around. Meanwhile thread 
2 casts it to unshared, tries to lock it, and when it checks the 
locked bit, that area of memory has been replaced with another 
object entirely by the GC.


That seems like a really contrived situation, and maybe not a 
problem at all, if casting away shared doesn't make that memory 
eligible for being moved around. But, color me cautious before 
doing exactly what the FAQ says not to do.


https://dlang.org/faq.html#casting_from_shared


Re: Parse File at compile time, but not embedded

2016-06-09 Thread cy via Digitalmars-d-learn

On Tuesday, 7 June 2016 at 22:09:58 UTC, Alex Parrill wrote:


Accessing a SQL server at compile time seems like a huge abuse 
of CTFE (and I'm pretty sure it's impossible at the moment). 
Why do I need to install and set up a MySQL database in order 
to build your software?


Presumably you wouldn't be building it at all, since this seems 
like a technique to provide obfuscated binaries where people 
aren't privvy to exactly what was used to compile it.


Re: Constraining template with function signature

2016-06-09 Thread cy via Digitalmars-d-learn

The other way is better, but since you asked...

On Wednesday, 8 June 2016 at 01:42:55 UTC, Carl Vogel wrote:
Now, I can use something like isCallable std.traits to make 
sure the predicate is a Callable, and there are various 
function traits in the module that I could combine with `is` 
clauses to enforce the signature it seems, but that seems very 
clunky.  Is there a better way?


You could put all that stuff into one single template like this:

template isCompatibleCallable(alias Src, alias Dest) {
 static assert(isSomeFunction!Src || isCallable!Src,
   "Source is not callable");
 static assert(isSomeFunction!Dest || isCallable!Dest,
   "Destination is not callable");

  static assert(is(ParameterTypeTuple!Src == 
ParameterTypeTuple!Dest),

"Type Tuples differ");
  pragma(msg,ParameterStorageClassTuple!Src ==
ParameterStorageClassTuple!Dest);
  static assert(ParameterStorageClassTuple!Src ==
ParameterStorageClassTuple!Dest,
"Storage classes differ");
  static assert(is(ReturnType!Src == ReturnType!Dest),
"Return type differs");
  immutable bool isCompatibleFunction = true;
}

That works if you have a "default action" when the callable isn't 
specified, because you can match the Callable to the default one. 
So like...


bool default_less(T)(T a, T b) { return a < b; }

T[] sortArray(alias less = default_less!T, T)(T[] arr) 
if(isCompatibleCallable(less,default_less!T) { ... }


But it's probably clearer to use that is(typeof({ how this 
function will be called })) trick.


Re: Pointer problems, changing for no reasons

2016-06-09 Thread cy via Digitalmars-d-learn
I can't help but notice that loadModel is not a static member 
function, yet you don't seem to call it with a Model object in 
your "get" function.


Also have a look at std.typecons.RefCounted if you want reference 
counted data..


shared Mutex?

2016-06-09 Thread cy via Digitalmars-d-learn
I was thinking of using threads in a D program (ignores unearthly 
wailing) and I need 1 thread for each unique string resource 
(database connection info). So I did this:


shared BackgroundDB[string] back;

I don't see any way to make less data shared there. If it weren't 
shared, it would be thread local, and two application threads 
trying to look up the same database would end up firing off two 
BackgroundDB threads, since they had separate copies of "back" 
that could not share keys. So it pretty much has to be shared. 
But that means freaking /everything/ has to be shared.


In the dedicated thread, I had it repeatedly waiting on a 
condition, and once that condition is signaled, it removes what's 
been queued up, and processes those queued items in the database. 
Except for one problem... conditions can't be shared.


Error: non-shared method core.sync.condition.Condition.mutex is 
not callable using a shared object


Obviously you shouldn't need mutexes if you're using shared... 
but how do you do conditions, then?


When I do something like this:

struct BackgroundDB {
  Condition stuff_ready;
  ...
}

Condition is implicitly converted to shared(Condition) when I 
create a shared(BackgroundDB), and BackgroundDB is implicitly 
converted to shared(BackgroundDB) when I have a shared 
BackgroundDB[string]. But shared(Condition) then has a 
shared(Mutex) inside it, and that can't be locked, since 
Mutex.lock is a non-shared function.


Is core.sync.mutex.Mutex even usable in D anymore? It seems every 
mutex that wasn't shared would be part of thread local data, so 
two threads locking on the same mutex would actually be locking 
separate mutexes.


Re: a lambda with arguments has type void?

2016-06-08 Thread cy via Digitalmars-d-learn

On Tuesday, 7 June 2016 at 22:17:03 UTC, ag0aep6g wrote:
You don't specify the types of the parameters of the function 
literals, so you effectively have templates there. As such the 
literals have no types, and can't be passed as arguments.


Yeah, I see that now. The compiler does have all the necessary 
information to infer the argument types in both templates, 
though. There's no reason that it /couldn't/ infer the type of 
the argument. Like this is why it doesn't really make sense:


import std.stdio;

auto foo(Callable)(Callable c) {
  return c(42);
}

auto foo2(alias c)() {
  return c(42);
}

void main() {
  // this works, when you know it's an int delegate(int) 
beforehand...

  writeln(foo!(int delegate(int))((arg) => arg + 1));
  // and this can infer that your argument is an int delegate(int)
  writeln(foo2!((arg) => arg + 1));
  // so why doesn't this work, if the compiler can infer that the
  // argument is an int delegate(int)?
  static assert(!__traits(compiles,
 writeln(foo((arg) => arg + 1;
}

My guess the reason this doesn't work is: nobody worked on it yet.


You can:
* make it `int bar` in the literals, or


Sure, but it's a bit of a pain to have to export SomeArgumentType 
just so my callbacks can go ((SomeArgumentType rows) => ...). I 
don't like anything that makes you have to go through even more 
trouble to specify your imported symbols explicitly.


* explicitly take a `void delegate(int)` or `void 
function(int)` in foo2,


The problem with that is you don't always know if it's going to 
be a void delegate(int) or a void function(int). You can use 
"toDelegate" to force the issue, but that's more boilerplate 
required for the caller, and really that's the purpose of 
templates, to adjust your code to fit whether a function pointer 
or a delegate pointer or whatever is being passed.


Or you could overload the function, copying and pasting all the 
code, one for "void delegate(int)" and one for "void 
function(int)". Which is exactly what templates are SUPPOSED to 
prevent, but in this case they just... don't.



* take the callback as a "template alias parameter":


Sure, that works great, except when the source is a member 
function. Then it doesn't work at all. But since D has the trick, 
where you can take a non-member-function and make it act like 
one, it's workable.


Like this is the problem:

import std.stdio;

version(logical) {
  struct foo {
int arg;
void bar(alias c)() {
  c("foobar",arg);
}
  }
} else {

  struct foo {
int arg;
  }

  void bar(alias c, foo)(ref foo f) {
c("foobar",f.arg);
  }

  void bar(alias c, foo)(foo* f) {
return bar!(c,foo)(*f);
  }
}

void main() {
  import std.stdio;
  foo f = foo(42);

  f.bar!((message,arg) => writeln(message,arg));
}

Not to mention if "foo/bar" is defined in a support module, you 
now have to separately import "bar" to get "struct foo" to work 
right, since it won't import along with "foo", which makes it 
more difficult to use explicitly named imports, and I try never 
to do that. Anything that makes it more difficult to explicitly 
name imports encourages people to write BAD CODE THAT NOBODY CAN 
READ BECAUSE WHERE DID THAT SYMBOL COME FROM RGH


ahem

It's probably the lesser of three evils, using 
non-member-function templates, to take a template as a callback. 
I can definitely see a use for being able to specialize templates 
using inferred types, rather than ones explicitly passed to the 
!() list.


a lambda with arguments has type void?

2016-06-07 Thread cy via Digitalmars-d-learn
This program errors out, when I try to pass lambdas that take 
arguments. How am I getting the syntax wrong here? Is there some 
reason you can't do this?


import std.stdio;

void foo(Callable)(Callable bar) {
  bar();
}

void foo2(Callable)(Callable bar, int baz) {
  bar(baz);
}

void main() {
  foo({
  writeln("okay");
});
  foo2((bar) {
  writeln("got",bar);
},42);
  foo2((bar) => writeln("yay",bar), 42);
}




Re: Newbie to D, first impressions and feedback on the 5 (and more) first minutes.

2016-05-24 Thread cy via Digitalmars-d-learn
https://p0nce.github.io/d-idioms/ I wanted to mention as well, if 
you like idioms. That guy has some good ideas.


On Tuesday, 24 May 2016 at 17:36:45 UTC, Ali Çehreli wrote:
Yes, a link from that page points to a book that *can* be 
bought but it's available online as well:


It's worth buying, but the question is who's going to be 
comfortable with reading all that? It's very involved, not 
exactly a quickly crafted tutorial to "learn D in 5 minutes."





Re: Newbie to D, first impressions and feedback on the 5 (and more) first minutes.

2016-05-24 Thread cy via Digitalmars-d-learn

On Tuesday, 24 May 2016 at 15:27:45 UTC, llaine wrote:
I'm running Fedora 23 on a daily basis and the installation was 
OK. Not as easy as on mac but still.


Yeah, rpm based distributions like Fedora/Redhat/etc have 
historically been a real pain when it comes to installing stuff. 
Depending on individual files with no indication what package 
those files are in for instance.


I recommend something based on "pacman" these days, though you'll 
have to hunt a while if you want one that hasn't gone and added a 
bunch of binary linkage to systemd to their entire dependency 
tree.


portage is also alright, but a little tricky to use, and you need 
a speedy CPU to compile quickly.


Congratulations on this point to all the people who made dub. 
Programming in 2016 should be like this.


It does have its issues, but dub is awesome.

The only bad point I can see here is that it looks like it's 
more easy easy to get ready on a mac than on a linux machine.


A Fedora machine. Installing dub on Arch or Debian should work 
just fine.


This part was a bit different. By being a total newbie to the D 
language I don't really know where to begins.

Of course I went to the getstarted.html page but


as a newbie with no system programming background I feel there 
are too many choices for me.


Oh, I don't think system programming is the issue here. It is 
kind of intimidating that the first place it points you for a 
basic total newbie tutorial is a big dead tree book that you can 
buy. It seems to me there could be something simpler than that 
for newbies, but a little more extensive than just the random 
code snippet it shows on the home page.


The only bad point here is that I can't find a "Effective D" 
page. A document that gives tips for writing clear, idiomatic D 
code.


Wow, good luck there. I think D programmers are pretty 
unopinionated as to how you should write code. The language is 
complex enough that it keeps things in line pretty well on its 
own. And "idiom" is another word for "opinion" so ultimately how 
you should code depends more on who you're working with than the 
language itself.


I would appreciate a tips and tricks page though, with advice 
like separate large amounts of code into separate projects to get 
it to compile faster, or use ld.gold since D has ludicrous 
amounts of linkage going on, or my trick of throwing in --nodeps 
after the first compile that fixes dub's issues with eager 
dependency tracking. Or how you make parsing easier by importing 
inside functions instead of globally to the module. I wonder if 
there should be a wiki page like that, hm...


https://wiki.dlang.org/Tutorials by the way


Well in one word. It sucks. I've tried to setup an editor with 
all the features that we can see in the wiki matrix.


Uh... huh. I just use emacs, because sometimes I'm coding on a 
netbook that isn't running X.



autocompletion


Not as simple as it sounds. What should auto-complete? Module 
names? Misspellings? Potential imports? Download the list of 
package imports? File names? function names? Local variables? 
How's it going to detect the names of local variables? How's it 
going to detect which function the cursor is in? Autocomplete is 
something I don't really like, because it requires that your 
editor be some big dumb kitchen sink IDE in order to manage all 
that complex logic of guessing what you mean when you hit .


There is one autocompletion bug that irritates the pants off of 
me, though. gdb. Why can't they fix their stupid debugger so that 
it let you auto-complete across the '.' character?


gdb's written in 69 megabytes of solid C though, not D.


Is NullableRef checked at compile time?

2016-05-23 Thread cy via Digitalmars-d-learn
I was squinting at the std.typecons.NullableRef code and it 
_looks_ like isNull is only checked at runtime (and not checked 
at all in release mode!) but D has surprised me before in its 
ability to pre-calculate stuff during compilation.


I was thinking of using something like this:

http://arsdnet.net/dcode/notnullsimplified.d

...which does the check once (during runtime) but after that it's 
compile-time verified not to have a null pointer. (Sort of like 
C++ references!) I think using NullableRef instead would have 
every instance of getting the pointer perform the check at 
runtime, even if it has already been verified as not null. That's 
correct, right? Yes I know, premature optimization etc, but I was 
just curious if a NotNull template might be a stronger 
declaration of a pointer's nullness.


Re: Speed up `dub`.

2016-05-23 Thread cy via Digitalmars-d-learn

On Thursday, 19 May 2016 at 17:50:44 UTC, ciechowoj wrote:

dub build --nodeps


I tried it, doesn't seem to do anything, maybe something is 
broken.


Perhaps you didn't complete "dub build" without --nodeps 
beforehand? You have to do that once, and it's still as 
annoyingly inefficient as anything, especially since it checks 
dependencies online even if you have the selected version 
downloaded already. But after that first compile, I add --nodeps 
to the dub build command, and it's lightning fast to recompile.


It doesn't fix the issues in DUB that slow down compiling 
programs, but it does speed up the compile-modify-check cycle.


Re: guard condition for a callable thingy, with THESE arguments

2016-05-15 Thread cy via Digitalmars-d-learn

On Sunday, 15 May 2016 at 02:12:38 UTC, Ann W. Griffith wrote:
use "Parameters" in the constraint or make a template that you 
can reeuse.


This is what I've got going so far. Using static asserts to have 
clearer errors when an incorrect callback is supplied. I'm not... 
sure storage class is important.


import std.traits: isSomeFunction, isCallable,
  ParameterTypeTuple, ParameterStorageClassTuple, ReturnType,
  isDelegate;

import std.stdio;

template isCompatibleFunction(alias Src, alias Dest) {
 static assert(isSomeFunction!Src || isCallable!Src,
   "Source is not callable");
 static assert(isSomeFunction!Dest || isCallable!Dest,
   "Destination is not callable");

  static assert(is(ParameterTypeTuple!Src == 
ParameterTypeTuple!Dest),

"Type Tuples differ");
  pragma(msg,ParameterStorageClassTuple!Src ==
ParameterStorageClassTuple!Dest);
  static assert(ParameterStorageClassTuple!Src ==
ParameterStorageClassTuple!Dest,
"Storage classes differ");
  static assert(is(ReturnType!Src == ReturnType!Dest),
"Return type differs");
  immutable bool isCompatibleFunction = true;
}


bool function_callback(string a) {
  return true;
}

template foobar(Callable) 
if(isCompatibleFunction!(function_callback,Callable)) {

  template foobar(Callable c) {
immutable bool foobar = c("foo");
  }
}

void main() {
  bool result = true;
  bool delegate_callback(string a) {
return result;
  }
  bool delegate(string) dg = _callback;
  static assert(isDelegate!dg);
  static assert(isCompatibleFunction!(function_callback, 
delegate_callback));

  struct Derp {
static bool opCall(string a) {
  return true;
}
bool opCall(string a) {
  return false;
}
bool member(string a) {
  return true;
}
  };
  static 
assert(isCompatibleFunction!(function_callback,Derp.init.member));
  static 
assert(isCompatibleFunction!(function_callback,Derp.init));

  static assert(isCompatibleFunction!(function_callback,Derp));
  static assert(isCompatibleFunction!(delegate_callback,Derp));
  if(foobar!function_callback) {
writeln("foo");
  } else {
writeln("bar");
  }
  writeln("derp");
}



guard condition for a callable thingy, with THESE arguments

2016-05-14 Thread cy via Digitalmars-d-learn
I take callbacks on occasion, and I don't really care if they're 
a delegate, or a function, or a callable object, and I can assert 
that in a template:


void foo(Callable)(Callable callback) if(isSomeFunction!Callable 
|| isCallable!Callable) {

 ...
}

That works, but it doesn't show you what arguments the callable 
will take, or how many, or what its return type should be.


You can of course read the body of the `foo` function to spy out 
where the text "callable(" might be, but it'd be really nice if I 
could put that information in my guard condition somehow. What I 
want is something like this.


bool default_callback(int foo, string bar, Something baz) {
 ...
}

void foo(Callable)(Callable callback) 
if(calledTheSameAs!(Callable,default_callback)) {

 ...
}

or

void foo(Callable)(Callable callback) 
if(calledTheSameAs!(Callable,bool function(int,string,Something)) 
{

 ...
}

Is that possible to do? Has it already been done?


Re: Speed up `dub`.

2016-05-14 Thread cy via Digitalmars-d-learn

On Monday, 7 March 2016 at 09:18:37 UTC, ciechowoj wrote:
I'm using `dub` to build project. And every time I run `dub` it 
seems to check if dependencies are up to date, which takes some 
time. Is there a way to switch of that checking? Or any other 
way to speed up building process? It really slows down my 
modify-compile-check iteration time.



dub build --nodeps

It's amazing.

dub has a few uh, issues with dependencies. It pulls all 
dependencies, even for disabled configurations, even for 
unselected optional dependencies, then just... leaves them pulled 
I guess, and doesn't link with them?

https://github.com/dlang/dub/issues/844

I don't know exactly what's going wrong. But after you run `dub 
build` the first time, everything will be downloaded and 
installed now, so you can recompile by specifying --nodeps and it 
just jumps straight past all those buggy issues.


ld.gold also will vastly speed up modify-compile-check cycles. 
dmd is fast at compiling, but linking it all up is really slow 
with vanilla ld.


Re: Small C wrapper in your DUB package?

2016-05-08 Thread cy via Digitalmars-d-learn
Well, just messing with it myself, the solution seems to be to 
make a .a library, link with /lib/libc.a since unlike .o, .a 
breaks shared linkage, and then refer to it in libs as 
"$PACKAGE_DIR/libmywrapper.a"


...
"preBuildCommands": ["make -C $PACKAGE_DIR"],   
	"libs": 
["$PACKAGE_DIR/libmymagick.a","ImageMagick","/lib/libc.a"]

...

basically.

Then it doesn't work, because when ImageMagick calls dlopen, dmd 
somehow switches the string "RegisterGIFImage" with 
"gif_LTX_RegisterGIFImage" in the resulting executable.


But the wrapper works fine at least.


Small C wrapper in your DUB package?

2016-05-08 Thread cy via Digitalmars-d-learn
I'm tiring of making extern (C) signatures for a million library 
calls and counting out the offset of members of C structures, to 
produce analagous D structures. Couldn't I just make a .c file 
that had my own specialized, opaque, D friendly interface?


I don't really know how to do that. Especially with DUB. Do I put 
it under "libs"? That seems like the only place you can put 
external stuff. Do I have to link my wrapper into a PIC shared 
library, or can I just make a .a static library? Or can I just 
use .o files?


How do I specify that it look for the C wrapper in my package 
directory, rather than systemwide? Just "libs": 
["./helpers/libchelper.a"]? I sure don't want to make a whole 
separate revision controlled project installed in /usr/lib just 
for a chintzy little wrapper for accessing a C library.


I can build any C wrapper binaries in preBuildCommands with just 
a Makefile, so that's no problem. But I'm not sure how to use 
them in my program.


Re: How to escape control characters?

2016-03-30 Thread cy via Digitalmars-d-learn

Oh, cool.

On Thursday, 31 March 2016 at 03:29:19 UTC, H. S. Teoh wrote:

Or implement manual substitution with a pipeline:
string myString = ...;
string escapedStr = myString
.chunks(1)
.map!(c => (c == "\n") ? "\\n" :
   (c == "\r") ? "\\r" :
   (c == "\t") ? "\\t" :
   c)
.joiner
.array;


What I did was

string escapedStr = myString
  .replace("\n",`\n`)
  .replace("\r",`\r`)
  .replace("\t",`\t`);

That makes like 3 copies of the string I guess, but whatever. I'm 
not sure how efficient a general chunking filter would be on 
1-byte chunks, and I certainly don't want to be creating a 
zillion unescaped 1-byte strings, so if I cared I'd probably do 
something like this:


auto escapedStr = appender!string;
for(c;myString) {
  switch(c) {
  case '\n':
   escapedStr.put("\\n");
  case '\r':
   escapedStr.put("\\r");
  ...
  default:
   escapedStr.put(c);
  }
}

It'd have to be long and boring to get all the control characters 
though, and possibly unicode ones too, or do "\xNN" style byte 
escapes. So I was hoping something standard already existed.


Re: How to escape control characters?

2016-03-30 Thread cy via Digitalmars-d-learn

On Thursday, 31 March 2016 at 03:23:52 UTC, Seb wrote:

http://dlang.org/spec/lex.html#WysiwygString

r"ab\n" or `ab\n`


Yes I know. But I mean like,

string a = r"ab\n";
writeln(escape(a)); // => ab\n



How to escape control characters?

2016-03-30 Thread cy via Digitalmars-d-learn
This might be a dumb question. How do I format a string so that 
all the newlines print as \n and all the tabs as \t and such?


Re: How to be more careful about null pointers?

2016-03-29 Thread cy via Digitalmars-d-learn

On Tuesday, 29 March 2016 at 06:21:49 UTC, Ali Çehreli wrote:

parent.prep.bind is translated to the following by the compiler:

"Call bind() for the object at address... let's calculate... 
Wherever parent is, we should add the offset of prep inside 
that object."


Okay, that's helpful actually. So, when accessing members of an 
object, it won't trigger a NPE, because the object is not 
dereferenced immediately, but the expected offset to the member 
is dereferenced. D puts off resolving pointer addresses as much 
as possible, so instead of bind((*parent).(*prep)) it's more like 
bind(parentlocation + prepoffset) and only (this.)member resolves 
to (*(parentlocation + prepoffset).member).


I thought it had an extra layer of pointer indirection, like if 
class object A has address 1234, and member A.b has offset 0x20, 
then you first dereference address 1234 (to get 4321 say) and 
then add 0x20 to that. But actually a class object is... already 
dereferenced, and is an integer representing the address to the 
object, not a pointer to that address.


Variables representing fixed, definite memory locations really 
throws me sometimes. You can't assign to a const, because that 
assigns to const marked memory, and doesn't just move the 
variable somewhere else. And NPE doesn't occur with a class, 
because setting it to NULL, and accessing a member is more like 
this in C:


intptr_t a = 0;
(struct B*)(a+0x20).member

and less like this in C:

intptr_t* a = 0;
(struct B*)(*a+0x20).member


Re: How to be more careful about null pointers?

2016-03-29 Thread cy via Digitalmars-d-learn

On Monday, 28 March 2016 at 21:24:48 UTC, Adam D. Ruppe wrote:
If it didn't give the error, either you swallowed it or you 
didn't actually dereference null.


Okay, so it's not actually supposed to happen. Hopefully it's 
something I did wrong...


What is the db library you are using? Did you compile it along 
with your program or use a .lib with it?


d2sqlite3: https://github.com/biozic/d2sqlite3

Compiled it along with my program. And "Database.prepare" is 
neither static, nor final. I keep describing it wrong though, 
what I ended up doing. It's easier to just write a program to 
describe it. What I ended up doing was like this:


struct Database {
  string derp;
  Statement prepare(string s) {
return Statement(1234);
  }
}

struct Statement {
  int member;
  void bind(int column, int value) {
import std.stdio;
writeln("derp",member);
  }

}


class Wrapper {
  Database something;
  Statement prep;
  this() {
something = Database("...");
prep = something.prepare("...");
  }
}

Wrapper oops;
void initialize() {
  oops = new Wrapper();
}

class Entry {
  Wrapper parent;
  this(Wrapper parent) {
//this.parent = parent;
//oops
parent = parent;
  }
  void usefulmethod() {
parent.prep.bind(1,42);
//parent.prep.execute();
//parent.prep.reset();
  }
}

void main() {
  initialize();
  auto entry = new Entry(oops);
  entry.usefulmethod();
}

That program causes a segmentation fault on my machine. Somehow 
despite never initializing Entry.parent, a class object (whose 
default init is a null pointer), I can still call methods on it, 
access members on it, and call methods on those members. No 
warnings or errors. The segfault doesn't happen until the bind() 
method.


Re: How to be more careful about null pointers?

2016-03-28 Thread cy via Digitalmars-d-learn

On Monday, 28 March 2016 at 21:01:19 UTC, cy wrote:
I invoked db.find_chapter.bindAll(8,4), when db was a null 
pointer.


No, no, no it's worse than that. What I did was (db.)find_chapter 
= (db.)backend.prepare("...") when backend was null, and got no 
error. find_chapter was garbage of course, but there was no 
error. And only much later, when I called 
db.find_chapter.bindAll(...) did it react to the garbage data, by 
messily segfaulting. db was a good pointer, but db.backend was 
bad, and db.backend.prepare() didn't even flinch getting passed a 
null this, and dereferencing that null internally to construct 
Statement(Database,string).


How to be more careful about null pointers?

2016-03-28 Thread cy via Digitalmars-d-learn
I finally found the null pointer. It took a week. I was assigning 
"db = db" when I should have been assigning "this.db = db". 
Terrible, I know. But...


I invoked db.find_chapter.bindAll(8,4), when db was a null 
pointer. There was no null pointer error. No exception raised for 
dereferencing a null. I'm not in release mode. Assertions are 
enabled. Shouldn't that have raised a null pointer exception?


Instead, it accesses db as if db were not null, producing a 
garbage structure in find_chapter, which bindAll chokes on, then 
causes the whole program to segfault.


I realize enforce(db).find_chapter would work, but... I thought D 
was more careful about null pointers? At least enough to die on 
dereferencing them?


Re: How do you append to a dynamic array using move semantics?

2016-03-23 Thread cy via Digitalmars-d-learn

On Wednesday, 23 March 2016 at 23:44:55 UTC, ag0aep6g wrote:

You got the order of arguments wrong here. Source goes first,


Oh, derp. Thanks. Right then... it works as expected.


How do you append to a dynamic array using move semantics?

2016-03-23 Thread cy via Digitalmars-d-learn

struct Thing {
  @disable this(this);
}
...
items ~= move(item); // Error: struct Thing is not copyable 
because it is annotated with @disable


++items.length
move(items[$-1],item); // Error: struct Thing is not copyable 
because it is annotated with @disable


appender(items).put(move(item)); // Error: template 
std.array.Appender!(Thing[]).Appender.put cannot deduce function 
from argument types !()(Thing)


...?


inout and templates don't mix...

2016-03-23 Thread cy via Digitalmars-d-learn

halp

There's a module that tries to define complex operations on both 
const and non-const structs, since it's the same operation for 
both. So every function that invokes those operations is 
copy-pasted twice, just with "const" added. Switching to inout to 
eliminate that huge amount of code duplication causes an error, I 
can't figure out how to fix.


struct Someop(Type) {
  Type thing;
  void foo() {
thing.bar();
  }
}

struct Foo {
  void bar() {
import std.stdio: writeln;
writeln("bar");
  }
}

struct Bar {
  void thingy(inout(Foo) foo) inout {
auto op = Someop(foo);
op.foo();
  }
}

void main() {
  Foo foo;
  Bar bar;
  bar.thingy(foo);
}

=>

Error: struct derp.Someop cannot deduce function from argument 
types !()(inout(Foo))


if I put in Someop!(typeof(foo))(foo) it gives the error:

Error: variable derp.Someop!(inout(Foo)).Someop.thing only 
parameters or stack based variables can be inout


...even though Someop is a struct allocated on the stack.

What I'm dealing with is like:

struct Bar {
  void thingy(Foo foo) {
auto op = Someop(foo);
//...lotsastuff...
op.foo();
  }
  void thingy(const(Foo) foo) const {
auto op = Someop(foo);
//...lotsastuff...
op.foo();
  }
  // repeat ad-nauseum...
}


Re: If I understand const right...

2016-03-23 Thread cy via Digitalmars-d-learn

On Wednesday, 23 March 2016 at 21:10:49 UTC, ag0aep6g wrote:

Just to be 100% clear: you're adding to the pointer here,


No, that's what I meant to do.


b = new int(*b + 1);
Here "b" is pointing to mutable heap allocated data, which got 
cast to constant.


with b = b + 1, it's still constant memory.




If I understand const right...

2016-03-23 Thread cy via Digitalmars-d-learn

a = a + 1

a is const, a + 1 is const, yet a can't be assigned to a + 1. And 
I think the reason is like...


const(int) a = 23;
while(something()) {
  a = a + 1;
}

in the first iteration, a is set to 23, and the value of "a + 1" 
is 24, but where is the computer gonna store that 24? It can't 
store it where 23 is, because that's constant data. In a register 
variable? What about the next iteration? A runtime queue of 
previously calculated consts that builds up with each iteration?


...not gonna happen. So since there's nowhere to store that 24 
(without some non-const variable to store it in), you can't point 
"a" at the new address, even if 24 itself would fit inside 
another constant bit of memory just fine.


I'm actually used to the runtime queue thing, from scheme and the 
like. "a = a + 1" allocates a new bit of memory, made immutable 
and never changed from then on, storing "a + 1" in it and 
pointing a at it. And if "a + 1" has already been calculated, it 
finds that old value and reuses it.


So I think that's why you can't assign to a constant variable, is 
that there's no locating/initializing of new constant memory on 
the fly, to have a place to put that 24, 25, etc. Variables, even 
mutable variables, always have the same address, and any of us 
who are confused can think of assigment as a storage operation, 
more like erlang's "=>" rather than scheme's "(let)".


To "change" an address, you have to use a mutable pointer (or the 
like). The variable will always have the same address, but 
there's a second address stored at that address, and since the 
storage is mutable, that second address can be changed, by 
mutating the memory stored at the first address.


So like...

const(int)[2] a = [23,24];
const(int)* b = a;
writeln(," always constant");
writeln(a, " always constant");
writeln(a[0]," always constant");
writeln(," always constant");
writeln(b," always mutable");
writeln(*b, "constant");
b = b + 1;
writeln(*b, "also constant, but a different one.");

something like that...


Re: Using ffmpeg in command line with D

2016-03-22 Thread cy via Digitalmars-d-learn

On Monday, 21 March 2016 at 17:26:09 UTC, Karabuta wrote:


Will this work


Yes.


and is it the right approach used by video convertor front-ends?


Well, yes, provisionally. When you invoke "ffmpeg" via 
spawnProcess, that isolates ffmpeg as its own process, obviously. 
From a security and maintenance standpoint, that is very, very 
good. None of the code in ffmpeg has to be considered when 
writing your own code, other than how it acts when you call it. 
If ffmpeg scrambles its own memory, your program won't get messed 
up. If your program scrambles its own memory, ffmpeg won't get 
corrupted, and neither will your video file.


There are a few downsides though. It's expensive to set up that 
very restricted, isolated interface (executing a process) but 
considering the amount of number crunching involved in processing 
videos it's a pretty negligible cost. If you're doing some sort 
of web server that serves up a million generated pages a minute 
though, all that executing can bog it down. But you wouldn't use 
ffmpeg for that.


The extreme isolation of a separate process means that you're 
restricted in what you can do with the video. You can do anything 
that ffmpeg devs write in their interface, but that's it. If they 
change the format of their command, all your stuff will break 
until you fix that, but considering how old ffmpeg is, that's 
probably not going to happen any time soon.


In some cases, there are resources that cannot be reused between 
two processes, that are very expensive to set up and tear down. 
You wouldn't use mpv like ffmpeg for instance, because it would 
have to recreate the video display window every execution. 
Instead, mpv has a "socket" interface that you can connect to 
after launching one process, and use that to control the player.


So, for video conversion, yes it's the right approach. Your 
mileage may vary if you want to display that video, or generate 
videos on-demand from a high performance webserver. (in which 
case the video processing will still be 99.999% of what slows you 
down, not process execution).


Re: byChunk odd behavior?

2016-03-22 Thread cy via Digitalmars-d-learn

On Tuesday, 22 March 2016 at 07:17:41 UTC, Hanh wrote:

input.take(3).array;
foreach (char c; input) {


Never use an input range twice. So, here's how to use it twice:

If it's a "forward range" you can use save() to get a copy to use 
later (but all the std.stdio.* ranges don't implement that). You 
can also use "std.range.tee" to send the results to an "output 
range" (something implementing put(K)(K)) while iterating over 
them.


tee can't produce two input ranges, because without caching all 
iterated items in memory, only one range can request items 
on-demand; the other must take them passively.


You could write a thing that takes an InputRange and produces a 
ForwardRange, by caching those items in memory, but at that point 
you might as well use .array and get the whole thing.


ByChunk is an input range (not a forward range), so there's 
undefined behavior when you use it twice. No bugs there, since it 
wasn't meant to be reused anyway. What it does is cache the last 
seen chunk, first iterate over that, then read more chunks from 
the file. So every time you iterate, you'll get that same last 
chunk.


It's also tricky to use input ranges after mutating their 
underlying data structure. If you seek in the file, for instance, 
then a previously created ByChunk will produce the chunk it has 
cached, and only then start reading chunks from that exact 
position in the file. A range over some sort of list, if you 
delete the current item in the list, should the range produce the 
previous item? The next item? null?


So, as a general rule, never use input ranges twice, and never 
use them after mutating the underlying data structure. Just 
recreate them if you want to do something twice, or use tee as 
mentioned above.


Re: setting stringImportPaths in dub.json

2016-03-20 Thread cy via Digitalmars-d-learn

On Monday, 21 March 2016 at 04:58:37 UTC, cy wrote:
I also tried symlinking ../sharedViews into views/shared and 
importing "shared/common.stuff" but that didn't work either.


Oh. I was editing dub.selections.json. Never mind, I'm just an 
idiot.


Re: setting stringImportPaths in dub.json

2016-03-20 Thread cy via Digitalmars-d-learn
I also tried symlinking ../sharedViews into views/shared and 
importing "shared/common.stuff" but that didn't work either.


setting stringImportPaths in dub.json

2016-03-20 Thread cy via Digitalmars-d-learn

"stringImportPaths": ["../sharedViews/"]

nope...


"buildSettings": {
"stringImportPaths": ["../sharedViews/"]
}

nope...

"package": {
"name": "myownfreakingpackage",
"buildSettings": {
"stringImportPaths": ["../sharedViews/"]
}
}

nope...

"package": {
"name": "myownfreakingpackage",
"stringImportPaths": ["../sharedViews/"]
}

nope...

How do you add stringImportPaths? I want to import stuff besides 
in just views/, some multi-project shared folders.


Re: Linux blocked on file read on exit, need select

2016-03-20 Thread cy via Digitalmars-d-learn
I don't know, but you could always just use fcntl if you already 
can assume you're on Linux.


extern (C) int fcntl(int, int, int);

C keeps the constants under lock and key of course, so you have 
to specify them manually. But you could write a C program to 
print them out, or generate D code I suppose.


const int F_SETFL = 4
const int F_GETFL = 3
const int O_NONBLOCK = 2048
fcntl(fd,F_SETFL,O_NONBLOCK | fcntl(fd,F_GETFL,42));

not tested or anything.



How to allocate arrays of objects?

2016-02-10 Thread cy via Digitalmars-d-learn
The following program segfaults for me, compiling it with 
dmdv2.070 as well as the latest git. I must be doing it wrong. 
There's a way to specify class construction, or emplace, or 
something. But I can't find it! How do I deal with arrays of 
objects?


class A {
int stuff;
}

void main()
{
A[] as = new A[2];
assert(as.length==2);
as[0].stuff = 42;
}

Looking at it in gdb, the program segfaults on "A[] as = new 
A[2]" and never reaches "as[0].stuff = 42". But removing 
"as[0].stuff = 42" causes the program to stop segfaulting! 
assert(as.length == 2) doesn't get reached either.


Re: How to allocate arrays of objects?

2016-02-10 Thread cy via Digitalmars-d-learn

On Thursday, 11 February 2016 at 04:07:18 UTC, cy wrote:


A[] as = new A[2];
assert(as.length==2);
as[0].stuff = 42;


Oh, I get it. `as` is an array of 2 pointers to A objects, both 
pointers set to null. So I need to say like:


as[0..$] = new A();

before accessing .stuff on as[0].

Still no clue why it segfaulted on the allocation though, rather 
than the statement with the null dereference. Hidden optimization?


How to warn of unused imports?

2016-02-08 Thread cy via Digitalmars-d-learn
When I factor out code from my modules, it really, really often 
leaves import statements that just sit there doing nothing, 
making it look like my program is more complex than it is. How do 
I get warned for leaving those, and a list of which ones I can 
safely remove?


Re: Bug or intended?

2016-02-08 Thread cy via Digitalmars-d-learn

On Saturday, 6 February 2016 at 14:15:04 UTC, rsw0x wrote:
I was playing around with alias templates and came across this, 
I reduced it to:


---
struct A(alias C c){

  auto foo(){
return c.i;
  }
}

struct B{
  C c;
  A!c a;
}

struct C{
  int i;
}
---

It gives me a "need 'this' for 'i' of type 'int'" error.


I think the "alias C c" you pass actually must be a value "c" of 
some sort. A!c would have to produce a different A struct, for 
every c value. (as opposed to A!C which works fine.) So, if you 
made B with a C with an i = 23, then you'd have an A!(23) and if 
you made another one with i = 42, you'd have an A!(42).


That doesn't seem very useful, for general integers. Maybe if it 
was an enum of finite, limited size it'd make sense.


in a template argument, specify which object member to access?

2016-02-08 Thread cy via Digitalmars-d-learn
object.member lets me access the member of the object, but what 
if I want to access those members in a generic way, but in a 
different arrangement depending on context? Like if I wanted to 
first follow a tree down, and second priority would be going left 
to right, but then I wanted to first go right, and second 
priority would be going down to up.


struct A {
string up;
string down;
string left;
string right;
}

template goPlaces(D1,D2,D3) {
string go(A a) {
return "go " ~ a.D1 ~ " then go " ~ a.D2 ~ " then go " ~ a.D3;
}
}

import std.stdio;

void main() {
A a = {"north","south","east","west"};
writeln(goPlaces!(up,down,left)(a));
}

Do I just have to use a mixin? Or implement those members as 
indexes in an array, if I want to use them differently?


enum Way { UP, DOWN, LEFT, RIGHT };
struct A {
string[Way.max+1] ways;
}
...


Re: How to warn of unused imports?

2016-02-08 Thread cy via Digitalmars-d-learn

On Monday, 8 February 2016 at 18:57:52 UTC, Basile B. wrote:

Otherwise, it sounds like a decent enhancement request for DMD. 
I know other compilers who do this warning.


It definitely does sound like a decent enhancement request. I 
didn't know it wasn't implemented yet, but it should be pretty 
straightforward, since within DMD you can access the AST. 
Alternatively, implementing DIP50 might let you do it outside the 
compiler.


http://wiki.dlang.org/DIP50


Re: in a template argument, specify which object member to access?

2016-02-08 Thread cy via Digitalmars-d-learn
This is what I have so far. Using mixin(rawstring~templatearg) 
for every time I access the member is kind of cludgy though.


struct A {
string up;
string down;
string left;
string right;
}

template goPlaces(string D1, string D2, string D3) {
string goPlaces(ref A a) {
mixin("a."~D2) = "deetoo";
return "go " ~
mixin("a."~D1) ~ " then go " ~
mixin("a."~D2) ~ " then go " ~
mixin("a."~D3);   
}
}

void main() {
import std.stdio;
A a = {"north","south","east","west"};
writeln(goPlaces!("up","left","down")(a));
writeln(a.left);
}


top postinglol

On Monday, 8 February 2016 at 21:09:47 UTC, cy wrote:
object.member lets me access the member of the object, but what 
if I want to access those members in a generic way, but in a 
different arrangement depending on context? Like if I wanted to 
first follow a tree down, and second priority would be going 
left to right, but then I wanted to first go right, and second 
priority would be going down to up.


struct A {
string up;
string down;
string left;
string right;
}

template goPlaces(D1,D2,D3) {
string go(A a) {
return "go " ~ a.D1 ~ " then go " ~ a.D2 ~ " then go " ~ a.D3;
}
}

import std.stdio;

void main() {
A a = {"north","south","east","west"};
writeln(goPlaces!(up,down,left)(a));
}

Do I just have to use a mixin? Or implement those members as 
indexes in an array, if I want to use them differently?


enum Way { UP, DOWN, LEFT, RIGHT };
struct A {
string[Way.max+1] ways;
}
...




Re: in a template argument, specify which object member to access?

2016-02-08 Thread cy via Digitalmars-d-learn

On Monday, 8 February 2016 at 22:38:45 UTC, Mengu wrote:

i believe you can use __traits(getMember) there.


Great! Should have refreshed before sending that reply...

I wonder if mixin("a."~member) is better or worse than 
__traits(getMember,a,member)...


Re: What is a short, fast way of testing whether x in [a, b]?

2016-02-07 Thread cy via Digitalmars-d-learn

On Monday, 8 February 2016 at 03:09:53 UTC, Enjoys Math wrote:

was wondering if there's a D

native way of doing it.


That is the D native way of doing it, but you could clean up a 
lot of the boilerplate with some more templates. Also, || tests 
for exclusion, as in whether something is NOT in the range [a,b] 
(it's either above or below).


Also not sure why you have EPS=1 for integers. 1 ∈ [1,1] but 1-1 
is outside of [1,1].


template EPS(T) {
static if (is(T == double)) {
T EPS = 0.000_000_001;
}
static if (is(T == float)) {
T EPS = 0.000_001;
}
static if (is(T == int)) {
T EPS = 0;
}
}

struct DerpRange(T) {
T low;
T hi;
}
// because the constructor Range(1,2) can't POSSIBLY be deduced
// to be Range!(int)(1,2)
DerpRange!T Range(T) (T low, T hi) {
return DerpRange!T(low, hi);
}


bool in_range(T) (T what, DerpRange!T range) {
return
what - EPS!T >= range.low &&
what + EPS!T <= range.hi;
}

bool in_range(T) (T what, T low, T hi) {
return in_range(what,DerpRange!T(low,hi));
}

void main() {
import std.stdio: writeln;

void check(bool success) {
if(success) {
writeln("yay!");
} else {
throw new Exception("fail...");
}
}
check(!in_range(3,4,5));
check(in_range(3,3,5));
check(in_range(3,2,5));
check(in_range(3,2,3));
check(!in_range(3,2,2));
check(in_range(3,Range(0,99)));
auto r = Range(0,99);
check(in_range(42,r));

for(int i=0;i<10;++i) {
import std.random: uniform;
int what = uniform!"[]"(0,99);
check(in_range(what,r));
check(in_range(what,0,99));
check(in_range(what,Range(0,99)));
}
}



Re: Things that keep D from evolving?

2016-02-06 Thread cy via Digitalmars-d-learn
On Saturday, 6 February 2016 at 10:29:32 UTC, Ola Fosheim Grøstad 
wrote:

This prevents fast GC: Pointers.


Would it be possible to write a fast garbage collector that just 
didn't track any pointers? Just offer a head's up that if you use 
"this collector" and pointers on collectable data, you're gonna 
have a bad time? How limited would you be if you couldn't use 
pointers in your code? Do all D references count as pointers, or 
is it only the T* types? Does Nullable!T count as one of those 
pointers that can't be tracked quickly?


Re: What's going to replace std.stream?

2016-02-06 Thread cy via Digitalmars-d-learn

On Saturday, 6 February 2016 at 08:24:59 UTC, Jakob Ovrum wrote:

foreach(chunk; File("path/to/file").byChunk(16 * 1024))


Ohh, cool so the streaming...ish logic is in std.stdio now. I 
thought that module was only for text output.


Why can't compile time expressions do ___?

2016-02-06 Thread cy via Digitalmars-d-learn
I'm not clear on why you aren't allowed to allocate memory with 
compile time execution, or why access to the filesystem is 
restricted. (Unless you pass -J/ I think?)


Re: Detecting exception unwinding

2016-02-06 Thread cy via Digitalmars-d-learn
On Saturday, 6 February 2016 at 14:25:21 UTC, Ola Fosheim Grøstad 
wrote:

See, even Python supports this. :-)


And D supports the "with" statement in python, in the form of 
"scope()" statements. The D way is slightly less misleading too, 
as


with somethingThatFails() as e:
  print(e)

doesn't make it obvious that neither __enter__ nor __exit__ will 
be called if you raise an exception in the creation of the 
object, or that if you raise an exception in __enter__, then 
__exit__ won't be called.


auto e = somethingThatFails()
scope(failure) cleanup(e);

makes more sense to me, since it's blatantly obvious that the 
construction (and entering) process isn't covered by the cleanup 
routine.


Re: Custom hash table key is const, how to call dtors?

2016-02-06 Thread cy via Digitalmars-d-learn

On Saturday, 6 February 2016 at 03:57:16 UTC, Marco Leise wrote:

No, but they could have dtors because they contain malloc'd 
data. E.g. string literals that don't live on the GC heap.


Character arrays allocated with glibc malloc are immutable? News 
to me...


Re: print function

2016-02-05 Thread cy via Digitalmars-d-learn

On Friday, 5 February 2016 at 12:35:14 UTC, Artur Skawina wrote:
D's std lib implementations are sometimes really awful, but in 
this case it's not actually that bad:


   print("hi","there");

->

   fwrite("hi", 1, 2, 0x7ff68d0cb640) = 
2
   fwrite(" ", 1, 1, 0x7ff68d0cb640)  = 
1
   fwrite("there", 1, 5, 0x7ff68d0cb640)  = 
5
   fwrite("\n", 1, 1, 0x7ff68d0cb640) = 
1


Oh wow, and you thought to actually test it. I was just 
eyeballing the code and running my mouth off. I can't fathom how 
that's possible, because the only thing the write() template does 
is translate each string argument to put(w,arg) where w is a 
LockingTextWriter, and LockingTextWriter.put only outputs a 
string if the sizeof... oh.


Yeah, my bad. Now I see it only puts each character as a string, 
one at a time, if those characters are wide characters or 
multibyte characters. It only does that if C.sizeof!=1 and I was 
confusing .sizeof for .length. So for w"abc" it would put "a\0" 
"b\0" "c\0" three times, I think, but for just "abc" it goes 
straight to fwrite. It's the length of each character in bytes, 
not the length of each string.


utf-8 encoded is still C.sizeof==1 I'm pretty sure. It's only 
when you try to decode the characters or make "ropes" that you 
end up with that iterative expansion of put().


Years ago I had to investigate why phobos showed up in the perf 
profile of a program, when the only used part was some `write` 
call used to print diagnostics. What I saw made me never use or 
look at D's std lib again. Except for meta programing and 
toy/example programs where it doesn't matter.


Maybe you should look again? I thought it was rather elegant, 
except for the bizarre individual-character expansion that I 
mistook for reality. It's not fast, but... very safe. Any D 
process is going to lock the specific area of the file, so that 
when you read a bunch, you're not going to have it change halfway 
through, and two things aren't going to be writing in the same 
place at the same time, at least not within individual write 
calls.


What's going to replace std.stream?

2016-02-05 Thread cy via Digitalmars-d-learn
Let's say I have a socket, and a file, and I want to send the 
contents of that file to the socket. What's the best way to do 
that? Yes I'm aware that in Linux, you can use a combination of a 
pipe and splice(2) to keep all buffers kernel side for that, but 
I was thinking more generally. The traditional C way is to read() 
into a buffer, then write() it out, until the input is exhausted. 
But apparantly in D we're not supposed to do that?


It's just that I tried to use std.stream, and found that the 
whole module had been marked as deprecated some time last year. 
What exactly is going to replace it? Some sort of lazy file 
contents accessor, that can take advantage of zero copy things 
like splice() when hooked together? A source/sink paradigm maybe?


I don't see anything analagous to what std.stream does in 
phobos... has it just not been made public yet?


Re: Template to create a type and instantiate it

2016-02-05 Thread cy via Digitalmars-d-learn

On Saturday, 6 February 2016 at 06:39:27 UTC, Marco Leise wrote:
using the template multiple times with the same arguments will 
always give you the first instance.


Hmm, consider that the argument was a particular line of code 
though, and that's not likely to repeat. I didn't test what would 
happen if you did the same code twice, though...


Re: Custom hash table key is const, how to call dtors?

2016-02-05 Thread cy via Digitalmars-d-learn

On Friday, 5 February 2016 at 22:18:50 UTC, Marco Leise wrote:
But when you remove items from the table you need to call a 
const/immutable dtor that needs to be written for everything 
that can be a hash table key.


You need to write destructors for hash keys? How would you use 
string literals as keys then? Could you provide an example 
maybe...?


Re: Template to create a type and instantiate it

2016-02-05 Thread cy via Digitalmars-d-learn
On Friday, 5 February 2016 at 07:44:29 UTC, Rikki Cattermole 
wrote:

That code is completely wrong anyway.


Well, obviously it's wrong. If I don't know correct code that 
will do what I want, then I can't tell you what I want using 
correct code.



But you could do:

alias Derp = TFoo;
Derp obj;


I wasn't trying to make instances of TFoo. I was trying to make a 
type on the spot every time TFoo is used.


Sort of like std.functional.unaryFun!, which I found since 
looking around for information about it. It looks like the key to 
doing it is using "mixin" inside the template declaration itself. 
Also in realizing that "template" can be treated like its own 
source code for the purpose of mixins.


template Thing(alias code) {
class Thing {
int a, b;
this() {
mixin(code);
}
static Thing instance;
static this() {
instance = new Thing;
}
}
}
import std.stdio: writeln;

mixin Thing!q{
writeln("a ",this.a," b ",this.b);
};

int main() {
writeln("the instance exists... somewhere...");
return 0;
}

You could also say alias Q = Thing!... if accessing Q.instance is 
important.


Re: Detecting exception unwinding

2016-02-05 Thread cy via Digitalmars-d-learn
On Friday, 5 February 2016 at 08:16:05 UTC, Ola Fosheim Grøstad 
wrote:
If you can test for "uncaught_exceptions" you can implement the 
equivalent of scope(failure/success) etc within destructors.


Sorry, years of python programming have made me shy of 
destructors. It just looks a little less "magic" to me if I 
specify the destruction explicitly after creating the object, 
using the "scope(exit)" syntax. "scope(success)" and 
"scope(failure)" have no analogy in destructors as far as I know. 
Destructors just destroy the object, and doing more than that is 
risking weird edge conditions.


But again, if you already have your elaborate destructor, you can 
set "o.fail = true" in a "scope(failure)" statement, and the 
destructor just has to check this.fail for how it's being 
destroyed..


Re: Detecting exception unwinding

2016-02-04 Thread cy via Digitalmars-d-learn
On Wednesday, 3 February 2016 at 11:09:00 UTC, Ola Fosheim 
Grøstad wrote:
Is there some reliable way to detect that a destructor is 
called because of exception unwinding?


I basically want to change behaviour within a destructor based 
on whether the destructor is called as a result of a regular or 
an exceptional situation.


E.g. commit changes to a database on regular destruction, or 
inhibit logging during exception unwinding.


I think you might be talking about two very different concepts 
here. Unwinding only happens within the context of a certain 
scope. That's where it gets the backtrace from. If you construct 
an object, then save it somewhere globally, then return from the 
function, then go back into the event loop, then whatever... you 
no longer have your original scope. There can be no exceptional 
situation, nor can there be "regular destruction" because the 
scope has already unwound. Saving your object globally keeps it 
from being destructed, and you might use reference counting in 
that case I guess, but ultimately, when an exception occurs, your 
object will have nothing to do with it at all.


That might be your situation, in which case you simply do this:

bool fail = false;
...
class Foo {
...
  ~this() {
if(!fail) writeln(shakespeare);
...
  }
...
}

int main() {
  scope(failure) fail = true;
  ...
}

When your program exits due to an uncaught exception, it can't 
unwind higher than main, so "scope(failure)" for main will apply 
to all uncaught exceptions that kill the program.  Any globally 
stored variables destructed after that will see fail as being 
true.


The other situation is easier, and probably what you're trying to 
do, so sorry for wasting your time. If you have a local variable 
in a local scope, then when you leave that scope normally, the 
variable will be destroyed, as well as when you fail out of it. 
You want to find out whether you are leaving that scope normally 
in the destructor, and it's not anything about whether the 
program is dying or not, but instead it's making sure your local 
objects with global state clean up before they die.


If that's what you're doing then you do this:

void some_routine() {
  ...
  Foo foo;
  scope(failure) foo.fail = true;
  ...proceed normally...
}

When some_routine exits normally, foo has not set fail, and it 
will be destroyed knowing that. When some_routine errors out, 
"scope(failure)" will set the fail on foo, and then when foo is 
destroyed it can do so quietly.


But again, two different situations. If you try to do this:

Foo foo;
void some_routine() {
  scope(failure) foo.fail = true;
  ...no exceptions...
}
void failure_routine() {
  ...
  throw new SomeException();
  ...
}

int main() {
  some_routine();
  failure_routine();
}

...then fail will never be set, since you exited some_routine 
before throwing any exceptions. Thus why you set "scope(failure)" 
on the main function, if you're concerned about globals being 
destructed due to program failure. You set "scope(failure)" on 
the local function when you're concerned about locals complaining 
as they destruct when the function returns from an exceptional 
situation. If you want the former and do the latter, then your 
globals will not see that any exception occurred. If you want the 
latter and do the former, then any local variables will destruct 
long before main reaches "scope(failure)"


YMMV. I haven't tested any of this, and I'm kind of shaky at D 
too.


Template to create a type and instantiate it

2016-02-04 Thread cy via Digitalmars-d-learn
I'm guessing I have to use a "mixin" mixin for this, but... 
there's no way to do something like this is there?


template TFoo(T) {

struct T {
  int a;
  int b;
}

T obj;
}

TFoo!Derp;
Derp bar;

Neither templates, nor mixin templates seem capable of this. Easy 
enough to use mixin, with tokenized string literal format, I 
think. I just hesitate to make opaque string evaluation a thing 
if some more meaningful method exists.


Re: print function

2016-02-04 Thread cy via Digitalmars-d-learn

On Thursday, 4 February 2016 at 15:32:48 UTC, Artur Skawina wrote:

   void print(A...)(A a) {
  foreach (N, ref e; a)
 write(e, N==A.length-1?"\n":" ");
   }



will be unrolled at compile time


Mind if I elaborate on this a bit? If that is unrolled, I 
understand it will unroll into several calls to write, as in 
print("1","2","3") => write("1"," ");write("2"," 
");write("3","\n");


And presumably, write() unrolls its arguments too. Each string 
argument to write() unrolls to a put(). And put("abc") unrolls 
into put("a");put("b");put("c"), each of which that call the C 
routine fwrite with a length 1.


So the above print, if you did print("hi","there") it would become
write("hi"," "); write("there","\n")
which would become
put("hi");put(" ");put("there");put("\n");
which would become
put("h");put("i");put(" 
");put("t");put("h");put("e");put("r");put("e");put("\n");


And then it compiles.

Any literal string you pass to std.stdio.write will be expanded 
into 1 fwrite invocation per character. And 
std.format.formattedWrite is called on aggregate types like 
lists, which stringifies each value, and passes the string to 
put(), resulting in again, 1 fwrite per character.


Why put() doesn't just call fwrite without expanding into 1 
character strings, I have no idea. Something with wide 
characters, I guess? But even then it could use one fwrite for 
normal characters. It's not like

fwrite("a",1,1,stdout);fwrite("b",1,1,stdout);
will fail any less if the output stream dies before "b" than
fwrite("ab",2,1,stdout);

Why put() doesn't call the C "fputc" function for 1 character 
strings, I *really* have no idea.


Seems to me some fancy code generation producing write("a"," ", 
"b", " ", "c", "\n") or even put("a b c\n") would still expand 
into 1 put() per character, before it finished compiling.


tl;dr speed demons use std.stream.InputStream.read() whenever you 
can, and std.stream.OutputStream.write() its result. Don't expect 
std.stdio to let you have nice things. std.file.write is always 
preferable if you can generate the whole file beforehand.