ごもっとも。
0と1を次々返す方法 - a2c.get.diaryTrueだったらFalseで、FalseだったらTrueにしたい。
なんかそんなことそこかしこで必要で、その為の便利なものが
あるのかなぁと思ったんだけど無いぽい
Closure
本来は一番おすすめなのだが…
JavaScript
()が煩わしいが、perlやrubyよりは自然。
#!/usr/bin/js
var flipflop = function(p){
p = !p;
return function(){
return p = !p;
};
};
var fl = flipflop();
console.log(fl());
console.log(fl());
console.log(fl());
console.log(fl());
Perl
->()がわずらわしい。
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
sub flipflop{
my $p = !shift;
sub { $p = !$p }
}
my $fl = flipflop();
say $fl->();
say $fl->();
say $fl->();
say $fl->();
Ruby
callは煩わしいし[]はきしょい。
#!/usr/bin/ruby
def flipflop(p=false)
p = !p
Proc.new{ p = !p }
end
fl = flipflop()
puts fl.call
puts fl.call
puts fl[] # .call の代わりにOK
puts fl[]
Python
Pythonの鬼門はClosureかも知れない。なんとこれが動かない。
def flipflop(p=False):
p = not p
def ret():
p = not p
return p
return ret
fl = flipflop()
print fl()
print fl()
print fl()
print fl()
Python 3だと何とか書けるが…
def flipflop(p=False):
p = not p
def ret():
nonlocal p
p = not p
return p
return ret
fl = flipflop()
print(fl())
print(fl())
print(fl())
print(fl())
nonlocalがきしょい。
Class + Operator Overloading
Perl
実装はとにかく、利用はこれが一番自然かも知れない。
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
{
package FlipFlop;
use overload
'bool' => \&fetch,
'0+' => \&numify,
'""' => \&numify
;
sub new {
my $class = shift;
my $self = !shift;
bless \$self, $class;
}
sub fetch {
my $self = shift;
$$self = !$$self;
}
sub numify {
shift->fetch + 0;
}
}
my $fl = new FlipFlop;
say $fl;
say $fl;
say $fl;
say $fl;
python
bool()でキャストしなければならないのが煩わしい。
#!/usr/bin/python
class FlipFlop:
def __init__(self, v=False):
self.x = not bool(v)
def __nonzero__(self):
self.x = not self.x
return self.x
fl = FlipFlop()
print bool(fl)
print bool(fl)
print bool(fl)
print bool(fl)
print fl
ruby
puts oでo.to_sが暗黙で呼ばれるのと異なり、#to_boolに相当するメソッドが論理演算の時に暗黙で呼ばれるということはない。後述のYieldの例に似てしまう。
#!/usr/bin/ruby
class FlipFlop
def initialize(init=false)
@p = !init
end
def to_b
@p = !@p
end
end
fl = FlipFlop.new()
puts fl.to_b
puts fl.to_b
puts fl.to_b
puts fl.to_b
puts fl && true # false になってはくれない
Yield
python
実装は自然だが、next()がわずらわしい。
#!/usr/bin/python
def flipflop(p=False):
p = not not p
while True:
yield p
p = not p
fl = flipflop();
print fl.next();
print fl.next();
print fl.next();
print fl.next();
JavaScript 1.7(参考)
現状Firefox/SpiderMonkeyしかサポートしていない。
var flipflop = function(p){
p = !!p;
while(true){
yield p;
p = !p;
};
};
var fl = flipflop();
console.log(fl.next());
console.log(fl.next());
console.log(fl.next());
console.log(fl.next());
Macro
C
意外といける?
#define flip(p) !((p) = !(p))
void main(){
int p = 0;
printf("%d\n", flip(p));
printf("%d\n", flip(p));
printf("%d\n", flip(p));
printf("%d\n", flip(p));
}
回数を気にしなければこれでも。
#define flip(p) ((p)++ & 1)
void main(){
int p = 0;
printf("%d\n", flip(p));
printf("%d\n", flip(p));
printf("%d\n", flip(p));
printf("%d\n", flip(p));
}
簡単なお仕事だけあって、やり方も多すぎる…
Dan the Binary Blogger
追記
Perl
Re: Algorithm - 0と1を次々と返す簡単なお仕事 - TokuLog 改メ tokuhirom’s blogPerl5.10 なら state がつかえるから、以下のように書けるのではないか。#!/usr/bin/perl use 5.010; use strict; use warnings; use Test::More; sub flipflop { state $p = !shift; $p = !$p } ok !flipflop(); ok flipflop(); ok !flipflop(); ok flipflop(); done_testing;
stateを避けたのは、$pを共有したくない、要するにsingletonにしたくなかったから。要は
my $true1st = flipflop(1); my $false1st = flipflop(0);
としたかった、と。でもsingletonでいいならstateがベストプラクティスだと私も思う。
Python
@dankogai python版は__nonzero__ではなく__call__を定義すればboolにキャストする必要ないのでは。 QT: 404 Blog Not Found:Algorithm - 0と1を次々と返す簡単なお仕事 http://htn.to/bGWDnq
()が必要とはいえ、これが一番よさげ。
#!/usr/bin/python
class FlipFlop:
def __init__(self, v=False):
self.x = not bool(v)
def __call__(self):
self.x = not self.x
return self.x
fl = FlipFlop()
print fl()
print fl()
print fl()
print fl()
print fl
JavaScript
Re: Algorithm - 0と1を次々と返す簡単なお仕事 - 葉っぱ日記JavaScript で呼び出しの () が煩わしいなら、以下のように書けるのではないか。
というわけで少し改変。JSはこれで決定かな?
#!/usr/bin/js
var flipflop = function(p){
return {
p : 0,
valueOf : function(){ return this.p = !this.p; },
toString : valueOf
};
};
var fl = flipflop();
console.log(+fl);
console.log(+fl);
console.log(+fl);
console.log(+fl);
console.log(fl);

def flipflop(p=False):
p = [not p]
def ret():
p[0] = not p[0]
return p[0]
return ret
Closureは確かにPythonの鬼門です。というかfunctional programmingそのものがPerlなんかに比べるとPythonの鬼門です。