Skip to content

Instantly share code, notes, and snippets.

@delonnewman
Last active November 9, 2015 21:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save delonnewman/4f637ab23b0fa9aa12aa to your computer and use it in GitHub Desktop.
Save delonnewman/4f637ab23b0fa9aa12aa to your computer and use it in GitHub Desktop.
Messing around with mimicking Scheme in Ruby by implementing the Yin Yang puzzle with Kernel#callcc and a fake 'let' macro
require 'continuation'
#
# Messing around with mimicking Scheme in Ruby by implementing the Yin/Yang puzzle with Kernel#callcc and a fake 'let' macro
#
# See also:
# http://blog.gonzih.me/blog/2013/11/26/yin-yang-callcc-puzzle-in-ruby/,
# http://stackoverflow.com/questions/16843853/how-to-implement-let-in-scheme
#
# In Scheme (the original)
#
# (let ((yin ((lambda (cc) (display "@") cc) (call/cc (lambda (c) c))))
# (yang ((lambda (cc) (display "*") cc) (call/cc (lambda (c) c)))))
# (yin yang))
# In Ruby without a let (macro-ish method)
#
# 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 }))
# my let method with some funky metaprogramming
def let(bindings, &blk)
Class.new do
def initialize(bindings)
bindings.each do |name, value|
instance_variable_set(:"@#{name}", value)
self.class.send(:attr_reader, name.to_sym)
end
end
define_method :eval, &blk
end.new(bindings).eval
end
# the result is pretty comparable to the scheme version
let yin: -> (cc) { print "@"; cc }.(callcc { |c| c }),
yang: -> (cc) { print "*"; cc }.(callcc { |c| c }) do
yin.(yang)
end
@luikore
Copy link

luikore commented Jan 20, 2015

You can just use parallel assignment

require "continuation"

yin, yang =
  callcc{|x| x }.tap{ print '@' },
  callcc{|x| x }.tap{ print '.' }

yin.(yang)

@delonnewman
Copy link
Author

Actually that doesn't work, I think the issue is that the call yin.(yang) needs to be enclosed by the definitions, hence the "let" in scheme and the "lambda" in the raw Ruby version, I just created my funky "let" method to make it look more like the Scheme version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment