Re: How to divide by space keeping words with spaces inside quotes?
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
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
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?
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?
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?
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?
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)
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?
import std.algorithm.searching: startsWith, commonPrefix; if(s1.startsWith(s2)) {...} string prefix = commonPrefix(s1,s2);
Re: How to avoid ctRegex (solved)
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)
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)
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?
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?
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
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?
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?
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" ?
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" ?
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?
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?
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?
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?
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?
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
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
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?
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
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
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?
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?
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
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
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
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?
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?
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?
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.
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.
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?
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`.
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
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
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`.
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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...
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...
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...
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
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?
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
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
I also tried symlinking ../sharedViews into views/shared and importing "shared/common.stuff" but that didn't work either.
setting stringImportPaths in dub.json
"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
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?
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?
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?
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?
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?
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?
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?
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?
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]?
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?
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?
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 ___?
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
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?
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
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?
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
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?
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
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
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
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
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
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.