2026年6月1日月曜日

👓SWIFTでCannot assign to property: 'self' is immutableとはどういう意味ですか?

 Cannot assign to property: 'self' is immutable というエラーメッセージはSwiftで見られるもので、これはオブジェクトのプロパティや自身の値を変更しようとした際に、そのオブジェクトが不変(immutable)であることを示しています。具体的には、以下のような状況でこのエラーが発生することが一般的です:

  1. 構造体のインスタンスが定数として宣言されている場合: Swiftの構造体は値型であり、インスタンスが定数(let で宣言された)として作成された場合、そのプロパティは変更できません。

  2. 関数やメソッド内でのselfの不変性: 値型(例えば構造体)のメソッド内で、self 自体を変更しようとした場合にもこのエラーが発生します。これを回避するためには、メソッドを mutating として宣言する必要があります。

  3. このエラーは、Swiftの値型と参照型の基本的な特性に関連しています。値型のインスタンスは、不変性が保証されている場合にはその状態を変更することができません。これに対し、参照型(例えばクラス)の場合、定数としてインスタンスを宣言しても、そのプロパティを変更することが可能です。

SwiftUIのビューは構造体であるべきで、それはデフォルトで不変であることを意味します。これが私たち自身のコードであれば、値を変更することをSwiftに伝えるためにmutatingを使用してメソッドをマークすることができますが、SwiftUIでは計算されたプロパティを使用するため、それを行うことはできません。
プログラムの実行中にプロパティの値を変更したい場合は、次のように@Stateを使用してマークする必要があります:

https://www.hackingwithswift.com/quick-start/swiftui/how-to-fix-cannot-assign-to-property-self-is-immutable


森毅と話のふら

 森毅の文章には、同じ話を何度も出す良さがある。数学者でありながら、森は数学の専門的な成果だけを語った人ではなかった。教育、学校、老い、仕事、世間、遊びについて、多くのエッセイを書いた。その文章では、「ものぐさ」「ええかげん」「まちがってもよい」といった言葉が繰り返し現れる。

この反復は、単なる使い回しではない。森毅の場合、同じ話題が別の場所で少しずつ角度を変えて出てくる。数学の話として出たものが、教育論にもなり、人生論にもなる。学校の管理を語っていたはずが、いつのまにか人間の余白や失敗の話になる。そこで読者は、新しい主張を読むというより、聞き慣れた噺をもう一度聞く感覚になる。

この点で、森毅の文章は落語に近い。落語では、演目そのものは昔からある。同じ粗筋、同じ人物、同じ場面が繰り返される。それでも、話し手の間、声、脱線、時代の空気によって聞こえ方が変わる。森毅のエッセイも、毎回まったく新しい思想を提出するのではなく、持ちネタを生活の場面に合わせて振り直す。そのため、文章に無理な新奇さがない。

森毅の話の振り方は、読者を驚かせるためのものではない。まず身近な経験から入る。学校での違和感、世間の窮屈さ、勉強のしんどさ、老いの感覚などが置かれる。次に、それを少しだけ数学者らしい距離から眺める。そして最後に、正解を押しつけず、少し肩の力を抜く方向へ持っていく。この順番があるので、文章は奇をてらわずに進む。

森毅の反復には、読者に考え方を定着させる働きがある。一度だけ言われた思想は、標語で終わることがある。しかし、同じ言葉が本をまたいで何度も出てくると、それは著者の癖であり、読者にとっての道具になる。「まちがったっていい」「ものぐさでよい」という言葉は、森毅の中で理論であると同時に、生活の構えでもあった。

だから森毅の文章は、体系的な思想書として読むより、噺の蓄積として読むとよく見える。新しい結論を探すより、同じ話がどの場面で出てくるかを見る。そこに森毅の執筆スタイルがある。数学の厳密さを背景に持ちながら、文章では人を追い詰めない。同じネタを繰り返し、少しずつ世間の固さをゆるめていく。その反復の仕方に、森毅の芸がある。

📏バックトラッキング(逆引き)のテクニック解説

 

バックトラック」という言葉は、1950年代にアメリカの数学者D.H.レーマーによって作られた

〔意見・約束などを〕撤回する
〔来た時と〕同じ道を引き返す

90%以上のプログラミング用語は定義があいまいだ。アパッチヘリから窓、最終的にはおしゃぶり(pacifier)まで登場するこの渡世で、バックトラッキングとは何を提示することばなのか。

バックトラックとは,制約充足問題をはじめとする計算問題のすべて(または一部)の解を求めるための一般的なアルゴリズムで,解の候補を段階的に構築し,その候補が有効な解に完成できないと判断した時点で候補を放棄する(「バックトラック」)ものである

とにかくなにかをやめるんだな、おまえは

バックトラックが適用できる場合は、1回のテストで多くの候補を排除できるため、すべての完全な候補を総当りで列挙するよりもはるかに高速であることが多い。

順番が決まってれば、効率がいい時があるんだな

他の多くのメタヒューリスティックな手法とは異なり、有限の問題に対するすべての解を一定の時間内に見つけることが保証されてる。

バックトラック」という言葉は、1950年代にアメリカの数学者D.H.レーマーによって作られた

