Skip to content
Browse files

var access, cleanup, etc

  • Loading branch information...
1 parent 4b7f561 commit 5cc724373880c9c606291b489ef3a7460b53e31a @daveray committed Oct 9, 2011
Showing with 92 additions and 4 deletions.
  1. +25 −0 README.md
  2. +66 −3 lib/familiar.rb
  3. +1 −1 test/test_familiar.rb
View
25 README.md
@@ -18,6 +18,13 @@ becomes:
Some functions have additional Ruby sugar. See below.
+Use `Familiar.with` if you don't feel like writing `Familiar` over and over:
+
+ Familiar.with do
+ reduce fn {|acc,v| acc + v}, 0, range(100)
+ end
+ => 4950
+
# Functions
Make a function from a proc or lambda:
@@ -105,3 +112,21 @@ Make a future:
f.get -> "return value"
+# Examples
+
+ # Primes example from clojure docs
+ # http://clojuredocs.org/clojure_core/clojure.core/reduce
+ x = Familiar.with do
+ reduce fn { |primes,number|
+ if some(vars.zero?, map(fn {|x| number % x}, primes))
+ primes
+ else
+ conj(primes, number)
+ end
+ },
+ vector(2),
+ take(100, iterate(vars.inc, 3))
+ end
+ Familiar.println x
+ => [2 3 5 7 11 13 17 19 23 29 31 ... 67 71 73 79 83 89 97 101]
+
View
69 lib/familiar.rb
@@ -2,21 +2,59 @@
require "clojure-1.3.0.jar"
module Familiar
+ module Vars
+ def self.__lookup(ns, var)
+ m = Java::clojure.lang.RT.var(ns, var.to_s.gsub("_", "-"))
+ m.is_bound? ? m : nil
+ end
+
+ def self.method_missing(meth, *args, &block)
+ __lookup("clojure.core", meth) or super
+ end
+ end
+
- # map some_func to clojure.core/some-func
+ # Provides access to Clojure vars for when you need to use a Clojure
+ # var without invoking it.
+ #
+ # Example:
+ #
+ # Familiar.with do
+ # filter vars.even?, range(100)
+ # end
+ #
+ def self.vars
+ Familiar::Vars
+ end
+
def self.method_missing(meth, *args, &block)
#puts "Missing #{meth}"
- m = Java::clojure.lang.RT.var("clojure.core", meth.to_s.gsub("_", "-"))
- if m.is_bound?
+ m = self.vars.send meth
+ if m
m.invoke(*args)
else
super
end
end
+
+ # Run a block of code without having to qualify everything in this module:
+ #
+ # Examples:
+ #
+ # # Here, reduce, fn, range are all from Clojure
+ # Familiar.with do
+ # reduce fn {|acc, x| acc + x}, range(100)
+ # end
+ #
+ def self.with(&block)
+ instance_eval &block
+ end
+
#############################################################################
# Functions
+ # Wrap a Proc in a Java Callable
class Callable
include Java::java.util.concurrent.Callable
def initialize(callable)
@@ -28,6 +66,7 @@ def call
end
end
+ # JRuby impl of clojure fn
class Fn < Java::clojure.lang.AFn
def initialize &block
@block = block
@@ -38,6 +77,16 @@ def invoke(*args)
end
end
+ # Create a Clojure fn from a block
+ #
+ # Example:
+ #
+ # (fn [x] (+ x 1))
+ #
+ # is the same as:
+ #
+ # Familiar.fn {|x| x + 1}
+ #
def self.fn(p = nil, &code)
if block_given?
Fn.new &code
@@ -61,10 +110,13 @@ def self.atom?(v)
end
class Java::ClojureLang::Atom
+
+ # Like clojure.core/swap! except block is used as update function
def swap!(&code)
swap(Familiar.fn(code))
end
+ # Same as clojure.core/reset!
def reset!(v)
reset(v)
end
@@ -73,11 +125,15 @@ def reset!(v)
#############################################################################
# Refs and STM
+ # Run a block in an STM transaction
def self.dosync(&code)
Java::clojure.lang.LockingTransaction.runInTransaction(Callable.new(code))
end
+ # Add some helpers to refs
class Java::ClojureLang::Ref
+
+ # Like clojure.core/alter except block is used as update function
def alter(&code)
java_send :alter,
[Java::clojure.lang.IFn.java_class,
@@ -86,6 +142,7 @@ def alter(&code)
nil
end
+ # Like clojure.core/commute except block is used as update function
def commute(&code)
java_send :commute,
[Java::clojure.lang.IFn.java_class,
@@ -99,16 +156,22 @@ def commute(&code)
# Agents
class Java::ClojureLang::Agent
+
+ # Like clojure.core/send except block is used as update function
def send_(&code)
Familiar.send(self, Familiar.fn(code))
end
+ # Like clojure.core/send-off except block is used as update function
def send_off(&code)
Familiar.send_off(self, Familiar.fn(code))
end
end
+ #############################################################################
+ # Misc
+ # Pass a block to clojure.core/future
def self.future(&code)
Java::clojure.lang.Agent.soloExecutor.submit(Callable.new(code))
end
View
2 test/test_familiar.rb
@@ -1,7 +1,7 @@
require 'test/unit'
require 'familiar'
-class FamiliarAtomTest < Test::Unit::TestCase
+class FamiliarTest < Test::Unit::TestCase
def test_can_create_a_function_from_a_lambda
f = Familiar.fn(lambda {|x| x * 2 })

0 comments on commit 5cc7243

Please sign in to comment.
Something went wrong with that request. Please try again.