ここで正直に言うと、関数型プログラミングに関しては、それについて読んだり、単純な問題を解決したりする以上のことはしませんでした。簡潔で保守しやすいソース コードのアイデアは気に入っていますが、このパラダイムを使用する理由が見つかりませんでした。今日まで: いくつかのネットワーク ツール (traceroute
または などping
) を Python で実装し、可能な限り "機能的" になるように ( 、scapy
、functools
およびを使用して) したいと考えていますitertools
。まず、ping
:
def tcp_ping(destination_ip, destination_port, n_probes=10, timeout=1):
source_ports = [randint(49152, 65535) for i in range(n_probes)]
probes = IP(dst=destination_ip)/TCP(sport=source_ports, dport=destination_port, flags='S')
responses = map(partial(sr, timeout=timeout, verbose=0), probes)
answered = filter(lambda x: len(x[0]) > 0, responses)
lost = filter(lambda x: x not in answered, responses)
rtts = map(lambda x: int(1000 * (x[0][0][1].time - x[0][0][0].sent_time)), answered) or [0]
return dict(loss=float(len(lost))/n_probes,
min_rtt=min(rtts),
max_rtt=max(rtts),
avg_rtt=mean(rtts),
std_rtt=std(rtts))
そして、traceroute
:
def takeuntil(predicate, iterable):
for x in iterable:
yield x
if predicate(x):
break
def traceroute_probes(destination_ip, destination_port):
ttl = 1
while ttl <= 255:
p = IP(dst=destination_ip, ttl=ttl)/TCP(dport=destination_port, flags='S')
yield p
ttl = ttl + 1
def is_finalhop(x):
return (len(x[0]) > 0 and
not x[0][0][1].haslayer('ICMP'))
def hop_ip_latency(x):
if len(x[0]) > 0:
return (x[0][0][0].ttl,
x[0][0][1].src,
max(0, int(1000 * (x[0][0][1].time - x[0][0][0].sent_time))))
else:
return (x[1][0][0].ttl, '*', 0)
def tcp_traceroute(destination_ip, destination_port, timeout=1):
responses = takeuntil(is_finalhop,
imap(partial(sr, timeout=timeout, verbose=0),
traceroute_probes(destination_ip,
destination_port)))
return map(hop_ip_latency, responses)
さて、質問:
- このコードをより「機能的」にするにはどうすればよいでしょうか?
traceroute
不必要な副作用を導入することなく、さらに複雑にするにはどうすればよいですか (たとえば、タイムアウトが 3 回連続して停止するなど)。- 命令型/オブジェクト指向の罠に陥らずに
sr
(世界へのインターフェース) 動作 (RTT に応じてタイムアウトを変更するなど) を変更するにはどうすればよいですか?ping
- ネットワークツールを実装するのに十分なだけでなく、「より機能的」であることを強制する純粋な(r)関数型言語はありますか?
takeuntil
Python のに追加するのを忘れたのは誰itertools
ですか?