Re: Problem overloading operator for a struct with an immutable member
On Thursday, 26 March 2015 at 04:57:55 UTC, ketmar wrote: by the way. do you know that you still CAN overload postincrement operation? yes, the code is still here, and it works... somethimes. ;-) Thnaks. Indeed, this works: --- struct S { int i; immutable(Object) o; void opAddAssign(int j) { i += j; } S opPostInc() { ++i; return this; } void opAssign(S other) {} } unittest { S s; ++s; assert(s.i == 1); s++; assert(s.i == 2); } --- Old operator overloading to the rescue !
Re: Problem overloading operator for a struct with an immutable member
On Thu, 26 Mar 2015 09:02:53 +, Nicolas Sicard wrote: > On Thursday, 26 March 2015 at 04:57:55 UTC, ketmar wrote: >> >> by the way. do you know that you still CAN overload postincrement >> operation? yes, the code is still here, and it works... >> somethimes. ;-) > > Thnaks. Indeed, this works: > --- > struct S { > int i; > immutable(Object) o; > > void opAddAssign(int j) { i += j; } > S opPostInc() { ++i; return this; } > void opAssign(S other) {} > } > > unittest { > S s; > ++s; > assert(s.i == 1); > s++; > assert(s.i == 2); > } > --- > > Old operator overloading to the rescue ! just make sure you didn't add `opUnary` there, as it will kill `opPostInc`. it worth nothing that `opPostInc` is not deprecated yet. ;-) signature.asc Description: PGP signature
Re: Problem overloading operator for a struct with an immutable member
On Thu, 26 Mar 2015 09:17:21 +, ketmar wrote: > worth nothing heh. my pet misspelling. signature.asc Description: PGP signature
Re: problems with std.bitmanip.append (bug?)
On Thursday, 26 March 2015 at 02:39:56 UTC, Steven Schveighoffer wrote: An array as an output range writes to the front. You can use std.array.Appender to get appending behavior. I know, it's weird. Alternatively, you can add more bytes to the array, and append to the slice, but that may be ugly/hard to do. -Steve Hmm... isnt that't what the std.bitmanip.write function is for? It even provides an index. I could make an 8 byte buffer and then make a slice with the last 4 bytes and use append there, but it would be rather a hack around something that should have worked. Perhaps I have found a bug. Actually I am not sure because I am not yet familiar with the way to use templates, so there is the possibility that I am using incorrect arguments. If only the documentation and/or test units were more clear...
Re: problems with std.bitmanip.append (bug?)
On Thursday, 26 March 2015 at 10:07:07 UTC, Hugo wrote: If only the documentation and/or test units were more clear... OK, I made a simpler test, using an example from the documentation: void main() { import std.stdio, std.array, std.bitmanip; auto buffer = appender!(const ubyte[])(); buffer.append!ushort(261); assert(buffer.data == [1, 5]); writefln("%s", buffer.data); } It seems to work, so apparently one has to explicitly create a buffer with the appender template. Not terribly useful IMHO. Wouldn't it be possible for the append function to automaticaly change the mode of an already existing buffer? Also, can anyone provide a similar example but using little endian order? If only to contrast differences between modes of invocation...
Re: problems with std.bitmanip.append (bug?)
On 3/26/15 6:07 AM, Hugo wrote: On Thursday, 26 March 2015 at 02:39:56 UTC, Steven Schveighoffer wrote: An array as an output range writes to the front. You can use std.array.Appender to get appending behavior. I know, it's weird. Alternatively, you can add more bytes to the array, and append to the slice, but that may be ugly/hard to do. Hmm... isnt that't what the std.bitmanip.write function is for? It even provides an index. Quite possibly write and append do the same thing for arrays because of the way slices support the output range idiom. Perhaps I have found a bug. Actually I am not sure because I am not yet familiar with the way to use templates, so there is the possibility that I am using incorrect arguments. No, it's not a bug. A slice does not support appending in the way you expect as an output range. Think of a slice/array as a buffer in which to put information, maybe it's a stack buffer. If you output to this buffer, you wouldn't expect it to allocate more memory and append to the end would you? Instead, you'd expect to write data starting at the beginning. If you want append behavior, use std.array.Appender, as is described in the example of std.bitmanip.append. I do, however, think that the term "append" is very misleading. If it were named "putInto", that might have been a less confusing term. -Steve
Re: problems with std.bitmanip.append (bug?)
On Thursday, 26 March 2015 at 12:21:23 UTC, Hugo wrote: On Thursday, 26 March 2015 at 10:07:07 UTC, Hugo wrote: If only the documentation and/or test units were more clear... OK, I made a simpler test, using an example from the documentation: void main() { import std.stdio, std.array, std.bitmanip; auto buffer = appender!(const ubyte[])(); buffer.append!ushort(261); assert(buffer.data == [1, 5]); writefln("%s", buffer.data); } It seems to work, so apparently one has to explicitly create a buffer with the appender template. Not terribly useful IMHO. Wouldn't it be possible for the append function to automaticaly change the mode of an already existing buffer? Also, can anyone provide a similar example but using little endian order? If only to contrast differences between modes of invocation... void main() { import std.stdio, std.array, std.bitmanip, std.system; auto buffer = appender!(const ubyte[])(); buffer.append!(ushort, Endian.littleEndian)(261); assert(buffer.data == [5, 1]); writefln("%s", buffer.data); }
Re: std.typecons.Flag -- public import for API users?
On Tuesday, 24 March 2015 at 16:41:28 UTC, Rene Zwanenburg wrote: Should not be necessary. privately import Flag and make a public alias: module a; import std.typecons : Flag; alias SomeFlag = Flag!"SomeFlag"; SomeFlag.Yes and SomeFlag.No should be usable in other modules without additional imports. Nice idea Rene, thanks!
Re: Looking for a little help with the win32 headers
Thank you guys, I tried the second reply and it works great!
need help with CTFE
I'm compiling the following application (2 d modules) // file c/tool.d module c.tool; struct Tool { string name; auto generate() { version (DOES_NOT_WORK) { import std.traits : hasMember; if (hasMember!(Tool, name)) return `writeln("this is a ` ~ mixin ("this." ~ name ~ "()") ~ `.");`; } else { if (name == "hammer") return `writeln("this is a ` ~ this.hammer() ~ `.");`; } return `writeln("unknown tool ` ~ name ~ `.");`; } auto hammer() { return "screwdriver"; } } string code(string input) { auto tool = Tool(input); return tool.generate(); } - // file x/app.d class Application { void run() { import c.tool; import std.stdio; mixin (code("hammer")); mixin (code("transmogrifier")); } } int main(string[] args) { auto app = new Application(); app.run(); return 0; } When I compile version DOES_NOT_WORK, I get the following error: c/tool.d(13): Error: variable name cannot be read at compile time c/tool.d(13):while looking for match for hasMember!(Tool, name) However, the other version ('else' case) compiles, runs, and outputs (as expected): this is a screwdriver. unknown tool transmogrifier. What's the fundamental difference that makes the variable 'name' readable in one version and unreadable in another? Should the version DOES_NOT_WORK not be compilable in principle or is it only a limitation of the current CTFE implementation in the front-end? Thanks.
Re: Looking for a little help with the win32 headers
No, wait, the first code is even better because it uses the headers so I don't need to declare the API myself and it uses the MAX_COMPUTERNAME_LENGTH define, too, nice!
Re: need help with CTFE
On Thursday, 26 March 2015 at 16:19:17 UTC, Dmitri Makarov wrote: When I compile version DOES_NOT_WORK, I get the following error: c/tool.d(13): Error: variable name cannot be read at compile time c/tool.d(13):while looking for match for hasMember!(Tool, name) However, the other version ('else' case) compiles, runs, and outputs (as expected): this is a screwdriver. unknown tool transmogrifier. What's the fundamental difference that makes the variable 'name' readable in one version and unreadable in another? Should the version DOES_NOT_WORK not be compilable in principle or is it only a limitation of the current CTFE implementation in the front-end? In DOES_NOT_WORK you're trying to pass `name` in a template value parameter. You cannot do that, because `name` is a "dynamic value" but you can only pass a "static value" there. (There may be better terms than dynamic/static value.) You may think: But it all happens in CTFE, so all values are "compile time values" or "static values", aren't they? They aren't. The semantics during CTFE are the same as for run time. `name` is still a dynamic value. If it doesn't fly for run time execution, it doesn't fly in CTFE. To solve the problem at hand, here's one solution that's similar to what you tried: string generate() { import std.traits : isCallable; foreach(memberName; __traits(allMembers, Tool)) { if(memberName == name) { alias M = typeof(mixin("this." ~ memberName)); static if(isCallable!M) { return `writeln("this is a ` ~ mixin("this." ~ memberName ~ "()") ~ `.");`; } } } return `writeln("unknown tool ` ~ name ~ `.");`; } The foreach is (implicitly) a 'static' one, because __traits(allMembers, ...) results in a static/type/expression tuple (I don't know what's the best name to set it apart from other kinds of tuples). That means, `memberName` is a static value. And so it can be used in mixin, whereas `name` cannot be used there.
Re: Looking for a little help with the win32 headers
On Thursday, 26 March 2015 at 16:46:06 UTC, Belly wrote: No, wait, the first code is even better because it uses the headers so I don't need to declare the API myself and it uses the MAX_COMPUTERNAME_LENGTH define, too, nice! Using this will return only the first 15 characters of the computer name, if longer. Please use the unicode version of the function GetComputerNameW instead of the ANSI one (GetComputerNameA), because the second one has a known bug, returning always 0 as required buffer size. import std.stdio; import std.c.windows.windows; wstring getComputerName() { enum ERROR_BUFFER_OVERFLOW = 111; uint size; if (GetComputerNameW(null, &size) == 0 && GetLastError() == ERROR_BUFFER_OVERFLOW) { wchar[] buf = new wchar[size]; if (GetComputerNameW(buf.ptr, &size)) return buf[0 .. size].idup; } return "Unknown"; } int main(string[] argv) { writeln(getComputerName()); getchar(); return 0; }
Re: need help with CTFE
On Thursday, 26 March 2015 at 17:30:40 UTC, anonymous wrote: value parameter. You cannot do that, because `name` is a "dynamic value" but you can only pass a "static value" there. (There may be better terms than dynamic/static value.) Thank you, anonymous. It makes sense. I guess rather than "static/dynamic", I would think of "known/unknown at compile-time". In this case, 'if (name == "hammer")' seems no more static or less dynamic than 'hasMember!(Tool, name)'. Nevertheless, I appreciate your help and will use the solution that you offered.
feature request for dlang.org library preview
So I just noticed, when I click on "source code" button for a function in dlang.org library preview, it brings me to the source code as of that release, but to the file itself (on github). I'd like it to go to the specific line where that function is defined instead. I'm not sure if we need updated output from dmd, or if this is all ddox, so I don't know where to file this feature request. Does one file ddox requests on issues.dlang.org? -Steve
HTTP() from std.net.curl hidden state
Hello! I am using HTTP structure to perform calls to a simple REST API. Like this: class API { HTTP http; this() { http = HTTP(); } void call() { http.url = "some url"; http.method = POST; http.setPostData("data", "type"); http.perform(); } } My issue is that I have to reinitialize http with HTTP() every call(), otherwise some state keeps on adding. For example, headers Content-Type keep on multiplying, and after setting method to DELETE it can not be changed to POST again (request still sends as delete). Reinitializing http seems fine, however I suspect that something is lost (DNS cache, from example). Is there any workaround? Thank you. Example (without reinitialization): 3 subsequent requests with verbose curl, >> lines are what is desired, << received, rest is curl debug output. POST http://localhost:9515/session {"desiredCapabilities":{},"requiredCapabilities":{}} * Hostname was NOT found in DNS cache * Trying 127.0.0.1... * Connected to localhost (127.0.0.1) port 9515 (#0) POST /session HTTP/1.1 User-Agent: Phobos-std.net.curl/2.067 (libcurl/7.35.0) Host: localhost:9515 Accept: */* Content-Type: application/json;charset=UTF-8 Content-Length: 52 * upload completely sent off: 52 out of 52 bytes < HTTP/1.1 200 OK < Content-Length:550 < Content-Type:application/json; charset=utf-8 < Connection:close < * Closing connection 0 << 200 {"sessionId":"d833e91674e2d14d2a81133821ab76fd","status":0,"value":{"acceptSslCerts":true,"applicationCacheEnabled":false,"browserConnectionEnabled":false,"browserName":"chrome","chrome":{"userDataDir":"/tmp/.com.google.Chrome.AlM0Ze"},"cssSelectorsEnabled":true,"databaseEnabled":false,"handlesAlerts":true,"javascriptEnabled":true,"locationContextEnabled":true,"mobileEmulationEnabled":false,"nativeEvents":true,"platform":"Linux","rotatable":false,"takesHeapSnapshot":true,"takesScreenshot":true,"version":"41.0.2272.76","webStorageEnabled":true}} DELETE http://localhost:9515/session/d833e91674e2d14d2a81133821ab76fd * Hostname was found in DNS cache * Trying 127.0.0.1... * Connected to localhost (127.0.0.1) port 9515 (#1) DELETE /session/d833e91674e2d14d2a81133821ab76fd HTTP/1.1 User-Agent: Phobos-std.net.curl/2.067 (libcurl/7.35.0) Host: localhost:9515 Accept: */* Content-Type: application/json;charset=UTF-8 Content-Type: text/plain Content-Length: 0 < HTTP/1.1 200 OK < Content-Length:72 < Content-Type:application/json; charset=utf-8 < Connection:close < * Closing connection 1 << 200 {"sessionId":"d833e91674e2d14d2a81133821ab76fd","status":0,"value":null} POST http://localhost:9515/session {"desiredCapabilities":{},"requiredCapabilities":{}} * Hostname was found in DNS cache * Trying 127.0.0.1... * Connected to localhost (127.0.0.1) port 9515 (#2) DELETE /session HTTP/1.1 User-Agent: Phobos-std.net.curl/2.067 (libcurl/7.35.0) Host: localhost:9515 Accept: */* Content-Type: application/json;charset=UTF-8 Content-Type: text/plain Content-Type: application/json;charset=UTF-8 Content-Length: 52 * upload completely sent off: 52 out of 52 bytes < HTTP/1.1 404 Not Found < Content-Length:24 < Content-Type:text/plain < Connection:close < * Closing connection 2 << 404 unknown command: session
Re: problems with std.bitmanip.append (bug?)
On Thursday, 26 March 2015 at 12:29:03 UTC, John Colvin wrote: On Thursday, 26 March 2015 at 12:21:23 UTC, Hugo wrote: Also, can anyone provide a similar example but using little endian order? If only to contrast differences between modes of invocation... void main() { import std.stdio, std.array, std.bitmanip, std.system; auto buffer = appender!(const ubyte[])(); buffer.append!(ushort, Endian.littleEndian)(261); assert(buffer.data == [5, 1]); writefln("%s", buffer.data); } Thanks, although it puzzles me that one has to move the type inside the parenthesis and the value after them, otherwise it doesn't compile. It looks quite irregular, at least to someone like me, more used to function than templates. :( I wish one could simply append a buffer using the concatenation operator, which would be the obvious choice, but it doesn't seem to work for ubytes...
Re: Looking for a little help with the win32 headers
On Thursday, 26 March 2015 at 17:41:37 UTC, rumbu wrote: On Thursday, 26 March 2015 at 16:46:06 UTC, Belly wrote: No, wait, the first code is even better because it uses the headers so I don't need to declare the API myself and it uses the MAX_COMPUTERNAME_LENGTH define, too, nice! Using this will return only the first 15 characters of the computer name, if longer. Please use the unicode version of the function GetComputerNameW instead of the ANSI one (GetComputerNameA), because the second one has a known bug, returning always 0 as required buffer size. import std.stdio; import std.c.windows.windows; wstring getComputerName() { enum ERROR_BUFFER_OVERFLOW = 111; uint size; if (GetComputerNameW(null, &size) == 0 && GetLastError() == ERROR_BUFFER_OVERFLOW) { wchar[] buf = new wchar[size]; if (GetComputerNameW(buf.ptr, &size)) return buf[0 .. size].idup; } return "Unknown"; } int main(string[] argv) { writeln(getComputerName()); getchar(); return 0; } I changed the code to use GetComputerName, so I guess GetComputerNameA is actually used, right? Anyway it's not really important, I'm just playing around with winAPIs to get a feel of things. I'm making a simple health cheat for a game I've written in FreeBasic! I'm going through a nice D2 tutorial here: http://ddili.org/ders/d.en If anyone reading this can save me some time and help me with this: How to declare a byte pattern, for example to pass to WriteProcessMemory? I guess it's uint[] bytes; How do I set it to 0x12345678 ?
Re: Looking for a little help with the win32 headers
On Friday, 27 March 2015 at 01:27:25 UTC, Belly wrote: If anyone reading this can save me some time and help me with this: How to declare a byte pattern, for example to pass to WriteProcessMemory? I guess it's uint[] bytes; How do I set it to 0x12345678 ? Since WriteProcessMemory accepts a LPCVOID (that is const void*), you can use any type of array (provided that you will take care of endianess): uint[] ints = [0x12345678]; ushort[] shorts = [0x1234, 0x5678]; ubyte[] bytes = [0x12, 0x34, 0x56, 0x78]; WriteProcessMemory(processHandle, address, ints.ptr, ints.length * 4 null); WriteProcessMemory(processHandle, address, shorts.ptr, shorts.length * 2, null); WriteProcessMemory(processHandle, address, bytes.ptr, bytes.length, null);
OT; Donald Knuth on beauty, efficiency, and the programmer as artist
An old essay that may yet be relevant today at a time when intellectual fashion has continued in the direction he was moved to address in his speech. "there is a way to make a big improvement: it is still a pleasure to do routine jobs if we have beautiful things to work with. For example, a person will really enjoy wiping off the dining room table, day after day, if it is a beautifully designed table made from some fine quality hardwood." "Language designers also have an obligation to provide languages that encourage good style, since we all know that style is strongly influenced by the language in which it is expressed. The present surge of interest in structured programming has revealed that none of our existing languages is really ideal for dealing with program and data structure" http://www.paulgraham.com/knuth.html CACM, December 1974 When Communications of the ACM began publication in 1959, the members of ACM'S Editorial Board made the following remark as they described the purposes of ACM'S periodicals [2]: "If computer programming is to become an important part of computer research and development, a transition of programming from an art to a disciplined science must be effected." Such a goal has been a continually recurring theme during the ensuing years; for example, we read in 1970 of the "first steps toward transforming the art of programming into a science" [26]. Meanwhile we have actually succeeded in making our discipline a science, and in a remarkably simple way: merely by deciding to call it "computer science." Implicit in these remarks is the notion that there is something undesirable about an area of human activity that is classified as an "art"; it has to be a Science before it has any real stature. On the other hand, I have been working for more than 12 years on a series of books called "The Art of Computer Programming." People frequently ask me why I picked such a title; and in fact some people apparently don't believe that I really did so, since I've seen at least one bibliographic reference to some books called "The Act of Computer Programming." In this talk I shall try to explain why I think "Art" is the appropriate word. I will discuss what it means for something to be an art, in contrast to being a science; I will try to examine whether arts are good things or bad things; and I will try to show that a proper viewpoint of the subject will help us all to improve the quality of what we are now doing. ... As I was looking up these things about the meanings of "art," I found that authors have been calling for a transition from art to science for at least two centuries. For example, the preface to a textbook on mineralogy, written in 1784, said the following [17]: "Previous to the year 1780, mineralogy, though tolerably understood by many as an Art, could scarce be deemed a Science." According to most dictionaries "science" means knowledge that has been logically arranged and systematized in the form of general "laws." The advantage of science is that it saves us from the need to think things through in each individual case; we can turn our thoughts to higher-level concepts. As John Ruskin wrote in 1853 [32]: "The work of science is to substitute facts for appearances, and demonstrations for impressions." It seems to me that if the authors I studied were writing today, they would agree with the following characterization: Science is knowledge which we understand so well that we can teach it to a computer; and if we don't fully understand something, it is an art to deal with it. Since the notion of an algorithm or a computer program provides us with an extremely useful test for the depth of our knowledge about any given subject, the process of going from an art to a science means that we learn how to automate something. ... From this standpoint it is certainly desirable to make computer programming a science, and we have indeed come a long way in the 15 years since the publication ot the remarks I quoted at the beginning of this talk. Fifteen years ago computer programming was so badly understood that hardly anyone even thought about proving programs correct; we just fiddled with a program until we "knew" it worked. At that time we didn't even know how to express the concept that a program was correct, in any rigorous way. It is only in recent years that we have been learning about the processes of abstraction by which programs are written and understood; and this new knowledge about programming is currently producing great payoffs in practice, even though few programs are actually proved correct with complete rigor, since we are beginning to understand the principles of program structure. ... A scientific approach is generally characterized by the words logical, systematic, impersonal, calm, rational, while an artistic approach is characterized by the words aesthetic, creative, humanitarian, anxious,