経済成長はなぜ必要か

あままこ(id:amamako)さんのこの記事へのお返事です。

長らくブログでの議論からは離れていたのですが、Twitter のつぶやきで済ますには込み入った話ではあるのでエントリにします。あままこさんのブログも何年ぶりかもわからないくらい久しぶりに読んだので、色々前提を見逃しているかもしれませんが、ご容赦ください。

「富国強兵と経済成長をごっちゃにしてるところで読むのやめた」とコメントした安冨氏の記事はその後も読んでないのですが、この件に関してはたぶん差し支えないと思うので読まずに書きます。

僕は日頃から「経済成長が大事」と主張していますが、そこで僕が言いたいのは「生産性を上げていこう」という話ではない、という話をします。

そもそも生産性というのは嫌でも上がっていくものなのです。労働者の日々の創意工夫や突発的な技術革新によって、同じモノを作ったりサービスを提供したりするのに必要なコストは下がっていきます。言い換えるとより少ない労働者で同じだけのモノ・サービスが供給できるようになります。*1

ということは、ただ生産性が上がるばかりで需要の拡大が伴わないと労働者が要らなくなるわけで、失業が発生したり所得が減少したりします。「供給ではなく需要が問題」というのはそういうことなのです。つまり、生産性の上昇に見合っただけの需要の拡大=経済成長が必要である、というのが僕の考え方です。なので、経済成長と言っても年率にして数%程度が必要だと言っているに過ぎません。

以上は『経済成長って何で必要なんだろう?』の飯田泰之氏と岡田靖氏の説に依拠しています。*2 このあたり、はっきり理論化されて定説になっているわけではないので、どこまで正しいのかわからないのですが、ともあれ、僕はそういう立場から「経済成長が大事」と言っているわけです。

なので、僕の経済観からすると、あままこさんの言う「「経済成長を維持することを第一に考える社会」というのは、「生産と消費を増やすことを常に人々に強いる社会」」というのは前提からして違う、と言わざるを得ません。

生産性の向上は、経済成長のために強いられているのではなく、個々の生産者が利益を追求する過程で必然的に生まれるもので、しかし経済成長がないと副作用として失業やらラッダイト運動やらが発生してしまいます。そういう順番の理屈なのです。

なので、僕の立場からは「生産性で人間をはからせない世の中」と経済成長は両立します。

というよりは、経済成長がなければ労働力は余り、余った労働力を選別する際に「生産性で人間をはかる」論理が顕在化してしまうので、低すぎる経済成長は「生産性で人間をはからせない世の中」の実現の足を引っ張ることになるのではないでしょうか。

経済成長があれば「生産性で人間をはからせない世の中」になるというわけではありませんし、そもそも所有権の根拠を労働に求める以上「生産性で人間をはかる」考え方からは逃れられないのかもしれませんが、誰かのクビが切られなければ自分のクビが切られるという状況では「あいつの方が生産性が低い!」という足の引っ張り合いが横行してしまいます。

生きられた現実を「生産性で人間をはかる」論理で正当化し、その論理に絡め取られてしまって非人道的な政策を容認してしまう、といったことも起こるかもしれません。そういう意味では、「生産性で人間をはからせない世の中」を作りたいなら経済成長はあった方がいいのではないでしょうか。

一方で経済がどうであろうと経済成長を「富国強兵」の言い換えぐらいにしか思っていない人がいるのも事実でしょう。安倍首相だってそうかもしれません。市民の生活よりも日本を偉大な国家たらしめるために経済成長率は高ければ高いほどいい、そして国家に貢献しない生産性の低い「生きるに値しない命」*3 は… みたいなことを考えている人だっているでしょう。

でも「富国強兵」を否定するために経済成長を否定する必要はないのです。僕ならただ一言「「生きるに値しない命」などない」と言います。それ以上の理屈など不要ではないでしょうか。

