This is a library that allows you to define a “multi-named” method, like Smalltalk.
require 'chatter' class Kid def initialize(name) @name = name end extend Chatter # this is how to use "chat" to define a multi-named method chat(:pass, :to, :saying) do |item, target, words| puts "#{@name} passes #{item} to #{target}, saying '#{words}'" end end jack = Kid.new('Jack') # this is how the method is called jack.pass('ball').to('Jill').saying('catch!') # >> "Jack passes ball to Jill, saying 'catch!'"
This library is mostly tailored for creating DSLs. For example, a DSL for describing finite-state machines can look like
a_state - a_symbol > another_state
And with Chatter this can be easily implemented with
class State chat(:-, :>) {|symbol, target_state| ...} end
For another example, (this code does not work yet due to the first limitation listed below) a Ruby API for a GUI tookit might use Rubyish accessor methods (property
, property=
) as aliases to (getProperty
, setProperty
). But this is not directly possible with properties that take arguments, for example, TableWidget#getCellText(x, y)
, TableWidget#setCellText(x, y)
. By using
class TableWidget chat(:cell_text, :[]) do |_, (x, y)| getCellText(x, y) end chat(:cell_text, :[]=) do |_, (x, y, value)| setCellText(x, y, value) end end
We can do
a_table_widget.cell_text[x, y] = " (cool)"
-
“Multi-name methods” with overlapping components are not yet supported. For example, if you do
chat(:pass, :to) {} chat(:pass) {}
Only the second one will work.
-
Sub-methods that take blocks are not yet supported. For example, you cannot yet implement
(1 == 1).ifFalse {'wrong'}.ifTrue {'right'}
-
Sub-methods must be called in order they’re listed in
chat