2010年09月03日 05:30 [Edit]

Algorithm - 0と1を次々と返す簡単なお仕事

ごもっとも。

0と1を次々返す方法 - a2c.get.diary
TrueだったらFalseで、FalseだったらTrueにしたい。
なんかそんなことそこかしこで必要で、その為の便利なものが
あるのかなぁと思ったんだけど無いぽい

Closure

本来は一番おすすめなのだが…

JavaScript

()が煩わしいが、perlやrubyよりは自然。

#!/usr/bin/js
var flipflop = function(p){
  p = !p;
  return function(){
    return p = !p;
  };
};

var fl = flipflop();
print(fl());
print(fl());
print(fl());
print(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 oo.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 blog
Perl5.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/bGWDnqless than a minute ago via web

()が必要とはいえ、これが一番よさげ。

#!/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();
print(fl);
print(fl);
print(fl);
print(fl);
print(uneval(fl));

この記事へのトラックバックURL

この記事へのトラックバック
初トラックバックだ。 ブログ読んでたら0と1を次々と返したいなんていうのがあったのでやってみた。 Algorithm - 0と1を次々と返す簡単なお仕事 class Cycle(object): def __init__(self, vals=[0,1]): import itertools self.it = itertools.cycle(vals) def __call__(self
0と1を次々と返す【yanolabの日記】at 2010年09月03日 11:18
TrueだったらFalseで、FalseだったらTrueにしたい。 なんかそんなことそこかしこで必要で、その為の便利なものが あるのかなぁと思ったんだけど無いぽい。 0と1を次々返す方法 - a2c.get.diary Yield python 実装は自然だが、next()がわずらわしい。 404 Blog Not Found:Alg
[Python] Function that returns function that repeats boolean results【agwの日記】at 2010年09月03日 14:48
http://blog.livedoor.jp/dankogai/archives/51512419.html JavaScript で呼び出しの () が煩わしいなら、以下のように書けるのではないか。 #!/usr/bin/js var fl = { p : 0, valueOf : function(){ return this.p = !this.p; }, toString:valueOf }; print(fl); print(fl)
[JavaScript] Re: Algorithm - 0と1を次々と返す簡単なお仕事【葉っぱ日記】at 2010年09月03日 15:33
http://blog.livedoor.jp/dankogai/archives/51512419.html Perl5.10 なら state がつかえるから、以下のように書けるのではないか。 #!/usr/bin/perl use 5.010; use strict; use warnings; use Test::More; sub flipflop { state $p = !shift; $p = !$p } ok !flipflop();
Re: Algorithm - 0と1を次々と返す簡単なお仕事【TokuLog 改メ tokuhirom’s blog】at 2010年09月03日 15:35
Algorithm - 0と1を次々と返す簡単なお仕事にscheme版がなかったので、やってみた。 (define (make-flipflop p) (lambda () (set! p (not p)) p)) (define flfp (make-flipflop #f)) 実行。 gosh> (define (make-flipflop p) (lambda () (set! p (not p)) p)) make-flip
[プログラミング]Algorithm - 0と1を次々と返す簡単なお仕事 - scheme版【tmurataの日記】at 2010年09月03日 17:37
Algorithm - 0と1を次々と返す簡単なお仕事 なんとなくphpでも。 あんまりおもしろくないかな。 <?php function flipflop() { static $flipflop = false; $flipflop = !$flipflop; return $flipflop; } function printTrueOrFalse($p) { $str = $p ? "True¥n" ...
[プログラミング]Algorithm - 0と1を次々と返す簡単なお仕事 - php版【tmurataの日記】at 2010年09月03日 18:37
たまたま昨日クロージャを勉強したので書いてみた。 結果は同じようになってるけどあってるのかなぁ・・・? <?php $flipflop = function($p = false){ $p = !$p; return function() use (&$p) { return $p = !$p; }; }; $fl = $flipflop(); var_dump($fl()); var_d
[PHP]0と1を次々と返す簡単なお仕事を考えてみた【なげっぱなし日誌】at 2010年09月04日 10:46
Algorithm - 0と1を次々と返す簡単なお仕事 LLじゃないけど、C#でもやってみた。 using System; class FlipFlop { static void Main(string[] args) { Func<bool, Func<bool>> flipflop = f => () => {f = !f; return f;}; var ff = flipflop(false
[C#] FlipFlopワンライナー【espresso3389の日記】at 2010年09月05日 10:01
ネタ元: a2c.get.diary ■[python] 0と1を次々返す方法 404 Blog Not Found - Algorithm - 0と1を次々と返す簡単なお仕事 すでに旬を過ぎたみたいだけど、C#で僕も書いてみました。 espresso3389の日記 で、espresso3389 さんが素晴らしいコードを紹介しているけど、...
falseとtrueを交互に返す簡方法(C#)【窓際プログラマーの独り言 -C#の話題を中心に】at 2010年10月04日 22:27
この記事へのコメント
ClosureのPythonですが、Python2.*でもそれっぽいものは書けます。きしょいことには変わりませんが。

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の鬼門です。
Posted by eigonvalue at 2010年09月03日 20:12