*1:ここまでの話は、モノやサービスを作るのに必要な資源は足りているというのが前提で、資源が枯渇して同じモノを作るのに必要なコストが上がっていくような状況では話は違ってきますが、現状あるいは向こう数十年はトータルで見れば資源不足は問題にならない、という認識で話を進めます。

*2:

*3:ナチスの障害者殺害政策(T4作戦)のキーワード。

Ubuntu 18.04 の Shotwell で Flickr にログインできない

Ubuntu 18.04 の Shotwell (0.28.4)から Flickr に写真をアップロードしようとしたところ、間違ってログアウトボタンを押してしまい、しょうがないなーと思ってログインしなおそうとしたらログインできませんでした。

最初は yahoo.com のアカウントのメアドとパスワードを入れてもパスワードが違うと言われてログインできず、おかしいなと思いブラウザ上から yahoo.com にログインしたところ普通にログインできて、同じメアドとパスワードで flickr にログインしようとするとやはりパスワードが違うとエラーに。

わけがわからないのですが、とりあえずパスワードリセットをかけてパスワードを再設定したところ数分ラグがありましたがログイン出来るようになりました。

問題はその後で、Shotwell の Flickr ログインの方は OAuth の許可画面が出るところまではたどり着いたのですが、許可のボタンを押しても Flickr authorization failed となってアップロードに失敗します。

"Flickr authorization failed" でググると、どうも Shotwell のバグのようで既に修正済みとのこと。ずっとログインしっぱなしだったから気付きませんでした…

ソースコードの修正は2018年11月14日。Ubuntu 18.04 の Shotwell の最新は 0.28.4 で更新は11月12日ということで、修正は入ってません。

しょうがないので PPA から最新の 0.30.4 を入れることにしました。

上の修正をコミットした人がやってる PPA だから大丈夫でしょう。

パッケージ構成が変わったのか shotwell-common が削除されたりしてビビりましたが、無事アップロードできるようになりました。デフォルトでダークモードになってましたが、これは設定で変えられるようです。

はてなブログライター v0.9.1

はてなブログライター v0.9.1 をリリースしました。新機能はなく、バグフィックス版です。

変更点

  • hbw.rb で初回投稿を行う前に hbw.rb を実行した場合にエラーになるバグを修正しました。
  • hbw.rb で初回投稿を行う前に hbwdl.rb を実行した場合にエラーになるバグを修正しました。

hbwdl.rb がエラーになった場合の注意点

hbwdl.rb が上記バグでエラーになった場合、エントリファイルが1件ダウンロードされた状態で停止しますが、このファイルは次に hbw.rb を実行する前に必ず削除してください。そうしないとこのファイルがローカルで新規作成したエントリファイルと誤認され、hbw.rb で新規エントリとして投稿されてしまいます。

実は hbwdl.rb 開発中にダウンロードされたエントリが新規エントリとして投稿される現象が発生してその後再現しなくて気になっていたのですが、どうやら上の現象と同様の現象のようです。

開発中のバグでダウンロードしたエントリの投稿データファイル(.dat)の保存に失敗した場合に、対応する dat ファィルのないエントリファイル=新規エントリファイルとして扱われてしまったようです。hbwdl.rb を再実行してもそのようなファイルに対しては上書きを行わず同じエントリのファイルを連番のファイル名で保存するので問題は解決しません。

ということは上記バグ以外でもIOエラーや強制終了などの理由で .dat が保存されなかった場合は同じ現象が発生するはずですが、これはどうしようかな… .dat 保存完了までエントリを仮のファイル名で保存して最後にエントリファイルの書式のファイル名にリネームすればいいのかな?これは次のバージョンで対応するかもしれません。

このブログについて

はてなダイアリーのインポートの件も落ち着いたので、このあたりでこのブログの自己紹介をします。

このブログは「はてなダイアリー」で2004年から15年近く続けていた「児童小銃」というブログの移転先です。id:rna = なんばりょうすけ が書いています。

