D言語 Part34©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
>>197
ありがとうございます。
std.traitsにenumのメンバの配列を作る機能があったんですね。 あ、配列なんだからuniform(0, $)でよかった…。
タプルの配列化?みたいな
他にも関数の引数リストとか、構造体のメンバ変数を
タプルでとれたり、std.traitsは結構楽しい メンバにUDAを付加するだけで
文字列化やシリアライズのメソッドが自動or暗黙生成されるような
いい感じの小技はないかしら static ifと文字列mixinを駆使すればなんでもできそう
コードはくっそ汚くなるけど…というかいくらなんでも汚すぎるので俺がなにか勘違いしてる
class Cls {
@getset(true, true) private string prop;
mixin Prop!(__traits(allMembers, typeof(this)));
}
struct getset {
bool get, set;
this (bool get, bool set) { this.get = get; this.set = set; }
}
mixin template Prop(Members...) {
static if (Members.length) {
mixin("alias Alias = " ~ Members[0] ~ ";");
static if (is(typeof(__traits(getAttributes, Alias)[0])==getset)) {
static if (__traits(getAttributes, Alias)[0].get) {
mixin("auto get_" ~ Members[0] ~ "() { return " ~ Members[0] ~ "; }");
}
static if (__traits(getAttributes, Alias)[0].set) {
mixin("void set_" ~ Members[0] ~ "(" ~ typeof(Alias).stringof ~ " value) { " ~ Members[0] ~ " = value; }");
}
}
mixin Prop!(Members[1..$]);
}
}
void main() {
import std.stdio;
auto cls = new Cls;
cls.set_prop("getset");
writeln(cls.get_prop()); // write "getset"
} これいいなあ
それにしてもstatic foreachが欲しい… >>190
そんなのは日本だけだぞ
海外ではPCとモバイルを使い分けるのが普通 DmInst ver.0.0を公開しました。
コンパイラーのDMCとDMDを簡単にインストールできるプログラムです。
http://katahiromz.web.fc2.com/dminst/ AliasSeq を Alias Equal と読み間違ってしまうマン >>212 がgithub版でもおきるかなー?と思ったんだけど、github版dmdをコンパイル中にエラーが出た。
内容は、「ソースに\r\nが含まれますよ」というもの。
出してるのは、dmd -run src/checkwhitespace.d の部分。
このツールは
1. \r\n がソースに含まれている場合。
2. インデントに\tを使っている場合。
3. 行末に不要な空白文字がある場合。
にエラーを出すようなんだけど、3はともかく、これで行くことに決まったのかな。
smart-tab派なんだけどなー。
あ、github版でも212は再現しました。 おまいらこれはなんでなんだぜ
http://dpaste.dzfl.pl/7fa1a12a8c4a
1. enum をクラスインスタンスで初期化できない→わかる。構造体でラップすると通る→?
2. 1. において、ラップされたクラスが mutable。 This Week in D (英語)
http://arsdnet.net/this-week-in-d/
年初から続いてて筆者はDの入門書出版したりしてる 2.068.2 出てた
ちなみに Win32-COFF が隠しオプション(-m32mscoff)で出来るようになってるので
OMF/optlink がイケてないと思っていた諸兄は試してみるがよいよいよい int arr[x][y][z];
これと同じメモリレイアウトでヒープに確保するにはどうすればいいですか? new int[x*y*z]でよかった。
問題なのはint[]のメモリへのアクセスをint[x][y][z]と同じようにする方法だった。 自己解決。
[0][0][0],[0][0][1]...[0][1][0],[0][1][1]...の順番で並んでるだけだった。 くっそ!
↓Manifest ConstantsのenumとAAのからみがおかしい。
http://dpaste.dzfl.pl/36ab529d6fc5c
↓CTFEで変数を修飾する方のscope class使うと abnormal termination
http://dpaste.dzfl.pl/8ad7e24e5d05 const class A { int a; this(int v) { a = v; } }
このクラスAを値に持つ連想配列を作りたいんだけど、
const(A)[int] hoge = [1: new const A(1)];
hoge[3] = new const A(3); // cannot modify const expression hoge[3]
みたいに、初期化はできても代入ができない。
A[int] hoge = cast(A[int])[1: new const A(1), 2: new const A(2)];
hoge[3] = cast(A)new const A(3);
てなふうにcastしたら回避できたけど、なんか美しくない。
typeof(new const A(1)).stringof == "const(A)" なのがおかしい気がするんだが。 書き込んでから思い出したけど、Rebindableとかできて結構経つしあきらめるしかない気がしてきた。
>>218 optlink死んでまうん? const classとかscope classとかは今もまともに使おうと思えないね
普通のclass内でメンバをconstにするとかじゃないとまともに動く気しない nullではなく、空の連想配列で初期化するにはどうすればよいですか? 空の配列 == null なので無理
ただし空文字列 "" は例外 落とし穴になりがちなので注意 ちょっと良くわかりませんが、D言語は空の配列すら作れないんですか?
不便ですね >>227-230 レスありがとう。やりたかったのはこういうことです。
string[string] buf;
auto buf2 = buf;
buf2["hello"] = "world";
buf.writeln; // > []
これと↓
string[string] buf = ["": ""];
buf.remove("");
auto buf2 = buf;
buf2["hello"] = "world";
buf.writeln; // > ["hello":"world"]
では結果が違うわけだけど、後半の上2行を初期化1行で書きたいな。
という話でした。 結局どういうことなんですか?
Dでは空の配列を作れないんですか?
必ず何か入っていなければダメなんですか?
int[] a; って書けば空の配列になるんじゃないんですか? >>232
int[] a; で空の配列になりますよ。
226のは「連想配列」が俺にはややこしいっていう話です。 >>231
string[string] buf = (a => (a.remove(""), a))(["" : ""]);
ところで、コンマ演算子を廃止しようとか言ってたのは自然消滅したのか? >>234 ありがとうございます。ところでもっと基本的な疑問がわいたのですが、
>>231 の後半での、bufとbuf2の中身がずっと同じであるっていうのは、仕様で保証されてるんでしょうか?
Windows版dmd2.068.2では、1000個値を追加しても同じでした。 >>231
バグっぽい removeしつくしたら null になってるはずなんだけど それに連想配列の内部実装は最近まで大きく書き換えられてて
動作の微妙な違いとかあるのでトリッキーなことは避けるべき >>236-237 そうなんですね。書き換えます。ありがとうございます。 リンクエラー。2.067.1では通ってた。
http://dpaste.dzfl.pl/255495e7489a
1. -m64 で
2. CTFEで実行されるラムダ内で定義されている
3. 配列をメンバに持つ構造体の
4. 配列のconcatを行う ↓CTFEでtoHash/opEqualsが効いてない。
http://dpaste.dzfl.pl/ec40b544f45d
CTFEはまだまだなかなかナヤマシイな! >>237 がらみかしらん。 D言語って、Javaみたいにソースファイル名とクラス名を同じにしてしまうと、
他のソースでクラス名のつもりで記述したものがパッケージ名扱いになってしまうため
Hoge.Hoge のように同じ名前を2回書かないとクラス名と解釈してくれないと思うのですが、
これを1回だけの記述で済ましたい場合、皆さんはどのように解決されているんでしょうか?
ソースファイル名を変えるのもmodule文で別名にするのも、何か違うように感じてしまいます。 モジュール名とファイル名は小文字
クラス名は大文字始まり
それでもカブるようなケースはパッケージを作るからまず困らない >>241 D言語の命名規則に則れば >>242 の言うとおり。
ただ、どうしてもと言うならこんなんはいかがか。
http://dpaste.dzfl.pl/dce8977dacc7
えーと。やっぱ242で。 >>242
なるほと確かにD言語の命名規則からするとモジュール名は小文字でしたね。
でも、どうしても大きなクラスは同名の一ソースにしたいのです‥すみません。
ところでパッケージで気付かせてもらったのですが、この問題って、
クラスのソースらをルート階層に置いているからこそ起きる問題なのですね。
というわけでディレクトリを一つ掘ってパッケージ下に配置することで一応解決しました!
ただ、パッケージ下にあるソースって module パッケージ名.モジュール名 の記述は必ず必要なのでしょうか?
module文の記述が無いとルートパッケージ下として格納されてしまうようで、
module文を普段省略していた身からするとちょっと面倒に感じています。
この辺りの挙動はjavaのpackage文の踏襲かなと思うのですが、
D言語ではパッケージはディレクトリに対応すると書かれているようなので、
module文を省略しても適切なパッケージに配置してくれて良いような?
>>243
おぉ‥改名選択importというやつでしょうか。確かにこれで通りました。
import _Hoge = Hoge : Hoge; という風に変換されるんですね。
import文までコンパイル時生成できるとは、D言語きm‥素晴らしいです。
ただこの書き方ではモジュール名変更リファクタリングの際にIDEが解析しにくい気がするので
(そもそもそこまでお世話してくれるIDEは現存しないようですけれど‥)、
取り敢えずは先のパッケージへの配置法でがんばってみます。
凄いものをありがとうございました。今後の困難の際に参考にします。 Error: template std.algorithm.searching.countUntil cannot deduce function from argument types !()(int[11], int), candidates are:
こういうエラーが出たんですけど、countUntilに静的配列は使えないということでしょうか?
Error: template instance sort!((uint a, uint b)
あと、sortに無名関数を渡したらエラーが出ました。無名関数も使えないのでしょうか? 静的配列に対して popFront() が呼べない(初めて知った!)
だからレンジ系操作に対しては全滅に近い
ソートの方はそれだけじゃ分からんね
無名関数は使い方間違えた時にわかりづらい 静的配列は要素数が変更できないからですか。
Rangeの要件を満たしてないとなると結構不便ですね。
sortはエラーメッセージがこの1行しか出ないんですよね。
シンプルな例でテストしたらコンパイルは通ったんですけど、他のコードが影響してるのかなぁ。 固定長配列の全体のスライスを取って動的配列に見せかければ
ある程度のRange操作だったら固定長配列にもかけられるのでちょっと便利です delegateのcovariane/contravarianceはなくなったんですかね SortedRange!(R, ((a, b) => binaryFun!less(unaryFun!transform(a),
unaryFun!transform(b))))
schwartzSort(alias transform, alias less = "a < b",
SwapStrategy ss = SwapStrategy.unstable, R)(R r)
if (isRandomAccessRange!R && hasLength!R)
{ ... }
こんなの見ても揺らがないのが真のD言語er 真のD言語erはそんなに書いて(書かせて)もらえることに感謝する デバッグ用に関数名を出力したいんですけど、関数名を取得する方法はあるでしょうか?
__FILE__や__LINE__みたいな感じのが欲しいです。 標準入出力をフラッシュするにはどうすればいいですか? 基本的には、DではCの標準ライブラリと同等の関数をほぼそのまま薄いラッパで提供しています dout.flush()ということですか。
writeln()に対応するものはないんでしょうか? >>254
__FUNCTION__ も使える
日本語訳サイトは古すぎるから
英語サイトも必ず併用すべき >>259
関数名の取得もあったのですね。
英語苦手だけど見ないとだめですね。 自作のプログラムを実行すると毎回同じ場所でobject.Error: Access Violationが発生します。
エラーとは関係なさそうな修正(stderr.writeln()を増やしたり減らしたり)をするとエラー発生の場所が変わったり、
InvalidMemoryOperationErrorに変わったりします。
エラーの原因がさっぱり分からないんですけど、どういうことが考えられるでしょうか? GCのある言語でメモリリークとなると、どういうケースがあるのか想像がつかないです。
エラー発生の場所も変わるので謎です。 GCのリーク以外に
確保してない場所に書き込むのもリークって言わない? こマ?初めて聞いたその結び付け
リーク=解放処理漏れ 以外の認識ないわ newする前のクラスのインスタンスの関数を使ってAccess Violationが出たことは過去にありますね。
しかし、今回はちゃんとnewされているし、1回目の呼び出しでエラーが発生してるわけでもないんですよね。
そして>>261で書いたようにstderr.writeln()を追加するだけでエラー発生のタイミングが変わるので難解です。 AVならばぬるぽか RangeErrorか deleteの間違い
-g -debug してないんかいな
InvalidMemoryOperationError
ならばデストラクタの中で何か変なことしてる疑い
デストラクタの中でdeleteとかしちゃダメダメよ〜 似たことなったことあるなあ。なんやったか。
templateとかmixinがらみで依存関係見落としててobjの更新忘れとか。 すみませんReleaseビルドになってました。
DebugビルドにしたらRangeErrorになりました。 char *hoge[] = new char *[N];
scope(exit) free(hoge.ptr);
とするのと
char **hoge = cast(char **)(new char *[N]);
scope(exit) free(hoge);
とするのとでは同じ動作が期待出来ますか?
あとガベコレを期待するなら
scope(exit) free(hoge.ptr);
も
scope(exit) free(hoge);
もどちらも不要ですか? 色々とカオス(感想)
C : malloc/free
C++: new/delete
D : new/[destroy]
GCがあるので解放は不要だが、領域が不要になったことをdestroyで明示してもよい
ただしdestroyで領域が即時解放されるわけでなく、GCが必要に応じてよしなにやる
C++のdeleteと区別するために、destroyになった(想像)
---
auto hoge = new int[][N]; // int型の動的配列をN要素もてる動的配列(二次元配列)
foreach (elem; hoge)
elem = new int[色々]; // ジャグ配列も可能
// 以下は不要(してもよい)
foreach (elem; hoge)
destroy(elem);
destroy(hoge);
---
GCを使わずmalloc/freeすることも一応可能
(今だと、std.experimental.allocatorを使うべき?)
newしたものをfreeすることに保証はないと思う、知らんけど × foreach(elem; hoge)
○ foreach(ref elem; hoge) クラスのstaticメンバ関数で、継承先の型って見られますか?
class Base {
static T[] takusanMake(T)(int n) { //Hogeから呼んでT=Hogeがほしい
T[] ret = new T[n];
foreach (ref e; ret) {
e = new T;
}
// ... Baseのフィールドしかいじらないような設定 ...
return ret;
}
}
class Hoge : Base {
}
void main() {
//Hoge
auto hoge = Hoge.takusanMake(30);
}
内容はともかく、大体こんな感じのことをしたいです
Baseから派生したクラスで定義するとか、ちゃんと!(Hoge)してもいいんですが、
(this T)を見てから何か方法があるような気がしてきて・・・ staticなメンバ関数からは、thisは見えないので
UFCS前提でいっそ外部に出して
===
import std.stdio;
class Base {}
class Hoge : Base {}
class Other {}
T[] takusanMake(T : Base)(lazy T d, int n) {
auto ret = new T[n];
foreach (ref e; ret) {
e = d();
}
return ret;
}
void main() {
auto hoge = (new Hoge).takusanMake(30);
typeid(hoge).writeln;
// Baseに暗黙変換できない型はNG
//auto other = (new Other).takusanMake(30);
}
===
こういうのはどうだろう
(もっといい方法ありそう。。) Hoge という型と Fuga という型があって
Hoge[Fuga] hage;
という連想配列は定義できるみたいなのですが
Any という任意の型があるとして
Any[Any] moge;
みたいな連想配列は作れますか? ちなみに
["A": "B", "C": 3, 4: "E"]
みたいなのを作りたいのです Object[Object] moge = ["A": "B", "C": 3, 4: "E"];
これでだめでした orz import std.variant;
auto moge = [Variant("A"): Variant("B"), Variant("C"): Variant(3), Variant(4): Variant("E")];
とかいうダサい感じのしか思いつかない。 >>277
確かにもう外に出してしまう方がいいかもしれないですね
外に出すことは考えてなかったのでもうちょっと考えてみます >281
ダサくてよければ
Variant[Variant] constructor(T...)(T plist){
Variant[Variant] result;
foreach(ref p; plist) result[new Variant(p.keys[0])] = new Variant(p[p.keys[0]]);
return result;
}
Variant[Variant] moge = constructor(["A": "B"], ["C": 3], [4: "E"]);
試してないけど 引数が1個ずつ別のAAになってる…?
きもちわるすぎる import std.variant;
import std.stdio;
Variant[Variant] makeTable(T...)(T p) {
static assert(T.length%2 == 0);
Variant[Variant] t;
foreach (i, ref v; p) {
static if (i%2 == 0) {
t[Variant(p[i])] = Variant(p[i+1]);
}
}
return t;
}
void main() {
auto t = makeTable(1, 2, "hoge", 123.2);
writeln(t);
} やろうとしてること自体闇魔術臭いしわりと妥当なのかもしれない >>284 と >>286 ってどちらもコンパイル時に
解決された型変換のコードが生成されるのですか?
つまり前者も後者も実行時の速度パフォーマンスは同じですか? >>291
どんなコードが生成されるか知らないのでベンチとって見た結果
http://dpaste.dzfl.pl/85212474e9f0
281: TickDuration(3595337)
284: TickDuration(9347285)
286: TickDuration(4128184)
288: TickDuration(3554533) Dでcomのclientを書こうとして付属のサンプルソースを試したら動作しました
wshサーバーをdispatchしてEcho('hoge')みたいなポップアップを出したいのですが
サンプルをどのように書き直せばよいのですか 途中まで書いたコードです
extern (Windows) HRESULT CLSIDFromProgID(const wchar *, CLSID *);
const string wsh = "WScript.Shell";
interface IWSH : IUnknown {
extern (Windows) int Echo();
}
DWORD dwVer = CoBuildVersion();
HRESULT hr = CoInitialize(null);
hr = CLSIDFromProgID(wsh.toUTF16z(), &clsid);
IWSH pIWSH;
hr = CoCreateInstance(&clsid, null, CLSCTX_ALL, &IID_IUnknown, &pIWSH);
// FAILED(hr)の判定コードは省略していますがここまでは動作しているようです
// pIWSHに値は入っているようですが次の場所でAccessViolationします
pIWSH.Echo();
CoUninitialize();
pIWSH.Echo(); の行をコメントアウトすると何も起きませんが正常に完了します
あと
&IID_IUnknown
のところを
&IID_IDispatch
に書き換えてもだめでした >>294
ちょっとまだよく分かってなくてEcho呼んでも何も起きなかったけど、
PopUp呼べたので参考になりますか?
http://dpaste.dzfl.pl/15f1655e540e >>294
IDLとかタイプライブラリとか見ずに静的バインディングしようとしてる
普通は中間ヘッダを入手するかツールで生成する
C++で一度やったことがないとダメ
ちなみに >>295 は動的バインディング >>294
WScript.Shell に Echo は無いよw ■ このスレッドは過去ログ倉庫に格納されています