[#380721] Can you search in REXML by attributes? — "Kyle X." <haebooty@...>

Hello and thank you to all the wonderful and helpful people at this

19 messages 2011/04/01
[#380737] Re: Can you search in REXML by attributes? — Robert Klemme <shortcutter@...> 2011/04/01

On Fri, Apr 1, 2011 at 2:53 AM, Kyle X. <haebooty@yahoo.com> wrote:

[#380755] Re: Can you search in REXML by attributes? — "Kyle X." <haebooty@...> 2011/04/01

Robert K. wrote in post #990336:

[#380762] Searching a CSV file - beginner seeking help — Simon Harrison <simon@...>

Hi all. I've written a little script to search a csv file for films. It

10 messages 2011/04/01

[#380843] Using grep on subarrays - help! — Simon Harrison <simon@...>

Can anyone help with this? I thought grep would find any element that

12 messages 2011/04/03

[#380849] Splitting each_cons? — Simon Harrison <simon@...>

I'm not sure if each_cons can do what I'm trying to achieve:

13 messages 2011/04/03

[#380883] pipe question — wolf volpi <wolf_volpi@...>

What does the pipe in this example do?

15 messages 2011/04/04

[#380949] functional languages -- any recommendations? — 7stud -- <bbxx789_05ss@...>

Haskell, Scala, or Erlang? Which one is the best?

18 messages 2011/04/05

[#380977] Separate new lines from an output — "Leo M." <leo.mmcm@...>

Hello!

12 messages 2011/04/05

[#381015] Match a pattern multiple times, returning matches, captures and offset? — Markus Fischer <markus@...>

Hi,

10 messages 2011/04/05

[#381035] capture the output of a grandchild — Chandan Bansal <chandan89@...>

hi

12 messages 2011/04/06

[#381075] Hello — Moises Montenegro <moemonty@...>

Hello,

43 messages 2011/04/06
[#381086] Re: Hello — James Nathan <badlands_2004@...> 2011/04/07

hello I am trying to get it stated myself, but I am not sure if I am setting Ruby up right.

[#381155] Re: Hello — James Nathan <badlands_2004@...> 2011/04/08

I am having a hard time to get it up and running. that is Ruby and Ruby on Rails. it seems that no one is willing to help so that we can enjoy this porgram. If their anyway that I can get it downloaded to me, some help to make sure that have the right porgrams.

[#381263] Re: Hello — James Nathan <badlands_2004@...> 2011/04/10

does the Free Ride program for Ruby the command program that I need to run and write my program?

[#381308] Re: Hello — James Nathan <badlands_2004@...> 2011/04/11

is there a disk that we can seen off and use. so that we can all the parts of ruby and ruby on rails. I would like this disk.

[#381313] Re: Hello — jake kaiden <jakekaiden@...> 2011/04/11

James Nathan wrote in post #992175:

[#381314] Re: Hello — Vincent Manis <vmanis@...> 2011/04/11

On 2011-04-11, at 16:50, jake kaiden wrote:

[#381322] Re: Hello — James Nathan <badlands_2004@...> 2011/04/12

I will just give up on Ruby and Ruby on Rails for now=20

[#381347] Re: Hello — James Nathan <badlands_2004@...> 2011/04/12

No, I will try another program to learn to write a program. Ruby is just to=

[#381351] Re: Hello — Phillip Gawlowski <cmdjackryan@...> 2011/04/12

On Tue, Apr 12, 2011 at 3:27 PM, James Nathan <badlands_2004@yahoo.com> wrote:

[#381358] Re: Hello — Martin DeMello <martindemello@...> 2011/04/12

On Tue, Apr 12, 2011 at 7:59 PM, Phillip Gawlowski

[#381087] Hash Surprises with Fixnum, #hash, and #eql? — Clifford Heath <no@...>

Folk,

44 messages 2011/04/07
[#381099] Re: Hash Surprises with Fixnum, #hash, and #eql? — Robert Klemme <shortcutter@...> 2011/04/07

On Thu, Apr 7, 2011 at 6:05 AM, Clifford Heath <no@spam.please.net> wrote:

[#381107] Re: Hash Surprises with Fixnum, #hash, and #eql? — Phillip Gawlowski <cmdjackryan@...> 2011/04/07

On Thu, Apr 7, 2011 at 11:19 AM, Robert Klemme

[#381109] Re: Hash Surprises with Fixnum, #hash, and #eql? — Robert Klemme <shortcutter@...> 2011/04/07

On Thu, Apr 7, 2011 at 1:20 PM, Phillip Gawlowski

[#381115] Re: Hash Surprises with Fixnum, #hash, and #eql? — Phillip Gawlowski <cmdjackryan@...> 2011/04/07

On Thu, Apr 7, 2011 at 1:53 PM, Robert Klemme

[#381182] Re: Hash Surprises with Fixnum, #hash, and #eql? — Clifford Heath <no@...> 2011/04/08

On 04/07/11 19:19, Robert Klemme wrote:

[#381187] Re: Hash Surprises with Fixnum, #hash, and #eql? — Robert Klemme <shortcutter@...> 2011/04/08

On Fri, Apr 8, 2011 at 9:30 AM, Clifford Heath <no@spam.please.net> wrote:

[#381233] Re: Hash Surprises with Fixnum, #hash, and #eql? — Clifford Heath <no@...> 2011/04/09

On 04/08/11 20:12, Robert Klemme wrote:

[#381269] Re: Hash Surprises with Fixnum, #hash, and #eql? — Charles Oliver Nutter <headius@...> 2011/04/11

Top-replying with a general observation: you can't please everyone all the =

[#381274] Re: Hash Surprises with Fixnum, #hash, and #eql? — Clifford Heath <no@...> 2011/04/11

On 04/11/11 10:02, Charles Oliver Nutter wrote:

[#381337] Re: Hash Surprises with Fixnum, #hash, and #eql? — Robert Klemme <shortcutter@...> 2011/04/12

On Mon, Apr 11, 2011 at 5:20 AM, Clifford Heath <no@spam.please.net> wrote:

[#381393] Re: Hash Surprises with Fixnum, #hash, and #eql? — Clifford Heath <no@...> 2011/04/13

On 04/12/11 19:09, Robert Klemme wrote:

[#381399] Re: Hash Surprises with Fixnum, #hash, and #eql? — Charles Oliver Nutter <headius@...> 2011/04/13

On Tue, Apr 12, 2011 at 9:05 PM, Clifford Heath <no@spam.please.net> wrote:

[#381402] Re: Hash Surprises with Fixnum, #hash, and #eql? — Clifford Heath <no@...> 2011/04/13

On 04/13/11 15:51, Charles Oliver Nutter wrote:

[#381416] Re: Hash Surprises with Fixnum, #hash, and #eql? — Charles Oliver Nutter <headius@...> 2011/04/13

On Wed, Apr 13, 2011 at 1:35 AM, Clifford Heath <no@spam.please.net> wrote:

[#381469] Re: Hash Surprises with Fixnum, #hash, and #eql? — Clifford Heath <no@...> 2011/04/13

On 04/13/11 22:23, Charles Oliver Nutter wrote:

[#381506] Re: Hash Surprises with Fixnum, #hash, and #eql? — Charles Oliver Nutter <headius@...> 2011/04/14

On Wed, Apr 13, 2011 at 4:40 PM, Clifford Heath <no@spam.please.net> wrote:

[#381510] Re: Hash Surprises with Fixnum, #hash, and #eql? — Clifford Heath <no@...> 2011/04/14

On 04/14/11 15:36, Charles Oliver Nutter wrote:

[#381876] Re: Hash Surprises with Fixnum, #hash, and #eql? — Charles Oliver Nutter <headius@...> 2011/04/19

On Thu, Apr 14, 2011 at 12:55 AM, Clifford Heath <no@spam.please.net> wrote=

[#381970] Re: Hash Surprises with Fixnum, #hash, and #eql? — Clifford Heath <no@...> 2011/04/21

Charles,

[#381090] can we use direct ruby instaed of javascript ? — Sniper Abandon <sathish.salem.1984@...>

Hi Ninjas,

29 messages 2011/04/07
[#381113] Re: can we use direct ruby instaed of javascript ? — Peter Zotov <whitequark@...> 2011/04/07

On Thu, 7 Apr 2011 15:44:50 +0900, Sniper Abandon wrote:

[#381136] Re: can we use direct ruby instaed of javascript ? — Chad Perrin <code@...> 2011/04/07

On Thu, Apr 07, 2011 at 09:50:14PM +0900, Peter Zotov wrote:

[#381147] Re: can we use direct ruby instaed of javascript ? — Peter Zotov <whitequark@...> 2011/04/07

On Fri, 8 Apr 2011 01:48:58 +0900, Chad Perrin wrote:

[#381160] Re: can we use direct ruby instaed of javascript ? — Chad Perrin <code@...> 2011/04/08

On Fri, Apr 08, 2011 at 05:37:49AM +0900, Peter Zotov wrote:

[#381167] Re: can we use direct ruby instaed of javascript ? — Julian Leviston <julian@...> 2011/04/08

I think it might be actually quite interesting for the original poster =

[#381195] Re: can we use direct ruby instaed of javascript ? — Josh Cheek <josh.cheek@...> 2011/04/08

On Thu, Apr 7, 2011 at 11:46 PM, Julian Leviston <julian@coretech.net.au>wrote:

[#381125] String.gsub with regex and block — Alexey Petrushin <axyd80@...>

Probably a stupid question, but is there a way to use :gsub replacement

12 messages 2011/04/07

[#381210] Calling to_enum on a MatchData object — Vahagn Hayrapetyan <vahagnh@...>

Hi, I have the following snippet of code:

15 messages 2011/04/08

[#381281] Copying parameters to singleton class — Lars Olsson <lasso@...>

Hi list!

23 messages 2011/04/11

[#381306] Creating a full application with Ruby — Fily Salas <fs_tigre@...>

Hi,

22 messages 2011/04/11

[#381355] Ruby for beginners (was: Re: Hello) — Phillip Gawlowski <cmdjackryan@...>

On Tue, Apr 12, 2011 at 5:08 PM, Vincent Manis <vmanis@telus.net> wrote:

37 messages 2011/04/12
[#381365] Re: Ruby for beginners (was: Re: Hello) — andrew mcelroy <sophrinix@...> 2011/04/12

On Tue, Apr 12, 2011 at 10:30 AM, Phillip Gawlowski <

[#381373] Re: Ruby for beginners (was: Re: Hello) — Phillip Gawlowski <cmdjackryan@...> 2011/04/12

On Tue, Apr 12, 2011 at 7:48 PM, andrew mcelroy <sophrinix@gmail.com> wrote:

[#381388] Re: Ruby for beginners (was: Re: Hello) — Vincent Manis <vmanis@...> 2011/04/13

OK, so here's another kick at the can.=20

[#381420] Re: Ruby for beginners (was: Re: Hello) — Josh Cheek <josh.cheek@...> 2011/04/13

On Tue, Apr 12, 2011 at 8:30 PM, Vincent Manis <vmanis@telus.net> wrote:

[#381430] Re: Ruby for beginners (was: Re: Hello) — Vincent Manis <vmanis@...> 2011/04/13

On 2011-04-13, at 05:59, Josh Cheek wrote:

[#381434] Re: Ruby for beginners (was: Re: Hello) — Phillip Gawlowski <cmdjackryan@...> 2011/04/13

On Wed, Apr 13, 2011 at 4:48 PM, Vincent Manis <vmanis@telus.net> wrote:

[#381487] Re: Ruby for beginners (was: Re: Hello) — Vincent Manis <vmanis@...> 2011/04/14

On 2011-04-13, at 08:03, Phillip Gawlowski wrote:

[#381495] Re: Ruby for beginners (was: Re: Hello) — Chad Perrin <code@...> 2011/04/14

On Thu, Apr 14, 2011 at 10:35:42AM +0900, Vincent Manis wrote:

[#381530] Re: Ruby for beginners (was: Re: Hello) — Phillip Gawlowski <cmdjackryan@...> 2011/04/14

On Thu, Apr 14, 2011 at 5:03 AM, Chad Perrin <code@apotheon.net> wrote:

[#381423] so, who's writing a dedicated ruby ide? — Martin DeMello <martindemello@...>

The recent thread on newbie-friendliness and a "ruby in a box" IDE

11 messages 2011/04/13

[#381444] Tk : non blocking Tk.mainloop — Juju SL <jujusl@...>

Hi all,

21 messages 2011/04/13

[#381547] Running Ruby script in emacs — duke <sidney.reilley.ii@...>

Hey ...

14 messages 2011/04/14

[#381548] To Yield or Not to Yield: An Inferable Question — Michael Edgar <adgar@...>

Hi Rubyists,

14 messages 2011/04/14

[#381562] What do you do when you need to attach data to an object instance? — "Aaron D. Gifford" <astounding@...>

What do you do when you see a need to be able to attach some data to

17 messages 2011/04/14
[#381566] Re: What do you do when you need to attach data to an object instance? — Kevin Mahler <kevin.mahler@...> 2011/04/14

Aaron D. Gifford wrote in post #992841:

[#381573] Re: What do you do when you need to attach data to an object instance? — "Aaron D. Gifford" <astounding@...> 2011/04/14

On Thu, Apr 14, 2011 at 3:11 PM, Kevin Mahler <kevin.mahler@yahoo.com> wrot=

[#381582] Re: What do you do when you need to attach data to an object instance? — "Aaron D. Gifford" <astounding@...> 2011/04/14

> On Thu, Apr 14, 2011 at 3:11 PM, Kevin Mahler <kevin.mahler@yahoo.com> wrote:

[#381596] Re: What do you do when you need to attach data to an object instance? — Kevin Mahler <kevin.mahler@...> 2011/04/15

Aaron D. Gifford wrote in post #992887:

[#381567] Re: Chad Perrin — Everett L Williams II <rett@...>

*Hasn't anybody in the management of this forum the guts to either quiet

16 messages 2011/04/14

[#381605] looking for an "inversion" pattern — Fearless Fool <r@...>

I'm sure there's a clean way to do this in Ruby, but I haven't figured

13 messages 2011/04/15

[#381622] Get the real object in a Hash key — Iñaki Baz Castillo <ibc@...>

Hi, let's suppose this simple code in which I add internal attributes

14 messages 2011/04/15
[#381623] Re: Get the real object in a Hash key — Robert Klemme <shortcutter@...> 2011/04/15

On Fri, Apr 15, 2011 at 2:50 PM, I=F1aki Baz Castillo <ibc@aliax.net> wrote=

[#381626] Re: Get the real object in a Hash key — Iñaki Baz Castillo <ibc@...> 2011/04/15

2011/4/15 Robert Klemme <shortcutter@googlemail.com>:

[#381644] Extract a range i.e. svr[100..130] ? — Richard Sandoval <skolopen@...>

What best method could extract the range of a given list of servers?

13 messages 2011/04/15

[#381742] Telnet "More?" — "Eric T." <erictetz@...>

I'm trying to use the telnet library. I don't know Ruby AT ALL

15 messages 2011/04/17

[#381768] Tail Call Optimization (Tail Recursion) — Terry Michaels <cmhoward@...>

I did some googling to find out if Ruby supports tail call optimization,

18 messages 2011/04/18

[#381781] Need for speed -> a C extension? — Martin Hansen <mail@...>

Hello all,

28 messages 2011/04/18
[#381788] Re: Need for speed -> a C extension? — "WJ" <w_a_x_man@...> 2011/04/18

Martin Hansen wrote:

[#381792] Re: Need for speed -> a C extension? — Martin Hansen <mail@...> 2011/04/18

WJ wrote in post #993576:

[#381794] Re: Need for speed -> a C extension? — Ryan Davis <ryand-ruby@...> 2011/04/18

[#381836] Re: Need for speed -> a C extension? — Martin Hansen <mail@...> 2011/04/19

>> def match?(char1, char2)

[#381849] Re: Need for speed -> a C extension? — brabuhr@... 2011/04/19

On Tue, Apr 19, 2011 at 6:30 AM, Martin Hansen <mail@maasha.dk> wrote:

[#381853] Re: Need for speed -> a C extension? — Martin Hansen <mail@...> 2011/04/19

unknown wrote in post #993757:

[#381822] anonymous closures with Proc,new, lambda and -> — Stu <stu@...>

I am new to the study of functional paradigm. If this question is academic

32 messages 2011/04/19
[#381829] Re: anonymous closures with Proc,new, lambda and -> — Brian Candler <b.candler@...> 2011/04/19

Stu wrote in post #993687:

[#381830] Re: anonymous closures with Proc,new, lambda and -> — Brian Candler <b.candler@...> 2011/04/19

Brian Candler wrote in post #993704:

[#381875] Re: anonymous closures with Proc,new, lambda and -> — Stu <stu@...> 2011/04/19

how would i break it down to two functions?

[#381884] Re: anonymous closures with Proc,new, lambda and -> — 7stud -- <bbxx789_05ss@...> 2011/04/20

Stu wrote in post #993854:

[#381890] Re: anonymous closures with Proc,new, lambda and -> — Stu <stu@...> 2011/04/20

Lots of helpful information in this thread. Thank you all for helping me.

[#381942] Re: anonymous closures with Proc,new, lambda and -> — 7stud -- <bbxx789_05ss@...> 2011/04/20

Stu wrote in post #993922:

[#381946] Re: anonymous closures with Proc,new, lambda and -> — Steve Klabnik <steve@...> 2011/04/20

Naw, monads are actually really, really easy. They're just poorly

[#381952] Re: anonymous closures with Proc,new, lambda and -> — Brian Candler <b.candler@...> 2011/04/20

Steve Klabnik wrote in post #994098:

[#381958] On the Capitalization of Project Files — Intransition <transfire@...>

I have noticed a trend with regards to the case of project files. In

10 messages 2011/04/20

[#382043] Reversing a string without using array, classes and reverse function — Rubist Rohit <passionate_programmer@...>

I am trying this:

20 messages 2011/04/22

[#382092] How to split dot “.” only before equal “=” — Sira PS <ploy.sukachai@...>

I need to split dot only before equal to assign to hash

10 messages 2011/04/23

[#382156] Replace any multiple whitespaces with single white space — Michelle Pace <michelle@...>

Hello, I need to make the first string below into the second string.

10 messages 2011/04/25

[#382264] File position and buffers — Cee Joe <cyril_jose@...>

Hi all,

22 messages 2011/04/27

[#382292] Is everything object ? — "amir e." <aef1370@...>

Hi

35 messages 2011/04/28
[#382296] Re: Is everything object ? — Josh Cheek <josh.cheek@...> 2011/04/28

On Thu, Apr 28, 2011 at 4:48 AM, amir e. <aef1370@gmail.com> wrote:

[#382306] Re: Is everything object ? — Chad Perrin <code@...> 2011/04/28

On Thu, Apr 28, 2011 at 08:52:35PM +0900, Josh Cheek wrote:

[#382318] Re: Is everything object ? — Josh Cheek <josh.cheek@...> 2011/04/28

On Thu, Apr 28, 2011 at 10:12 AM, Chad Perrin <code@apotheon.net> wrote:

[#382334] Re: Is everything object ? — Chad Perrin <code@...> 2011/04/28

On Fri, Apr 29, 2011 at 02:23:32AM +0900, Josh Cheek wrote:

[#382347] Re: Is everything object ? — Josh Cheek <josh.cheek@...> 2011/04/28

On Thu, Apr 28, 2011 at 3:22 PM, Chad Perrin <code@apotheon.net> wrote:

[#382356] Re: Is everything object ? — Chad Perrin <code@...> 2011/04/29

On Fri, Apr 29, 2011 at 08:39:14AM +0900, Josh Cheek wrote:

[#382361] Re: Is everything object ? — Josh Cheek <josh.cheek@...> 2011/04/29

On Thu, Apr 28, 2011 at 10:40 PM, Chad Perrin <code@apotheon.net> wrote:

[#382395] Re: Is everything object ? — Chad Perrin <code@...> 2011/04/29

On Fri, Apr 29, 2011 at 01:09:25PM +0900, Josh Cheek wrote:

[#382416] Re: Is everything object ? — Josh Cheek <josh.cheek@...> 2011/04/29

On Fri, Apr 29, 2011 at 2:37 PM, Chad Perrin <code@apotheon.net> wrote:

[#382429] Re: Is everything object ? — Chad Perrin <code@...> 2011/04/30

On Sat, Apr 30, 2011 at 08:01:48AM +0900, Josh Cheek wrote:

[#382310] Initialize Struct from Hash — Brian Candler <b.candler@...>

I just want to check I've not missed something here. Is there a built-in

10 messages 2011/04/28

[#382312] calling methods, beginner help — Ronnie Aa <liquid98@...>

Hello Guys,

13 messages 2011/04/28

[#382350] Ruby Beginner Need Help.. — Didin Ibnu Sarnan <didinna@...>

Hi,

18 messages 2011/04/29
[#382352] Re: Ruby Beginner Need Help.. — 7stud -- <bbxx789_05ss@...> 2011/04/29

Didin Ibnu Sarnan wrote in post #995669:

[#382354] Re: Ruby Beginner Need Help.. — Didin Ibnu Sarnan <didinna@...> 2011/04/29

Hi,

[#382401] How do I read HTTP POST XML sent to CGI? — Ting Chang <aumart@...>

Hello Ruby Masters,

14 messages 2011/04/29

[#382452] Why defining a constant in a method is not allowed but using self.class.const_set is allowed? — Iñaki Baz Castillo <ibc@...>

Hi, assinging a value to a constant within a method is not allowed

14 messages 2011/04/30
[#382454] Re: Why defining a constant in a method is not allowed but using self.class.const_set is allowed? — Robert Klemme <shortcutter@...> 2011/04/30

On 30.04.2011 21:25, I=F1aki Baz Castillo wrote:

[#382456] Re: Why defining a constant in a method is not allowed but using self.class.const_set is allowed? — Iñaki Baz Castillo <ibc@...> 2011/04/30

2011/4/30 Robert Klemme <shortcutter@googlemail.com>:

[#382465] Re: Why defining a constant in a method is not allowed but using self.class.const_set is allowed? — Christopher Dicely <cmdicely@...> 2011/04/30

On Sat, Apr 30, 2011 at 12:58 PM, I=C3=B1aki Baz Castillo <ibc@aliax.net> w=

[#382466] Re: Why defining a constant in a method is not allowed but using self.class.const_set is allowed? — Iñaki Baz Castillo <ibc@...> 2011/04/30

2011/5/1 Christopher Dicely <cmdicely@gmail.com>:

[ANN] ambit-0.9.1 released

From: Jim Wise <jwise@...>
Date: 2011-04-26 21:23:43 UTC
List: ruby-talk #382221
=3D ambit

https://github.com/jimwise/ruby/tree/master/ambit

Author::    Jim Wise  (mailto:jwise@draga.com)
Copyright:: Copyright (c) 2011 Jim Wise
License::   2-clause BSD-Style (see LICENSE.txt)

=3D=3D DESCRIPTION:

This is an all-ruby implementation of choose/fail nondeterministic
programming with branch cut, as described in Chapter 22 of Paul Graham's
<em>On Lisp</em>[1], or Section 4.3 of <em>SICP</em>[2].

=3D=3D HISTORY:

=3D=3D=3D 0.9.1 / 2011-04-26

* Minor documentation improvements

=3D=3D=3D 0.9 / 2011-04-26

* First public release of ambit

=3D=3D REQUIREMENTS:

<b>This code will not work in JRuby or MacRuby (no callcc).  It should work
in Ruby 1.9 with minor changes (callcc has moved to the 'continuation'
stdlib).</b>

=3D=3D INSTALL:

To install:=20

    $ gem install ambit

=3D=3D DEVELOPERS:

After checking out the source, run:

    $ rake newb

This task will install any missing dependencies, run the tests/specs,
and generate the RDoc.

=3D=3D SYNOPSIS:

=3D=3D=3D What is Nondeterministic Programming?

Nondeterministic programming is a novel approach to problems where a program
must find a working solution out of many possible choices.  It greatly
simplifies problems such as graph searching, or testing combinations of
values, where there are many possible values to consider, often in some sort
of hierarchical order, but the right combination is not known in advance.

In such a situation, it can be useful to develop a program by pretending
our programming language includes knowledge of the future -- and is thus
able to _choose_ the right answer off the bat, and simply programming as
if this were the case.

A language with support for nondeterministic programming (such as Ruby
with this gem) helps us keep up this pretense by saving the state of
computation (with some limits) whenever we make an important choice.  If
we later determine that we did _not_, in fact, make the correct choice
(lacking true language support for knowing the future), we can _fail_ the
current computation, which <em>causes computation to rewind to the last
choice made, and continue as if a different choice had been made</em>.

When all possible choices have been tried, the next time computation
_fails_, computation will be rewound to the previous choice point, and
will continue with the next possible choice from there.

Imagine, for instance, that we wish to test a combination lock with a
three-number combination, with each number between 1 and 10, inclusive.
Instead of writing code ourself to try every possible combination, we
simply proceed as if each choice was the correct one, failing if the lock
fails to open.  In short:

    first =3D Ambit.choose(1..10)
    second =3D Ambit.choose(1..10)
    third =3D Ambit.choose(1..10)

    Ambit.fail! unless open_lock(first, second, third)

    # when we get here, lock is open!

As our language does not actually implement knowledge of the future, this
will still try as many combinations as are needed to find the right one --
but we can program as if it has chosen the right one on the first try!

=3D=3D=3D How to Use This Gem

To get started, include this gem using

    require 'rubygems'
    require 'ambit'

This gem provides the Ambit module.  This module provides several methods
which implement nondeterministic programming.

=3D=3D=3D=3D Choosing and Failing

The central method of Ambit is Ambit::choose.

Ambit::choose takes any enumerable (actually, any object which responds to
#each) as an argument, and begins a nondeterministic generate-and-test
process with the members of this object.

Ambit::choose immediately returns the first member of the enumerable, or
calls Ambit::fail! if the enumerable is empty:

    a =3D Ambit::choose([1, 2, 3])
    puts a
prints
    1

If, later, Ambit::fail! is called, <em>computation is rewound until the
point when Ambit::choose was last called</em>, and the next member of the
enumerable is returned <em>from the same call to Ambit::choose</em>:

    a =3D Ambit::choose([1, 2, 3])
    Ambit::fail! unless a.even?
    puts a
prints
	2
(and only "2")

<em>This means that computation now proceeds as if that had been the value
returned by Ambit::choose all along.</em>

As an alternative, Ambit::assert can be used to fail unless a condition
holds.  Ambit::assert will rewind to the previous invocation of
Ambit::choose if and only if it's (single) argument is false:

    a =3D Ambit::choose([1, 2, 3])
    Ambit::assert a.even?
    puts a
prints
    2
(and only "2")

Note that this call to Ambit::fail! (or Ambit::assert) can occur any amount
of time later, and works <em>even if the function which called choose has
since exited</em>.  Execution is still rewound as needed to allow the next
value to be returned from the same call to Ambit::choose.

Calls to Ambit::choose can be nested to arbitrary depth -- each call to
Ambit::fail! will rewind to the <em>most recent</em> call to Ambit::choose.
If that set of choices has already returned every member of its enumerable,
execution is instead rewound to the previous invocation of Ambit::choose,
and execution continues with the next choice from that invocation's
enumerable:

    a =3D Ambit::choose([1, 3, 5, 7, 9, 11, 13, 15])
    b =3D Ambit::choose([0, 5, 10, 15])
    Ambit::assert a =3D=3D b
    puts a
prints
	5
(and only "5")

If all choices from all past calls to Ambit::choose have been exhausted (or
if Ambit::fail! is called before any call to Ambit::choose), an exception of
type Ambit::ChoicesExhausted is raised instead.

=3D=3D=3D=3D Side Effects

We've talked a lot above about "rewinding" computation to a previous choice
point.  Not all computations can be rewound, however -- if the computation
we have performed since the choice point we are rewinding to has had side
effects (other than the choices made), those side effects will not
themselves be rewound.  While some side effects (setting of variables) could
theoretically be tracked and undone, this would require very careful
semantics -- nd other side effects could not be undone by any level of
complexity added to our language.  If we have printed output to the user,
for instance, no amount of rewinding will make the user forget what he has
seen; while we simulate the ability to see the future and to change the
past, we can, in fact, do neither.

This can sometimes cause confusion.  This code, for instance:

    a =3D Ambit::choose([1, 2, 3])
    puts a
    Ambit::fail! unless a.even?

prints

    1
    2

instead of only "2" -- the printing has already been done by the time we
call Ambit::fail!.

Such side effects can also be useful, however.  This code:

    i =3D 0
    first =3D Ambit.choose(1..10)
    second =3D Ambit.choose(1..10)
    third =3D Ambit.choose(1..10)
    i +=3D 1
    Ambit.fail! unless open_lock(first, second, third)
    puts i

prints out the number of combinations which were tried in total (since +i+
remains incremented even when we rewind computation).

=3D=3D=3D=3D More Than One Answer

Often, more than one combination of choices is interesting to consider -- it
may be useful, for instance, to see _all_ combinations which do not fail,
instead of only the first.

Since Ambit::fail! will always rewind to the previous choice point, getting
more possible combinations is as easy as calling Ambit::fail! in order to
try the next combination -- even though we have not, strictly, failed.  When
no more successful combinations are available, this call to Ambit::fail!
will instead raise an exception of type Ambit::ChoicesExhausted.

    begin
      a =3D Ambit::choose([1, 3, 5, 7, 9, 11, 13, 15])
      b =3D Ambit::choose([0, 5, 10, 15])
      Ambit::assert a =3D=3D b
      puts a
      Ambit::fail!
    rescue Ambit::ChoicesExhausted
      puts "Done."
    end
prints
    5
    15
    Done.

Note that this code, too depends on a side effect -- +a+ is output each time
we get a match, even though we then call Ambit::fail! to rewind computation
and try the next combination.

=3D=3D=3D=3D Cleaning up

Ambit::clear! can be called at any time to eliminate all outstanding choices
on the default Generator, ending nondeterminism (and allowing any
outstanding alternate paths of execution to be garbage collected).  This is
most useful when a given computation is finished, so that future invocations
of Ambit::fail! will not restart the now-finished computation with another
choice.

=3D=3D=3D=3D Marking and Cutting

While Ambit::clear! can be used to abandon an entire set of nondeterministic
computations, sometimes it is useful to abandon only one branch of a
computation, while still keeping the ability to rewind to the choice which
first took us down that branch.

Suppose, for instance, that we are trying to guess a word with four letters:

    a =3D Ambit::choose('a'..'z')
    b =3D Ambit::choose('a'..'z')
    c =3D Ambit::choose('a'..'z')
    d =3D Ambit::choose('a'..'z')
    Ambit::assert good_word(a, b, c, d)
    print a, b, c, d

This works.  But what if we were able to determine, once all four letters
were chosen, whether the first letter was correct?  How would we proceed?

If we failed because the first letter was incorrect, we would continue tryi=
ng
every possible value for the second, third and fourth letters -- even thoug=
h none of
them could be correct.  We need a way to rewind to an earlier choice point.

To work around this, Ambit provides a method, Ambit::cut! which "locks in" a
set of past choices, preventing them from being revisited later:

    a =3D Ambit::choose('a'..'z')
    Ambit::mark
    b =3D Ambit::choose('a'..'z')
    c =3D Ambit::choose('a'..'z')
    d =3D Ambit::choose('a'..'z')
    if !good_first_letter(a, b, c, d)
      Ambit::cut!=20
      Ambit::fail!
    end=20=20=20
    Ambit::assert good_word(a, b, c, d)
    print a, b, c, d

When Ambit::cut! is called in the code above, all choices back to the
<em>most recent</em> call of Ambit::mark are wiped out -- the next call to
Ambit::fail! will rewind to the most recent Ambit::choose invocation
<em>before</em> the most recent call to Ambit::mark.

Ambit::cut! can also be used without Ambit::fail! to "commit" to all choices
since the last call to Ambit::mark -- in this case, we are saying that we
know these choices are good, so if we (later) fail, we want to rewind out of
the whole current branch of computation.

=3D=3D=3D=3D Private Generators

In addition to using methods of the Ambit module directly, another option is
to allocate an Ambit::Generator object explicitly.  All methods of the Ambit
module are also available as methods of Ambit::Generator (and in fact, the
module allocates a default Generator object to handle all calls made at the
module level).

Ambit::Generator::new can be used to allocate a new Generator:

    nd =3D Ambit::Generator::new
    nd.choose('a' .. 'e')

each object allocated in this fashion has its own set of choices, and
failing one will not directly affect others.  Nesting choices from different
Generators is a good way to make code confusing, however, and should be
avoided -- this capability is mainly provided to allow multi-threaded
programs to safely use Ambit from more than one thread (see below).

Ambit::Generator#clear! is provided for the same reason as Ambit::clear!,
but it is often clearer to use a new Ambit::Generator object for each
unrelated set of nondeterministic computations.

=3D=3D=3D=3D Compatibility

For historical reasons, Ambit::amb and Ambit::Generator#amb are provided as
aliases for Ambit::choose and Ambit::Generator#choose.  Likewise, for
historical reasons, calling Ambit::choose (and Ambit::Generator#choose) with
no arguments is equivalent to calling Ambit::fail! (or
Ambit::Generator#fail!).

For the same reason, Ambit::require and Ambit::Generator#require are
provided as aliases for Ambit::assert and Ambit::Generator#assert.

These aliases allow for a more direct translation of programs written with
the _amb_ operator discussed in _SICP_ and elsewhere.

=3D=3D=3D=3D Interaction with Threading

Given the strong modifications to flow of control which occur when a path of
computation is _failed_, care must be taken when using nondeterministic
programming in a multi-threaded program.  The two main ways to do this are:

* perform all nondeterministic programming from a single thread of execution

* give each thread which will be using nondeterministic programming its own=
 Ambit::Generator object.  This can be done easily using thread local varia=
bles:

    def nd_begin
      Thread.current[:AMB] =3D Ambit::Generator.new
    end

    def nd_choose choices
      Thread.current[:AMB].choose choices
    end

    def nd_fail!=20
      Thread.current[:AMB].fail!
    end

    def nd_clear!=20
      Thread.current[:AMB].clear!
    end

=3D=3D=3D Longer example

This solution to the N queens problem is inspired by the prolog version in
<em>The Art of Prolog</em> by Leon Sterling and Ehud Shapiro[3], but is less
elegant, as this is not prolog (and I am not Sterling or Shapiro).

    # we want to place N queens on an NxN chess board.  Since we know no tw=
o queens
    # can be in the same row, an array of N integers between 0 and N-1 will=
 do to
    # represent the placement.  Since we know no two queens can be in the s=
ame column,
    # each number from 1 .. N will appear once in this array;  this means t=
he solution
    # is a permutation of 1 .. N

    # Here is the complete board generator.  Next is the test if a position=
 is safe.

    def queens n, board =3D []
      if board.size =3D=3D n
        board
      else
        c =3D Ambit.choose(1..n)
        Ambit.fail! unless safe board, c
        queens n, board + [c]
      end
    end

    # board is the first M columns of an NxN board, and is valid so far.
    # piece is a proposed piece for the M+1th row of the board.
    # returns true if piece is a valid placement, false otherwise

    def safe board, piece
      board.each_with_index do |c, r|
        return false if c =3D=3D piece  # same column
        # they're on the same diagonal if the distance in columns =3D=3D th=
e distance in rows
        rdist =3D board.size - r
        cdist =3D (piece - c).abs
        return false if rdist =3D=3D cdist
      end
      true
    end

The file examples/queens.rb, installed with this gem, contains a version of
this with display code, and a command-line driver to print all solutions for
a given N.

=3D=3D=3D References

[1] Graham, Paul, <em>On Lisp</em>, Prentice Hall, 1993. Available online a=
t http://www.paulgraham.com/onlisp.html

[2] Abelson, Harold and Gerald Jay Sussman, <em>Structure and Interpretatio=
n of Computer Programs, 2nd Edition</em>, MIT Press, 1996.  Available onlin=
e at http://mitpress.mit.edu/sicp/

[3] Sterling, Leon and Ehud Shapiro, <em>The Art of Prolog</em>, MIT Press,=
 1994

=3D=3D LICENSE:

(The BSD 2-clause License)

  Copyright (c) 2011 Jim Wise
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:

  1. Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIB=
UTORS
  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.

=2D-=20
				Jim Wise
				jwise@draga.com

In This Thread

Prev Next