元々このブログはダイアリー以外のあちこちの場所に書き散らした文章を一か所に集める目的で始めたものです。ブログの名前「rna fragments」*1 も断片的な文章を集めたものという意味でつけた名前です。

はてなダイアリーのサービス終了にあたり、「児童小銃」の移転先をどうするか考えたのですが、このブログにコンテンツをマージして移転先としました。リダイレクト設定もしてあるので、「児童小銃」の記事へのリンクはこちらのブログの記事に転送されるようになっています。

「児童小銃」のテーマは「見えない自由がほしくて/見えない銃を撃ちまくる」(THE BLUE HEARTS『TRAIN TRAIN』)でした。精神の自由のために容赦ない言論を書き綴る、という意味をこめて、ブログのトップにこの歌詞を引用していました。

「児童小銃」はプライベートな日記ではありましたが、社会問題について議論することも多く、トラックバックやコメント等で多くの方々とやりとりをさせていただきました。得るものも失うものもありましたが貴重な体験でした。

移転にあたって、ブログの名前をどうするか少し悩んだのですが、今の自分はもう「見えない銃を撃ちまくる」ような気力も体力もないですし、思考の断片を残すのがせいぜいだろうという思いもあって、「rna fragments」のままにすることにしました。

このブログとは別に、2017年から「Deep Sky Memories」という天文の趣味に特化したブログを始めて、そちらをメインブログにしています。「Deep Sky Memories」の紹介はこちらのエントリを参照してください。

はてなでブログを始めて15年、個人サイトで日記を書いていた頃から数えると22年以上ネットに文章を書き綴る生活を続けてきましたが、ここ10年ほどはつぶやきばかりでまとまった文章を書くことがほとんどなくなりました。

理由は色々あるのですが、一つにはネットでのコミュニケーションが負担になってきたということがあります。議論する際に、立場の違いはあっても前提は共有できている、という期待ができなくなってきたと思います。

また、これは特に東日本大震災原発事故の後からだと思いますが、通じ合える部分をみつけて仲間意識を持つというよりは、通じ合えない部分をみつけて敵対する、という関係が多くなったように思います。

理由のもう一つは、専門家のネット進出です。ネットの黎明期と違って今は様々な分野の専門家が自らネットで情報発信し、議論する時代です。特に若手はデジタルネイティブでネットでの立ち回りも一流です。ネットに強くてちょっと文章が書ける、という程度の素人の出る幕はありません。

もちろん素人の書くものにも意味はあります。同じ事を考える仲間がそこにいる、ということに勇気づけられる人も多いでしょう。でも僕自身がそういう連帯感にあまり興味がない、というか、どうしても違う意見を持ち出した時に生まれる軋轢の方を心配してしまうのです。

そういうわけで、以前のようには続けられませんが、気が向いた時に何か書く場としてこのブログを使おうと思います。

あと、はてなブログ投稿用のコマンドラインツール HatenaBlogWriter のサポート窓口としてもこのブログを使います。

そういうわけでよろしくお願いします。

*1:昨日まで fragments のスペルが間違っていました…

ISBN/ASIN リンクの修正

はてなダイアリーインポート後の「やり残し」の件。

確認中に気付いたのですが、a タグの href 属性値に書いたisbn記法やasin記法もはてなブログでは展開してくれないんですね… これは別途対処しようと思います。
id記法のリンクの修正 & お詫び

これですが、以下のようなスクリプトで対処しました。id記法リンクの修正まで終わったエントリファイルを orig2 ディレクトリにコピーしてから実行します。

#!/usr/bin/env ruby
# coding: utf-8
# HatenaBlogWriter のワーキングディレクトリで実行します。
# orig2 ディレクトリに変換前のエントリファイルをコピーしてから実行します。

ORIG_DIR = "orig2"
TB_SECTION_SEPARATOR = '<!-- trackback -->'

