JavaScript
FizzBuzz
AST
babel

面接でFizzBuzzを書けと言われたときにすべきこと

こんなツイートを見つけました。

FizzBuzzにTensorFlowが必要?
ウケる。
もちろんFizzBuzzに必要なのは、Babelですよね。

では、まずBabelをインストールします。

$ yarn add --dev babel-cli babel-plugin-fizzbuzz
$ echo '{"plugins": ["fizzbuzz"]}' > .babelrc

REPLで実行します。

$ yarn run babel-node
>  for(var i = 1; i < 100; i++) { console.log(i) }
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
...

https://gyazo.com/f2340f77fa9668181cba42c8e19132c1

これで面接のFizzBuzz対策も完璧ですね。

何が起きていますか?

for (var i = 1; i < 100; i++) {
  console.log(i)
}

           

for (var i = 1; i < 100; i++) {
  console.log(
    i % 15 === 0 ? 'FizzBuzz' : i % 3 === 0 ? 'Fizz' : i % 5 === 0 ? 'Buzz' : i
  )
}

どうやっていますか?

console.logを問答無用でFizzBuzz出力マシーンに変換にします。

// @flow weak
import looksLike from 'babel-looks-like'
// import blog from 'babel-log'

const consoleLogPath = {
  node: {
    callee: {
      type: 'MemberExpression',
      object: { name: 'console' },
      property: { name: 'log' },
    },
  },
}

const CREATED = Symbol('CREATED')

export default ({ types: t, template }) => {
  const builder = template(`
  console.log(ID % 15 === 0 ? 'FizzBuzz' : ID % 3 === 0 ? 'Fizz' : ID % 5 === 0 ? 'Buzz' : ID)
  `)

  return {
    name: 'fizzbuzz',
    visitor: {
      CallExpression(nodePath) {
        if (nodePath[CREATED]) {
          return
        }

        if (!looksLike(nodePath, consoleLogPath)) {
          return
        }

        const { node: id } = nodePath.get('arguments.0.name')
        nodePath.replaceWith(builder({ ID: t.identifier(id) }))
        nodePath[CREATED] = true
      },
    },
  }
}

おわりに

もしこれを面接でやって落ちても一切の責任は取りません。

akameco/babel-plugin-fizzbuzz
Babel Plugin for fizzbuzz

関連

JavaScriptのfloatで正確な比較を行う - Qiita

もしより邪悪なBabelPluginについて知りたければ以下の記事もご覧ください。

さよならボイラープレート。s2sによる高速reduxアプリケーション構築
https://qiita.com/akameco/items/e1489c6bbf3439ec6ca4