Yin-Yang Call/cc Puzzle in Ruby

| Comments

Digging deeper in to the call/cc land I found interesting puzzle called yin-yang.

Here is Scheme implementation:

1
2
3
4
5
(let* ((yin
        ((lambda (cc) (display #\@) cc) (call-with-current-continuation (lambda (c) c))))
       (yang
        ((lambda (cc) (display #\*) cc) (call-with-current-continuation (lambda (c) c)))))
(yin yang))

It will print @*@**@***@****@*****@******@... forever.

Here you can find good explanation, also few of explanations can be found on StackOverflow.

After I understand how it works I got all that excited and implemented given puzzle in ruby:

1
2
3
4
5
6
require "continuation"

yin  = ->(cc) { print "@"; cc }.call(callcc { |c| c })
yang = ->(cc) { print "*"; cc }.call(callcc { |c| c })

yin.call(yang)

And it doesn’t work. It prints @*@*********... forever.

No idea why. Maybe there are some limitations of ruby’s call/cc. I will research further, but if you have any information about that feel free to comment or email me.

Cheers!

UPDATE Abinoam Praxedes Marques Junio figured out that let (which is basically lambda application underneath) is crucial here. So here is his fixed version:

1
2
3
4
5
6
require "continuation"

lambda do |yin, yang|
  yin.call(yang)
end.call(lambda { |cc| print "@"; cc }.call(callcc { |c| c }),
         lambda { |cc| print "*"; cc }.call(callcc { |c| c }))

Comments