バックトラックは、クロスワード、暗算、数独などの制約充足問題を解くための重要なツールとなる

なんか、穴埋め問題的なやつを総当たりでやらなくてすむという

ナップザック問題をはじめとする組み合わせ最適化問題の解析[3]においても,最も便利な手法であることが多い.

試してみてうまくいかなかったならば、別のものを試す

深さ優先探索 - Wikipedia ja.wikipedia.org

深いところまで一旦降りると、

画像3

時を戻そう(バックトラッキング)

めちゃめちゃ簡単なバックトラッキングの例をみつけた。

Recursive Backtracking | Brilliant Math & Science Wiki Backtracking can be thought of as a selective tree/graph trav brilliant.org

ブリリアントさん、ありがとう。

長さNの配列Aには,N! の並び順があるはずです。

画像6

3x2x1で6ね。

def permutation(list, start, end):

   if (start == end):
       print list
   else:
       for i in range(start, end + 1):
           list[start], list[i] = list[i], list[start]  # The swapping
           permutation(list, start + 1, end)
           list[start], list[i] = list[i], list[start]  # Backtracking

permutation([1, 2, 3], 0, 2)  # The first index of a list is zero

これなら読める(泣 いや、ほんとは読めないけど、中身見たら多分分かる。。

と思ったが、こんなに短いが、やってることが意味不明。とりあえず、2箱しかない配列にして、スワップとバックトラッキングの詳細を表示するようにする。

画像7

再帰の仕組みも最小で終わるので、所定の数をスワップしたあともとに戻しているのがわかる。

これがバックトラッキングだー、理由はまだよくわからんが。。。

動きを確認するために、_で内部変数を作って、動きの確認ができるコードを作ってみた。

import copy
_stack=[]
def permutation(list, start, end,count):
   if (start == end):
       print(list)
   else:
       for i in range(start, end + 1):
           _backup=copy.copy(list);
           list[start], list[i] = list[i], list[start]  # The swapping
           _stack.append(_backup[i])
           print("swapped",_backup[start],"->",_backup[i],"then",list,_stack)
           permutation(list, start + 1, end,count)
           _backup=copy.copy(list);
           list[start], list[i] = list[i], list[start]  # Backtracking
           _stack.pop()
           print(" backte",_backup[i],"<-",_backup[start],"then",list,_stack)

permutation(['a', 'b','c'], 0, 2,0)  # The first index of a list is zero

結果はこんな感じで推移する

swapped a -> a then ['a', 'b', 'c'] ['a']
swapped b -> b then ['a', 'b', 'c'] ['a', 'b']
['a', 'b', 'c']
backte b <- b then ['a', 'b', 'c'] ['a']
swapped b -> c then ['a', 'c', 'b'] ['a', 'c']
['a', 'c', 'b']
backte b <- c then ['a', 'b', 'c'] ['a']
backte a <- a then ['a', 'b', 'c'] []
swapped a -> b then ['b', 'a', 'c'] ['b']
swapped a -> a then ['b', 'a', 'c'] ['b', 'a']
['b', 'a', 'c']
backte a <- a then ['b', 'a', 'c'] ['b']
swapped a -> c then ['b', 'c', 'a'] ['b', 'c']
['b', 'c', 'a']
backte a <- c then ['b', 'a', 'c'] ['b']
backte a <- b then ['a', 'b', 'c'] []
swapped a -> c then ['c', 'b', 'a'] ['c']
swapped b -> b then ['c', 'b', 'a'] ['c', 'b']
['c', 'b', 'a']
backte b <- b then ['c', 'b', 'a'] ['c']
swapped b -> a then ['c', 'a', 'b'] ['c', 'a']
['c', 'a', 'b']
backte b <- a then ['c', 'b', 'a'] ['c']
backte a <- c then ['a', 'b', 'c'] []

お分かりいただけただろうか?スワップをバックトラッキングでもどしてるんだが、再帰で戻ったときにやるから慣れてあらめちゃめちゃ処理が追いづらい。いくつか見やすい方法を考えて、スワップごとにスタックに積んで、バックトラッキングでスタックから出すコードを入れて、積んである文字の動きがなんとなくわかるようになった。

さらば、Nクイーン

なんとか分かりやすい例を見つけて、バックトラッキングのなんとなくを理解できるようになった。

非線形パターン(1つのパターン内で同じ変数が複数現れるパターン)に対するパターンマッチをサポートしている。 また、パターンマッチのよるデータの分解方法が複数ある場合でも、パターンマッチのための探索空間を効率よくバックトラッキングする。

https://ja.wikipedia.org/wiki/Egison
Amazon.co.jp: プログラムの構造と実行〈上〉 (COMPUTATION&SOFTWARE SCIENCE) : エーベルソン,H., サスマン,G.J., 文男, 元吉: Japanese Books Amazon.co.jp: プログラムの構造と実行〈上〉 (COMPUTATION&SOFTWARE SCIENC amzn.to
バックトラック バックトラック(バックトラッキング、BackTracking)はPrologでのインタプリタで解を探すときのプロセスのこと www.thothchildren.com