Ubuntu 8.04 (vmware) + rails 2.3.2

Ruby on Rails 2.3.2 を使える環境を作る手順。何度も同じ失敗をしたので、備忘録として書きます。

使用したのは Ubuntu 8.04 日本語リミックスの VMware 仮想マシン(VMware Player 2.5.1 on Windows XP)。

安易に 8.10 にアップグレードしたら open-vm-tools がおかしくなり、eth0 を認識しなくなったので、8.04 のまま使うことにしました。HGFS は使えないのですが、ホストOS(Windows XP)とのあいだでコピー&ペーストができるので便利です。

apt-get でインストールされる gem はバージョンが古いので、このままでは後の作業がうまく行きません。

/var/lib/gems/1.8/ にインストールされるのは古い gem の挙動、/usr/lib/ruby/gems/1.8/ にインストールされるのが新しい(望ましい?)gem の挙動のようです。

  • 2009-08-12 追記:Debian パッケージの gem をそのまま使うと /var/lib/gems 以下にインストールされる、ということらしいです。Ubuntu 9.04 の /usr/bin/gem1.8 (gem 1.3.1) においても /var/lib/gems に実行ファイルが生成されることを確認しました。
$ sudo apt-get install ruby rubygems
$ gem -v
0.9.4
$ which gem
/usr/bin/gem
  • 追記 (2009-05-20) Ubuntu 9.04 の rubygems1.8 はバージョン 1.3.1 でした。

手作業で gem 1.3.1 を入れる。

$ sudo gem install rubygems-update-1.3.1.gem
$ sudo /var/lib/gems/1.8/bin/update_rubygems
...
RubyGems installed the following executables:
/usr/bin/gem1.8
If `gem` was installed by a previous RubyGems installation, you may need
to remove it by hand.

古い /usr/bin/gem と新しい /usr/bin/gem1.8 が共存しているので、手作業で対応。

$ gem -v
/usr/bin/gem:10:Warning: Gem::manage_gems is deprecated and will be removed
on or after March 2009.
/usr/bin/gem:23: uninitialized constant Gem::GemRunner (NameError)
$ gem1.8 -v
1.3.1
$ pushd /usr/bin; sudo mv gem gem.org ; sudo ln -s gem1.8 gem; popd
$ gem -v
1.3.1

gem 1.3.1 を使って rails を入れる。

$ sudo gem install rails
Successfully installed rake-0.8.4
Successfully installed activesupport-2.3.2
Successfully installed activerecord-2.3.2
Successfully installed actionpack-2.3.2
Successfully installed actionmailer-2.3.2
Successfully installed activeresource-2.3.2
Successfully installed rails-2.3.2
7 gems installed
...
$ rails -v
Rails 2.3.2

アプリケーション hoge を作って、sqlite3 で rake test を通す。

$ rails hoge
$ cd hoge
$ rake test
rake aborted!
no such file to load -- sqlite3

sqlite3 環境が足りないから rake test が通らない。下記サイトを参考に対処。

$ sudo apt-get install ruby1.8-dev swig libsqlite3-dev
$ sudo gem install sqlite3-ruby

migrate して test する。

$ rake db:migrate
(in /home/nishi/hoge)
$ rake test
(in /home/nishi/hoge)
/usr/bin/ruby1.8 -I"/home/nishi/hoge/lib" -I"/home/nishi/hoge/test"
"/usr/lib/ruby/gems/1.8/gems/rake-0.8.4/lib/rake/rake_test_loader.rb"
/usr/bin/ruby1.8 -I"/home/nishi/hoge/lib" -I"/home/nishi/hoge/test"
"/usr/lib/ruby/gems/1.8/gems/rake-0.8.4/lib/rake/rake_test_loader.rb"
/usr/bin/ruby1.8 -I"/home/nishi/hoge/lib" -I"/home/nishi/hoge/test"
"/usr/lib/ruby/gems/1.8/gems/rake-0.8.4/lib/rake/rake_test_loader.rb"

test が通ったので、server を動かしてブラウザから確認する。

$ script/server
Welcome aboard
You're riding Ruby on Rails!
About your application's environment
Ruby version	        1.8.6 (i486-linux)
RubyGems version	1.3.1
Rack version	        1.0 bundled
Rails version	        2.3.2
Active Record version	2.3.2
Action Pack version	2.3.2
Active Resource version	2.3.2
Action Mailer version	2.3.2
Active Support version  2.3.2
Application root	/home/nishi/hoge
Environment	        development
Database adapter	sqlite3
Database schema version	0

