immutableな静的配列の初期化


投稿ツリー



前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 .2 .3 | 投稿日時 2011/9/19 3:42
tama  一人前   投稿数: 111
今書いてるライブラリで,ホスト名の一部を保存しておきたいと思っています,それはプログラム通してimmutableなので一回の初期化でいいかとshared static thisで初期化しようとしたら出来ませんでした,これってどうやったら出来るんでしょう?

#code(d){{{
struct Hoge
{
immutable static ubyte[4] name;

shared static this()
{
name = [1, 2, 3, 4]; // Error: slice name[] is not mutable
}
}
}}}

今は仕方なくimmutable外して__gsharedにしてるんですが,負けた気がします.int[int]なら丸ごと代入でちゃんと動くので,slice扱いになっているのが問題?
投票数:19 平均点:2.11
返信する
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2011/9/19 9:24
9rnsr  新米   投稿数: 7
静的配列の代入(初期化も含む)は、現状左辺をsliceに、右辺を「ヒープに確保される配列リテラル」に変換され、結果スライス要素の代入として実行されます。

またコンストラクタ(this()/static this()/shared static this())での初期化は、name[0]のような間接的な参照に現状対応していません(dmdの検出アルゴリズムの問題)。

以上2点から、現状ではimmutableな静的配列はコンストラクタでの初期化はできません。
投票数:21 平均点:4.76
返信する
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2011/9/19 23:39
SHOO  管理人   投稿数: 658
それは仕様かもしれません。

The initializer for a non-local immutable declaration must be evaluatable at compile time
(非ローカルな immutable 宣言の初期化子はコンパイル時評価可能でなければなりません)

また、 shared static this() でimmutableなデータを初期化出来るとは一言も述べられていません。(sharedなグローバルデータの初期化のための使用が意図されています。 とは書いてありますが、immutableはsharedではありません。)


ただ、これ、仕様がバグってんじゃねーのとは思います。
投票数:21 平均点:5.24
返信する
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2011/9/20 1:01
9rnsr  新米   投稿数: 7
一応補足しておくと、自分が述べた「出来ない理由」は現状のdmdの実装からくるもので、仕様からの制限についてはなにも言及していません。

> The initializer for a non-local immutable declaration must be evaluatable at compile time
> (非ローカルな immutable 宣言の初期化子はコンパイル時評価可能でなければなりません)

これはinitializerを指定する場合の要件で、initializerなしの場合(つまりコンストラクタでの初期化を行う場合)は当てはまらないと思います。

> また、 shared static this() でimmutableなデータを初期化出来るとは一言も述べられていません。

これは現状の実装の穴かもしれません。immutableなグローバル変数はstatic this()とshared static this()の両方で初期化可能ですが、本来はshared static thisのみが初期化可能であるべきかもしれません。

immutable int x;
static this() { x = 10; } // コンパイルエラーになるべき?
shared static this() { x = 20; }
import std.stdio;
void main() { writeln(x); }

また型の上でもis(immutable(int) : shared(const(int)))なので、immutableな値はsharedでもあると考えたほうが自然だと思います。
投票数:15 平均点:6.00
返信する
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 .2 | 投稿日時 2011/9/20 1:45
SHOO  管理人   投稿数: 658
>これはinitializerを指定する場合の要件で、initializerなしの場合(つまりコンストラクタでの初期化を行う場合)は当てはまらないと思います。

それについても一応気づいてはいましたが、初期化を初期化子で行うか、コンストラクタで行うかはあまり重要ではなく、データをROMに置くかRAMに置くかってなあたりが違うのかなと思いました。

+ 「非ローカルなimmutableなデータはROMに置かれる」が真であれば、ランタイムでの初期化はできません。
+ 「非ローカルなimmutableなデータは、初期化子で初期化されるか静的コンストラクタで初期化されるかで置かれる場所がROMとRAMで可変」だとすると、妥当といえば妥当かもしれませんが、なんかもやっとします。
+ 「非ローカルなimmutableなデータはRAMに置かれる」であればランタイムの初期化を行うことができます。つまり、静的コンストラクタで初期化しても問題ないはずです。

現状おそらく2番か3番あたりなのかなと勝手に想像していますが、仕様としては1番でも問題ないように書かれているのかなと思いまして。
実際にはimmutableなデータがどこに置かれようが、変更することは未定義動作なので、意識しなくてもいいところなのかなとは思いますが。
(なお、ただのstaticなデータも初期化子だとコンパイル時に値が決定、動的には静的コンストラクタでできるよと言っていますので、ROMとかRAMはあまり関係ないかも。)

> また型の上でもis(immutable(int) : shared(const(int)))なので、immutableな値はsharedでもあると考えたほうが自然だと思います。

これも当然わかってはいますが、だとすると仕様の曖昧な部分なのかなと思います。
仕様をそのまま言葉通りに捉えると、静的コンストラクタでは(通常のmutableな型と)shared型の変数のみ初期化でき、const(shared(T))型の変数やimmutable型の変数、const型の変数は初期化できない、とも見ることができます。(要するに、静的コンストラクタは型システムを無視して代入可能な特殊な関数ではない、とも言えます。((いや、でもどこぞでconstな値にもコンストラクタなら代入できるって話があったような…どこにそんなような話があったっけ)))

仕様の文言が、意図してこうなっているのか、意図せずこうなってしまっているのかよくわかりませんが、どちらにしろ曖昧なので記載を改善するべきじゃないかなと思います。
投票数:28 平均点:3.93
返信する
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2011/9/20 2:07
9rnsr  新米   投稿数: 7
Initializerがコンパイル時に決定する値を要求するのは、C/C++でグローバル変数の初期化子として関数呼び出しを使えたことに対して、それを行えないようにするための記述ではないでしょうか。
(モジュール間の初期化順序依存性を、モジュールコンストラクタの呼び出し順序のみで考えられるようにするため)

確かに仕様の曖昧さはあるかもしれません。ここ1年ぐらいは根本的な仕様のdocumentはあんまり改定されていないようですし。
投票数:73 平均点:1.23
返信する
前の投稿 - 次の投稿 | 親投稿 - | 投稿日時 2011/9/20 21:29
tama  一人前   投稿数: 111
なるほど.実装ベースで現状出来ないというのが分かったので,とりあえず今のままで行きたいと思います.まぁBSONの実装であまり拘る気はないので…

有り難うございました.
投票数:52 平均点:1.15
返信する
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2011/9/20 21:33
tama  一人前   投稿数: 111
> ROM

これって確定してたんでしたっけ?immutableなデータはROMに置ける可能性がある,って感じだと仕様見てて思ったんですが.なので2 or 3が今のdmdのケースかなっと勝手に思ってました.

> immutable

グローバルなimmutableはsharedと同等の扱いな気がするので,確かに記述を考慮すると曖昧な所ですねぇ.チケット切ってみるか…
投票数:15 平均点:3.33
返信する
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2011/9/21 18:00
KU6  新米   投稿数: 5
あたしには難しいことはよくわからんのですが、

immutable static ubyte[4] name = [1, 2, 3, 4];

って書いたらいいのではないですか?
投票数:23 平均点:4.78
返信する
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2011/9/22 22:13
SHOO  管理人   投稿数: 658
非ローカルでimmutableな静的配列を、ランタイムで決定する値で、一度だけ初期化したいということかと。
投票数:13 平均点:4.62
返信する

このトピックに投稿する

題名
ゲスト名
投稿本文

  条件検索へ


メインメニュー

ログイン

ユーザー名:


パスワード:





パスワード紛失  |新規登録

Menu