def load_entry_file(filename)
  header = []
  body = []
  tb = []
  File.open(filename) { |file|
    in_header = true
    in_tb = false
    file.each_line(chomp: true) { |line|
      if (line == TB_SECTION_SEPARATOR) then
        in_tb = true
        next
      elsif in_header && /^$/.match(line) then
        in_header = false
        next
      end
      if in_header then
        header.push(line)
      elsif in_tb then
        tb.push(line)
      else
        body.push(line)
      end
    }
  }
  return { :header => header, :body => body, :tb => tb }
end

def dump_entry_file(filename, entry)
  File.open(filename, "w") { |f|
    f.puts entry[:header]
    f.puts ""
    f.puts entry[:body]
    unless entry[:tb].empty? then
      f.puts TB_SECTION_SEPARATOR
      f.puts entry[:tb]
    end
  }
end

def convert_id_links(lines)
  in_super_pre = false
  new_lines = []
  lines.each { |line|
    if in_super_pre then
      new_lines.push(line)
      in_super_pre = false if line.match(/^||<$/)
      next
    end
    if !in_super_pre && line.match(/^>\|\w*\|$/) then
      new_lines.push(line)
      in_super_pre = true
      next
    end
    # href: isbn/asin
    new_line = line.gsub(/href=['"]\[?(isbn|asin):([^\]'"]+)?\]?['"]/i) { |matched|
      type, code = $~.captures
      url = "http://d.hatena.ne.jp/asin/#{code}/hatena-blog-22"
      "href=\"#{url}\""
    }
    new_lines.push(new_line)
  }
  return new_lines
end

def print_diff(src_lines, dst_lines)
  src_lines.each_index { |i|
    if src_lines[i] != dst_lines[i] then
      puts "- #{src_lines[i]}"
      puts "+ #{dst_lines[i]}"
    end
  }
end

check = (ARGV[0] == "check")
Dir.glob("#{ORIG_DIR}/????-??-??_*.txt").sort.each { |src|
  dst = File.basename(src)
  entry = load_entry_file(src)
  body = entry[:body]
  new_body = convert_id_links(entry[:body])
  if (body != new_body) then
    puts "#{src}:"
    print_diff(body, new_body)
    unless check then
      entry[:body] = new_body
      dump_entry_file(dst, entry)
      puts "saved: #{dst}"
    end
  end
}

URL にくっつけてる hatena-blog-22 はアマゾンアソシエイトIDだと思うのですが、ISBN/ASIN 記法を使うとデフォルトで付いてくるので付けてあります。ID持ってる人は自分のIDと差し替えるといいかも。

これではてなダイアリーの移行作業は一通り終わったかな… 例のフラグメント識別子付きリンクの問題は残っていますが、これははてなが対応してくれればこのままでもいいし、一応リンクの指す情報は飛び先にある(探さないといけないけど)ので、そこまで深刻ではないですし。

はてなブログライター v0.9

はてなブログライター v0.9 をリリースしました。

変更点

  • 新しいコマンド hbwdl.rb を追加しました。
    • Web側で追加・更新したエントリをローカルにダウンロードするツールです。
    • 詳細は README-hbwdl.md を参照してください。
  • hbw.rb に fix_data_url サブコマンドを追加しました。
    • 0.9 より前のバージョンの hbw.rb で投稿したエントリの投稿データファィルにエントリのURLの情報を追加するものです。
    • 通常は使用する必要はありません。詳細は README.md を参照してください。

注意事項

  • hbwdl.rb はまだバグがあるかもしれません。エントリのバックアップを取るなどして自衛しつつ使用してください。
  • 一部のエントリ(おそらく特殊な日付のエントリ)は hbwdl.rb ではダウンロードできません。

id記法のリンクの修正 & お詫び