テンプレートの階層

音声対話ツールキット Galatea のプロジェクトに関わり、マルチモーダル対話記述・アーキテクチャの標準化に関わり、Ruby on Rails による VoiceXML アプリケーションの実装について考えた末、「階層化されたシステムの実装は、テンプレートエンジンの階層になる」と思うようになりました。

Webアプリケーションのフレームワークの多くがテンプレートエンジンを提供しています。いくつもの階層でそれぞれに記述の標準化を行っていることのメリットは十分にありますが、記述が冗長になるというデメリットもあります。テンプレートエンジンはこうした問題を解決する一つの手段です。

音声対話技術コンソーシアム(ISTC)では、音声入出力、GUI入出力などを有するインタフェースシステムについて、各階層でのインタラクション記述仕様の標準化について検討を行い、いわゆる Model/View/Controller の構造をさらに詳細化した6階層を提案しています。

私が開発を続けている Galatea Dialog Studio という対話制御エンジンについて考えると、いくつかの階層は Ruby on Rails のMVCフレームワークに対応していると考えられます。また、いわゆる Web アプリケーションをまず実装して、HTML に依存するレイヤーだけを VoiceXML に差し替える、という音声対話システムの実装も、妥当な手法になると思います。

Galatea Toolkit の Linux 版について、インストールや設定の難しさという課題が残っています。当初の設計によって各モジュールを統合することに成功しました。しかし、カスタマイズやデバイス設定が必要な場合に、現時点では、多くの箇所を矛盾なく変更する必要があります。

インタラクション記述ではないものの、各階層を動作させるためには、それぞれ必要なパラメータや設定情報があります。例えば音声合成であれば、言語処理や話者モデルのリストを与える必要があります。音声認識についてはオーディオ入力、音声検出、音響モデルなど数多くのパラメータが存在します。これらの設定を Galatea Toolkit で統合的に扱いたいと考えています。設計していくとこれはやはり「テンプレートの階層」になりそうです。

具体的には、以下のようなアーキテクチャで実装を進めています。

  1. システム領域にインストールされるファイルやツール
    • 汎用的なエンジンやファイル
      • プロジェクトファイルのテンプレート
      • 実行時ファイルのテンプレート
    • パスを固定してインストールする必要があるツール
    • プロジェクトを生成する galatea-generate コマンド
  2. ユーザ領域にプロジェクトファイルとして生成されるファイル群
    • config ディレクトリ
      • システム設定ファイル: システム領域の path などを参照する
      • プロジェクト設定ファイル:プロジェクト固有の設定
    • 拡張モジュール用ディレクトリ:プロジェクト固有のモダリティ拡張など
    • log / tmp 用ディレクトリ
    • runner スクリプト
    • プロジェクトの編集を支援するスクリプト
    • 対話アプリケーションサーバ:例えば rails のプロジェクト
  3. 実行時に生成されるファイル群
    • システム領域のテンプレートとプロジェクト設定ファイルに基づいて生成

これらをできるだけ Ruby on Rails の作法に馴染むように設計を行っています。

私は Rails に触れる前に、Java で簡易テンプレートエンジンを実装してみたり、PHP や Perl のテンプレートエンジンを使ったりしましたが、インストールが面倒であったり、テンプレートエンジン独自の記述言語を使用していたり、といったところに不満を感じました。

Ruby が ERB というテンプレートエンジンを標準で備えていて、ERB の中で Ruby 言語そのものが使用できる、自作の Ruby スクリプトから簡単に ERB の機能が利用できる、ということに、好感を持っています。

VoiceXML ブラウザと HTML ブラウザは完全に等価な位置づけと見なせない部分がいくつかあります。またモダリティを使い分けるのではなく組み合わせる場合にはさらに考慮が必要となります。どの階層をどのように補っていくべきか、今後システム実装の経験を踏まえた提案をしていきたいと考えています。

Python vs Ruby

「Python チュートリアル」という本を読み、同じことを Ruby でやったら、と思って書きかけたエントリを、この日記に刺激されて、第3章「気楽な入門編」の部分だけ、とりあえず公開することにしました:

  • ruby 1.8 / python 2.6 で確認。

電卓として使う

Python

$ python
>>> 2+2
4

Ruby

