[#147004] How and where Fixnum are created — "Eustaquio Rangel de Oliveira Jr." <eustaquiorangel@...>

-----BEGIN PGP SIGNED MESSAGE-----

10 messages 2005/07/01

[#147009] no clue — Joe Van Dyk <joevandyk@...>

I thought for all of five seconds for a good subject line for this

36 messages 2005/07/01
[#147028] Re: no clue — Daniel Brockman <daniel@...> 2005/07/02

Joe Van Dyk <joevandyk@gmail.com> writes:

[#151840] Re: no clue — Joe Van Dyk <joevandyk@...> 2005/08/12

On 7/1/05, Daniel Brockman <daniel@brockman.se> wrote:

[#151998] Re: no clue — Simon Krer <SimonKroeger@...> 2005/08/12

[#152051] Re: no clue — Simon Krer <SimonKroeger@...> 2005/08/13

Hi Joe,

[#152078] Re: no clue — Joe Van Dyk <joevandyk@...> 2005/08/13

On 8/13/05, Simon Krer <SimonKroeger@gmx.de> wrote:

[#152089] Re: no clue — Simon Krer <SimonKroeger@...> 2005/08/13

[#152093] Re: no clue — Joe Van Dyk <joevandyk@...> 2005/08/14

On 8/13/05, Simon Krer <SimonKroeger@gmx.de> wrote:

[#147044] Loading a file without cluttering the global namespace — Benjamin Hepp <benjamin-hepp@...>

Hello,

11 messages 2005/07/02

[#147056] class variable leading a double life — "Amarison" <amarison@...>

Can someone please explain why the @var variable leads a double life? One

20 messages 2005/07/02

[#147153] Ruby under Cygwin problems — JZ <usenet@...>

Whatever Ruby module I want to install under Cygwin I always get the same

30 messages 2005/07/04
[#147236] Re: Ruby under Cygwin problems — "karlin.fox@..." <karlin.fox@...> 2005/07/05

> No this is not the problem, it's just one more of this quick and dirty hacks (that i don't like in ruby).

[#147239] Re: Ruby under Cygwin problems — "Ryan Leavengood" <mrcode@...> 2005/07/05

karlin.fox@gmail.com said:

[#147280] Extract/Parse String? — tuyet.ctn@...

How do I extract "treeframe1120266500902" from this String class

12 messages 2005/07/06

[#147300] Inheriting Array and slice() behaviour — Sylvain Joyeux <sylvain.joyeux@...>

I have a class inheriting Array, and I expected slice() and []

43 messages 2005/07/06
[#147327] Re: Inheriting Array and slice() behaviour — Yukihiro Matsumoto <matz@...> 2005/07/06

Hi,

[#147348] Re: Inheriting Array and slice() behaviour — "Robert Klemme" <bob.news@...> 2005/07/06

William Morgan <wmorgan-ruby-talk@masanjin.net> wrote:

[#147437] Re: Inheriting Array and slice() behaviour — William Morgan <wmorgan-ruby-talk@...> 2005/07/07

Excerpts from Robert Klemme's mail of 6 Jul 2005 (EDT):

[#147443] Re: Inheriting Array and slice() behaviour — "Ara.T.Howard" <Ara.T.Howard@...> 2005/07/07

On Fri, 8 Jul 2005, William Morgan wrote:

[#147465] Re: Inheriting Array and slice() behaviour — William Morgan <wmorgan-ruby-talk@...> 2005/07/07

Excerpts from Ara.T.Howard's mail of 7 Jul 2005 (EDT):

[#147483] Re: Inheriting Array and slice() behaviour — Pit Capitain <pit@...> 2005/07/07

William Morgan schrieb:

[#147355] Major web host supports Rails — bertrandmuscle@...

One of the biggest web hosts on the internet (Dreamhost) now supports

32 messages 2005/07/06
[#147761] Re: Major web host supports Rails — Dennis Roberts <denrober@...> 2005/07/11

Want to support Ruby? Use Textdrive (http://www.textdrive.com/).

[#147421] Ruby as mathematical language — "none" <webb.sprague@...>

Hi Ruby world.

27 messages 2005/07/07

[#147504] ruby-1.8.2: test.rb: Seg Fault in test_check "exception" — me2faster@...

I reduced the sample/test.rb to just the test_check "exception"

12 messages 2005/07/07

[#147506] Ruby in XML. — John Carter <john.carter@...>

I have just stuck this on..

16 messages 2005/07/08

[#147542] Re: accessing index inside map — "Pe, Botp" <botp@...>

nobuyoshi nakada [mailto:nobuyoshi.nakada@ge.com] wrote:

26 messages 2005/07/08
[#147548] Re: accessing index inside map — "Robert Klemme" <bob.news@...> 2005/07/08

Pe, Botp wrote:

[#147651] Strings vs arrays — Luke Worth <luke@...>

Hi.

25 messages 2005/07/09
[#147670] Re: Strings vs arrays — Daniel Brockman <daniel@...> 2005/07/09

Luke Worth <luke@worth.id.au> writes:

[#147711] Programming the Lego robots using Ruby technology. — Victor Reyes <victor.reyes@...>

Do anyone knows if there is a Ruby API to program the Lego robots?

8 messages 2005/07/10
[#147712] Re: Programming the Lego robots using Ruby technology. — "daz" <dooby@...10.karoo.co.uk> 2005/07/11

[#147720] Re: accessing index inside map — "Pe, Botp" <botp@...>

Yukihiro Matsumoto [mailto:matz@ruby-lang.org] wrote:

28 messages 2005/07/11
[#147722] Re: accessing index inside map — Yukihiro Matsumoto <matz@...> 2005/07/11

Hi,

[#147790] class_attr_accessor — "Jeffrey Moss" <jeff@...>

I was playing around with class variables and class instance variables

16 messages 2005/07/11

[#147895] Updating GUIs — Joe Van Dyk <joevandyk@...>

Hi,

22 messages 2005/07/12

[#147952] Initialization via a Module — Gavin Kistner <gavin@...>

I have a module that needs to set a few instance variables on the

17 messages 2005/07/13

[#148046] Ruby has ruined my C++ — John Carter <john.carter@...>

These are exciting days in the world of C++. Every month the C/C++ User

52 messages 2005/07/13
[#148152] Re: Ruby has ruined my Java (was Re: Ruby has ruined my C++) — Kero <kero@...> 2005/07/14

> Two!

[#148497] Re: ] Re: Ruby has ruined my Java (was Re: Ruby has ruined my C++) — tony summerfelt <snowzone5@...> 2005/07/17

> After 4 years, Ruby still hasn't ruined itself.

[#148630] Re: ] Re: Ruby has ruined my Java (was Re: Ruby has ruined my C++) — mathew <meta@...> 2005/07/18

tony summerfelt wrote:

[#148709] Re: ] Re: Ruby has ruined my Java (was Re: Ruby has ruined my C++) — Daniel Amelang <daniel.amelang@...> 2005/07/18

Let's say that I have this...friend...um yea. And this 'friend' was

[#148711] Re: ] Re: Ruby has ruined my Java (was Re: Ruby has ruined my C++) — Jacob Fugal <lukfugl@...> 2005/07/18

On 7/18/05, Daniel Amelang <daniel.amelang@gmail.com> wrote:

[#148811] Re: ] Re: Ruby has ruined my Java (was Re: Ruby has ruined my C++) — Kero <kero@...> 2005/07/19

> Ha! You've reproduced my code almost exactly :)

[#148067] Ruby momentum? — Preston Crawford <me@...>

I'm an outsider to the Ruby community. I've used it a time or two,

62 messages 2005/07/14
[#148248] Re: Ruby momentum? — "gregarican" <greg.kujawa@...> 2005/07/15

Zach Dennis wrote:

[#148303] Re: Ruby momentum? — Devin Mullins <twifkak@...> 2005/07/15

Where I work (and I imagine most places), they don't bring developers on

[#148583] Re: Ruby momentum? — tsuraan <tsuraan@...> 2005/07/18

> *Actually when I've mentioned Ruby at work it's inspired more often a

[#148594] Re: Ruby momentum? — Kirk Haines <khaines@...> 2005/07/18

On Monday 18 July 2005 7:41 am, tsuraan wrote:

[#148104] difference? — G畸or SEBESTYノN <segabor@...>

Hi,

15 messages 2005/07/14

[#148229] Sampling (#39) — Ruby Quiz <james@...>

The three rules of Ruby Quiz:

97 messages 2005/07/15
[#148233] Re: [QUIZ] Sampling (#39) — James Edward Gray II <james@...> 2005/07/15

On Jul 15, 2005, at 8:00 AM, Ruby Quiz wrote:

[#148269] Re: [QUIZ] Sampling (#39) — Cassio Pennachin <pennachin@...> 2005/07/15

On 7/15/05, James Edward Gray II <james@grayproductions.net> wrote:

[#148273] Re: [QUIZ] Sampling (#39) — Jim Freeze <jim@...> 2005/07/15

* Cassio Pennachin <pennachin@gmail.com> [2005-07-16 03:04:12 +0900]:

[#148275] Re: [QUIZ] Sampling (#39) — Cassio Pennachin <pennachin@...> 2005/07/15

> Shouldn't those number be more like

[#148276] Re: [QUIZ] Sampling (#39) — Belorion <belorion@...> 2005/07/15

On 7/15/05, Cassio Pennachin <pennachin@gmail.com> wrote:

[#148284] Re: [QUIZ] Sampling (#39) — David Brady <ruby_talk@...> 2005/07/15

Belorion wrote:

[#148317] What does this construct mean? — "Casper" <caspertonka@...>

1. class MyController < ActionController::Base

22 messages 2005/07/16
[#148651] Re: What does this construct mean? — "Casper" <caspertonka@...> 2005/07/18

Devin Mullins wrote:

[#148656] Re: What does this construct mean? — "Ara.T.Howard" <Ara.T.Howard@...> 2005/07/18

On Tue, 19 Jul 2005, Casper wrote:

[#148321] Cascading <=> comparisons — Garance A Drosehn <drosihn@...>

Let's say I have a hash with some values in it, and I want to

15 messages 2005/07/16

[#148338] delaying string evaluation — Navindra Umanee <navindra@...>

Hi,

20 messages 2005/07/16
[#148339] Re: delaying string evaluation — Eric Hodel <drbrain@...7.net> 2005/07/16

On 16 Jul 2005, at 01:23, Navindra Umanee wrote:

[#148361] Re: delaying string evaluation — Navindra Umanee <navindra@...> 2005/07/16

Eric Hodel <drbrain@segment7.net> wrote:

[#148341] Just seen on c.l.py — Stephen Kellett <snail@...>

Hi Folks,

23 messages 2005/07/16
[#148418] Re: Just seen on c.l.py — ptkwt@... (Phil Tomson) 2005/07/16

In article <05th9VCgqN2CFwW4@objmedia.demon.co.uk>,

[#148357] Ruby VS PHP — Tristan Knowles <cydonia_1@...>

I was chatting with a PHP dev friend tonight, he is a

38 messages 2005/07/16
[#148396] Re: Ruby VS PHP — schlu-do@... (Dominik Schlter) 2005/07/16

Hi,

[#148384] `not' in parameter lists — Daniel Brockman <daniel@...>

I just noticed that all of the following give syntax errors:

18 messages 2005/07/16

[#148402] Nonblocking Sockets — James Edward Gray II <james@...>

Is this the "standard" way to make a nonblocking Socket in Ruby?

16 messages 2005/07/16

[#148542] Refactoring Tycho API - Opinions wanted — Hal Fulton <hal9000@...>

I've been revisiting my favorite Ruby project in the past

24 messages 2005/07/18

[#148689] Re: `not' in parameter lists — twifkak@...

On Jul 17, 2005, at 2:34 PM, Daniel Brockman wrote:

13 messages 2005/07/18

[#148721] Ruby/Rails as a starter language? — "SomeDude" <somedude@...>

Hello,

108 messages 2005/07/18
[#148736] Re: Ruby/Rails as a starter language? — vanek@... 2005/07/19

If you don't need to get involved in web programming right away, gawk

[#148743] Re: Ruby/Rails as a starter language? — James Britt <james_b@...> 2005/07/19

vanek@acd.net wrote:

[#148751] Re: Ruby/Rails as a starter language? — Navindra Umanee <navindra@...> 2005/07/19

James Britt <james_b@neurogami.com> wrote:

[#148752] Re: Ruby/Rails as a starter language? — Stefan Lang <langstefan@...> 2005/07/19

On Tuesday 19 July 2005 09:41, Navindra Umanee wrote:

[#148783] Re: Ruby/Rails as a starter language? — Mark Volkmann <r.mark.volkmann@...> 2005/07/19

On 7/19/05, Stefan Lang <langstefan@gmx.at> wrote:

[#148870] Re: Ruby/Rails as a starter language? — Hal Fulton <hal9000@...> 2005/07/19

Mark Volkmann wrote:

[#148873] Re: Ruby/Rails as a starter language? — Daniel Amelang <daniel.amelang@...> 2005/07/19

> In Java, classes aren't objects.

[#148875] Re: Ruby/Rails as a starter language? — Devin Mullins <twifkak@...> 2005/07/19

Daniel Amelang wrote:

[#148880] Re: Ruby/Rails as a starter language? — "Adam P. Jenkins" <thorin@...> 2005/07/20

Devin Mullins wrote:

[#148961] Re: [WAY OT] Re: Ruby/Rails as a starter language? — ptkwt@... (Phil Tomson) 2005/07/20

In article <Pine.LNX.4.62.0507192121430.10750@harp.ngdc.noaa.gov>,

[#148969] Re: [WAY OT] Re: Ruby/Rails as a starter language? — Rick Nooner <rick@...> 2005/07/20

On Thu, Jul 21, 2005 at 02:05:56AM +0900, Phil Tomson wrote:

[#148972] Re: [WAY OT] Re: Ruby/Rails as a starter language? — Jim Freeze <jim@...> 2005/07/20

* Rick Nooner <rick@nooner.net> [2005-07-21 02:59:56 +0900]:

[#148975] Re: [WAY OT] Re: Ruby/Rails as a starter language? — Rick Nooner <rick@...> 2005/07/20

On Thu, Jul 21, 2005 at 03:21:08AM +0900, Jim Freeze wrote:

[#148988] Re: [WAY OT] Re: Ruby/Rails as a starter language? — Jim Freeze <jim@...> 2005/07/20

* Rick Nooner <rick@nooner.net> [2005-07-21 03:57:35 +0900]:

[#148993] Re: [WAY OT] Re: Ruby/Rails as a starter language? — Rick Nooner <rick@...> 2005/07/20

On Thu, Jul 21, 2005 at 04:47:41AM +0900, Jim Freeze wrote:

[#149008] Ruby/OCaml Was Re: [WAY OT] Re: Ruby/Rails as a starter language? — Rick Nooner <rick@...> 2005/07/20

> I was just at the OCaml site,

[#148730] Memory profiling? — Scott Ellsworth <scott@...>

Hi, all.

12 messages 2005/07/19

[#148763] nil for unassigned keys — Simon Strandgaard <neoneye@...>

Sometimes I find myself writing :key=>true,

17 messages 2005/07/19

[#149035] C extension makes things slower — ptkwt@... (Phil Tomson)

In general I've always seen things speed up when I've writtten C

16 messages 2005/07/21

[#149059] Segmentation fault with a threads/forks script — Lucas Nussbaum <lucas@...>

Hi,

13 messages 2005/07/21
[#149069] Re: [BUG] Segmentation fault with a threads/forks script — "Ara.T.Howard" <Ara.T.Howard@...> 2005/07/21

On Thu, 21 Jul 2005, Lucas Nussbaum wrote:

[#149153] FreeRIDE: Where does the output go? — "basi" <basi_lio@...>

I'm trying out FreeRIDE and I have a truly embarrassing question.

15 messages 2005/07/22

[#149184] Drawing Trees (#40) — Ruby Quiz <james@...>

The three rules of Ruby Quiz:

18 messages 2005/07/22

[#149198] Abstract class or interface? — EdUarDo <eduardo.yanezNOSPAM@...>

Hi all again :),

13 messages 2005/07/22

[#149286] Local Instance Methods — "Trans" <transfire@...>

Hi All--

25 messages 2005/07/23

[#149302] Any interest in writing gui library on top of qtruby? — meruby@...

wax is a gui written on top of wxPython. It allows seamless integration

19 messages 2005/07/23

[#149322] Lisp on Lines — "luke" <lduncalfe@...>

Read on the comp.lang.lisp group that someone is developing 'Lisp on Lines'

44 messages 2005/07/24
[#149343] Re: Lisp on Lines — "Ara.T.Howard" <Ara.T.Howard@...> 2005/07/24

On Sun, 24 Jul 2005, luke wrote:

[#149366] Re: Lisp on Lines — "William James" <w_a_x_man@...> 2005/07/24

How much less powerful than Lisp is Ruby?

[#149397] Nitro + Og 0.21.0 Compiler, Og custom joins, Og dynamic injection, new builder — "George Moschovitis" <george.moschovitis@...>

Hello everyone,

13 messages 2005/07/25

[#149481] What's so special about operators, built-in classes and modules? — Jim Freeze <jim@...>

I just noticed this little quirk. Is there something

30 messages 2005/07/25

[#149490] Trying to understand symbols — "Sam Kong" <sam.s.kong@...>

Hello!

18 messages 2005/07/25

[#149515] Factory Patterns in Ruby — Lyndon Samson <lyndon.samson@...>

Factory is a very common pattern in the java world, in some places

17 messages 2005/07/26

[#149555] — "Adrian Petru Dimulescu" <adrian.dimulescu@...>

Hello,

13 messages 2005/07/26

[#149616] Next Official Ruby Version

Is it somehow planned to build a new official Ruby before Ruby 2, that means a version called 1.10 or so?

26 messages 2005/07/26

[#149654] (X)Emacs users going to RubyCOnf — Forrest Chang <fkc_email-news@...>

Hi All:

14 messages 2005/07/27

[#149720] Re: What's so special about operators, built-in classes and modules? — twifkak@...

>Then you will have complex network of classes instead of simple tree

56 messages 2005/07/27
[#149765] Re: What's so special about operators, built-in classes and modules? — Daniel Brockman <daniel@...> 2005/07/28

gabriele renzi <surrender_it@remove-yahoo.it> writes:

[#149770] Re: What's so special about operators, built-in classes and modules? — Yukihiro Matsumoto <matz@...> 2005/07/28

Hi,

[#149772] Re: What's so special about operators, built-in classes and modules? — Devin Mullins <twifkak@...> 2005/07/28

Yukihiro Matsumoto wrote:

[#149773] Re: What's so special about operators, built-in classes and modules? — Yukihiro Matsumoto <matz@...> 2005/07/28

Hi,

[#149776] Re: What's so special about operators, built-in classes and modules? — Devin Mullins <twifkak@...> 2005/07/28

Yukihiro Matsumoto wrote:

[#149905] Re: What's so special about operators, built-in classes and modules? — Daniel Brockman <daniel@...> 2005/07/28

Yukihiro Matsumoto <matz@ruby-lang.org> writes:

[#149783] Ruby in embedded applications — "treefrog" <stephen.hill@...>

Hi folks,

14 messages 2005/07/28

[#149793] Idea for Ruby 2.0 — Nikolai Weibull <mailing-lists.ruby-talk@...>

Lately I've found myself using pseudo-anonymous variables a lot, e.g.,

24 messages 2005/07/28

[#149801] Combination of two arrays — Claus Spitzer <docboobenstein@...>

Greetings!

18 messages 2005/07/28

[#149876] Linux Journal article on Ruby — pat eyler <pat.eyler@...>

http://www.linuxjournal.com/article/8356 it's always nice to see another

13 messages 2005/07/28

[#149968] Which Regex-Engine will be used in Ruby 1.8.3 Release?

One short question.

12 messages 2005/07/29

[#149982] Chopping the beginning of a string elegantly — "francisrammeloo@..." <francisrammeloo@...>

Hi all,

13 messages 2005/07/29

[#150133] Ruby-Python; using python from within ruby — "Norjee" <Norjee@...>

At the moment I'm looking at rails, it seems like a great framework.

13 messages 2005/07/30

[#150154] Ruby-Oniguruma interoperability on Named Groups

Let me first explain the reason for and the kind of this message.

10 messages 2005/07/30

[#150205] Yet Another useless Ruby 2 Idea — gabriele renzi <surrender_it@...>

Hi gurus and nubys,

69 messages 2005/07/31
[#150680] Re: Yet Another useless Ruby 2 Idea — Daniel Brockman <daniel@...> 2005/08/04

Jeff Wood <jeff.darklight@gmail.com> writes:

[#150684] Re: Yet Another useless Ruby 2 Idea — Austin Ziegler <halostatue@...> 2005/08/04

On 8/3/05, Daniel Brockman <daniel@brockman.se> wrote:

[#150688] Re: Yet Another useless Ruby 2 Idea — Jeff Wood <jeff.darklight@...> 2005/08/04

I'm not saying there are NO features of python that are cool... I like

[#150860] Re: Yet Another useless Ruby 2 Idea — gabriele renzi <surrender_it@...> 2005/08/05

Jeff Wood ha scritto:

[#150899] Re: Yet Another useless Ruby 2 Idea — Jacob Fugal <lukfugl@...> 2005/08/05

On 8/5/05, gabriele renzi <surrender_it@remove-yahoo.it> wrote:

[#150910] Re: Yet Another useless Ruby 2 Idea — gabriele renzi <surrender_it@...> 2005/08/05

Jacob Fugal ha scritto:

[#151275] Re: Yet Another useless Ruby 2 Idea — mathew <meta@...> 2005/08/08

gabriele renzi wrote:

[#151354] Re: Yet Another useless Ruby 2 Idea — gabriele renzi <surrender_it@...> 2005/08/09

mathew ha scritto:

[SUMMARY] Inference Engine (#37)

From: Ruby Quiz <james@...>
Date: 2005-07-07 13:05:51 UTC
List: ruby-talk #147407
	irb(main):005:0> are any programmers happy programmers?
	=> Yes, some programmers are happy programmers.
	irb(main):006:0> are all Ruby programmers happy programmers?
	=> Yes, all ruby programmers are happy programmers.
	irb(main):007:0> are any Python programmers happy programmers?
	=> I don't know.

True artificial intelligence doesn't seem that far off after all.

Did you know you could use irb as an interface like that?  I didn't!  Be sure
and glance at Pit Capitain's code to see just how that is done.

Daniel Sheppard sent in a nice object model, translating the rules into a class
hierarchy.  I recommend browsing through that too.

Here though, I want to look into Paulo Capriotti's code.  Paulo decided to model
the relationships as a directed graph, where vertices are the groups and edges
represent their relationships.  To save a little work, Paulo used the graph Ruby
library as a starting point.  Here's the beginning of the solution:

	require 'graph'

	def opposite_type(type)
	  type == :provable_true ? :provable_false : :provable_true
	end

	class Property
	  attr_reader :name, :type
	  def initialize(name, type)
	    @name = name
	    @type = type
	  end

	  def opposite
	    Property.new(@name, @type == :positive ? :negative : :positive)
	  end

	  def Property.create(x)
	    if x.respond_to?(:opposite)
	      x
	    else
	      Property.new(x, :positive)
	    end
	  end

	  def hash
	    "#{@name}##{@type}".hash
	  end

	  def eql?(other)
	    @name == other.name and @type == other.type
	  end

	  alias == eql?

	  def to_s
	    res = @name
	    if @type == :negative
	      "not-" + res
	    else
	      res
	    end
	  end
	end
	
	# ...

First we see the definition of a simple helper method to convert between two
opposites:  Things we can prove to be true and things we can prove are false.

Next, we have a helper class for a Property.  I wasn't sure what that meant at
first, so I had to dig a little.  Obviously, much of this class is just support
for hashing the object (hash() and eql?()).  We have a class method to create()
a Property when needed and an interesting method to give us an opposite()
Property.  The to_s() method is also interesting.  We can see from it that a
negated Property gets a leading "not-" when converted to a String.

All of this clicked into place for me when I turned on Paulo's debug mode and
watched the code work.  Here's an example:

	> All dogs are mammals
	adding edge dog, not-dog, provable_false
	adding edge not-dog, dog, provable_false
	adding edge dog, dog, provable_true
	adding edge not-dog, not-dog, provable_true
	adding edge mammal, not-mammal, provable_false
	adding edge not-mammal, mammal, provable_false
	adding edge mammal, mammal, provable_true
	adding edge not-mammal, not-mammal, provable_true
	...
	adding edge dog, mammal, provable_true
	adding edge not-mammal, not-dog, provable_true
	...
	adding edge not-mammal, dog, provable_false
	adding edge not-dog, mammal, provable_false
	...
	adding edge mammal, not-dog, provable_false
	adding edge dog, not-mammal, provable_false
	...

As you can see, a Property is a representation of the groups we are describing
to the inference engine.  Opposites represent everything not in that Property,
or group.  So the "dog" Property has an opposite of "not-dog", or non-dog, if
it's easier to think of that way.

What's the rest of that stuff about edges and what we can prove though?  That's
the graph being built, as I mentioned earlier.  Let's examine that code now:

	# ...
	
	class Knowledge < DirectedHashGraph
	  attr_reader :contradiction

	  def initialize
	    @contradiction = false
	    super
	  end

	  # Add a property and some tautologies.
	  # Here we assume that the property and
	  # its opposite are not void.
	  def add_property(x)
	    x = Property.create(x)
	    safe_add_edge(x, x.opposite, :provable_false)
	    safe_add_edge(x.opposite, x, :provable_false)
	    safe_add_edge(x, x, :provable_true)
	    safe_add_edge(x.opposite, x.opposite, :provable_true)
	    x
	  end

	  # Add en edge. Never throw.
	  def safe_add_edge(x, y, type)
	    catch(:add_edge_throw) do 
	      add_edge(x, y, type)
	    end
	  end

	  # Add an edge. Throw if the edge already exists.
	  def add_edge(x, y, type)
	    debug_msg "adding edge #{x}, #{y}, #{type}"
	    if self[x,y]
	      unless self[x,y] == type
	        @contradiction = true
	        debug_msg " \tcontradiction"
	        throw :add_edge_throw, :contradiction
	      else
	        debug_msg "\ti know"
	        throw :add_edge_throw, :i_know
	      end
	    else
	      super(x, y, type)
	    end
	  end

	  # Add an edge and its contrapositive.
	  def add_assertion(*args)
	    x, y, type = get_stmt(*args)
	    catch(:add_edge_throw) do
	      add_edge(x, y, type)
	      add_edge(y.opposite, x.opposite, type)
	      :normal
	    end
	  end

	  # Extract statement values.
	  def get_stmt(*args)
	    case args.size
	    when 1
	      x, y, type = args[0].x, args[0].y, args[0].type
	    when 3
	      x, y, type = args[0], args[1], args[2]
	    else
	      raise "Invalid argument list in #{caller.first}"
	    end  
	    return add_property(x), add_property(y), type
	  end

	  # Discover all possible deductions
	  # and add the corresponding edges to the graph.
	  def deduce
	    each_vertex do |v1|
	      each_vertex do |v2|
	        each_vertex do |v3|

	          if self[v1,v2] == :provable_true and
	             self[v2,v3] == :provable_true
	            add_assertion(v1, v3, :provable_true)
	          end

	          if self[v2,v1] == :provable_false and
	             self[v2,v3] == :provable_true
	            add_assertion(v3, v1, :provable_false)
	          end

	          if self[v1,v2] == :provable_true and
	             self[v3,v2] == :provable_false
	            add_assertion(v3, v1, :provable_false)
	          end

	          break if @contradiction
	        end
	      end
	    end
	  end

	  # Return true if a statement is provable.
	  # Return false if its negation is provable.
	  # Return nil if it is undecidable.
	  def test(*args)
	    x, y, type = get_stmt(*args)
	    case self[x,y]
	    when nil
	      return nil
	    when type
	      return true
	    else
	      return false
	    end
	  end
	end
	
	# ...

This class isn't as complicated as it appears, once you grasp the flow of how
it's used.  When an assertion is made to the engine, it will first call test()
to see if it already knows that information or if it contradicts any other
information.

Assuming the test passes, add_assertion() gets called.  That method starts by
calling get_stmt() to turn its arguments into two properties and a type
(:provable_true or :provable_false).  Note that the return sequence of
get_stmt(), uses add_property() to ensure that the graph already contains basic
relationships for that property (all dogs are dogs, for example).  These basic
relationships are added using safe_add_edge(), which is really just a shell over
add_edge() that filters out the symbols that are thrown by the latter.  Getting
back to add_assertion(), we can see that it too uses add_edge(), but it returns
the symbol thrown or its own :normal to indicate if we already knew about the
assertion or if it contradicts what we did know.  I know that's a lot to take
in, but if you just follow the chain of method calls it's pretty basic stuff.

Finally, deduce() is called after an assertion has been added.  By walking the
edges, deduce() will fill in any details the new assertion uncovers.  This is
done by checking relationships between three independent complete sets of
vertices, so relationships of the form one -> two -> three will be spotted.

You can see that this class is always monitoring for a @contradiction in each of
these methods.  However, I don't think this ever comes into play, since each
assertion is tested before it's added.  (Correct me if I'm wrong Paulo!)

On to the user interface:

	# ...
	
	["Assertion", "Question"].each do |c|
	  Struct.new(c, :x, :y, :type)
	end

	class UI

	  # Parse input and return a statement
	  def get_statement(line)
	    case line
	    # assertions
	    when /^all (.*)s are (.*)s\.?$/
	      return Struct::Assertion.new( Property.create($1),
	                                    Property.create($2),
	                                    :provable_true )
	    when /^no (.*)s are (.*)s\.?$/
	      return Struct::Assertion.new( Property.create($1),
	                                    Property.create($2).opposite,
	                                    :provable_true )
	    when /^some (.*)s are not (.*)s\.?$/
	      return Struct::Assertion.new( Property.create($1),
	                                    Property.create($2),
	                                    :provable_false )
	    when /^some (.*)s are (.*)s\.?$/
	      return Struct::Assertion.new( Property.create($1),
	                                    Property.create($2).opposite,
	                                    :provable_false )
	    # questions
	    when /^are all (.*)s (.*)s\?$/
	      return Struct::Question.new( Property.create($1),
	                                   Property.create($2),
	                                   :provable_true )
	    when /^are no (.*)s (.*)s\?$/
	      return Struct::Question.new( Property.create($1),
	                                   Property.create($2).opposite,
	                                   :provable_true )
	    when /^are any (.*)s not (.*)s\?$/
	      return Struct::Question.new( Property.create($1),
	                                   Property.create($2),
	                                   :provable_false )
	    when /^are any (.*)s (.*)s\?$/
	      return Struct::Question.new( Property.create($1),
	                                   Property.create($2).opposite,
	                                   :provable_false )
	    # description
	    when /^describe (.*)s\.?$/
	      return Property.create($1)
	    else 
	      return nil
	    end
	  end

	  # Return a description of the relation
	  # between x and y. 
	  # Assume that x is positive and that
	  # x -> y is not undecidable.
	  def describe_edge(x, y, aff = true)
	    case @k[x,y]
	    when :provable_true
	      case y.type
	      when :positive        
	        return "All #{x.name}s are #{y.name}s"
	      when :negative
	        return "No #{x.name}s are #{y.name}s"
	      end
	    when :provable_false
	      case y.type
	      when :positive
	        if aff
	          return "Some #{x.name}s are not #{y.name}s"
	        else
	          return "Not all #{x.name}s are #{y.name}s"
	        end
	      when :negative
	        if aff
	          return "Some #{x.name}s are #{y.name}s"
	        else
	          return "Not all #{x.name}s are not #{y.name}s"
	        end
	      end
	    end
	  end

	  # Return a list of sentences which describe
	  # the relations between x and each other node.
	  # Assume that x is positive.
	  def describe_node(x)
	    res = []
	    @k.each_vertex do |y|
	      if y.type == :positive and not x == y
	        if @k[x,y] == :provable_true
	          res << describe_edge(x,y)
	        elsif @k[x,y.opposite] == :provable_true
	          res << describe_edge(x,y.opposite)
	        elsif @k[x,y]
	          res << describe_edge(x,y)
	        elsif @k[x,y.opposite]
	          res << describe_edge(x,y.opposite)
	        end
	      end
	    end

	    res
	  end  

	  def say(value)
	    case value
	    when true
	      "Yes"
	    when false
	      "No"
	    else
	      "I don't know"
	    end
	  end

	  def initialize
	    @k = Knowledge.new
	  end

	  def wait_for_input
	    print '> '
	    gets
	  end

	  def run
	    while line = wait_for_input
	      line.chomp!
	      line.downcase!
	      stmt = get_statement(line)
	      if stmt.class == Struct::Assertion
	        case @k.test(stmt)
	        when true
	          puts "I know"
	        when false
	          puts "Sorry, that contradicts what I already know"
	        else
	          @k.add_assertion(stmt)
	          @k.deduce
	          puts "OK"
	        end
	      elsif stmt.class == Struct::Question
	        value = @k.test(stmt)
	        print say(value)
	        if value.nil?
	          print "\n"
	        else
	          puts ", #{describe_edge(stmt.x, stmt.y, value).downcase}"
	        end
	      elsif stmt.class == Property
	        describe_node(stmt).each do |sentence|
	          puts sentence
	        end
	      else
	        puts "I don't understand"
	      end
	    end
	  end
	end
	
	def debug_msg(msg)
	  puts msg if $debug
	end

	if $0 == __FILE__
	  ui = UI.new
	  ui.run
	end

Again, this looks like a lot of code, but it's not overly complicated, once you
find the flow.  Look at the last few lines to get a hint about where to begin. 
First, initialize() creates a Knowledge object to keep tract of our assertions
and answer our questions.  From that point on, run() handles the interactive
session.

The first thing you need to know is that run() uses a couple of helper methods: 
say() for output and wait_for_input() for input.  It also calls get_statement()
to parse input.  The return from get statement is either a single Property (the
"describe" command), a Struct::Assertion representing an assertion made, or a
Struct::Question representing a question asked.  You can see those Structs
defined just before the UI class starts.  They're just two properties and a
type.

The other thing to notice about get_statement() is that it does very basic
Regexp based parsing.  It uses a super clever trick of spotting a trailing "s"
to find the two groups in a line like, "Are all Ruby programmers happy
programmers?"  Of course, this does not work across all legal inputs:

	> All oxen are mammals.
	I don't understand
	> All James's pets are Dana's pets.
	OK
	> Are all James's pets Dana's pets?
	I don't know

To see another approach, examine Pit Capitain's parsing, especially the
IE.split() method.

Getting back to run() in Paulo's UI class, you'll see that the rest of the
method just handles the three different returns from get_statement(). 
Assertions are handled as I explained earlier.  Questions rely on
describe_edge() for answers and the "describe" command triggers a call to
describe_node().  That's the entire UI.

I promise to end this long summary very soon now, but I wanted to mention just
one more detail.  Paulo uses a helper method all through the code that's defined
near the end.  Here's another look at it:

	def debug_msg(msg)
	  puts msg if $debug
	end

The goal here is obvious, print a lot of extra information if I set this global
variable to true.  This is a trick that we all use sometimes in testing.  I just
wanted to suggest one minor change to enhance this trick:  Switch $debug to
$DEBUG.  Then you can trigger the messages with a command-line switch like so:

	$ ruby -e 'p $DEBUG'
	false
	$ ruby -d -e 'p $DEBUG'
	true

Slide that one into your bag of tricks, because it comes in handy.

My thanks to all three submitters for some really great code to poke around in
and play with.

Tomorrow, we have a simple but handy hack to explore.  It's an easy quiz so I
want to see all you beginners out there playing along!

In This Thread

Prev Next