はてなダイアリーのインポートで移行した記事ですが、id記法で記述したはてなダイアリーへのリンクが全滅しています。これははてなダイアリーはてなブログではid記法の仕様が異なるせいです。なんでうまいこと変換してくれないかなーと思いつつ一括で修正してみました。

例によって HatenaBlogWriter (hbw) を使うのが前提です。

はてなダイアリーはてなブログでのid記法の違い

詳しくは今村さんのブログエントリを参照してください。

ここには書かれてなかったと思うのですが、もう一つ違いがあります。

はてなダイアリーでは a タグの href 属性値にid記法を書くとURLに展開してくれるのですが、はてなブログでは展開してくれません。はてなブログで有効な d:id:rna:20190128:p1 のようなid記法で書いてもダメです。

idリンクの置換

以下のようなスクリプトを書きました。要は正規表現置換なのですが、正規表現は苦手科目です… 何度も試行錯誤できるように元のエントリファイルをサブディレクトリにコピーして、それを入力として変換するようにしました。

convert-id-links.rb:

#!/usr/bin/env ruby
# coding: utf-8
# HatenaBlogWriter のワーキングディレクトリで実行します。
# orig ディレクトリに変換前のエントリファイルをコピーしてから実行します。

ORIG_DIR = "orig"
TB_SECTION_SEPARATOR = '<!-- trackback -->'

def load_entry_file(filename)
  header = []
  body = []
  tb = []
  File.open(filename) { |file|
    in_header = true
    in_tb = false
    file.each_line(chomp: true) { |line|
      if (line == TB_SECTION_SEPARATOR) then
        in_tb = true
        next
      elsif in_header && /^$/.match(line) then
        in_header = false
        next
      end
      if in_header then
        header.push(line)
      elsif in_tb then
        tb.push(line)
      else
        body.push(line)
      end
    }
  }
  return { :header => header, :body => body, :tb => tb }
end

def dump_entry_file(filename, entry)
  File.open(filename, "w") { |f|
    f.puts entry[:header]
    f.puts ""
    f.puts entry[:body]
    unless entry[:tb].empty? then
      f.puts TB_SECTION_SEPARATOR
      f.puts entry[:tb]
    end
  }
end