$ irb
irb(main):001:0> 2+2
=> 4
  • 以下、irb のプロンプトは略記

複素数

Python

>>> a=1.5+0.5j
>>> a.real
1.5
>>> a.imag
0.5
>>> abs(a)
1.58113...
  • a.abs とはできない(’complex’ object has no attribute ‘abs’)

Ruby

> require 'complex'
> a = Complex(1.5, 0.5)
> a.real
=> 1.5
> a.imag
=> 0.5
> a.abs
=> 1.58113...
  • abs は Python ではビルトイン関数だが Ruby では Complex オブジェクトのメソッド

文字列

Python

>>> '\"Yes,\" he said.'
'"Yes," he said.'
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'
>>> "'Isn\'t,' she said."
"'Isn't,' she said."
  • \ は常にエスケープ記号。
  • ‘ ‘の場合は’ ‘で表示され、” “の場合は” “で表示される。内部的な区別あり?

Ruby

> '\"Yes,\" he said.'
=> "\\\"Yes,\\\" he said."
> '"Isn\'t," she said.'
=> "\"Isn't,\" she said."
> "'Isn\'t,' she said."
=> "'Isn't,' she said."
  • \ は “” の場合のみエスケープ記号。
  • 常に “” で表示される。内部的な区別がない?

Python

>>> hello = "multi-line string\n\
 ... second line\n\
 ...     third line with indent"
>>> print hello
multi-line string
second line
third line with indent
>>>

Ruby

> hello = "multi-line string
 " second line
"     third line with indent"
=> "multi-line string\nsecond line\n    third line with indent"
> puts hello
multi-line string
second line
third line with indent
=> nil
>
  • irb ではコンテクストに応じてプロンプトが変わる

Python

>>> print """line 1
 ... line 2
 ... """
line 1
line 2
>>>

Ruby

> puts """line 1
 " line 2
" """
line 1
line 2
=> nil
  • トリプルクオートは Ruby でも使える(ように見える)
  • 最後の改行の扱いが Python と Ruby で異なる
  • puts は返り値 nil を返す

Ruby

> puts <<EOS
 " line 1
 " line 2
 " EOS
 line 1
 line 2
 => nil
  • 念のためにヒアドキュメントも実験。最初の行の直前の改行の扱いがトリプルクオートと異なる。

文字列の結合

Python

>>> word = 'a' + 'b'
>>> word
'ab'
>>>

Ruby

> word = 'a' + 'b'
=> "ab"
> word
=> "ab"
>

Python

>>> 'str' 'ing'
'string'
>>>

Ruby

> 'str' 'ing'
=> "string"
>
  • 隣接する2つの文字列リテラルは Ruby でも自動的に連結される

文字列のインデックス付け

Python

>>> 'abcdefg'[4]
'e'
  • Python にはキャラクタ型は存在せず、1文字のキャラクタは長さ1の文字列。

Ruby

> 'abcdefg'[4]
=> 101
  • Ruby の文字列は文字コード列であることを意識しなくてはならない。C 言語に似ているとも言えるが、うっかり文字列が得られると思いこみがち。
  • Python における ‘abcdefg'[4] と同じようにインデックス4の文字から成る新たな文字列を得るには。。
  • self[nth,len] : nthバイト番目から長さlenバイトの部分文字列を作成
> 'abcdefg'[4, 1]
=> "e"
  • self[first..last] : インデックス first から last までのバイトを含む文字列を作成
> 'abcdefg'[4..4]
=> "e"
  • self[first…last] : 文字列先頭を0番目の隙間として、fist 番目の隙間から last 番目の隙間までに含まれるバイト列を含んだ新しい文字列
> 'abcdefg'[4...5]
=> "e"

文字列のスライス

Python

>>> 'abcdefg'[0:2]
'ab'
>>> 'abcdefg'[1:3]
'bc'
>>> 'abcdefg'[:3]
'abc'
>>> 'abcdefg'[3:]
'defg'

Ruby

> 'abcdefg'[0...2]
=> "ab"
> 'abcdefg'[1...3]
=> "bc"
> 'abcdefg'[0...3]
=> "abc"
> 'abcdefg'[3...-1]
=> "def"
> 'abcdefg'[3...0]
=> ""
> 'abcdefg'[3..-1]
=> "defg"
  • Python における : でのスライスは Ruby では … とほぼ同じ。
  • ただし Python における [3:] は Ruby では [3..-1] となる。
  • Ruby では .. / … は Range というオブジェクトである。.. 演算子で生成されれば終端を含む。… 演算子で生成されれば終端を含まない。

