正木です。
原 信一郎様、御教示有難うございます。
"Ruby プログラミング入門" は分かりやすくて、愛読しています。
ただ DelayedList の所は理解するのに苦労しました。
(ほかには問題の instance_eval)
MLも初心者でなかなか真意の伝わる書き方ができませんが,誤解されない様に
できるだけ注意して書くことにします。
In mail "[ruby-list:28342] Re: argument to instance_eval block"
"Shin-ichiro HARA" <sinara / blade.nagaokaut.ac.jp> wrote
|class Sequence
|
| include Enumerable
|
| def initialize( list, &block )
| @list = list
| @proc = block
| end
.....
|Prime = Sequence.new([2,3]){|seq, n|
| m = seq[n - 1] + 2
| m += 2 while seq.find{|k|
| break if k * k > m
| m % k == 0
| }
| m
|}
|Prime.each do |x|
| p x
| break if x > 100
|end
これは私の script で $mod=2 としたものと本質的には同じものだと
(B$*$b$$$^$9$,!"
break 行の 100 を m に変えると意図通りには動きません。
これは致命的な欠陥だと思って採用しなかったわけです。
Prime の定義のなかでの m は本来 dummy(他の変数名とぶつからなけl$
何を使ってもいい)変数の筈なのに、この場合はこの block が mai
n の
context で評価されるため dummy になりません。
こういう場合は他では絶対に使わないような変数名を使いなさいという
解決策は、Programming の基本に反する(dummy は dummy であk$Y$-$@$
いう意味で)と思うので受け入れられません。
第2引数の必要性についてですが、上の script に 次のような
(B
----
class Sequence
def *(y)
x=self
Sequence.new([]){|seq,n| x[n]*y[n]}
end
end
----
method $rDI2C$7$F
p (Prime*Power[2])[m]
とやれば当然 error になります。
無限数列や級数に使うのが主な目的なのでこれが出来ないと使い物になりま
せん。(Cauchy 列または級数として実数そのものを表す Real class r9M$
ていますが実行速度に問題があり実用的なものは未だ出来ません。)
以上のようなことは間接的にですがちゃんと書いたつもりでいたんですが、
書き方が悪かったと反省しています。すみませんでした。
instance_eval は初心者が使うと 危険なようなので使わないことにします。
この話は block は block で渡すのが自然だと思って、その方法をき$$F$_$
だけで、特に困っているわけではないので(すっきりはしないですが)d$H$7$
はこの辺で終りにしたいと思います。
これは便利だと思ってくれた人が一人もいなかったのがちょっと残念だった
ので、最後に使用例を少しだけ:
Γ関数やゼータ関数を計算するときに Bernoulli 数が必要になりますが、(
B
<!$N$h$&$K4JC1$KDj5A$G$-$^$9!#
class Sequence
def *(y)
x=self
case y
when Numeric
Sequence.new([],x,y){"|n,x,y| x[n]*y"}
else
Sequence.new([],x,y){"|n,x,y| x[n]*y[n]"}
end
end
def sum(n=0,m=nil,s=nil)
each(n,m){|x| (break if not yield(x)) if iterator?;if s;s+=x;else s=x end
}
s
end
end
Binom =Sequence.new([Sequence.new([1]){"|i| 0"}]){"|n| Sequence.new([1],n){\"|
i,n| Binom[n-1][i-1]+Binom[n-1][i]\"}"} #二項係数
require "rational.rb"
Bernoulli =Sequence.new([1,Rational(-1,2)]){"|n| -(Binom[n+1]*Bernoulli).sum(0
,n-1)/(n+1)"}
計算は必要な時に一回するだけなので、速くするための工夫が不必要な
ことも利点です。
漸化式でない例
def (Dirichlet={}).[](s)
super || Dirichlet[s]=Sequence.new([1],s){"|n,s| (n+1)**(-s)"}
end
class Sequence
def DirichletSeries(s)
self*Dirichlet[s]
end
end
Moebius=Sequence.new([0,1]){"|n| (p=Prime.prime_factors(n);pu=p.uniq;(p!=pu)?
0:Sgn2[pu.size])"}
Moebius.DirichletSeriws(s).sum{|x| x.abs > $error} #=1/zeta(s)
最後の例を出せば漸化式だけが目的ではないということは、書かなくても
分かってもらえるだろうといった書き方を今まではしていました。すみま
せんでした。
無限列の間の演算を自由に定義できるようにするのが目的だということを
はっきり書くべきでした。
長文失礼しました。