スパムアカウント(物理)
PayPal、死去したユーザーに死去は規約違反だと通告 | スラド IT
https://it.srad.jp/story/18/07/13/2345240/
草
文脈を把握してないけど、 pulseaudio と ALSA 的なノリの何事かが container でも必要とされているっぽい??(わかってない)
This account is not set to public on notestock.
それを言ったら、個人サイトだろうが商業同人問わず出版だろうが演説だろうが、いかなる言論の場においても、完全な匿名でない限りは別の場所から横槍が入るわけで、そんなものは今に始まったものでもないし、この問題について ActivityPub が特筆すべき何かを提供しているわけではないのも、それはそう
ていうか、なのでインターネットで「見せない」って対策は基本的に無駄かも>< 大きいものに守ってもらう(例えばツイッターの鍵アカとか)のではなければ><
公開されたくない話、気持ちはわかるがそりゃ無理よとしか思わないし、「どうしても秘匿したくば自分でそれ用のサービスを持て」としか
少なくとも ActivityPub は Pub するものだし、そうでない使い方ができるにしろ、基本的に秘匿する何事かに使うものではない
目的にあった道具を使ってほしい(し、インターネットや web がどういう道具なのか少しはわかってないと頓珍漢なアイデアしか思い付けないので、多少はそっちにも目を向けてほしい)
同人のクラスタで見かける「同士に届いて欲しいけど、無関係な人から突っ込みを受けたくないのでひっそりしたい」の扱いが難しい。
結局、それは道具や原理よりも「同志判定」「敵判定」あたりの人間的判断基準の話だから……
極論言えば、「自分の同志かを完全に正確に判定する方法」みたいなのが用意できるなら、部分的に開いている閉じた場だって技術的には可能
問題なのは公開非公開の仕組みの部分ではなく、「この人には公開したい/したくない」の判定の部分
これを人間に完全に委託したのが登録型の閉じたグループ管理であって、そっちの方が向いているならそれを使えばいい
そういえば、関数型言語文化圏の人々って「型を!」「型ありきの発想!!」って言うわりに、「自明なら書かなくてもいいよね」って型推論多用しまくる人が多い気がするのすごく謎かも><
や、高階関数とか多用すると型変数ばかりになって大して嬉しくないようなことはあるんでしょうけどね
Rust は関数のパラメータと戻り値について型を指定しなければならない (変数や式では省略できる) ので、その辺り結構バランスが良いと思っている
どちらかというと私は x とか xs とか x'' みたいなめちゃくちゃ短い変数名が苦手ですね
や、高度に抽象化したとき名前に意義を持たせられなくなるというのもわかるんですが、それはまあわかるとして、私の脳がそういうのを解釈して記憶しておけるほど性能良くないから……
This account is not set to public on notestock.
例えば(架空の言語として)
//これは整数になります
let hoge = 1;
みたいな記述でも、なんか「・・・><;」ってなる><;(極端に言うとサフィックス必須とかにしてほしい><;)
たとえば
let url = "https://example.com/"; // ここで文字列
let url = Url::parse(url).expect("Invalid URL"); // ここで Url 型
みたいなシャドーイングしたい場合があって、これもまあ賛否分かれるかもしれないけど、あくまで変数の意味を扱ってロジックを書きたいならこれもアリだと思いますね
あと、シャドーイングをすると、たとえばこの例だと「2回目の束縛以降で、不正でありうる文字列型の URL データにアクセスできなくなる」という利点がある (URL でなく文字列として取り出したければ、明示的にそういう操作を行うべき)
たとえば
let age = read_line();
let age = age.parse::<u32>().expect("Invalid age");
みたいにすれば、あるべき型の age にしかアクセスできなくなるので、 age_str と age_int が共存するよりも望ましいと考えることができる
まあブロックが式を返せることを使って
let age = {
let age_str = read_line();
age_str.parse::<u32>().expect("Invalid age")
};
のようにすることもできるけど(私はこっちの方が好みかな)
ただ、この方式だと lifetime あたりの問題があって、たとえば
let name = read_line(); // 所有権ありの文字列
let name = name.trim(); // 旧 name の一部を borrow しているスライス
みたいなことができない (旧 name の生存期間が新 name の生存期間以上でなければならない) ので、万能ではない
This account is not set to public on notestock.
これはすごくわかるし、同時に、設計思想の合わない言語は(書けるんだけど)とてもとても書きたくないという気持ちがある
授業のチーム開発で Python でサーバ書いてるチームが苦しんでるのを傍目に見ながら Rust でサーバ書いてるマンです
同一スコープ内での同名変数の再宣言とシャドウイング|Rustでは再宣言が可能 https://qiita.com/aimof/items/01911a187d7351c8313c
"別の言語ではどうなるか? その2:再宣言できる言語"
"Haskellでは、再宣言可能です。ちなみにHaskellの変数(と呼ぶのが適切かはわかりませんが)はimmutable(不変)です。"
めっちゃくちゃ変化してるじゃん?><;
あと Rust の shadowing は redeclaration ではないと思います
let foo = 1;
let foo = "foo";
bar(foo);
というのは、実際には
{
let foo = 1;
{
let foo = "foo";
{
bar(foo);
}
}
}
のようなことをやっているわけで、 shadow された変数が消えるわけでもないし破棄されるわけでもないし上書きされるわけでもない、あくまで shadow されて「名前で」参照できなくなるだけ
C でもブロックを明示すれば同じことはできるので、よーするに Rust ではブロックを暗黙に作ってくれるというだけのようなもの (あと Rust ではブロックも式であり値に評価されるので、この解釈とは相性が良い)
ある意味というか(最適化後の実装はさておき、表面的な振舞いは)完全にそうです。変数の破棄も、基本的に宣言の逆順で行われます
さっきのURLの処理みたいなの、オレンジの好みの架空言語ならば・・・><;
ReadOnly StringUTF8 url_string = "example .com";
Url url = new Url( url_string );
url.Check();
//不正な文字列なら例外
bool urlDanepposa = url.IsInvalidURL;
//不正かどうかのプロパティ
bool urlDaijoubupposa = url.IsValidated;
//ポジティブとネガティブもどっちも要るよね!><;
Url 型のオブジェクトが出現したその瞬間から死ぬまで、ずっと Url は URL として valid な値しか持てないでほしい (型を妥当な値の集合として考えれば) ので、 new からの url.Check() で例外を飛ばすのは、ちょっと型の意味が弱すぎるかなぁという気持ちがしますね
理想的には型チェックが通った時点で、表明されていたあらゆる制約が満たされていることを確認したいわけで、「URL として妥当であるか」というのは「Url 型のオブジェクトとして存在できるか」と一致してほしい
C++ も (iostream 辺りは歴史的事情か例外のパフォーマンスの事情かアレな感じだけど)、基本的に「不正な状態のオブジェクトを作らず、 ctor で例外を投げろ」という感じになっているし、「正しいものしか存在できない」という感じの世界を作りたさが感じられる
なんでこんな謎方式にしたいかと言うと、宣言時に例外が出ると後始末がぐちゃってするのが嫌で、それを回避できるならチェックするのは分けたいし、毎回チェックする手間が増えてもって感覚がある><;
そこで、例外でなく Result (Haskell なら Either) などを使うことで、正常値と異常値を値として扱えるようにすることで、コードを整理できるわけです
同時に、戻り値型が Result であることで、「必ずしも構築できるとは限らない」という表明にもなっている
https://doc.rust-lang.org/stable/std/string/struct.String.html#method.from_utf8
たとえばこの String::from_utf8 みたいな感じで
panic が実質そんな感じの挙動だけど、まあ panic は panic するために使うものであって、復帰はできるけどそういう仕組みは常用されるものではない
ある意味null安全に近い話なのかも?><;(オレンジは、内容が不正であることのフラグとして(手抜きで)null許容型を使うこともたまにある><;)
不正な値でありうるか否かというのも、 Result とか Option とかによって型で表現されてほしい
std::sync::Mutex - Rust
https://doc.rust-lang.org/stable/std/sync/struct.Mutex.html#method.lock
たとえば Mutex::lock() なんかちょっと面白いんですが
https://doc.rust-lang.org/stable/std/sync/struct.Mutex.html#method.try_lock
Mutex::try_lock() が panic しないし、こっちの方がいいか
std::sync::PoisonError - Rust
https://doc.rust-lang.org/stable/std/sync/struct.PoisonError.html
mutex を持ったスレッドが解放しないまま死んだ場合、 mutex で管理されている値が不正状態になっている場合があるので、それを表現するために PoisonError<T> でラップされている
PoisonError の中はある種の聖域のようなもので(潜在的に)壊れた値の存在が認められているけど、ここから(壊れているかもしれない)値を取り出して正常な値の世界に持ってくるのはプログラマの責任
This account is not set to public on notestock.
This account is not set to public on notestock.
オレンジの物事の発想が「世の中は全て、機能と状態の集合で出来ている!><」って発想で、その延長で、ある型のものの状態にも「正常である状態」と「正常ではない状態」があるかも><って発想で、物事を考えてるかも・・・><
「正常でない」にも複数種類あるわけで、いわゆる異常系と正常系みたいな話になるけど……
たとえば「文字列を URL にしたい」が失敗したとき出てくるのは「URL にしたかったけどできなかった『文字列』」であるわけで、であればこれは Url 型で表現できなくても文字列型として表現できるわけで、「正しい状態しか表現できない」というのはそういう程度の話です
返す時に例外だしてもよくない?><(もちろんエラーはなるべく早く出したいので、チェックは明示的に(><;)早くやるべきだけど、忘れてたら返す時に最後の砦として的な><)
これって、「潜在的に壊れているかもしれないけどわからない値」を持ち回っているわけで、何が嬉しいのかという話です
「Url 型を持ち回って、いざ大事な場面で URL を得ようとするとエラーになりうる」というのと、
「String 型を持ち回って、いざ大事な場面で Url に変換しようとするとエラーになりうる」というのと、
大差ないはずだし、であれば「Url 型が必ず正しい URL を持っている」ということを表明できる後者の方が型による制約が強くかかっていて望ましいように思われます
あるいは、 Invalid でありうる (get 時にエラーを投げうる)値を事前にチェックして正当性を確認したとして、その正当性が型に現れないのって、型の制約表明が弱くないですか?という
Rust における panic の扱いは、「プログラムが(エラーハンドリングまで含めて)実行されてよい条件が満たされなくなった」という意図の表明であって、ゆえに異常終了するわけですが、「実行されなくてよい条件」はユーザがコードによって明示します
(たとえば、 Option::unwrap() などを使うと、「 None が返ってきたらもはやプログラムが扱う状況の範囲外なので、前提条件が満足されなくなった」ということで panic して落ちる)
オレンジ的にはURLはURLであって(さっきの例に限って言うのであれば)文字列ではなくて、不正な文字列から作られたurlは、urlを作りたかったけど失敗してぶっ壊れたもので、文字列は明示的にrawな文字列として取り出す場合以外では、例えば文字列型にキャスト出来るのであれば、その時にも例外を出してほしいかも><;
1. String → Url
2. Url に対してなんらかの操作 (たとえば path を得るなど)
のどちらでエラーが出るかという話はわかるんですが、 URL として壊れた文字列の扱いについての言及がよくわからない
変換で所有権が移動されない場合は元の値が破棄されないのでいいとして、所有権が移動される場合は、たとえば
String::from_utf8()
https://doc.rust-lang.org/stable/std/string/struct.String.html#method.from_utf8
がバイト列から UTF-8 文字列への変換に失敗したとき
FromUtf8Error
https://doc.rust-lang.org/stable/std/string/struct.FromUtf8Error.html
型の値を返すのですが、これが FromUtf8Error::into_bytes() を持っていて、ここから変換に使おうとしていた元の値を得られます
この場合、
「成功すれば String が得られる、失敗すれば(それ専用の)エラー型の値が得られる」
「エラー型の値はエラーの状況を保持しており、そこから元の Vec<u8> を得られる」
ということになっているわけで、「文字列にしようとしたけど UTF-8 として壊れている文字列」はあくまで文字列ではないし、かつバイト列へは失敗の可能性なく戻すことができるという状況なので、これに特に不都合や駄目さを感じたことはないです
基本的にはURLとして不正な文字列を内部に持つUrlは存在しない方がいいかも>< なので不正ではないかのように扱おうとした瞬間に例外をはいてほしいんけど、
ただし!><;宣言や、コンストラクタを呼ぶ場面だけは例外出されて後始末の流れがぐちゃぐちゃになるのがいやなので、そんな変な事に><;
私は「Url 型の値として存在させる」こと自体が「URL として不正でないものとして扱っている」と見做しているので、その辺りか
あとは「URL として正しいことが既に確約されている」という、特徴というか情報を型に持たせているという意識がある
あと例外のフローについては、それは単に例外の扱いが悪い言語に慣れているのではみたいな気持ちです
Rust の話になってしまうけど、エラーも結局単なる型と値として扱われるので、特になにかフローが滅茶苦茶になったりすることはないです
Recoverable Errors with Result - The Rust Programming Language
https://doc.rust-lang.org/book/second-edition/ch09-02-recoverable-errors-with-result.html
この辺り
Rust ではエラーをその場で処理するにしろ呼び出し元に伝播させるにしろ、それは明示的だし、かつそれ用の簡潔な手段が用意されているので (Result::and_then とか Option::unwrap_or とか)
暗黙であることはよろしくない、みたいな意識が割と強くある(たとえば処理フローであったり制約であったり mutability であったり)
あと明示的であることは必ずしも煩雑であることを意味しないし、古い言語の都合は忘れてくださいという感じです
URLだとあれだけど、URLの型の変数を作ろうとして準備してしまった何らかのリソースを失敗した結果好きな順番(環境上の都合に適した順番)で後始末したいって発想がある><;(小さなもの(?)なら例外の所から逆に破棄していけばなんとかなるけど、そうじゃない何らかのハードウェア上の都合とかがある場合に・・・><)
デフォルトの(スコープ逆順の)破棄の順番でないやりかたで値を破棄したい場合、 drop() すればいいので
あと、その drop 後に値が生き残りうるのであれば、それは Option<T> とかで表明されるべき
「絶対に壊れていない」「壊れているかもしれない」もまた、ドキュメントではなく型の在り方によって明示されるべきという考えで、どうしても「壊れているかもしれない」という状態を持ち回りたいのであれば、
enum MaybeValid<S, T, E> {
Valid(T),
Invalid(E, S),
Unchecked(S),
}
みたいな型を作って、
MaybeValid<String, Url, UrlParseError>
みたいな型の値を持ち回るべきという感じです
ていうかRustとか的発想(?)で言うならば、「なんとか型」と「なんとかが壊れてる型」を作って、後始末に必要なものはどちらにも持たせるってすれば、オレンジの発想に近い?><
たとえば「なんでも goto を使うより while や for や iterator を」とか「なんでも再帰を使うより map や filter や fold を」みたいなのと同じで、高階のものとパラメータを組み合わせることで制約を人間にとってわかりやすく、かつ機械が理解可能な状態で表現するということが可能になります
型でも同じようなことをやってほしくて、「なんでも単一の型を用意してドキュメントで補足するよりも、 Result とか Option とかその他『意味だけを表明する容れ物』を利用して意図する型を作る方がよい、という感じです
そうなったとき、一番基本になる型は「必ず○○である」という制約を表明できる型であって、そういうものを作る。これを組み合わせて制約を弱くすることは簡単だし
https://mastodon.cardina1.red/@lo48576/100372543578692110
意味というか意図か? まあいいや
"url is a possibly-broken-url" はまあ真ですけど、「壊れてるかもしれない○○型」を継承して「○○型」を作るのってどうなのという感じしません?
Option とか Result みたいなコンテナ的なジェネリックな型は「制約を弱める」方向に作用するので、それゆえ基本部品を強い制約で作ろうという感じになります
あれも制約を強める方向にいきますけど、基底型が弱い制約で作られて、そこから派生していろいろ作る感じになるので、「まず最初に表明の弱い型を作ります」という感じになって、うーん
壊れてない型を継承して、壊れてるインタフェースをくっつけた壊れてる型を作れば、「これって壊れてる型?(=壊れてるインタフェース持ってる?)」って型チェックもできるかも・・・><
インターフェースは実装を増やすことにはなるけど状態を増やすことはできないと思うので、「壊れている型を表明するインターフェース」はあまり意味なさそう
むしろ、 possibly broken な型について「これは必ず正しい値を持っていますインターフェース」を用意する方がインターフェースとして正しそう?
std::iter::ExactSizeIterator - Rust
https://doc.rust-lang.org/stable/std/iter/trait.ExactSizeIterator.html
たとえば Rust ではイテレータが長さを見積って (usize, Option<usize>) による範囲で返すことになっている(つまり曖昧、潜在的に不正確)んだけど、「このイテレータ型は何が何でも絶対正しい長さを知っとるんやで!!!」ということを表明するために ExactSizeIterator という trait (実質 interface) を対象イテレータ型に対して実装する
そもそも「もしかして壊れてる○○型」と「壊れてない○○型」を両方作るのって明らかに重複多くて無駄なので、
「○○型」と「もしかして壊れてる表明」だけ用意して、「もしかして壊れてる<○○>」を使うと、新たな型をいちいち名付けたり定義せず使える
名付けず使えると、表明 (「もしかして壊れてる<○○>」の「もしかして壊れてる」部分)がそのまま露出するので素敵になる
型パラメータで渡すのも木構造みたいなもんだし、このくらいのケースであれば継承を使わずとも綺麗に表現できますね
それオレンジの最初の「壊れてるかも」モデルに壊れてるかもインタフェースを標準化して追加したらほぼそれのような・・・><(nullは「壊れてる」ではないけど、null流用で言うならnull許容型っぽさ・・・><)
壊れてるかも許容型?><(null許容なるべくやめようって潮流のなかでは流行らなそう><;)
デフォルト許容だと「制約を追加して値域を小さくしていく」という方式になるんでしょうけど、その制約も実装方法も、元の(たとえば文字列であったり整数であったり)型の中身によるわけで、あまり統一的には実現できなそう
で、デフォルト拒否で「拒否する値を追加していく」という方式だと、追加される値自体は enum の variant であったり既存の型で表明可能なわけで、しかも多相型を使えば「値を(元の型の値の集合に)追加する」というのは元の型の表現や内容に全く依存せず実現可能である
典型的には「Option<Option<T>>」をデフォルト null 許容でどう表明するのか、というような話がありまう
まあ Option<Option<T>> はべつに Unspecified / ExplicitNull / ExplicitValue のような variant で enum 作ってもいいんですが……
たとえば
enum ConfigEntry<T> { Unspecified, ExplicitNull, ExplicitValue(T) }
から Unspecified を取り除くには、 ConfigEntry の定義についての特別な知識が要求されるわけで、「デフォルトが null 許容型で、特殊な仕組みや記述で null を取り除く」というのは、本質的にはそういった不自然な処理をやっているのではと思うわけです(すべての型が潜在的に Option<T> のような構造を持っているという特殊な状況だから不自然に見えないだけで)
で、たとえば Java の boxing あたりの話だとこの「すべての型が潜在的に Option<T> という構造を持っている」の仮定が破れるので、ハイ滅茶苦茶、と
そういえば、なんでmathって名前がついてるような数学な標準ライブラリ、どの言語のでもほとんど(?)、maxとminはあっても、最大値と最小値を両方指定してその範囲にカットする(?)って無いっぽいんだろう?><
特にGUIでは使う場面が結構あると思うんだけど・・・><
clamp - OpenGL 4 Reference Pages
https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/clamp.xhtml
GLSL にはある(一般の言語ではないけどw)
まあ min(upper, max(lower, v)) ってちょっと考えないと逆に書いてしまうので、欲しいといえば欲しいような
どうなんだろう、 min / max よりも条件演算子とかで書けという天の意思だったりするのだろうか (GLSL とかだと条件分岐は致命的なので clamp があるのはわかる)
This account is not set to public on notestock.
This account is not set to public on notestock.
This account is not set to public on notestock.
This account is not set to public on notestock.