インデックスにおける負の数

Python

>>> 'abcdefg'[-1]
'g'
>>> 'abcdefg'[-2]
'f'
>>> 'abcdefg'[-2:]
'fg'
>>> 'abcdefg'[:-2]
'abcde'

Ruby

> 'abcdefg'[-1]
=> 103
> 'abcdefg'[-1,1]
=> "g"
> 'abcdefg'[-2,1]
=> "f"
> 'abcdefg'[-2..-1]
=> "fg"
> 'abcdefg'[0..-2]
=> "abcdef"
> 'abcdefg'[0...-2]
=> "abcde"

文字列の長さ

Python

>>> len('abcdefg')
7
>>> 'abcdefg'.len
AttributeError: 'str' object has no attribute 'len'
  • Python ではビルトイン関数 len を使う

Ruby

> 'abcdefg'.length
=> 7
> 'abcdefg'.len
NoMethodError: undefined method `len' for "abcdefg":String
> length('abcdefg')
NoMethodError: undefined method `length' for main:Object
  • Ruby では String オブジェクトのメソッド length を使う

マルチバイト文字列

  • UTF-8 でソースを記述して、Python 2.6 / Ruby 1.8.6 の Win32 版で実行。

Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
print u'あいうえお'
print u'あいうえお'[2]
print len(u'あいうえお')
C:\>python mbstring.py
あいうえお
う
5

Ruby

puts 'あいうえお'
puts 'あいうえお'[2]
puts 'あいうえお'.length
縺ゅ>縺・∴縺
130
15
  • 望ましい挙動を実現する例(1)
