今回実装する「型推論やりすぎ足し算」をする関数はこちらです。
既出だったらごめんなさい。
(画像が読み込めない時用のコード)1
2
3// 実装省略
declare function add<T extends number, U extends number>(a: T, b: U): Add<T, U>;
const a = add(12, 34); // testの型が46になる
a
の型が 46
になり、型レベルでも足し算をして、その結果を返します。Add<T, U>
という型は用意されていないので、これを工夫して作ります。
TypeScriptには、リテラル型というのがあり、 "hello"
や 10
、 true
などの値も型となりえます。
このようにして、型レベルでも足し算を行うのが、この「やりすぎ」関数となっています。
ちなみに、普通にジェネリクスを使って実装しても、返り値は number
となってしまいます。1
2
3
4function add2<T extends number, U extends number>(a: T, b: U) {
return a + b;
}
const b = add2(12, 34); // 型はnumber
この a + b
という演算が返す型はリテラル型ではなく number
にされてしまうのですね。
TypeScript 4.2.3
型レベルプログラミングは、TypeScriptのバージョンの違いをもろに受けるので、気を付けてください。
まず、型 Add<T, U>
の実装ですが、ここでは簡単に載せます。
1 | type Repeat<T extends number, R extends any[] = []> = R["length"] extends T ? R : Repeat<T, [any, ...R]>; |
Repeatで任意長(ただし再帰制限のため45程度まで)のTupleを作って、それを用いて足し算します。Tupleの長さが数値リテラル型で返ってくることから、それを足し算結果とします。
詳しくは別の記事で説明したので、そちらをご覧ください。
参考はいつもお世話になっているこのサイトのページです。
https://kgtkr.net/blog/2020/09/02/typescript-disable-recursion-limit
なお、再帰制限を回避してもっと大きな数まで扱いたい場合は、 Multiple<1, ...>
を用いる手があります。内部的に文字列操作を行っているのです。この実装はややこしく、ちょっとテーマとそれるので、先ほどの記事を参照してください。
後は、これを関数の定義に含めれば完成です。
1 | declare function add<T extends number, U extends number>(a: T, b: U): Add<T, U>; |
T,U
は実は引数に応じてリテラル型に推論してくれるみたいです。助かった。
実装を含める場合は、次のようにします。
a + b
は number
型となってしまうので、 as any as
が必要です。
1 | function add<T extends number, U extends number>(a: T, b: U): Add<T, U> { |
型レベルプログラミングが、実際のプログラミングにも役に立ってくるともっと楽しいですね。
この関数の使いどころがあるかどうかはわかりませんがw
今回のプログラムは、こちらで試すことができます。
]]>変な型を作るのは楽しいですよね。
というわけで、今回は次のような型(Add<T, U>
型、 Minus<T, U>
型、 Multiple<T, U>
型)を実装しようと思います。
1 | type AddTest = Add<3, 5>; // 8 |
さらに、より大きな数にも対応できるために工夫をします。
(大きな数には再帰制限が働きやすいので、工夫が必要なのです。後述します)
最終的には、次くらいの大きさの演算でも行けるようにします。1
type MultipleTest2 = Multiple<20, 100>; // 2000
実装にはタプル型を用います。
まず、型レベルプログラミングでよく扱われるタプル型について少し書きます。
型レベルプログラミングでは、 0
や 1
、 2
などのリテラル型を、 []
や [any]
、 [any, any]
のように、その長さを持ったタプル型に変換して処理することが多いです。
これはなぜかというと、タプルにおいて、演算をしていくうえで不可欠な操作が可能だからです。
この「不可欠な操作」は大きく次の3つになると思います。
1 | // 操作1 |
すなわち、型プログラミングにおいて、要素の追加(操作1)と、一部取り出し(操作2)があり、
そして実用的な表現に戻す手法として、タプル長をリテラル型として取得する(操作3)が存在するのです。
Haskell などでの関数型プログラミングでは、ペアノの公理的に自然数を次のように定義し、演算を作っていくのが自然でしょう。
1 | Zero, Next<Zero>, Next<Next<Zero>>, ... |
ですが、TypeScriptでは 再帰回数の制限が厳しく 、あまり値の定義に再帰を使いたくないのです。
また、既に演算が一部定義されていて、さらに操作3により実用的な表現に落とし込めるタプル型を上回るメリットが、このような再帰的な自然数定義にはありません。
何だかんだタプル型が強いので、これを使っていきます。
このサイトを参考に、 Repeat
型を用います。
(ここに書かれているbrainf*ckインタプリタもなかなか気になっちゃいますね)
このサイトはマジで凄くて、型プログラミングをするうえで大事なヒントが沢山載っています。
眺めているだけでも楽しい。このブログもこういう風にしていきたいですね。
というわけで、上のサイトを参考に Repeat
型を実装します。
ここはそのままです。
1 | type Repeat<T, N extends number, R extends any[] = []> = R["length"] extends N |
型プログラミングはかなり可読性が低いですが、このくらいなら分かりやすいですね。
再帰を利用して、所定の長さになるまでタプル型を伸ばしています。
これを用いて数値を表したいので、分かりやすくするため、エイリアスを用意しましょう。
1 | type ToTupleNum<T extends number> = Repeat<any, T>; |
こうすると、 toTupleNum<4>
は [any, any, any, any]
型になります。
ここは簡単です。というかタプル型がやはり強すぎる。
1 | type TupleNum = any[]; |
こうすると、 ToNumber<TupleNum<4>>
は 4
(リテラル型)になります。ToNumber
は関数のように機能する型です。対して TupleNum<T>
は変数のように機能しますね。意味論的には、TypeScript の型には色んな種類があるようです。
もう簡単ですね。
1 | type _Add<T extends TupleNum, U extends TupleNum> = [...T, ...U]; |
単純にextractしてあげればよいです。
これで足し算が実装できます。1
type testAdd = Add<5, 8>; // 13
引き算は色々実装方法があると思います。ここでは最も楽そうな方法を書きます。
1 | type _Minus<T extends TupleNum, U extends TupleNum> = T extends [...U, ...infer X] ? X : never; |
これで引き算が実装できます。1
type testMinus = Minus<10, 8>; // 2
ちなみに、負の数は定義していないので、 Minus<1, 2>
のようにすると死にます。
足し算と引き算は出オチでしたね。...T
と infer
を用いて、簡単に足し算と引き算を定義することができました。
問題は掛け算です。
最も計算理論的に思いつきやすいのは、やはり再帰による定義でしょう。
$$
Multiple(a, b)=
\begin{cases}
Multiple(a, b-1)+b & (b>1) \\
a & (b=1)
\end{cases}
$$
ただし、$a\neq 0,b\neq 0$としています。(実際の実装では0の時を考慮しています)
1 | type _Multiple<T extends TupleNum, U extends TupleNum> = { |
確かにこれでも行けます。ですが、先ほども書きましたが、TypeScriptは再帰回数に厳しい。
この計算では、僕の環境では高々×23くらいまでしか出来ませんでした。
そこで応急的な改善。こうしたら確かに×40くらいまではいけました。
$$
Multiple(a, b)=
\begin{cases}
Multiple(a, b-2)+2\times b & (b>1) \\
a & (b=1) \\
0 & (b=0)
\end{cases}
$$
ただし、$a\neq 0$としています。(実際の実装では0の時を考慮しています)
$2\times b$ の $\times$ は$Multiple(a,b)$ とは区別しています。これは実装が異なるからです。
$2\times b$ は、TypeScriptでは [...T, ...T]
で実装しています。
1 | type _Multiple<T extends TupleNum, U extends TupleNum> = { |
確かに、これはやればやるほど確かに計算限界は上がります。
今はステップ数を2にしていますが、これを3,4,5,…という風にしていけば、線形に再帰数は減少するでしょう。
ですが、根本的解決にはなりませんよね。そこで、次のような方式を取りました。
まずはコードを見てください。
1 | type DigitsStr = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"; |
最近追加された Template Literal Types を用いています。
こちらの記事をやや参考にしました。
やっていることは、筆算です。
$$
12\times 345=12\times 5+(12\times 34)\times 10 \\
=12\times 5+(12\times 4 + (12\times 3)\times 10)\times 10
$$
一般化すると、次のようになります。
$$
Multiple(a, b)=
\begin{cases}
a\times last(b)+Multiple(a, otherthanlast(b))\times 10 & (b\geq 10) \\
a\times b & (otherwise)
\end{cases}
$$
ただし、$a\neq 0$としています。(実際の実装では0の時を考慮しています)
$last(a)$は文字としてのaの最後の文字を取得し、それを数値にしています。
TypeScriptでも Last
型として定義しています。1
type testLast = Last<"12345"> // "5"
$otherthanlast(a)$は文字としてのaの最後の文字以外を取得し、それを数値にしています。
TypeScriptでも OtherThanLast
型として定義しています。1
type testOtherThanLast = OtherThanLast<"12345"> // "1234"
$a\times b$は$Multiple(a, b)$とは分けています。$\times$のほうは[...T, ...T]
のように、TypeScriptの機能を利用しています。
これで、掛ける数がとても大きくても掛け算ができるようになりました。めでたし。
1 | type testMultipleBig = Multiple<2, 4999>; // 9998 |
どうやら、今度はタプルの長さの最大に引っかかるようで、10000以上の長さにタプルを作れず、
結果が10000を超えてしまう場合は計算できなくなってしまいます。
一難去ってまた一難。これはまた、データ形式を工夫するなどして、今度対処しましょう。
先ほど、ToTupleNum
ではRepeatを用いていたので、再帰制限のためせいぜい45くらいまでの数しかTupleにできませんでしたが、
このMultipleを用いれば、実はもっと大きな数が作れるようになります。
1 | type SuperToTupleNum<T extends number> = Multiple<1, T>; |
TypeScriptの型システムは、本当に奥が深いです。
こういう変なことをするのが大好きなので、もう少し調べてみたいと思います。
今回のコードは、こちらで試すことができます。
型に計算結果が入っているので、カーソルをその型に合わせると、中身が分かると思います。
また、今日は情報系の選抜授業の合格発表があって、
無事履修することができました~よかった。
倍率2倍強ですが、絶対に取りたい授業で、チャンスは1回だけだったので、
本当に良かったです。堪能したいと思います。
さて、今回は、vue-composition-apiを使っていきたいと思います。
これが凄いんですよ。
おそらく、最初のモチベーションとしては、肥大化したViewModelを整理する、ということだったと思うんですが、
おなじみの watch
や、リアクティブな変数を生成する reactive
などをコンポーネントから分離して利用できるようになったことで、後で詳しく述べますが、幅広く使える可能性を備えたと思います。
特に、これはデータバインドを活用したアーキテクチャを設計し、プロトタイプを作るのにも向いていると考えたので、
ここでは、試しにVuexをvue-composition-apiを使って実装してみたいと思います!
詳しくは、Vue.jsの公式ドキュメントが分かりやすくて、APIが作られた背景までわかるようになっているので、そちらを見てください。
今回特に使う機能を紹介していきます。
リアクティブな変数を生成します。似たものに reactive
というのがありますが、こちらは値がオブジェクトの時に使えて、 .value
を省略できます。
コードの説明はTypeScriptで行っていきます。
1 | import { ref, Ref } from '@vue/composition-api'; |
これだと、ただ参照値を渡しているだけで、例えば、次のようにしても良いのではないかと思うかもしれません。
1 | const num1 = { value: 0 }; |
ですが、 ref
の強みは、Vueの便利なリアクティブシステムに値するものがすべて使えるところにあります。watch
、computed
などです。これを次に説明します。
Vueでおなじみのものと同じです。
1 | import { ref, watch, Ref } from '@vue/composition-api'; |
こういった機構を簡単に設計できるのです。
Vueのコンポーネントシステム以上の可能性を感じますよね。
今回は使いませんでしたが、 computed
もシンプルに使えます。
1 | import { ref, computed, Ref } from '@vue/composition-api'; |
すごいなあ。
こういうプログラムが普及すると、プログラムは上から実行されるんだよという説明が難しくなってきそうですよね。
もちろん間違ってはいないですが、このようなcomputed内のコールバックが実行される順番等を踏まえると、もっと別の意味づけのほうが適切なのではないか、と思えてしまいます。
プログラミング言語の命令型→宣言型への移行が垣間見える気がします。
個人的には、データフロープログラミングに興味があるので、この流れは賛成です。
computedが内部的にどのようにコールバックの実行タイミングを見極めているか、については、下の記事が分かりやすかったです。一旦中身を実行してみて、どのリアクティブ変数が取得されたか、を記録しているようですね。
条件分岐などがcomputed内であった場合は、一旦実行するのみでは足りないのではないか、と思いましたが、条件自体がリアクティブだとこれで足りそうですね。よくできてるなあ。
ここまでで Composition API の基本的な機能を見てきました。
Vueのコンポーネントに止まらず、もっと汎用的な使い道があるということがわかりました。
というわけで、実際の応用例として、Vuex的アーキテクチャを実装してみましょう。
今回はTodoアプリを作っていきますが、
あまり本質的でない部分は端折ります。
Actionはごめんなさい、さようなら。
そして本当はAction呼び出しは疎結合に行われますが、これはあまりメリットがないので、今回はMutation直呼びで代用します。
/store.ts
1 | import Vue from 'vue'; |
Composition APIを使うために、仕方なくVueを呼び出していますが、
あくまでVueをアプリケーションで使うわけではないです。
stateの定義に ref
を用いています。これは先ほど紹介した通りです。
本当は、Model部分はViewに影響されず、純粋なモデルにするべきですが、リアクティブ化する程度ならばいいかと思ってしまいました。どうですかね。
あと、 reactive([])
では配列はリアクティブになりません。注意してください。
mutationは普通にstateを書き換えています。
そして、ここが肝なのですが、
stateをexportするときに、stateをreadonlyにしています!!!!!
実は、ライブラリのほうのVuexはstateに双方向データバインドがかかっていて、
Mutationを介さずにバインドによってstateが書き換えられてしまうのですが、
これはどう考えてもbadなので、今回はComposition APIの機能をフル活用して、
readonlyにしています。
readonlyStateの型ですが、Composition API内部で使われている型を拝借しました。[P in keyof Type]
というのは、Mapped TypesというTypeScriptの機能です。反復処理の型バージョンみたいなやつです。
DeepReadonlyでは、 T extends U ? A : B
という、型バージョンの条件分岐を使っているようです(参考:API内部)。
どうしてここまでして型を組みたいかというと、こうすることで、readonlyStateの値に関して保証ができるからです。
つまり、stateにあるのにreadonlyStateにない!とか、readonlyになっていない!とかいうことが、TypeScriptのエラーとして把握できます。
このように、ただ型がつくと嬉しい!楽しい!というだけでなく、開発上のミスが無いようにするために型を使うべきです。この使い方は never
型などでよくします。
まずはインターフェース実装。/components/component.ts
1
2
3export default interface Component {
render(): HTMLElement
}
Todoを追加するやつ。/components/todoList.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18import Component from './component';
import state from '../store';
import { watch } from '@vue/composition-api';
export default class TodoList implements Component {
render() {
const ul = document.createElement('ul');
watch(state.todoList, () => {
ul.innerHTML = '';
for (let todoItem of state.todoList.value) {
const li = document.createElement('li');
li.textContent = `${todoItem.title}`
ul.appendChild(li)
}
});
return ul;
}
}
VuexなのにtextContentとかdocumentとか出てきてて草
今回は、Composition APIの汎用性を説明したかったので、
バニラでも十分役立つんだ!ということを説明したくてこうしています。
もちろん、バリバリVue使って実装してもらってもいいです。
ここでは、state.todoList
をwatch
しています。
さすがに直DOMに流すのはリアクティブにはできないので仕方ない。
また、ご確認いただけると幸いですが、state.todoList
はしっかりreadonlyになっているので、Viewからは改変できません!わーい
じゃあViewからstateを変えるにはどうするの?というのが次のコンポーネントになります。
/components/addTodo.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import Component from './component';
import { addTodo } from '../store';
export default class AddTodo implements Component {
render() {
const parent = document.createElement('div');
const input = document.createElement('input');
input.type = 'text';
parent.appendChild(input);
const button = document.createElement('button');
button.textContent = 'Add a task';
button.addEventListener('click', () => {
addTodo(input.value);
input.value = '';
});
parent.appendChild(button);
return parent;
}
}
mutationをimportして使っています。
ここはあまり大事ではないですが、コンポーネントを登録(物理)します。
/main.ts
1
2
3
4
5
6import AddTodo from './components/addTodo';
import TodoList from './components/todoList';
const app = document.querySelector('#app');
app.appendChild(new AddTodo().render());
app.appendChild(new TodoList().render());
Vueが完全に隠れていて気持ちがいいですね。
冷凍庫で3時間冷凍したものがGithubにあります。
実装にはViteを用いました。
速いですね。今風でいいですね。webpackもそろそろ引退かな。
デモはこちらで試すことができます。
いかがでしたでしょうか。Composition APIの汎用性が伝われば幸いです。
個人的には、アーキテクチャの実装等に興味があるので、
データバインドを活用したアーキテクチャのプロトタイプ作成などにどんどん使っていこうかと思います。
この前の記事にも書きましたが、プログラミング言語そのものへの興味が湧き始めました。
言語の仕様や、プログラミングパラダイムなどに興味があります。
それらがコンピューターの構造や、後述するデザインパターンやアーキテクチャとどのような関係があるのか、について知りたいと思っています。
プログラミングパラダイムの中でも、特にデータフロープログラミングに興味があります。
実は、僕自身、Vueの双方向データバインドを使ってきた経験から、
受験期の前半に、データバインドのみしか使えないようなプログラミング言語を構想していました。
そうしたら、ひょんなことから、Lucidというデータフロープログラミング言語を見つけて、びっくりしています。
色々Lucidについて調べていると、ちょっと古い言語のため、その時代のプログラミング言語に対する関心についても知ることができて楽しいですね。今より関心が数学的な証明可能性に向いているようです。
Lucid自体は、ちょっと現代プログラミングの仕様に合っていない面もある気はしますが、
Lucidの論文で、代数への命令型・手続き型アプローチが放棄された、と言われているように、
Webプログラミングにおいても、データバインディングの浸透により、命令型・手続き型から宣言型・非手続き型への移り変わりが起こるんじゃないかな、と思っています。
また、Nintendo LABOで使われるプログラミングがデータフローっぽいのも惹かれた理由の一つです。
これらは、長年Webプログラミングをしてきて、
どう書いたらコードがきれいになるか、秩序立ったものになるか、をずっと考えてきたことが影響しています。
Web界隈では、近年まで目まぐるしく流行が変わる激動の時代でしたが、
そんな中、MVVMなどが、「とりあえず流行っているから」使われることが多かった気がします。
そんなMVVM、Flux、MVCなどが、比較してどんな特徴があるのか、
また、それらが、プログラミング言語の仕様、パラダイムにどう影響され、
そして我々の理解方式にどう基づいているのか、に興味があります。
例えば、MVVMは、データバインドという言語上の仕様(あるいはそれに準ずる技術)に
強く依存しています。
細かいミクロなアルゴリズム(ソートなど)より、このようなマクロな構造のほうに興味があります。
ちょっとここだけ異色に見えるかもしれないのですが、僕はあまり違うものだとは思っていません。
合成生物学で、生物を作る、というより、生物でプログラミングをする、というほうに惹かれています。
遺伝子でのプログラミングも、プログラミングパラダイムの一つとなるのではないか、と考えています。
高校では生物が好きでしたし、「生物」による世界の理解と、人間による世界の理解の違い、にも興味があります。
受験期に読んだ『数学する身体』という本に、面白い話が載っていました。
簡単にまとめると、次のような話です。
遺伝的アルゴリズムを用いて、回路パーツを組み合わせて、特定の処理を行える回路を構成するようにしたところ、人間が必要とする最小パーツ数を下回るパーツ数で回路を作れてしまった。これは、「人間」が与えた回路パーツの「機能」だけでなく、電磁的な漏出や磁束の効果を上手く使ったことによるのだ。
人間による設計では、「誤差」として捨象される漏出や磁束ですが、そもそも何が本質で何がそうでないのか、は人間が恣意的に決めたことです。進化のプロセスは、そのような分節化は行わず、使えるものは何でも使う、というスタイルです。
同じく受験期に読んだ『ひとは生命をどのように理解してきたか』にも、似た話があり、こちらは目的の遺伝子がなかなか見つからない問題を取り上げ、それが我々の日常の理解の論理と、遺伝子の論理が別物だからだ、と言っています。
このような、「別の論理」が働くプログラミングパラダイムが、合成生物学だと思います。
遺伝子を単位としてプログラムを作ると、関数型プログラミングなどでは忌避される副作用がどんどん出てくるでしょう。ですが、実際の生命はそれを副作用だとして切り捨てず、進化してきて、ここまで来たわけです。
そのようなプロセス――倫理で習った事を使えば、ショウペンハウアーの「盲目的意志」のような営み――から、プログラミングについて、学べることも多いのではないか、と感じています。
出会いは高1の時の『数学ガール ゲーデルの不完全性定理』です。
数学を数学によって再構築していく感覚が何とも楽しかったです。
1つ1つの演算を数学で実装し直していく感覚は、プログラミングにも似ていて面白かったです。
当時は、「数式でプログラミングってできるのかもしれない」といった純粋な好奇心を持っていました。
そして今、先述したようなプログラミング言語仕様などを調べていると、
どうやら本当に、数式でプログラミングができるのかもしれず、
しかもそれができるかどうか、が実はかなり重要である、ということが分かってきました。
先ほどのLucidの話では、たびたび数学の論理と、プログラミングの記述が対比されています。
数式は静的(宣言的、非手続き的)な営みであり、プログラミングはマシンの制約(先ほど書いたように、マシンの制約とプログラミング言語仕様の関係性も好きです)上、動的(命令的、手続き的)になっている、とされています。
数学が、いったいどのようなものなのか、を数学する数学基礎論のメタ数学的議論と、
プログラミング言語はどういうものなのか、というメタプログラミング(とまではいきませんが、やはりメタい部分)的議論との間に、何か密接な関連性を感じています。
というわけで、こちらも合成生物学同様、
プログラミング側から見た数学、としての楽しさを感じています。
数学も1プログラミングパラダイムと見ることができるかもしれません。
これも『数学する身体』や『ひとはどのように生命を理解してきたか』の影響が大きいですが、
数学やプログラミング言語の体系が、どのように人の理解構造や身体性によって作られているか、に興味があります。
先ほど述べたように、生命が何でもありで目的を達成するのに対し、
例えばプログラミングでは、基本的に関数にはその機能を限定しますし、
オブジェクト指向、はまさに我々の物に対する理解方式を取り入れたものでしょう。
ここらへんは、The DCI Architectureという論文(の日本語訳)を読んで興味を持ちました。
関連して、そのように、数学やプログラミングが人間の身体性に依存していながらも、
本当に正しいと言えるのだろうか、という真理性についても気になっています。
なぜ、数学を用いた物理の予測、などが、人間の感覚基準なはずなのに、
これほど世界の現象を言い当てることができているのか、などです。
ここだけちょっと特殊な気がします。
受験期の入試問題や、受験後に読んだ『大学入試問題で語る数論の世界』という本を読んで、
数論が好きになりました。(※得意ではないです)
特に、全く関係ないように見える2つの概念が、突然出会う不思議さ・美しさや、
意味的に無駄がなく、本質を突くような証明の構造に惹かれました。
自分で何か新しく証明をしよう、とは思わない(できない)ですが、
数論の様々な概念がどう大事なのか、を体得し、
他人の証明を鑑賞したいな、と思っています。
しいて言えば、こちらも数学基礎論的な証明の仕方や、
人間の理解を超えたような2つの概念の結びつき、に興味があるのかもしれないです。
興味のあることはたくさんありますが、
これらには何か統一的テーマがあるのではないか、という気がしています。
ただ、これが本当に自分の興味を言い当てられているのかは分かりません。
今日も大学の図書館で色んな本をあさってみましたが、何となく満たされないというか、
ちょっとかゆいところが残っている感覚がまだあります。
大学の授業などで、いろんな経験をして、だんだんわかってくるのかな、と思います。
]]>さて、今日で高校生は終わりです。(※書いていたときは3/31でした)
高校での3年間で、物の捉え方や、考え方、好み、楽しいこと、などが大きく変わったと思います。
プログラミングに対する姿勢も変わったと思います。
高校に入るまで、また高校に入ってからしばらくは、
プログラミングを、あくまで何か制作物を作るための手段と考えて、
そのためにいかにパフォーマンスが良いコードを、綺麗に書くか、ということを大事にしてきました。
ですが、最近は、プログラミングそのものを目的にしたい、と考えるようになりました。
今回は、そのことについて書こうと思います。
高校では、ディベートシステム作成、文化祭の予約システム作成、
文化祭のサイト作成、発表会でのデモアプリ作成、など、
あらゆる場面で、HTML/CSS/JavaScriptを利用した、Webアプリを開発してきました。
ただ、色んなものを作っているうちに、
やりたいことを形にする過程が単調化してしまい、
もう大体どう書けばよいのか分かってきてしまったので、
タイピングゲームのようになってしまいました。
思えば、Web界隈でプログラミングを始めてからは早7年が経とうとしています。
懐古厨みたいになってすみませんが、最初のころは、まだjQuery全盛期で、
デザインではbootstrapとかが流行っていた頃でした。jQuery UIとかもありました。
Ajaxが「すげー」みたいになっていて、HTML5がこれから、という頃でした。
FlashやSilverlightから脱却しようか、という流れになった所で、
まだできることは限られており、「幕開け」という感じだったでしょうか。
(YouTubeもFlashだったんです。今の子供たちは信じてくれなさそう)
徐々に、Web「アプリ」が盛んになってきて、Web界隈は大きく進化したと思います。
「アプリ」として設計をしやすくする、Angular.jsとか、knockout.jsとかを使うようになり、
その後node.jsの台頭で、browserifyが流行りました。
requireがクライアントでも使える!という事にワクワクしていました。
盛者必衰、browserifyが衰退してWebpackが流行り始め、
それを基盤として、Angular 2、React、Vue、と目まぐるしく流行が変化する時代になりました。
Webプログラミングでできることも、増えていきました。
node.jsによるサーバーサイドプログラム、
それを応用したElectronによるデスクトップアプリ開発、
(Firefox OSはあまり流行りませんでしたが)PWAによるスマートフォン向けアプリ開発、などです。
またそれらを支える、フリーで使えるクラウドサービス(Heroku、Firebaseなど)も増えていきました。
ですが、最近はどうでしょう。僕が受験期で離れていて流行に疎くなったからかもしれませんが、
安定期に入ってきたのではないかな、と思います。
大体作りたいものは、Vue.js+Webpackで、かなり効率的に、綺麗に作れるようになってしまいました。
数あるサービスを使えば、デスクトップアプリも、スマホ向けアプリも、サーバーサイドも、これ一本でできてしまいます。
それらが発表され、最初に使い始めたときは、
新しいことができるようになり、また開発スタイルが大きく変わることに、
とても感動し、ワクワクしたものですが、
もう慣れてしまい、あまり目新しさを感じなくなってしまったのです。
Webプログラミングは、何かを作るためのツールとしては、
非常に強力なものになったと思います。
ただ、自分にとっては、そこでのプログラミング自体を楽しみとするのは、
もう終わりなのかな、と思うようになってしまいました。
Webプログラミングを始める前の約2年間は、
Visual BasicやC#をやっていたので、そこであらゆるプログラミングの元となる、
基本的な考え方は身に着けることが出来ていました。
その後、JavaScriptで開発するようになって、一番学べたことは、
やはり、Mozillaで、皆さんと一緒に開発することができた経験だと思います。
Webプログラミングは、そのオープン性の高さにより、
他のプログラミングと比べても、共同開発との親和性が高いな、と思います。
皆さんと開発できたことで、それまでプログラムは動けばいいや、自分が読めればいいやと思っていたのが、
どう実装したら綺麗だろうか、などの視点から考えるようになりました。
疎結合の大切さや、オブザーバーパターンなどを最初に学びました。
そして、MVCやMVVMのメリットなどを、実際の開発を通じて知ることができ、
大規模なサービス・アプリを作ることが多いWeb系だからこそ、の、
大局的な構造の整理の重要さや、その設計・実装の楽しさを感じることができました。
また、一分野が、時間を経てどのように変化するか、を生で見ていくことができたので、
言語の成長過程や、どのようにライブラリが台頭してくるのか、などを体感できました。
そのほか、GitやGitHubにも慣れることができて、よかったです。
受験が終わってからなので、最近ですが、
開発の都合で、SwiftやPythonに触れる機会がありました。
この2か月、swiftとpythonを触ることが結構多かったんだけど、マジでこの2つ対極的だった
— shundroid (@shundroid_p) March 31, 2021
swiftは、文法レベルで仕様どんどん増やしていくから、if case let
みたいな意味不明構文がたくさん、自由度低
pythonは、enumでさえライブラリレベル。metaclassすげえ。自由度高
かな
これらは、結構javascriptとは趣が異なっており、またそれぞれ性格が特徴的で、面白かったです。
そして、これは受験勉強の影響な気もしますが、
社会系の教科で、「思想」や「歴史」「制度」などを体系的理解の対象としてきたのと同様に、
「プログラミング言語」そのものも、体系的理解の対象として扱ってみたい、という気持ちが強くなりました。
その言語で書かれたもの、というより、
その言語自体が、どのような要請で設計され、どういう強みを持っているか、を、他の言語との対照の中で考えてみたい、と思うようになりました。
最近色んな言語に触れることが多いのだけれど,色々比べることでそれぞれの言語が持つ特徴とかが見えてきてやっぱ面白いね
— shundroid (@shundroid_p) March 30, 2021
ただ1つ1つをもっと味わいたいとも思う
最近は、ただ綺麗だ、パフォーマンスが良い、というだけでなく、
その言語の個性を生かしたプログラムを書こう、と意識しています。
metaclassとdecoratorと__から始まるプロパティを多用した、pythonらしいコードが書けたような気がして喜んでいる
— shundroid (@shundroid_p) March 31, 2021
今までは、プログラミングを、何か制作物を作るための手段だと考えてきたわけで、
3年前には下のような記事も書いていたようです。(今読むと恥ずかしい)
確かに、プログラミングを初めてする時は、手段として身につけた方が学びやすいでしょう。
これは確実にそうだと思います。
ただ、プログラミング自体を楽しみたい、深めたい、というふうに、目的が変化したときは、
実際に何の言語で書くか、も重要だな、と思うようになりました。
そこで、 最近作ろうと思うものがネタ切れ気味なのもあり、
プログラミングを目的とし、制作物を手段とする、という風に、
目的と手段を反転させてみてはどうか、と思っています。
例えば、pythonでmetaclassを使うために、interface的なものを実装する練習をしてみる、といった感じです。
こうすることで、プログラミングの世界が広がるのではないか、と思っています。
他言語との比較の上、そのプログラミング言語の固有性を味わう、という経験をしていきたい、と思っていますが、
これは、やはりWebプログラミング界隈で長い時間をかけ、その風土を体感してきたことが生きると思っています。
javascriptではこういう書き方は忌避されるけど、swiftだといいんだな、という風に、その体験を様々な発見の基準とすることができると思います。
この意味では、今までWebプログラミングをやってきて良かった、と感じています。
色々と貴重な経験をさせてくださった皆さま、ありがとうございました。
大学では、新しいプログラミング生活を過ごしていきたいです。
以下、今のところ迷っていることを書いておきます。
高校が休みになっているので、勉強・開発に励んでおりました。
そこで、Vue.js で Transition だけでなく、
Web Animations を取り入れたい状況が出てきました。
そこで次のようなコードを書いたのですが、
これは Vue.js としてはふさわしくないですよね。
1 | <template> |
どこがふさわしくないのでしょうか。 ref
を使っている辺りが明らかに良くないですけど、
問題はそれ以上にあると考えます。
事を大きくしすぎた気もしますが、根本的な問題はここにあると思います。
アニメーションのような 一過性 のものは、一般的には「動作」で書くのがふさわしいですよね。
そのため、 .animate
という メソッド によって「動作」を記述しているのです。
ただし、Vue.js は伝統的に、「動作」による記述よりも「状態」による記述を好みます。
例えば、View上の文字を変更するのに element.updateText('hoge!')
みたいに書いたりはしませんよね。{{ text }}
のような text
という data
の「状態」の記述によって、UIの変更を行っています。
インラインテキストだけでなく、属性やスタイルの変更、また Transition
についても同様に、「状態」による記述を行っています。
これはどうしてでしょうか。Vue.js の存在意義を考えるとこれは明らかです。
先ほども少し触れましたが、「動作」というのは一過的な概念です。
つまり、一回「動作」してしまえば、それが長い間ずっと続くようなことはありません。
ただし、Vue にとっては、これが長い間続いてほしいんですよね。これはなぜか。
まさしく、双方向データバインディング を保つためです。
データのリンクは、動作のように一回一回の時のみかろうじてつなぎ留められているようではいけないのです。
このように Vue で「状態」が重んじられている背景を踏まえると、そこに「動作」で記述されたプログラムを書くのは、
なんだか異物感を感じるわけです。もちろん動きはするんですけど、ちょっと消化不良というか、そういう感覚です。
HTML(XML) は非常に「状態」を書くのに優れた(マークアップ)言語です。
対してJSは「動作」を書くのを主としているわけなので、
例え .animate
メソッドの引数で渡されているオブジェクトが状態だ!と主張したとしても、<template>
タグ内で書けた方がよいですよね。
というわけで、Web Animation を「状態」で記述するようにしたのが、このライブラリです。
コードを見てみましょう。
※ もちろん Vue でも動作を好む場面はあります。 v-on
などに代表されますが、これらで実行される処理は View
の背後の、ロジック的な部分であって、Vue でなくても別に良い部分なわけなので、ここをとって「Vueは動作による記述を好む」というのは言いすぎな気がします。
インストールは、yarn または npm で行ってください。
1 | $ yarn add vue-animate-component |
または
1 | $ npm i --save vue-animate-component |
コードは次のようになります。
1 | <template> |
Web Animation をタグによって記述できます。 v-model
が true
になった時、
アニメーションの終了は v-model
が false
になったことを検知してください。今後 @finish
などを実装するかもしれませんが。
詳細な利用法は、Github レポジトリをご覧ください。
v-model
が false
になった時、アニメーションを pause
する@finish
などのイベントを実装する(「動作」による記述を奨励するようですが…)この実装は Github で見られるんですけど、スッカスカなので試しに keyframes.vue
を見てみましょう
1 | <template> |
えっ()
つまりそういうことなんです。察してください。animation.vue
のほうでは、自分と子要素の $attrs
をそのまま .animate
の引数に丸投げしているだけです。
そんな意味あることなの?と思われるかもしれませんが、大事なのはその変換過程ではなく、
状態は <template>
内で書く、という役割分担がはっきりすることと、
またアニメーションの開始を v-model
による状態変化で行えることであってほしいです(希望)
さて、昨日「キャンベル生物学」という太い本を読み終わったので
その感想をまとめようと思います。
キャンベル生物学 原書11版は1444ページ、目測でA4サイズくらいの本で、
生物学の幅広い分野の基礎が学べる本です。
「高校生にとっても最適の教科書」とありますが、まさにその通りで、
解説が非常に丁寧でわかりやすかったです。(英訳だからか独特の言い回しがありますがそれは慣れます)
わざわざどうしてこの本を読んだのかといいますと、高校の生物の先生に勧められたからです。
最初は割と緩く読んでいたんですけど、このままだといつまでたっても読み終わらない気がしたので、
4月あたりからスパートをかけました。グラフにも必死さが現れていますね()
全体的には「学校で習った分野」と「そうでない分野」に分かれていました。
前者は動物の形態と機能などで、復習になったほか、新たな概念などを取り入れて学びを深めることができました。
後者は生命史などで、少し負荷はありましたが、そこでも既習分野との関連性や相似性が見えてきて面白かったです。
次に、それぞれのテーマについて感想を書きたいと思います。
「空間としての推移」では、生体分子の構造という非常にミクロな視点から、
細胞小器官の構造、細胞の構造、組織、器官、個体、個体群、群集、生態系、と、マクロな視点に移っていく様子がよく理解出来ました。
「時間としての推移」では、遺伝的変異の頻度変化(小進化)がどう種分化(大進化)につながってくるのかとして、
「ミクロ」と「マクロ」のつながりが捉えられました。
少しそれますが、進化と生態系は相互作用するので、ここで「空間」と「時間」のつながりも生まれます。
生物学は空間にも時間にも広がりを持っているのが強く認識できました。
そこで気づいたことがあります。
生命が「フラクタル」のようであるということです。
(部活の先輩が作ってくださいました、マンデルブロ集合)
フラクタルとは Wikipedia によると、「部分と全体が自己相似」になっているもののことだそうです。
これは生物を通しても言えると思います。
例えば、空間としてのフラクタルを見てみましょう。
ミクロな視点で原子に注目します。原子は光を吸収して熱を放出することが多いです。
これをマクロな視点で考えると、生態系全体としても、やはりこのようなことが起きています。
生産者である主に緑色植物が光を吸収します。そのエネルギーは生態系内では化学エネルギーとして循環しますが、
生態系の外に出される形はやはり熱が多いです。
時間として考えてみてもこのことが当てはまります。
少し広い例となりますが、細胞は分裂し、死にます。また個体は誕生・死亡します。
同じように種は分化・絶滅します。
これらは同じような表し方がされています。p1194の細胞系譜や、よくある家系図、また種の系統樹は似た形をしています。
固有の例ですがミツバチはその個体群自身が一つの個体のようにふるまいます。女王バチが生殖細胞に当てはまったりします。
無限に続くフラクタルというわけではないですが、部分が全体に対応付けできます。
あくまで見方の1つですが、どうしてこのような見方ができるのか思うと不思議です。
1つ思っているのは、「全体」は「部分」より後にできるので、「部分」が環境に適合していた形態が、そのまま「全体」にも引き継がれるのかなっていうことです。
これも環境適合的な選択圧を受けているのでしょう。
本書にはこの視点の推移で「組織化」や「創発特性」という概念が取り上げられています。
創発特性は抽象度が上がる(=よりマクロになる)ことで新たに特徴が生まれるということです。
例えばニューロン一本ではこうやってブログは書けませんが、組織化して脳となることでブログが書けるようになっています。
組織化により個々の特徴が再び現れること(=フラクタル)と、新たな特徴が現れること(=創発特性)の2つがあって、
それぞれ大切なのだろうと思います。
読み進めるにあたって、生物学は様々な分野と連係しているのだと気づかされました。
例えば、統計などでは数学、化石記録などでは地学、バイオームでは地理、代謝には物理、環境保全では社会系、
シミュレーションなどでは情報、といった感じです。
生物学から見ると様々な分野とつながって、分野のカバー範囲の広さを感じさせられますが、
逆から見ると、様々な分野から生物学につながっています。
これは、私たちの生活の様々な場面に生物学が絡んでくるからなのでしょう。事実私たちは生物です。
色々あります。
最初の方では代謝がエネルギーの吸収・放出で表せる感じが楽しかったです。
化学エネルギーって(少なくともここでは)電子の位置エネルギーなんですね。
ATPがどうして高エネルギーを持っているのか、そのエネルギーをどうやって酵素等に付与するのかがわかって
もやもやが消えました。
ハーディ・ワインベルグ平衡や個体群生態学では数学とのつながりが個人的に好きでした。
最後にガイア理論です。(本文中ではガイア仮説)
これは結構気になっています。先ほどフラクタルの話をしましたが、なんと「地球全体」を1つの生命体と捉えて、
そこでも恒常性を維持する働きがあると考えるそうです。賛否両論あるそうですが。
これから調べてみたいと思います。
ただ知識を広げさせてくれるのではなく、それをもとに色々考えさせてくれたりする本でした。
忍耐力と読解力も上がったでしょう。
これから読む人へ
多分本気で読めば1か月くらいで終わります。僕は半年かかっちゃったんですけど()
あと、個々の章の話をそこで完結させないで、他の分野とのつながり、を意識して読むと見えてくるものが変わります。
結構疲れますが得られるものは大きいので頑張ってください(小並)
早いもので高校に入学してから1年になります。
この1年はプログラミング以外のことにもいろいろチャレンジして、
充実した高校生活を送ることができました。
クラス替えがドキドキ…
さて、今回は割と今年(少ない機会でも)愛用した Nuxt のビルド速度を
向上させる方法を紹介します。
あ、そだそだ、今年はプログラミングを目的にしてプログラミングすることは少なかったんですけど、
割と学校の発表で(Nuxtを使って)デモアプリを作ったり、ディベートの授業で電子投票用のシステムを作ったりと、
「手段」としてプログラミングをすることが多かったです。
プログラミングのスキルを身に着けておいて、できることが広がったので、
2020年プログラミング必修化で、よりプログラミングが普遍的なものとなり、
学校での学びが深められるようになるとよいと思います。
Webpack の hard-source-webpack-plugin です。
これを使うことで、ビルド時のキャッシュを取ってくれるので、二回目以降のビルドが爆発的に速くなります。
下の「参考」の記事では、DllPlugin というものも紹介しています。
しかし使ってみたものの、hard-source-webpack-plugin と比べると効果が少ないので、
今回は割愛したいと思います。
実際に上のリンクの readme を見ることで、生の webpack への導入手順は分かります。
が、今回は nuxt v2 で行いたいです。つまり、webpack の config を、nuxt を通していじる方法を知ることが大事になってきます。
これが分かれば、おそらく DllPlugin の導入方法もわかるでしょう。
yarn:
1 | $ yarn add --dev hard-source-webpack-plugin |
npm:
1 | $ npm i -D hard-source-webpack-plugin |
※ i
は install
、 -D
は --save-dev
の省略形
1 | const pkg = require('./package') |
予想以上に簡単でした。今回薄いな(確定)
yarn:
1 | $ yarn dev |
npm:
1 | $ npm run dev |
Client 側が 1.27m です。単位はm。つまり分です。
Server 側が 58.34s です。遅いですね。
えっ速い
Client 側が 2.14s、Server 側が 34.45s です。
かなり速度が上がっていることがわかります。
これは頼もしいですね。
Nuxt は SSR にしてくれるのもありますが、
実際 express のサーバーをセットアップしてくれるのがずいぶん楽なので、
使っています。
これでより良い Nuxt ライフとともに、新学期を迎えられそう!
さて、今回は、友人とアプリを1つ開発することになりました。
そこで、環境構築などを友人の pc で行うのは手間がかかるため、
その必要がない、クラウドIDEを用いることにしました。
使い方などを記録しておこうと思います。
同等のクラウドIDE サービスとして、AWS Cloud 9 と codeanywhere が有名です。
それぞれのサービスの特徴をあげておいます。
Codenvy は無料でわりと高機能に使えて、さらに友人と開発するのに必要な「チーム開発」機能があったので選びました。ただしバグが少しありますね…。
ここにアクセスして、アカウントを取得します。
そうするとこのような Dashboard が開きます。
今回は友人との開発なので、まず Team を作ります。
一人でしか使わない方はこの節は飛ばしてください。
左側の「Create Team」をクリックして、
https://codenvy.io/dashboard/#/team/create
に移動します。
チーム名を入力したら終わりです。簡単。
メンバーは後から追加可能です。
左側の「Create Workspace」をクリックして、
https://codenvy.io/dashboard/#/create-workspace
に移動します。
後はウィザード通りに進めればよいのですが、
チーム開発をするときにとても気を付けなければならないところがあります。
ここでWorkspaceを紐づけるTeamを決めることですね。なぜかこれは後から変える方法が見つからなかったので、ここでミスるとWorkspaceを作り直す必要があります。
Stack は Vue.js なので Node を選択してくださいね。
なお、この Projects のところからは Github のリポジトリをインポートしたり、
Git を選択すると非公開の Bitbucket のリポジトリをインポートしたりすることもできます。
Project は後から Workspace に追加したり、作成したりすることも可能です。
チームで Workspace を使う際、なんと Workspace を Team に紐づけるほかに、
Share という設定を変える必要があります。
左上の Workspaces をクリックして、
https://codenvy.io/dashboard/#/workspaces
に移動します。
Workspace を選択して、設定に移ります。
Share → Add Developer を選択して、Workspace を使う User を追加してください。
ここにつまづいて1時間くらいとられました…
Codenvy ではどうやらポートごとにサーバーが割り当てられるそうです。
例えば、9000 番ポートにアクセスするため、3000 番ポートにアクセスするため、・・・という風にそれぞれサーバーが設定されています。
デフォルトでは 9000 番や 3000 番が開けられています。他のポートを利用したい場合は、追加する必要があります。
Workspace を Share するときの設定画面に移動して、「Server」→「Add Server」から追加します。
Reference は何でもいいんですけど例えば「node-8080」、portに開放したいポート番号を入力します。(8080など)
※ここは vue-cli v3 を利用して生成されたプロジェクトについての話です。そうでない場合は適宜なんか補ってください。
僕は Bitbucket から Project を import しているので、それがそのまま codenvy で使えているのですが、codenvy 上で vue-cli を利用してプロジェクトを作る場合は、ターミナルを開き、
1 | $ npm i vue-cli |
を実行してください。
ターミナルは下のほう、もしくは Run → Terminal から開けます。
Codenvy で Webpack を利用して、App を実行するために必要となる変更は次の通りです。
host
の変更disableHostCheck
を true
にするport
の変更)デフォルトでは localhost
や 127.0.0.1
になっているかもしれませんが、外部からのアクセスを可能にするため、 0.0.0.0
にします。
<プロジェクト名>/config/index.js を、次のように変更します。
1 | // ... |
ここはハマりました。このままでもアクセスは可能なのですが、
「Invalid Host Header」というレスポンスがされてしまいました。
<プロジェクト名>/build/webpack.dev.conf.js を、次のように変更します。
1 | // ... |
あまりジェネレートされたファイルは変更したくないのですが、仕方がないですね。
先ほど Port の開放で、「8080」ポートを開放しているなら大丈夫なのですが、
9000 や 3000 ポートを利用したい場合はこの作業が必要です。
<プロジェクト名>/config/index.js を、次のように変更します。
1 | // ... |
下のターミナル(出ていない場合は Run → Terminal)で、次のように実行します。
1 | $ cd /projects/<プロジェクト名> |
こうすると、0.0.0.0 でアプリが実行されます。
この 0.0.0.0 にアクセスする方法ですが、先ほどの設定画面、「Server」より、それぞれのポートに対応する Server の Url が貼られていて、確認することができます。
Codenvy は便利ですが、情報が少ない面もあり、なかなか大変です。無料なので仕方がないのですが…
最後の URL の確認のところは、Commands という機能があって、それを利用すると手間が省けます。
それについてはいつか書くかもしれません。
]]>正直かなり焦ったのですが、今日の朝、凍結解除のお知らせが入っていました。
今回は、その道のりについて書きたいと思います。
まず、Twitter の凍結の種類について書きます。
一番軽いやつです。本人確認したら解除されます。
「ロック」というものもありまして、僕が調べた限り、
ロックと警告凍結の違いがよくわかりませんでした。
わかる方は教えてください。
画像は本垢が凍結されたとき、別垢を作ったらなぜかロックされたときの物です。
短時間にフォローをしすぎたのか「自動化」が引っ掛かったそうですね。
友達によると、最近はアカウントを作るとほぼ確実に最初にロックされるという情報もあるそうです。
今回僕の本アカがされたやつです。
ロックのように、本人確認だけでは解除できません。
異議申し立てをした後、メールのやり取りをして、
運が良ければ解除されるそうです。
スプラトゥーンが上手なた〇じさんがやられたやつですね。
基本復活しないそうですが、解除されたって言っている人もネット上にはいますね。
僕は体験していないので詳しく述べることはできないです。
夕ご飯を食べた後、Twitter を見たところ、
なんか画面の上の方に赤いバーが・・・
えっ・・・凍結?
思い当たることがないので、リンクをたどって、
異議申し立てをしました。
図のようなフォームに、必要事項を入力して送信しました。
数分で届きました。なぜか英語でした。
It appears that your account is in violation of Twitter’s Rules.
Twitter のルール違反があるそうですね。
返信をしました。
最後「アカウントを解除」は正しくは「凍結を解除」ですね。
訂正します。
日本支部があるはずなので日本語で書きましたが、
一応最初に英語で少し書きました。
ルール違反はしていないはずですが、どこがルール違反に当たるのか
少し推察をして、それがルール違反でないという反論を書きました。
その間に、新しいアカウントを準備しましたが、
ロックされました。↑で書いたのはこのタイミングです。
翌日。朝起きるとメールが届いていました。
さらなる調査の結果、ご利用のアカウントはTwitterルールに違反していないと思われるため凍結を解除しました。
誤凍結だったようでした。
無事 Twitter のアカウントを開いて解除されていることを確認できました。
今回は凍結が無事解除されたのでよかったですが、
友達には「何をやらかしたんだい」とか「なんで?」とか
色々聞かれました。
しかし「なんで?」と言いたいのは僕自身ですよねw
わからないとしか答えようがなかったです。
実際本当に何もやっていなかったようですし…
というわけで、周りに凍結されてしまった人がいる場合は、
あまり悪く思わないであげてくださいw
誤凍結という可能性もあります。
とりあえず凍結解除されてよかったです。
ありがとうございました。
確かに、プログラミングを始める段階では「言語は何でもよい」と思います。
ですが、プログラミングについて深く理解したい、と思う際は、どの言語か、が大事であるな、と最近痛感するようになってきました。
このことについて、新しく記事を書いたので、よろしければそちらもお読みください。
こんにちは。shundroid です。
夏休みが終わりに近づいてきました。
この夏にプログラミングを始めようという友達がいて、
どのようにプログラミングを教えるのが効率的なのか、
改めて色々考える機会がありました。
そこで思ったことを今回は書きたいと思います。
よく「Python がおすすめだ」とか「Unity できるやつかっこいい」とかいう言葉を聞くことが多いのですが、
僕はこれらの意見はプログラミングを始めるにあたってはそれほど関係ないと思っています。
これらの意見の根拠で、例えば「構文が簡略だ」というのであれば、僕は Scratch をおすすめすればいいじゃない、と思います。
また、「Python は深層学習などに強いから」というのもよく聞きますが、
果たしてプログラミングを始めた初心者は、本当にAIや深層学習の仕組みを理解し、自分で構築するレベルまで達するのでしょうか。
「プログラミングをやったことがある」と言う人たちでも、
サンプルコードを写して実行してできただけ、あるいは小規模なアプリを作っただけ、ということもあります。
これらの人たちは、本当に Python を学ぶことのメリットを享受できているのでしょうか。
他にも、「今流行だから」というのもよく聞きますが、流行はよく変わります。
流行に乗って選んだ言語でプログラミングを始めた人たちがその思考法を習得したころには、
もう流行はその言語ではなくなっているかもしれません。
だから、僕は、誰かが「この言語がいいぞ」などということは、そこまで重要なことではないのだと思います。
本当に大事なのは、プログラミングを通じて、自分が何を作りたいか ということです。
ゲームが作りたいわけではないのに Unity をおすすめするのは適していません。
スマホ向けアプリを作りたいなら、Java か Swift かを学んでみる、
自分が人工知能を作ってみたいなら Python を初めてみる、
Web サービスを作ってみたいなら HTML+CSS+JS を学んでみる、など。
プログラミングは 目的ではなく手段 なのです。
プログラミングを始めるにあたって、まず何を作るかを決めるのではなく、
言語を選び始める、というのは、僕は適切な手順ではないと思います。
言語ありきでプログラミングをしてはいけないと思います。
その意味で、僕は「言語なんて何でもいいのだ」と言っているのです。
先ほど「プログラミングは目的ではなく手段」だと書きました。
これは、プログラミングを学んでいく姿勢にもつながります。
例えば、変数や関数の概念や構文について、座学のようにネット上の記事を読んで理解したり、
ネット上のサンプルコードをコピペして動かしたりしているだけでは、
実際に思考法を身に着け、応用していく力には結びつかないと思っています。
「プログラミングって何なのか知りたい」という人で、割とそのような人がいるかもしれないのですが、
そのような学習方法をとっていると、進捗が生まれないか、あるいは挫折します。
また時間が空いて、ちょっとプログラミングしてみよっかなと思ったときに、忘れていたりします。
そこで、自分の作りたいものを開発しながら、プログラミングの基盤となる思考法を習得していく方法が、
最も効率の良い方法だと考えています。
もちろん、最初から壮大なアプリを作るわけではありません。
まずクイズアプリや Todo アプリなど、こういうのも作れるのだということを提示して、
それを自分なりにカスタマイズしながら製作していくうちに、プログラミングの「勘」がついていくものだと思います。
実際、僕も様々なアプリを製作していきながら、プログラミングを学んできました。
そこで学んだベースとなる考え方は、今も生きていると感じています。
さて、少し話題が変わりますが、「プログラミングができる」と名乗っていいのは、
どれくらいのレベルの人以上だと思いますか?
人それぞれだと思いますが、僕は 3.
以上だと思います。
「自分の考えているものを形にするプロセス」がプログラミングです。1.
2.
にはそのプロセスは含まれていないと思います。
誰かが書いたコードをコピペするのは誰だってできます。
それで正しく動いたとしても、そこには自分のクリエイティビティは入っていません。
何かを初めて自分の力で作れるようになった時、プログラミングができるようになったと言うのだと思います。
今まで僕は、小学生から大学院生、また社会人など、
色々な人とプログラミングをさせていただきました。
その中でお互いの持っている知識や考えていることを伝え合ったりする機会もありました。
今回このように友達にプログラミングを本格的に教えるということを通じて、
そこで考えていたことを明確にすることができ、
「教える」ということは本当に自分自身にも学びをもたらすのだと分かりました。
ご意見・ご感想などありましたら下のコメント欄にお書きください。
※今回はやけにまじめですね。これで終わります。
]]>ちなみにPC落としてから突然電源が落ちる問題が発生していたけど分解したら内部でねじが緩んでいたことが発覚しそこをきつくしたらなんと電源が落ちなくなりました。
— shundroid (@shundroid_p) 2018年8月7日
つまりノートパソコン直した―――――――やったーーーーーーーーーーー
こんにちは。shundroid です。
2年前の夏、ノートパソコンを落としてしまい、
そこから突然電源が落ちるようになっていた僕のノートパソコンが、
この度、なんと、直りました!
今回はその報告です。
ノートパソコンが壊れた話は前も↓の記事でちょろっとしましたね。
PC分解できたーー
— shundroid (@shundroid_p) 2018年8月7日
落としたのもあって左上のねじ穴が死んでたけど、外側のケースをひねってナットを固定したらねじが外せた。そこが一番難しかった。 pic.twitter.com/gBQRLNdyPG
PC は Sony 製 VAIO の SVE14A3AJ なのですが、
裏面のねじをすべて外したら簡単にケースを外すことができました。
確か分解したら Sony での修理が受けられなくなった気がするので、
本当に試すなら自己責任でお願いします。
この部分が落とした時に一番ダメージを受けたらしく、
ケースにも穴が開いていました。
そこは、分解するときにもナットが空回りしちゃって
ねじがなかなか外せない難しいポイントだったのですが、
それはいい感じの角度にケースを固定したら外せたのでまあよかったっす。
そしてこの分解した状態でPCを起動したとき、あることに気づいたのです。
ーこの部分の形が変形したときに、電源が落ちると。
どうやらここの部分の2つのねじがゆるんでいたようで、それをきつくしめてあげました。
そしたらなんと、電源が落ちなくなりましたーーー
復活です。やったーー
以上です。
まだ電源が落ちなくなってから1日しかたっていないので、
また再発するかもしれませんが、今のところいい感じです。
分解にはリスクも伴いますので、真似しないことをお勧めします。
]]>何かひと書きしてみたいところだったので、
クラスメートみんなで使える、何かを作ってみたいと思いました。
そこで LINE BOT の開発をしてみることにしました。
bot完成しました。近日中に仕組みをブログに公開します。 pic.twitter.com/oxhvmIq1fe
— shundroid (@shundroid_p) 2018年7月14日
「(名前)、○○」と話すと、某先生の写真と文字を合成した画像を返すbotです。
特徴はただ一定の画像を返すのでなく、「○○」の内容によって文字が合成されるので、
新たに名言が生まれても画像と合成できるようにしていることです。
次のようになっています。
LINEユーザーがメッセージを送信します。
これを bot 側は、Messaging API のメッセージイベントとして受け取ることができます。
そして、bot 側で登録した Webhook URL に POST リクエストが飛ぶので、
それを使って Heroku でデプロイしている node.js アプリケーションにメッセージを送信します。
ここですね。
node.js のほうとしては、LINE の Node.js SDK を使うと簡単に書くことができます。
内容も example の中身を少し変えただけなので、そっちを参考にしてもらったほうがよいでしょう。
Express を使っています。
ちなみに、ここはどうでもいいかもしれないんですけど、
最初は now というのを使おうとしていました。
しかし、これだと後ほど出てくる node-canvas をなぜかコンパイルしに行き、失敗するということをするので、
now 使おうとしたけど node-canvas をなぜかコンパイルしに行き失敗しちゃうから初めてトンネリングツール使ってみたけどかなり便利
— shundroid (@shundroid_p) 2018年7月14日
localtunnel というトンネリングツールで自分のPCに直接アクセスするようにしました。
しかしこれだと自分の PC がついていないとだめなので、Heroku を使うようになった次第です。
初めて Heroku 使いましたけど、かなり便利ですね。すごい。
画像形式でメッセージを送ります。
Messaging API のリファレンス を参考にして、
1 | { |
こういう形式で作ります。
ここで気を付けなければならないのは、画像の形式とサイズですね。
どちらもJPEGでなければなりません。なんと。
サイズは originalContentUrl のほうが1024x1024まで、
previewImageUrl のほうが240x240までです。
ここでの URL は今回は(original…、preview…どちらも)次のようにしました。
1 | https://xxxxx.herokuapp.com/image/<名言> |
後で URL を参照したとき、名言の文字が入っていないといけないからです。
さっき作ったメッセージを送りますね。
これも example と同じなのでそっちを見てください。
bot 側が URL を参照してきます。ここで初めて画像の合成をするようにしています。
先ほど名言は URL に含まれていたので、
1 | app.get('/image/:text', (req, res) => { |
というようにパラメーターで指定しておきます。:text
には req.params.text
としてアクセスできます。
HTML5 Canvas みたいな感じで合成出来たら手軽だと思ったので、
node-canvas というものを使いました。
使い勝手はほんとに HTML5 Canvas そっくりです。すごい。
はまりかけたところはまずフォントですね。
1 | const { registerFont, createCanvas } = require('canvas') |
このような感じで使えます。
あと、JPEG 画像として返すところですね。
1 | const { createCanvas } = require('canvas') |
こんな感じですね。createJPEGStream で Stream を作ったのを
pipe して res に渡すだけでおkでした。
Express こんな方法にも対応しているのですね。さすがー
本当に誰得かわかりませんが面白いものができました。
でもこういうものを通じて、今回は express、LINE bot の作り方、
Heroku、now、localtunnel、node-canvas など、様々なものについて学べました。
そして bot 作り自体はそこまで難しくなさそうですね。
これなら、身近な LINE ですし、プログラミングの入門としてもいいかもしれません。
今度部活のみんなでbot作ろう会をやってみよっかな。
]]>https://t.co/rXsQJEGyF7
— shundroid (@shundroid_p) 2018年6月2日
できた!!!!
こんにちは。お久しぶりです。shundroid です。
高校生になりました。
いやー忙しい。最近もテストがありましたが、
テスト範囲が広すぎて本当に大変でしたー。
そこで疲れを癒やしたいのもあり、1つサービスを作ってみました。
ガロア理論ジェネレーターです。
https://galois-gen.netlify.com/
製作期間は2日です。
今回はどうやって作ったかなどを紹介したいと思います。
これを入れておいたから許していただけるだろう pic.twitter.com/ytq0QWOQCR
— shundroid (@shundroid_p) 2018年6月2日
https://github.com/shundroid/galois-gen
Github に上げておきました。参考にしてみてください
スマートフォンやPCなど、多くのデバイスで動作させたいため、
Web アプリとして制作しました。
MVVM であり、Vue.js で書いていますね。
いやーほんとに Vue はシンプルで素晴らしい。
仕組みとしては、既存の表紙の画像の上に、
文字を HTML 要素としてのっけてって、
エクスポートするときに html2canvas を使って画像にするようにしています。
UI は Vuetify で作りました。
スマートフォンでもPCでも動くようにしたかったので、
避けては通れぬ壁でした。
表紙の画像のサイズが可変なので、それに合わせて文字などを
相対的な座標で表す必要がありました。
em とか % とか使っていますね。
margin で em を使う日が来るなんて思いもしなかったですね。
ちなみに em は親要素の font-size に応じて自由にサイズ調整ができるので便利ですよ
これはサイズを要素間の比率を維持したまま一括変更したいときに、font-size を変えるだけでいいので
非常に便利です。ここの話は聞き流してもらっても構いませんでした。はい。
HTML の要素として作られた冊子を画像に変換するときに、
このライブラリを使うんですけど、マジこれバグありすぎー
— shundroid (@shundroid_p) 2018年6月2日
writing-mode で縦書き指定してたら作者名が死にました。
そのせいで縦書きにするのに苦労しなければならなくなりました。
これはもう1文字ごとに <br />
を打ち込むようにしました。
仕方がないですね。お許しください。
字間は line-height で調整ー
英語はなんと、文字を回します
あーこれ writing-mode つかえないとか
transform 使わなきゃいけない感じじゃねーと察しますよね。
そうなんです。使うんです。
回しました。
最初は pivot がおかしくなりそうで苦労していましたが、
調べてみたら transform-origin とかいう神プロパティがあるそうで
それで意外とかんたんにできましたー。やったー
皆さんガロア理論の本おすすめです。
]]>今回は新しく作った Hexo のプラグインについて、
仕組みや工夫したところなどを書きたいと思います。
client 側の工夫したところが消えましたw
多分 vscode-vim で insert モードを解除せずに消しちゃったからかな
とりあえず大まかには書いておきました。
hexo-generator-search で生成された search.xml を使って、
検索結果を表示するページを作成します。
このブログでも使用しています。
サイドバーの検索ボックスで検索すると、このプラグインで生成されたページが表示されます。
1 | $ npm install hexo-generator-search |
続きは上のリポジトリのREADME.mdに書いてあります。
空のページを作成し、そこに {% search_result %}
と書くことで、
ページが表示されるようにしています。
このタグが読み込まれると、そこに <div>
<script>
<style>
が
挿入されるようになっています。
index.js1
2
3
4
5
6
7
8
9
10
11
12
13
14const fs = require('hexo-fs')
const path = require('path')
function insertSearchResult (args) {
return Promise.all([fs.readFile(path.join(__dirname, './client.js')),
fs.readFile(path.join(__dirname, './style.css'))]).then(contents => {
return '<div id="plugin-search-result"></div>' +
'<script>' + contents[0] + '</script>' +
'<style>' + contents[1] + '</style>'
})
}
hexo.extend.tag.register('search_result', insertSearchResult, {
async: true
})
script、style の読み込みは、webpack などをつかってもよかったのですが、
今回は小規模に作りたかったので、単純にファイル読み込み+inline 出力で実装しました。
この時、タグの中身に非同期プロセスを含みますので、tag.register
には引数で { async: true }
を渡しています。
また、fs は代わりに hexo-fs を利用して、それが Promise を返してくれています。
2ファイル読んでいるので、Promise.all を使用して並立にしています。
ここで読み込んでいる script は、ブラウザ側で動作しますね。
そちらも見てみましょう。
流れは、
という感じです。
このような感じでプラグインを作りました。
よろしければ使ってみてください。
バグ・機能要望などは Github Issues へ。
Spacechem の解法、Sync の3つ目です。
今回は Sync コマンドの応用の使用法の1つである、
何回かに1回
について説明しようと思います。
具体的には、
1つのウォルドが何回か実行するたびに、
もう1つのウォルドが1回処理する
というのを繰り返すことです。
例として、ヘーパイストスIV のサイドストーリー、
KOHCTPYKTOP の、ケイ素の分子を作り出すところを見てみましょう。
めちゃくちゃ長い処理になってしまったので、
早送りしていますが、
赤のウォルドで2回輪の形をしたケイ素の分子を作った後、
青のウォルドで1回3×3の正方形を作っています。
ここでは、「2回に1回」という仕組みが使われています。
どのような仕組みになっているのでしょうか。
このように、赤のウォルドに sync が2つあるのに対し、
青のウォルドに sync が4つあるので、
赤が2回回らないと、青が1回回らない、
つまり「2回に1回」が実現しています。
↑単純化してみました。
横が時間軸、赤と青が処理するウォルドを表しています。
公式っぽくすると、
赤がn回処理した後、青が1回処理する場合、
赤に sync を2つ、青に sync を 2n 個つける
と、3回に1回、4回に1回、…でもできます。
前回の交互に実行も、
今回の公式っぽいのを使えば、「1回に1回」として sync の数がわかります。
こっちのほうが言葉通りな気もします。
何回かに1回、同時に実行します。
2回目で重なって実行されます。
この2つ、何が違うのでしょうか。
実は Sync の位置がとても重要になっています。
Sync の位置により、この2つの動作が変わってきます。
この例でいえば青のウォルドの上下左右どれかに、奇数個の Sync があれば、
何回かに1回、別々に実行する、
先に書いたほうの動きをします。
この例でいえば青のウォルドの上下左右どれかに、偶数個の Sync があれば、
何回かに1回、同時に実行する、
後に書いたほうの動きをします。
次のような動きをするにはどうすればよいでしょう。
赤1回、青1回、赤1回、を繰り返します。
赤と青が同時に処理しないので、先に述べた方法で、
奇数個の sync が青の両側にあります。
そして、その sync の配分を替えると、タイミングが変わります。
こんな感じで、Sync を使えば、様々な処理を自在にできます。
かなり奥深いです。ぜひ実践してみてください!
Hexo にブログを移行しましたが、
一回一回記事を上げるごとに、git commit
して hexo deploy
するのは
めんどくさいですよね。
そこで、今回は wercker を使って git commit されると自動で
デプロイしてくれるようにします。
上のような形を目指し、今回 Wercker に関するところを作っていきます。
間に通しすぎじゃないか!?と言われるかもしれませんが、それぞれ意味があります。
Github がいらなそうですが、
ぼくはこのサイトを、パスワードなどを含めない部分はオープンソースにして、
構造などを公開したいと思っているので、いります!
Netlify じゃなくて Github Pages でもよさそうですが、
性能が Netlify のほうがいいので、そっちを使っています。
プロジェクトのルートディレクトリに、
wercker.yml を次のような内容で作成します。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31box: node
build:
steps:
- npm-install
- script:
name: echo nodejs information
code: |
echo "node version $(node -v) running"
echo "npm version $(npm -v) running"
deploy:
steps:
- script:
name: configure git
code: |-
git config --global user.email <Github メールアドレス>
git config --global user.name <Github ユーザー名>
- script:
name: install theme
code: |-
git clone https://github.com/shundroid/hexo-theme-chan.git themes/chan/ --depth=1
- script:
name: install hexo
code: |-
sudo npm install -g hexo
- script:
name: deploy to github
code: |-
hexo clean
hexo generate
hexo deploy
build のほうはデフォルトから変えていません。(デフォルトはあとで登場します)
deploy 側が独自です。ここには僕がハマった経験がたくさん詰まっています。
deploy 内で、install theme していますね。
これなのですが、テーマをクローンし忘れると、WARN No layout: xxx
というエラーが出まくり、
空のブログが作成されますw
ちなみに、 --depth=1
を入れると、深く log を取らないので、
パフォーマンスの改善になります。
ご自分のテーマに合わせて、クローン元・クローン先を変更してください。
プロジェクトにインストールされている hexo を、./node_modules/.bin/hexo
として実行しようとしましたが、全く反応しなかったです。
npm scripts にコマンドを追加してもやってみましたが、同様でした。
仕方なくグローバルインストールしました。
https://github.com/settings/tokens/new
↑にアクセスして、Token を作成します。
チェックは、public_repo にのみ入れてください。
トークンができたら、暗記してください(大嘘)
というか暗記できるくらいの記憶力が欲しいよ――
これから、プロジェクトにトークンを書き込みますが、
この時、プロジェクトが公開されていると、かなりセキュリティ的に危険です。
非公開にしましょう。※ブログを非公開にするのではありません
Github は学生でなければ非公開リポジトリは作れませんが、
Bitbucket は無料で作れます。ぼくは Bitbucket を使っています。
また、プロジェクトを公開しなければならない場合は、
Wercker 側にトークンを非公開で設定し、それを使うという方法もあるそうです。
プロジェクトのルートディレクトリにある、_config.yml を変更します。
deploy のところですね。
1 | deploy: |
↑にアクセスして、Sign up しておいてください。
https://app.wercker.com/profile/connections
ここにアクセスして、プロジェクトが使っているリモートのサービスとリンクしましょう。
ぼくは Bitbucket なので、Bitbucket とリンクしました。
https://app.wercker.com/applications/create
ここにアクセスして、アプリを作りましょう。
といっても超シンプルです。
まず SCM を選びます。これはプロジェクトが使っているやつですね。
ぼくは Bitbucket なのでそれを選びました。
選んだら Next
リポジトリを選びます。これはそのプロジェクト自体ですね。
選んだら Next
その次は deploy key に関するやつですが、recommended でいいので Next
その次は公開したいなら Make my app public ですが、
どっちでもいいです。
これで完了です。
色々出ていますが、すでに wercker.yml は作っているので気にしなくていいです。
あと少し!
上のほうのタブの「Workflows」を押します。
「Add new pipeline」します。
写真のように、Name も YML Pipeline name も deploy でお願いします。
Create を押します。
色々出るので、もう一度 Workflows を押します。
Editor の + を押して、
Execute Pipeline を deploy にして、Add しましょう。
これで、build 後に deploy が走るようになりました。
さて、これでコミットしてプッシュしたら、
deploy されるはずですね。
ローカルで、1
2
3
4
5$ git status
<wercker.ymlが追加されていることを確認>
$ git add .
$ git commit -m "added wercker.yml"
$ git push origin master
ブランチ名、リモート名は自分の環境に合わせ変えてください。
コミット名は何でもいいですよ。
こんな感じで build、deploy ともに成功すれば多分おkです。
Github のほうにも push されていることを確認しましょう。
ぼくがハマったポイントを改めて書いておきます。
さて、これで自動 deploy ができました。
しかし、まだ改善点はあります。
hexo を毎回グローバルインストールするのもあれなんで、
すでに hexo が入った box を使いたいですね。
wercker らしい感じもします。
やろうと思いましたが、ちょっと疲れちゃって挫折しました。
とりあえず現状で動くので、将来的に直します。
さて、ブログを WordPress から Hexo に移転しました!
ここではブログ移転の経緯などを説明していきたいと思います。
いつもありがとうございます。
Hexo ではデフォルトでメールアドレスによる購読ができません。
今後プラグインを使い、対応させていくかもしれませんが、
それまで、前のサイトでも使っていた、
Feedly などの RSS リーダーによる購読をよろしくお願いします。
WordPress は、ページを表示する際、動的にサーバー側でいろいろするので、重いんです。
それに対し、このサイトでは、すでにある Web ページをただ単に表示しているだけなので、処理が少なく、軽いんです。
WordPress は、プラグインの作成やテーマの編集に、php を使っていました。
Hexo では、すべて自分の専門分野である JavaScript で開発できるので、すごく楽なんです。
もうすでに1つ独自プラグインを使用しており、テーマも自分好みにがりがり改造しています。
それについても記事を上げたいと思います。
今まで polaris-bear.lolipop.jp
と、謎のドメイン名でしたね。
これは、母のサイトのドメインを使って、僕のブログをやっていたので、
こういう名前になってしまっています。
しかも lolipop って打ちにくいですよねw右手の薬指と小指がww
今回は URL が単純になります。ご安心ください。
サーバーサイドで記事を追加したり削除したりできないので、
不正ログインなどの概念が(Github を除けば)なくなります。
実はサイトの運営には一切お金がかかっておりません。
詳しくは、↓で書きたいと思います。
何度か書いていますが、このサイトは Hexo を利用して作られています。
Hexo とは、静的サイトジェネレーターで、
記事やテーマ、プラグインなどをもとに、静的なサイトを自動生成するものです。
その生成されたサイトが、Github のレポジトリに送られ、
それが Netlify によってホスティングされています。
Github のレポジトリを直接ホストする、Github Pages もありますが、
Netlify はよりパフォーマンスが良く、リポジトリをそのまま使えるので、使用しています。
Hexo による生成の処理は、ローカルで行っています。
Netlify の CI で自動生成もできるらしいのですが、タイムアウトがあるらしく、
15分以内にビルド&デプロイできないと、強制停止されてしまうそうです。
そのため、シンプルにローカルで生成するようにしました。
サイト全体のバージョン管理には、
無料で非公開リポジトリが作成できる Bitbucket を使用しています。
また、Github、Netlify、Hexo など、すべて無料で使用しています。
これがオープンソースの力よ!浮いたお金でいつかは独自ドメインとるぞ!
自分でプラグインやテーマなどを作れるので、
どんどんカスタマイズして、自分らしいブログを作っていきたいです!
Spacechem の解法、Sync の2つ目です。
今回は Sync コマンドの応用の使用法の1つである、
交互に実行
について説明しようと思います。
具体的には、
1つのウォルドの処理が終わったら、もう1つのウォルドの処理を行う
というのを繰り返すことです。
例として、ヘーパイストスIV のサイドストーリー、
KOHCTPYKTOP を見てみましょう。
ヒ素とホウ素を、1つずつ交互に ψ に出力しています。
これも Sync コマンドを使って実装しています。
どのように実装しているのか見てみましょう。
Sync コマンド2つが使われていますね。
これは前回、「待機」としての「同期」で説明したのと同じ方法で、
片方の処理が終わるのを待機している、という意味です。
注目すべきは Start ブロックの位置です。
赤のほうは Sync に挟まれて、
青のほうは Sync の手前にあります。
ここからわかるように、青のほうは赤の処理がすべて終わるのをまず待機していて、
その後、赤のほうは青の処理がすべて終わるのを待機しているのです。
このようにすることで、交互に実行することができています。
1つの物質を2つの反応装置へ分岐させたり、
あるいは2つの物質を1つの反応装置へ集めたりするときに使えます。
しかし、この方法は、後に出てくる Flip Flop で、
必要なくなってしまいます。
わざわざ2つのウォルドを使わなくても、1つのウォルドで交互に処理ができるようになるのです。
Flip Flop が使えるのはアトロポス基地以降なので、
それまではかなり使えて便利な解法パターンです。
Spacechem の解法、Sync の1つ目です。
今回は Sync コマンドの使い道の1つである、
「待機」としての「同期」
について説明したいと思います。
その前に、まずは Sync の基本的な使い方を説明します。
Sync は、基本的に
2つのウォルドのタイミングを合わせる
ために使います。
例として、アルコノストの1ステージ目「検出の基本」を見てみましょう。
このように、2つのウォルドが、自転車のペダルのように、
ぐるぐると回っていますね。
2つのウォルドのタイミングを合わせることで、原子同士の衝突を防いでいるのです。
2つのウォルドで操作すると、
速度は2倍になりますから、
クリアに必要なサイクル数は2分の1と、減らすことができます。
もちろん、タイミングを合わせるのは、結合時など、
これ以外の使い方もできます。
それでは、本題に移りましょう。
Sync コマンドは、「待機」としての使い方もできるのです。
例として、ダノプスのサイドストーリー、実験:その場で入れ替えを見てみましょう。
いくつか Sync コマンドがありますが、下の Sync コマンドに注目してください。
1ウォルドに2つずつ、Sync コマンドがありますね。
赤のウォルドが結合装置の手前に来た時に Sync して、
その後もう一度 Sync しています。
最初の Sync で、青のウォルドは結合の除去を開始していますね。
除去が終わったら再び Sync して、赤のウォルドを動かし始めます。
このように、Sync コマンドには、
片方の処理が終わるまで待機する
という使い方ができます。
このような場合、片方の処理を開始するため、
通常2つ Sync をセットにして使うことが多いです。
この考え方は、ゲームの最後の最後まで使うことができるので、とても便利です。
]]>