Home About Contact
GitHub Copilot , JavaScript

GitHub Copilot を体験した

GitHub Copilot and VSCode

GitHub Copilot が VS Code で使えるようになっていることが前提です。 ちょっとしたテキスト処理をすることがあるので、 それを念頭に試しました。

使い方は簡単で、おおざっぱに言えば「適宜ゴーストテキスト(Copilotによる提案)が出るからタブ押す」だけです。 もちろん、これ以外の使い方もあるはずです。

VS Code で main.js を作成して、次のコードを記述します。

const text = "Pikachu(h=60),Charmander(h=90),Squirtle(h=92),Metapod(h=85)"

この text を処理する方法をコメントとして書きます。

// カンマで名前を取り出して配列にする

実際はコメント書いている途中でもコメントの続きのゴーストテキストは出ます。 もしそれが期待したものであれば、タブ押すだけです。

コメントの入力が終わると、次のコードがゴーストテキストとして出ました。

const names = text.split(',')

はい、タブを押して確定。

まあ、このくらいは当然できるだろという想定範囲内です。

次に 括弧内のヒットポイント値でソートして出力したいので・・・ 次のコメントを記述:

// h の値が高い順にそーとする

「そーと」がひらがなになってますが、原文ママということで...

すると:

const names = text.split(',').sort((a, b) => {
  const aHP = a.match(/h=(\d+)/)[1]
  const bHP = b.match(/h=(\d+)/)[1]
  return bHP - aHP
})

がゴーストテキストとして出てきました。あってるかしらんけど、とりえあずタブを押す。 すると、次のゴーストテキストが出る:

console.log(names) // ["Squirtle(h=92)", "Charmander(h=90)", "Metapod(h=85)", "Pikachu(h=60)"]

まじで?!

実際にコンソールで node main.js すると確かに names は h の大きい順にソートされた配列になっています。

$ node main.js
[
  'Squirtle(h=92)',
  'Charmander(h=90)',
  'Metapod(h=85)',
  'Pikachu(h=60)'
]

ソートのコードの変数を見ると aHP, bHP となっている。 これ、コパイロットの中のひとは対象となるデータがポケモン名で h= の部分がヒットポイントだということに気づいているのだろうか? そういえば配列の変数名も names になっているし。

コードをよく確認してみる

Copilot が提案してきたコードはこれ:

const names = text.split(',').sort((a, b) => {
  const aHP = a.match(/h=(\d+)/)[1]
  const bHP = b.match(/h=(\d+)/)[1]
  return bHP - aHP
})

気になるのは正規表現でヒットポイント値を取り出しているところ。 数値だけにマッチ \d+ させてはいるものの・・・ aHP とか bHP の型はたぶん string だよね。

となるとこの部分:

  return bHP - aHP

string 同士の引き算をしていることになる。 これは気持ち悪い。

確認用のコードを書いてみる:

// check.js

const a = "Pikachu(h=60)"
const b = "Charmander(h=90)"

const aHP = a.match(/h=(\d+)/)[1]
const bHP = b.match(/h=(\d+)/)[1]
const sa = bHP - aHP

console.log(`aHP = ${aHP} : ${(typeof aHP)}`)
console.log(`bHP = ${bHP} : ${(typeof aHP)}`)
console.log(`sa  = ${sa}  : ${(typeof sa)}`)

実行する:

$ node check.js
aHP = 60 : string
bHP = 90 : string
sa  = 30  : number

string 型同士の引き算の結果の型は number になっている。 じゃあいいのか。気持ち悪いけど。

そんな細かいこと言うならはじめから TypeScript で書けよ、ってことかな。

このように string を明示的に number にキャストする記述を入れたならば許容できるのかな。

const names = text.split(',').sort((a, b) => {
  const aHP = a.match(/h=(\d+)/)[1]
  const bHP = b.match(/h=(\d+)/)[1]
  return Number(bHP) - Number(aHP)
  //return parseInt(bHP) - parseInt(aHP)
})

もちろん、ヒットポイントのないデータがあるとかヒットポイント値が間違って全角数値や数字以外の文字で指定されていると、たぶんこのコードでは対処できない。 ・・・とはいえ、 ここでは、はじめにこの text を提示した上で、Copilot にコードを提案してもらっている:

const text = "Pikachu(h=60),Charmander(h=90),Squirtle(h=92),Metapod(h=85)"

だから Copilot にしてみれば、 h=百二十 とか書いている場合を想定したコードを提案しろとか聞いてないわ!という話だと思う。