def convert_id_links(lines)
  in_super_pre = false
  new_lines = []
  lines.each { |line|
    if in_super_pre then
      new_lines.push(line)
      in_super_pre = false if line.match(/^||<$/)
      next
    end
    if !in_super_pre && line.match(/^>\|\w*\|$/) then
      new_lines.push(line)
      in_super_pre = true
      next
    end
    # id link
    new_line = line.gsub(/((\[\])|(href=['"]\[?)|[^:]|^)(id:([\w-]+):(\d{8})(:[\w]+|#[\w]+)?)(\[\])?/i) { |matched|
      pre, esc_begin, href, link, id, date, sect, esc_end = $~.captures
      unless (esc_begin && esc_end) || href
        url = "http://d.hatena.ne.jp/#{id}/#{date}"
        if sect then
          sect.gsub!(/^:/, "/")
          url += sect
        end
        "#{pre}<a href=\"#{url}\">#{link}</a>"
      else
        matched
      end
    }
    # href: diary
    new_line = new_line.gsub(/href=['"]\[?(d:)?id:([\w-]+)(:[^\]'"]+)?\]?['"]/i) { |matched|
      service, id ,path = $~.captures
      url = "http://d.hatena.ne.jp/#{id}"
      if path then
        path.scan(/^:((\d{8})$|(\d{8})(:[\w]+|#[\w]+)$)/) { |s,date1,date2,sect|
          if date1 then
            url += "/#{date1}"
          elsif date2 then
            sect.gsub!(/^:/, "/")
            url += "/#{date2}#{sect}"
          end
        }
      end
      "href=\"#{url}\""
    }
    # href: group
    new_line = new_line.gsub(/href=['"]\[?g:([\w-]+)(:id:([\w-]+)(:[^\]'"]+)?)?\]?['"]/i) { |matched|
      group, id_path, id, path = $~.captures
      url = "http://#{group}.g.hatena.ne.jp"
      if id then
        url += "/#{id}"
        if path then
          path.scan(/^:((\d{8})$|(\d{8})(:[\w]+|#[\w]+)$)/) { |s,date1,date2,sect|
            if date1 then
              url += "/#{date1}"
            elsif date2 then
              sect.gsub!(/^:/, "/")
              url += "/#{date2}#{sect}"
            end
          }
        end
      end
      "href=\"#{url}\""
    }
    # href: group keyword
    new_line = new_line.gsub(/href=['"]\[?g:([\w-]+):keyword:([^\]'']+)\]?['"]/i) { |matched|
      group, keyword = $~.captures
      url = "http://#{group}.g.hatena.ne.jp/keyword/#{keyword}"
      "href=\"#{url}\""
    }
    new_lines.push(new_line)
  }
  return new_lines
end

def print_diff(src_lines, dst_lines)
  src_lines.each_index { |i|
    if src_lines[i] != dst_lines[i] then
      puts "- #{src_lines[i]}"
      puts "+ #{dst_lines[i]}"
    end
  }
end

check = (ARGV[0] == "check")
Dir.glob("#{ORIG_DIR}/????-??-??_*.txt").sort.each { |src|
  dst = File.basename(src)
  entry = load_entry_file(src)
  body = entry[:body]
  new_body = convert_id_links(entry[:body])
  if (body != new_body) then
    puts "#{src}:"
    print_diff(body, new_body)
    unless check then
      entry[:body] = new_body
      dump_entry_file(dst, entry)
      puts "saved: #{dst}"
    end
  end
}

引数に check を指定するとエントリファイルを置換せずに置換する部分の差分表示だけして終わります。

hbw のエントリファイルのヘッダ部分を読み飛ばすようにしています。また、トラックバック以降作業後の作業ということで、以前の作業で追加したトラックバック部分も読み飛ばすようにしています。

基本的に自分の書き方でヒットするケースのみに対処しているので、人によってはこのままでは足りないかもしれません。またはてなダイアリーはてなグループ用のリンクにしか対応していません。

結果の確認

正規表現置換は思わぬ置換ミスを引き起こすことがあるので、上のスクリプトを実行後、diff を取って差分を目で一通り確認しました。350件分。2時間半くらいかかりました。

修正の実行

hbw を実行しておしまい。

やり残し

確認中に気付いたのですが、a タグの href 属性値に書いたisbn記法やasin記法もはてなブログでは展開してくれないんですね… これは別途対処しようと思います。

もう一つ、フラグメント識別子で日記内のセクションへリンクしている場合(http://d.hatena.ne.jp/rna/20190128#p1 等)、はてなブログに移行したダイアリーでリンク先のセクションに対応するエントリには飛ばないという問題があります。

これははてなの方に要望を投げているとことろです。対応してもらえるとありがたいのですが、ダメだった場合どうするか… 大抵の場合はURLを http://d.hatena.ne.jp/rna/20190128/p1 に置き換えてしまえばエントリに飛ぶんですが、なぜかそうならないブログもあるのです。

例えば上の記事で挙げた飯田さんのブログがそうです。おそらくダイアリーを日記モードで使っているとそうなるのかなとにらんでいますが、元がどっちモードだったかなんてわからないのでどうしたものか…

お詫び

最後に、今回の作業でまたidコールが飛びまくったかもしれません。もしそうでしたらお詫びします。

一応エントリの再編集では追加分のidにしかコールが飛ばないはずなのですが…

でも AtomPub からの編集でもそうなのか不明ですし、差分の取り方によっては追加分と認識されそうなので、やっぱり飛んでしまったかも…

人によっては10年以上も前のブログからコールが飛んできて不快かと思いますが、リンクはWebの命だと思っているのでリンク切れは極力なくしたいのです。どうかお許しください。