2022-02-23 VBA 配列のスライスはどうあるべきか

1
ほえほえ@スプシマン @hoehoe1234

VBAの配列のスライス、抽象化がむずかしいね。下限と、便利に使うための補数記法の両方で2つの選択肢ががでちゃう。いろいろ検討したけど、共通化のためにはどれかに決め打ちは出来ないという結論。それをやっちゃうと使うほうが常に変換を要求されるから。

2022-02-22 23:53:17
ほえほえ@スプシマン @hoehoe1234

start=2, end = 3, setp = 1 と合った時に要素がa, b, c, d, e, f の場合、どう表すかというのが記法の問題。 便利に使うためにはstart、endはマイナス値でも指定できなければいけない(例えば最後の要素は-1とか)。

2022-02-22 23:56:34
ほえほえ@スプシマン @hoehoe1234

なんにしろ、いい案がないかな・・・。

2022-02-23 00:01:19
ほえほえ@スプシマン @hoehoe1234

@toshi81350036 ですね。というか、マイナスが指定出来なければスライスはあまり意味がないのです。これも1系、0系があって ①0系 最後の要素が-1、最初の要素が-n ②1系 最後の要素が0、最初の要素がn となるんですね(このようにするとインデックスがきれいにつながります)。

2022-02-23 00:03:54
ほえほえ@スプシマン @hoehoe1234

@toshi81350036 結局、分けなきゃわかりにくくなってしまうという。案はあるのですが・・・。

2022-02-23 00:05:45
ほえほえ@スプシマン @hoehoe1234

最後の要素を-1で指定する手法は、 下限がlb、要素数がm、インデックスがiのときに iのマイナス表記=i-(lb+m)となり、任意のlbで成立するんだけど下限が1などのコレクションは最後の要素がゼロのほうがわかりやすくて、これは下限を基準に考えているので任意のlbでは成り立たずちょっと

2022-02-23 01:13:59
ほえほえ@スプシマン @hoehoe1234

使いづらい。ということは基準となるマイナス記法はやはり最後の要素を-1にせざるを得ない。となると 最初の要素が ①lb=0 neg = i - 4 ②lb=1 neg = i -4 -1 となり、やはり下限分だけずれる。

2022-02-23 01:18:31
ほえほえ@スプシマン @hoehoe1234

常に neg = i - m が成り立ってほしいのだが下限が1だと1つ、2だと2つずれる。ここにlbを導入して neg = i - m - lb とすれば常に成り立つのだがやはりこれしかないのか?

2022-02-23 01:23:16
ほえほえ@スプシマン @hoehoe1234

もともとはスライスの話し。 start = x, end = y, setp = z、要素数をm、下限をlbとするとx、yのマイナス表記は neg = i - m - lb となるということ。下限1のときに最後の要素を0にするとかっこいいのだがこれは諦めるしかなさそう。

2022-02-23 01:27:14
ほえほえ@スプシマン @hoehoe1234

これでマイナス表記の問題は解決できた。次はまたもどってSlice(3,5)の3,5の意味。これまでの検討から絶対座標(下限による補正なし)が正しそうだが3つめから5つ目との解釈で使う場合も多い。

2022-02-23 01:34:56
ほえほえ@スプシマン @hoehoe1234

ここでさらに下限1問題を持ち込むとややこしいので、先ほどと同じくこの検討は後にする。下限0で下限調整するのでであれば指定された数字からlbを引けば良い。そしてこの場合も先程のneg = i - m - lbでよい。

2022-02-23 01:40:46
ほえほえ@スプシマン @hoehoe1234

マイナス表記(neg)を ①neg = i - m - lb(それぞれでインデックス、要素数、下限) と定義したので、Slice(a_start, a_end, a_setp) のa_startとa_endは絶対座標軸となるので「何個目」は使ってはいけなくて、下限を考慮しない「何番目」になる。下限を考慮した何番目だとすると①式の「-lb」の部分を

2022-02-23 01:47:28
ほえほえ@スプシマン @hoehoe1234

取り除かなければいけない。この場合の、たとえばa_startはa_start - lbとなるのでインデックスゼロに相対化されているので相対化されたlb(すなわちゼロ)を引くとすれば①式はそのままでよい。

2022-02-23 01:49:10
ほえほえ@スプシマン @hoehoe1234

しかし、この場合に1相対は存在するのだろうか?インデックスはオフセット(差分)なので「差分が1」というのはあまりうまく機能しそうにない。かつ、VBAに関して言えば、呼び出し側が配列の下限、上限がわかるのでやはり相対指定は不用そうにみえるが、あえて作れば

2022-02-23 01:53:30
ほえほえ@スプシマン @hoehoe1234

ASlice(Absolute Slice)とRSlice(Relative Slice)という別のスライスになるだろう。引数で分けるより関数名でわけるほうがわかりやすいケースだと思う。もちろん引数にしてSlice(開始、終了、ステップ、絶対/相対)としてもよいかなと思う。

2022-02-23 01:56:23
ほえほえ@スプシマン @hoehoe1234

いままで2つの軸、4つのパターンがマイナス記法を整理することで2つのパターンにまで集約できた。1をベースとする記法はインデックスと相性が悪いので検討した結果、捨てた。最後の「相対/絶対」は消せないのでoptionalとし、既定値を絶対にするような対策がよいだろう。

2022-02-23 01:57:55
ほえほえ@スプシマン @hoehoe1234

配列のスライス指定のまとめ ①相対/絶対区分は残す。既定値は絶対 ②マイナス記法の定義は、neg = i - m - lbとする。 ③下限1の特殊記法は(便利そうだが)サポートしない というところに落ち着きそうですね。

2022-02-23 02:02:21
ほえほえ@スプシマン @hoehoe1234

ライブラリを書くときには、よくこのような問題に遭遇します。設計はトレードオフなので常によい解答があるとは限りませんが、このように検討を重ねないと「くみあわせられない」んです。これがライブラリが難しく、また、面白いところでもあります。

2022-02-23 02:03:29