#!/usr/bin/env ruby -Ku
# -*- coding: utf-8 -*-
require 'iconv'
class String
def to_sjis
Iconv.conv('shift-jis', 'utf-8', self)
end
def chars
self.split(//)
end
end
puts 'あいうえお'.to_sjis
puts 'あいうえお'.chars[2].to_sjis
puts 'あいうえお'.chars.length
C:\>ruby mbstring.rb
あいうえお
う
5
  • 望ましい挙動を実現する例(2)
#!/usr/bin/env ruby -Ku
# -*- coding: utf-8 -*-
require 'iconv'
class String
def chars
self.split(//)
end
end
module Kernel
alias_method :orig_puts, :puts
def puts(s)
orig_puts Iconv.conv('shift-jis', 'utf-8', s.to_s)
end
end
puts 'あいうえお'
puts 'あいうえお'.chars[2]
puts 'あいうえお'.chars.length
C:\>ruby mbstring.rb
あいうえお
う
5

リスト

Python

C:\>python
>>> a = ['ab', 'cd', 123, 45]
>>> a
['ab', 'cd', 123, 45]

Ruby

C:\>irb
> a = ['ab', 'cd', 123, 45]
=> ["ab", "cd", 123, 45]

個別の要素の操作

Python

>>> a[2] = a[2] + 23
>>> a
['ab', 'cd', 146, 45]
>>> a[2] += 23
>>> a
['ab', 'cd', 169, 45]

Ruby

> a = ['ab', 'cd', 123, 45]
=> ["ab", "cd", 123, 45]
> a[2] += 23
=> 146
> a
=> ["ab", "cd", 146, 45]
> a[2] = a[2] + 23
=> 169
> a
=> ["ab", "cd", 169, 45]

要素の置換と挿入

Python

>>> a
['ab', 'cd', 169, 45]
>>> a[0:2] = [111,222]
>>> a
[111, 222, 169, 45]
>>> a[1:1] = ['ab', 'cd']
>>> a
[111, 'ab', 'cd', 222, 169, 45]

Ruby

> a
=> ["ab", "cd", 169, 45]
> a[0...2] = [111,222]
=> [111, 222]
> a
=> [111, 222, 169, 45]
> a[1...1] = ['ab', 'cd']
=> ["ab", "cd"]
> a
=> [111, "ab", "cd", 222, 169, 45]
  • 文字列と同じく : は … に置き換えられる

リストの入れ子

Python

>>> q = [2,3]
>>> p = [1,q,4]
>>> p
[1, [2, 3], 4]

Ruby

> q = [2,3]
=> [2, 3]
> p = [1,q,4]
=> [1, [2, 3], 4]
  • ここまでは全く同じ

Python

>>> p
[1, [2, 3], 4]
>>> len(p)
3
>>> p[1].append('xtra')
>>> p
[1, [2, 3, 'xtra'], 4]

Ruby

> p
=> [1, [2, 3], 4]
> p.length
=> 3
> p[1].append('xtra')
NoMethodError: undefined method `append' for [2, 3]:Array
> p[1] << 'xtra'
=> [2, 3, "xtra"]
> p
=> [1, [2, 3, "xtra"], 4]
> p[1].push 'xtra'
=> [2, 3, "xtra", "xtra"]
> p
=> [1, [2, 3, "xtra", "xtra"], 4]
  • Python のビルトイン関数 len は Ruby では length メソッド
  • Python の append メソッドは Ruby では << または push メソッド

プログラミングの基礎

Python

>>> a, b = 0, 1
>>> while b < 10:
...   print b
...   a, b = b, a+b
...
1
1
2
3
5
8
>>>

Ruby

> a, b = 0, 1
=> [0, 1]
> while b < 10 do
*   puts b
>   a, b = b, a+b
> end
1
1
2
3
5
8
=> nil
>
  • Python はブロックをインデントで表現する
  • Ruby はブロックを do end で表現する
  • Python の print は Ruby では puts

Python

>>> a, b = 0, 1
>>> while b < 1000:
...   print b,
...   a, b = b, a+b
...
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>>

Ruby

irb(main):035:0> a, b = 0, 1
=> [0, 1]
irb(main):036:0> while b < 1000 do
irb(main):037:1*   print b
irb(main):038:1>   a, b = b, a+b
irb(main):039:1> end
1123581321345589144233377610987=> nil
irb(main):040:0>
irb(main):050:0> a, b = 0, 1
=> [0, 1]
irb(main):051:0> while b < 1000 do
irb(main):052:1*   print "#{b} "
irb(main):053:1>   a, b = b, a+b
irb(main):054:1> end
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 => nil
irb(main):055:0>
  • Python の “print ,” のような自動空白挿入は Ruby の print では行われない

YAML+ERB

前回の続きで、ERB に埋め込む情報を YAML で記述する実験。

# config.yml
books:
-
title: あいうえお
author: かきくけこ
price: 400
-
title: さしすせそ
author: たちつてと
price: 800
#!/usr/bin/ruby -Ku
require 'erb'
require 'yaml'
erb_doc = <<EOS
hello world 1
<% config['books'].each_with_index do |i,n| -%>
[<%= n %>] title:<%= i['title'] %> / author:<%= i['author'] %>
<% end -%>
hello world 2
EOS
class MyTemplate
def initialize
@config = YAML.load(File.new('config.yml'))
end
def config
@config
end
def result(script)
ERB.new(script, nil, '-').result(binding)
end
end
puts MyTemplate.new.result(erb_doc)
# hello world 1
# [0] title:あいうえお / author:かきくけこ
# [1] title:さしすせそ / author:たちつてと
# hello world 2

ERBとインスタンス変数

Rails の View のようなテンプレートエンジンを ERB 単体で使う例。

詳しい説明はあちこちで見かけたのですが私が確認したかったポイントに絞ってみました。

#!/usr/bin/ruby
require 'erb'
erb_doc = <<EOS
hello world 1
<% 1.upto(3) do |i| -%>
<%= @hoge %>:<%= i %>
<% end -%>
hello world 2
EOS
class MyTemplate
def initialize
@hoge = 123
end
def result(script)
ERB.new(script, nil, '-').result(binding)
end
end
puts MyTemplate.new.result(erb_doc)
# hello world 1
# 123:1
# 123:2
# 123:3
# hello world 2

島根県CMS

2002年に、ラジオフライでは音声合成を用いたインターネットラジオ番組「ラジオフライマガジン」の制作を行いました。ラジオフライのメーリングリストでのやりとりが、編集の達人・デーブ川崎氏によって、月刊ウェブマガジンとしてまず公開されました。それを私がHTMLから音声合成用のファイルに編集し直して、合成音声と効果音とテーマ音楽を使った、約1時間分のMP3コンテンツとして公開されました。この編集作業は数ヶ月続けて、技術実験としての目的を達成しつつ(メンバーの多忙もあって)終了しました。

こんなことをやった背景は、それまでの数年の活動で得た「インターネットラジオ番組を誰でも配信できるようになったけど、コンテンツを定期的に作るのは大変である」という経験からの着想でした。

そして、たまたま「こんなことやってるんですよ」と、ラジオフライマガジンを(当時発売されたばかりの)Apple iPod で聞かせた相手に「これはいいね」と言われ「ユビキタスラジオ」の開発が始まりました(と私は思っているのですが・・)。

最近、ネットワーク応用通信研究所からソースが公開された「島根県CMS」が注目を集めています。

しかし「ウェブサイトに読み上げ機能を持たせるのは、アクセシビリティのことを誤解した邪道なシステムだ」という意見も聞かれます。

恥ずかしながら、私は最近まで、島根県のウェブサイトで音声合成システム GalateaTalk が使われているのは知っていましたが、どのように使われているのかちゃんと知りませんでした。そこで島根県のウェブサイトを見てみました。

右上の「よみあげ」が index.m3u へのリンクになっています。立ち上げると開くのはデフォルトで関連づけられたメディアプレイヤーです。

島根県CMSの機能は、よくある「ActiveXで音声合成機能をクライアントにインストールしてしまうシステム」ではありません。そんなことをしてしまうと、なんのために「ユニバーサルなメディアとしてのテキスト」を公開しているのか分からなくなってしまいます。島根県CMSの機能は「ウェブアクセシビリティ」と呼ぶべきではなく、もっと別のメディアだと考えた方がよいと思うのです。

つまりこれは、HTMLというテキスト情報に「インターネットラジオ番組」という新しいメディアを付加し、両者を効率よく制作・配信するシステムなのだと思います。それはまさに、私が「ラジオフライマガジンをもっと効率よく制作したい」と思いながらほったらかしていた、私が欲しかった機能なのです。。

そう思いながら、島根県ウェブサイトの読み上げを聞いていると、別の問題が明らかになりました。つまり GalateaTalk の基本性能としての「読み付与」や「音声の明瞭性」などがよくないのです。無償だからといって、これは GalateaTalk の評判を下げてしまっているのではないかと。。でも、郵便番号を日付のように読み付与してしまうのは、使い方を工夫すれば解決するのでは。。

GalateaTalk は何度か商用化の打診があり、私もいろいろ頑張ったのですが、商用レベルの品質に持って行くには相当な努力が必要である、ということで断念した経緯があります。しかし、島根県CMSがGalateaTalkのキラーアプリの一つになれば、状況は変わるかも知れません。 島根県CMSの音声読み上げの改良にも取り組んでいかなくては、と思いを新たにした次第です。

Rubyのチカラ

夜中に松江のホテルの部屋で去年の人工知能学会全国大会の招待講演ビデオ配信「Rubyのチカラ」を見ました。

NaClさんがどういうつもりでまつもと氏を雇っておられたか、という話をその日に伺ったので、「NaClさんの業務にどう役立つか」という観点はおそらくRubyの発展過程で強く意識されたであろう、と思いました。

そして言語オタクのまつもと氏が人工知能の講演じゃないことを申し訳なさそうに語りはじめた、昨年6月の人工知能学会での講演。Rubyで導入された機能はすべて過去の言語の二番煎じだ、と謙遜しつつも、「単純さよりも自然さが重要」という言語設計のコンセプトがじっくり語られるのを聞いて、私にはある考えが浮かびました。

プログラミング言語Rubyは、プログラマーに「自然なコーディング」を許容するために設計された「人工知能」なのだ、と。

どこでどういう省略記法を許すか、という規則を実装したパーザーはルールベースで作り込まれているはずなので、言語を作っている側は人工知能だと思わないで作っているのでしょうが、実務の文脈でいかに自然な記述を許容するか、一つ一つ職人芸で仕様を選択した結果は、「高度な手作り人工知能」と言えるのかも。

人工知能としての自然言語処理技術では「人間がやりとりする言語のコーパスを集めて、それをどう処理したらいいか検討する」ということが行われるわけですが、「プログラミング言語が使われるシステム開発の現場のコーパスを集めて、それを効率よく記述できるプログラミング言語を設計する」ということがもしきちんと行われたら、Ruby のような言語はもっと工学的に設計できるのかも知れません。そのときに重要なのは「集めるコーパスにリアリティがあること」ではないでしょうか。

そんな視点を持ちつつ、私もすっかり固くなってしまった頭を柔らかくしながらプログラミングの勉強を続けたいと思ったのでした。