ルビー
UnixクローンのPATHでawkを見つけます。
p = ENV['PATH'].split ':'
# Find an executable in PATH.
def find_exec(name)
p.find {|d| File.executable? File.join(d, name)}
end
printf "%s is %s\n", 'awk', find_exec('awk')
おっとっと!
$ ruby21 find-awk.rb
find-awk.rb:5:in `find_exec': undefined method `find' for nil:NilClass (NoMethodError)
from find-awk.rb:8:in `<main>'
エラーから、がp.find
呼び出されたことがわかっているnil.find
ため、であるp
必要がありますnil
。どうしてそうなった?
Rubyでは、def
ローカル変数に独自のスコープがあり、外部スコープからローカル変数を取得することはありません。したがって、割り当てp = ENV['PATH'].split ':'
はスコープ内にありません。
未定義の変数は、通常は発生しNameError
ますが、p
特殊なケースです。Rubyにはという名前のグローバルメソッドがありp
ます。のp.find { ... }
ように、メソッド呼び出しになりp().find { ... }
ます。ときにp
引数がない、それが返されますnil
。(コードゴルファーはp
、のショートカットとして使用しnil
ます。)その後、nil.find { ... }
レイズしNoMethodError
ます。
Pythonでプログラムを書き換えて修正します。
import os
import os.path
p = os.environ['PATH'].split(':')
def find_exec(name):
"""Find an executable in PATH."""
for d in p:
if os.access(os.path.join(d, name), os.X_OK,
effective_ids=True):
return d
return None
print("%s is %s" % ('awk', find_exec('awk')))
できます!
$ python3.3 find-awk.py
awk is /usr/bin
おそらく印刷したいのですawk is /usr/bin/awk
が、それは別のバグです。