| Books & Tools | Techniques | |
|
Comprehensive coverage of Ruby 1.8 and 1.9
"The New Most Important Ruby Book" JudeJude is my Java documentation browser. It combines Sun's definitive javadocs with the easy-to-use format of Java in a Nutshell, and tops it off with easy keyboard-based navigation and full-text searching. Jude is available for free evaluation. See the user's guide for more info Java in a NutshellThe 5th edition is now out, with complete coverage of Java 5.0! It includes a fast-paced tutorial on the language, and a compact quick-reference for the core Java API. Java Examples in a NutshellThe 3rd edition, updated for Java 1.4 This edition has all-new coverage of the NIO and JavaSound APIs, completely rewritten Servlets and XML chapters, and coverage of new Java 1.4 features (assertions, logging, preferences, SSL, etc.) added througout. A great book for those who like to learn by example. 193 working examples: 21,900 lines of carefully commented code to learn from. Java 1.5 Tiger: A Developer's NotebookAmazon incorrectly credits me as the main author on this book. I'm actually the second author: really more of a consultant. This is a good book about all the language changes in the latest version of Java. Effective JavaI didn't write this excellent book, but I wish I had. Author Josh Bloch is probably best known for the collections classes in the java.util package. His experience and wisdom are apparent in this book. I learned from it and recommend it highly. |
June 06, 2007Functional Programming Hacks for RubyI've been noodling around with Proc, Method, UnboundMethod and Symbol, and have come up with the following utilities for:
I don't claim that any of this is actually useful. But it might be mind-expanding or character building. I'm relatively new to Ruby, so comments from more experienced rubyists are more than welcome.
#
# func.rb: experimental functional programming hacks for Ruby
# Copyright (c) 2007 by David Flanagan
# License: http://creativecommons.org/licenses/by/3.0/
#
# This module defines methods and operators for function composition,
# memoization and currying. It automatically includes itself in Proc and
# Method. It is suitable for use with any Proc-like class that
# responds to []. The methods and operators always return lambdas
# regardless of the type of argument.
module Functional
# Return a new lambda that computes self[f[args]]
# Examples, using the * alias for this method
#
# f = lambda {|x| x*x }
# g = lambda {|x| x+1 }
# (f*g)[2] # => 9
# (g*f)[2] # => 5
#
# def polar(x,y)
# [Math.hypot(y,x), Math.atan2(y,x)]
# end
# def cartesian(magnitude, angle)
# [magnitude*Math.cos(angle), magnitude*Math.sin(angle)]
# end
# p,c = method :polar, method :cartesian
# (c*p)[3,4] # => [3,4]
#
def compose(f)
if self.respond_to?(:arity) && self.arity == 1
lambda { |*args| self[f[*args]] }
else
lambda { |*args| self[*f[*args]] }
end
end
#
# Return a new lambda that caches the results of this function and
# only calls the function when new arguments are supplied.
# Example: a memoized recursive factorial function
#
# f = lambda {|x|
# return 1 if x==0
# x*f[x-1];
# }.memoize
#
def memoize
cache = {}
lambda { |*args|
# notice that the hash key is an array of arguments!
unless cache.has_key?(args)
cache[args] = self[*args]
end
cache[args]
}
end
#
# Return a lambda equivalent to this one with one or more initial
# arguments curried in. When only a single argument
# is being specified, the >> alias may be simpler to use.
# Example:
# product = lambda {|x,y| x*y}
# doubler = lambda >> 2
#
def curry_first(*first)
lambda {|*rest| self[*first.concat(rest)]}
end
#
# Return a lambda equivalent to this one with one or more final arguments
# curried in. When only a single argument is being specified,
# the << alias may be simpler
# Example:
# difference = lambda { |x,y| x-y }
# decrement = difference << 1
#
def curry_last(*last)
lambda {|*rest| self[*rest.concat(last)]}
end
# Here are operator alternatives for these methods
alias * compose # h = f*g
alias ~ memoize # cached_f = ~f
alias >> curry_first # g = f >> 2 -- set first arg to 2
alias << curry_last # g = f << 2 -- set last arg to 2
end
# Add these functional programming methods to Proc and Method classes
class Proc; include Functional; end
class Method; include Functional; end
#
# Add [] and []= operators to the Symbol class for accessing and setting
# singleton methods of objects. Read : as "method" and [] as "of".
# So :m[o] reads "method m of o".
#
class Symbol
# Return the method of obj named by this symbol. This may be a singleton
# method of obj (such as a class method) or an instance method defined
# by obj.class or inherited from a superclass.
# Examples:
# creator = :new[Object] # Class method Object.new
# doubler = :*[2] # * method of 2
#
def [](obj)
obj.method(self)
end
# Define a singleton method on object o, using Proc or Method f as its body.
# This symbol is used as the name of the method.
# Examples:
#
# :singleton[o] = lambda { puts "this is a singleton method of o" }
# :class_method[String] = lambda { puts "this is a class method" }
#
# Note that you can't create instance methods this way. See Module.[]=
#
def []=(o,f)
# We can't use self in the block below, since it is evaluated in the
# context of a different object. So we have to assign self to a variable
sym = self
# This is the object we define singleton methods on
eigenclass = (class << o; self end)
# define_method is private, so we have to use instance_eval to execute it
eigenclass.instance_eval { define_method(sym, f) }
end
end
#
# Define [] and []= operators for accessing and setting the instance
# methods of a module. Note that [] returns an UnboundMethod which
# must be bound to an object before it can be invoked.
#
class Module
# Access instance methods with array notation. Returns UnboundMethod
# Example: String[:reverse].bind("foo").call => "oof"
alias [] instance_method
# Define instance methods with array assignment notation
# Example: String[:backwards] = lambda { reverse }
def []=(sym, f)
self.instance_eval { define_method(sym, f) }
end
end
#
# Use the [] operator to bind unbound methods
#
class UnboundMethod
# Allow [] as an alternative to bind. With Module.[] above, we can
# write code like this: puts String[:reverse]["foo"][]
# The first brackets get the method, the second bind it, the third call it.
alias [] bind
end
|
Advertising
About
Store
Search
Archives
April 2008
March 2008 February 2008 January 2008 November 2007 October 2007 September 2007 August 2007 July 2007 June 2007 May 2007 April 2007 March 2007 February 2007 January 2007 December 2006 November 2006 October 2006 September 2006 August 2006 July 2006 June 2006 May 2006 April 2006 March 2006 January 2006 December 2005 November 2005 October 2005 September 2005 August 2005 July 2005 June 2005 April 2005 March 2005 February 2005 December 2004 October 2004 September 2004 July 2004 June 2004 May 2004 April 2004 March 2004 February 2004 January 2004 Syndicate
|