I love Ruby

I had to say it! I teach for LearningTree, so was able to attend a perl
course for free. I _hated_ perl - what a mess. Then I saw that python was
"perl done properly", so looked at that. _Much_ better, but a few
irritations. Then I thought "I'll try ruby". I did, but didn't have time
to do much. Got a couple of books - both very good, although I have some
constructive criticisms for both (Programming Ruby, & The Ruby Way), and
now I'm an expert (not!). I love that everything's an object, so I can
just do x.y.z.j.f combining methods - like this:

val=@data.fetch(datid.tr('~','$').sub(/\s*$/,'')

(I hope thats not considered bad form) So much that I intuitively try works
- which is great.

I've not crossposted to c.l.python, as this (really) isn't a troll, but I'm
coming to the conclusion that ruby is "python done properly". But don't
tell anyone - I don't want to be flamed senseless.
Anyway, antirant over, back to work.
Graham

PS. 1 complaint - begin and end. I use vi (vim/gvim), and would prefer the
use of braces so I can quickly go to the matching start/end block with %.
Any suggestions? a #define equivalent, perhaps?

···

--
With Linux, the answer's always "Yes"

I had to say it!

you're welcome :slight_smile:

<snip>

I love that everything's an object, so I can
just do x.y.z.j.f combining methods - like this:

val=@data.fetch(datid.tr('~','$').sub(/\s*$/,'')

(I hope thats not considered bad form) So much that I intuitively try works
- which is great.

yeah, we all love this feeling, and not, it's not considered bad form.
Remember that you can even chain methods on the end of blocks, like:
foo.gsub do |x|
...
end.gsub do |x|
...
end

I've not crossposted to c.l.python, as this (really) isn't a troll, but I'm
coming to the conclusion that ruby is "python done properly".

usually people seem to think that ruby is smalltalk or lisp or perl
done properly. Probably all of this are just unlambda done properly :slight_smile:

<snip>

PS. 1 complaint - begin and end. I use vi (vim/gvim), and would prefer the
use of braces so I can quickly go to the matching start/end block with %.
Any suggestions? a #define equivalent, perhaps?

I think ruby.vim allows you to do the same trick.
Anyway, usually you don't need begin..end.

Say, in a method you don't have to write:

def foo
begin
  bla
rescue
  blablsa
end
end

you can just write:

def foo
bla
rescue
blabla
end

And this is most of the begin..end usage :slight_smile:

···

il Fri, 09 Jul 2004 11:15:59 +0100, Graham Nicholls <graham@rockcons.co.uk> ha scritto::

I had to say it! I teach for LearningTree, so was able to attend a perl
course for free. I _hated_ perl - what a mess. Then I saw that python was
"perl done properly", so looked at that. _Much_ better, but a few
irritations. Then I thought "I'll try ruby". I did, but didn't have time
to do much. Got a couple of books - both very good, although I have some
constructive criticisms for both (Programming Ruby, & The Ruby Way), and
now I'm an expert (not!). I love that everything's an object, so I can
just do x.y.z.j.f combining methods - like this:

val=@data.fetch(datid.tr('~','$').sub(/\s*$/,'')

(I hope thats not considered bad form) So much that I intuitively try works
- which is great.

grab someone else and ask them, "is it obvious which object owns these
functions?"
to me, this does.
   data --> .fetch
   datid --> .tr
             .sub

but you appear to be missing a closing )
:wink:

I've not crossposted to c.l.python, as this (really) isn't a troll, but I'm
coming to the conclusion that ruby is "python done properly". But don't
tell anyone - I don't want to be flamed senseless.
Anyway, antirant over, back to work.
Graham

i've been gushing about ruby lately too, and i went through a similar
experience.
first i tried perl because so many sysadmin and early web cgi
programmers were raving about it, but TMTOWTDI made reverse-engineer
learning perl from cpan rather evil. (i had to learn that perl is
meant to be written, not read.) then i became thoroughly frustrated
with C++ and python looked like "interpreted C++ with none of the
mess", but the underscores bothered me more than tabbed delimiting.
then i looked into the history of programming languages, lisp, and why
alan kay invented smalltalk. then i remember hearing about ruby and
let go of "great... an even more niche language". now i feel smarter
when programming instead of dumber, as i did with C++. a near-perfect
blend of perl, lisp, and smalltalk (+eiffel, so people say). ruby
makes me happy.

PS. 1 complaint - begin and end. I use vi (vim/gvim), and would prefer the
use of braces so I can quickly go to the matching start/end block with %.
Any suggestions? a #define equivalent, perhaps?

i agree with your one complaint. maybe because C++ was the first
serious language i learned, maybe because { } looks more symmetrical
to me and take ~1/4 the number of keystrokes to input.

why are 'begin...end' and { } not always equivalent?

--
With Linux, the answer's always "Yes"

with a "but..."

-z

···

On Fri, 9 Jul 2004 19:17:32 +0900, Graham Nicholls <graham@rockcons.co.uk> wrote:

"Graham Nicholls" <graham@rockcons.co.uk> wrote in message
news:40ee705f$0$11817$afc38c87@auth.uk.news.easynet.net...

PS. 1 complaint - begin and end. I use vi (vim/gvim), and would prefer the
use of braces so I can quickly go to the matching start/end block with %.
Any suggestions? a #define equivalent, perhaps?

hi Graham, I think that's a good point. I personally feel that using {}
makes it easier
for the eye to match a block. maybe Ruby can include this alternate syntax
in the parser?

chok

why are 'begin...end' and { } not always equivalent?

This comes up once in a while, tell me if this answer is short enough:

def foo(arg=nil)
  if block_given?
    puts 'foo got block'
  end
end

def bar(arg=nil)
  if block_given?
    puts 'bar got block'
  end
end

foo bar do end # > foo got block
foo bar {} # > bar got block

best regards,
kaspar

semantics & semiotics
code manufacture

www.tua.ch/ruby

FYI, I have written a unlambda interpreter in Ruby. (I don't know
if I should be proud of it...) It was ridiculously easy, because
Ruby already provides everything (continuations, closures,...). I think
the implementation is even easier to understand than the spec.
It is not a very efficient implementation, since it uses recursion.
But you don't have very large unlambda programs that you absolutely
need to run, do you?

Here it is:
(Don't continue reading if you don't want to waste your time...)

#!/usr/bin/env ruby

#Unlambda interpreter
#written by Kristof Bastiaensen <kristof.bastiaensen@vleeuwen.org>

require "stringio"

def readchar
  $char_read = getc
end

K = lambda {|a| lambda { |b| a }}
S = lambda {|a| lambda { |b| lambda { |c| a[c][b[c]] }}}
I = lambda { |a| a }
V = lambda { |a| V }
R = lambda { |a| puts; a }
C = lambda { |a| callcc { |cc| a[cc] } }
D = lambda { |a| a}
AT = lambda { |a| (readchar() ? a : V ) }
PIPE = lambda { |a| $char_read ? a[$char_read] : V }

CharLookup = { ?k => K, ?s => S, ?i => I,
              ?v => V, ?r => R, ?c => C,
              ?@ => AT, ?| => PIPE,
              ?d => D, ?e => :dummy }

def compile(stream)
  loop do
    raise "Premature end of stream!" if stream.eof
    ch = stream.getc
    if ch == ?` #`
      return [compile(stream), compile(stream)]
    elsif ch == ?.
      a = stream.getc
      return lambda { |b| print a.chr; b }
    elsif ch == ??
      a = stream.getc
      return lambda { |b| b == a ? a : V }
    elsif CharLookup.member?(ch)
      return CharLookup[ch]
    end
  end
end

def eval_expr(expr)
  if expr.class == Array
    r = eval_expr(expr[0])
    e2 = expr[1]
    if (r == D and e2.class == Array)
      return lambda { |a| eval_expr(e2)[a] }
    else
      return r[ eval_expr(e2) ]
    end
  else
    return expr
  end
end

def eval(string)
  string = string.gsub(/#.*$/, "")
  stream = StringIO.new(string, "r")
  callcc do |exit|
    CharLookup[?e] = lambda { |a| exit[a] }
    tree = compile(stream)
    eval_expr(tree)
  end
end

if(ARGV.length != 1)
  $stderr << "Usage: %s <unlambda file>\n" % $0
else
  str = IO.read(ARGV[0])
  eval(str)
end

···

On Fri, 09 Jul 2004 10:52:17 +0000, gabriele renzi wrote:

usually people seem to think that ruby is smalltalk or lisp or perl
done properly. Probably all of this are just unlambda done properly :slight_smile:

Hi --

···

On Fri, 9 Jul 2004, ChokSheak Lau wrote:

"Graham Nicholls" <graham@rockcons.co.uk> wrote in message
news:40ee705f$0$11817$afc38c87@auth.uk.news.easynet.net...
> PS. 1 complaint - begin and end. I use vi (vim/gvim), and would prefer the
> use of braces so I can quickly go to the matching start/end block with %.
> Any suggestions? a #define equivalent, perhaps?

hi Graham, I think that's a good point. I personally feel that using {}
makes it easier
for the eye to match a block. maybe Ruby can include this alternate syntax
in the parser?

I don't think there would be any way to distinguish this from a hash
literal.

David

--
David A. Black
dblack@wobblini.net

zuzu wrote:

but you appear to be missing a closing )
:wink:

I noticed about 2 minutes after I posted, when I tried to run it, which was
really annoying!
G.

···

--
With Linux, the answer's always "Yes"

Kaspar Schiess wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

> why are 'begin...end' and { } not always equivalent?
This comes up once in a while, tell me if this answer is short enough:

I didn't even know there was a {} !
Documentation (up to date) would seem to be a minor problem with ruby - am I
being reasonable ? (To be fair, I've yet to read my 2 books from cover to
cover, so I've probably missed it.) For instance, I believe theres no 1.8
documentation. I'm still in love, though :wink:

···

--
With Linux, the answer's always "Yes"

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

> why are 'begin...end' and { } not always equivalent?
This comes up once in a while, tell me if this answer is short enough:

def foo(arg=nil)
        if block_given?
                puts 'foo got block'
        end
end

def bar(arg=nil)
        if block_given?
                puts 'bar got block'
        end
end

foo bar do end # > foo got block
foo bar {} # > bar got block

best regards,
kaspar

why the difference in scope?
why does 'do...end' pass into foo instead of bar?

p.s. "foo bar" feels quite ambiguous without any defining ( ).

semantics & semiotics

<topic bool="off">
ever look at "general semantics" by alfred korzybski?
do you have any opinion on fred dretske w/r/t semiotics?
</topic>

···

On Fri, 9 Jul 2004 20:28:41 +0900, Kaspar Schiess <eule@space.ch> wrote:

code manufacture

www.tua.ch/ruby
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFA7oKYFifl4CA0ImQRAn/NAKCH39gW0a58Uw/Y3eiNnxStOPVRtACgmNRF
Mpz4p0OGorKJ3ic+Wyje150=
=XIcv
-----END PGP SIGNATURE-----

:)))
I wa thinking to write an unlambda interpreter just after my exams'
session , end of july :wink:

Damn, now I have to write the COW one..
givent that brainf**k and OOk! are already there maybe we should start
a section on the wiki :slight_smile:

···

il Fri, 09 Jul 2004 14:02:46 +0200, Kristof Bastiaensen <kristof@vleeuwen.org> ha scritto::

On Fri, 09 Jul 2004 10:52:17 +0000, gabriele renzi wrote:

usually people seem to think that ruby is smalltalk or lisp or perl
done properly. Probably all of this are just unlambda done properly :slight_smile:

FYI, I have written a unlambda interpreter in Ruby. (I don't know
if I should be proud of it...) It was ridiculously easy, because
Ruby already provides everything (continuations, closures,...). I think
the implementation is even easier to understand than the spec.
It is not a very efficient implementation, since it uses recursion.
But you don't have very large unlambda programs that you absolutely
need to run, do you?

> why are 'begin...end' and { } not always equivalent?

Kaspar Schiess wrote:

This comes up once in a while, tell me if this answer is short enough:
[indentation added]

def foo(arg=nil)
    if block_given?
        puts 'foo got block'
    end
end

def bar(arg=nil)
    if block_given?
        puts 'bar got block'
    end
end

foo bar do end # > foo got block
foo bar {} # > bar got block

That is very helpful, thanks.

One thing I don't understand: *Why* does it work this way? What is the
purpose of having different precedence for {} and do...end? It's always
seemed a bit confusing to me, so knowing the purpose for this distinction
would help keep it straight.

Thanks,

-Mike

you're reasonable but not in this thing.
blocks in ruby are in the form:

amethod do |vars|
body
end

or

amethod { |vars|
body
}

this is the only place where {} are used as syntax delimiters, and the
common idiom is to use do..end for multiline stuff, and {..} for
one-line blocks.

You can't use them in place of begin..end, like:

begin
print 10
end while true

{
print 10
} while true

···

il Fri, 09 Jul 2004 12:51:27 +0100, Graham Nicholls <graham@rockcons.co.uk> ha scritto::

I didn't even know there was a {} !
Documentation (up to date) would seem to be a minor problem with ruby - am I
being reasonable ? (To be fair, I've yet to read my 2 books from cover to
cover, so I've probably missed it.) For instance, I believe theres no 1.8
documentation. I'm still in love, though :wink:

zuzu wrote:

why the difference in scope?
why does 'do...end' pass into foo instead of bar?

Actually the difference is one of 'operator precedence' and not one of
scope, as far as {} can be called an operator. {} just binds very thight
to the call to bar, whereas do end binds loosely to the call of foo.
This means that

~ puts str.gsub { ... }

will do what you expected but

~ puts str.gsub do ... end

will call puts with a block. Hence the single line/multiline difference.

Thank you for your OT (not to me) pointers, I will put them on the list
of things to
read ! Perhaps you will be interested in my opinion afterwards :wink: ?

yours,
kaspar

semantics & semiotics
code manufacture

www.tua.ch/ruby

:)))
I wa thinking to write an unlambda interpreter just after my exams'
session , end of july :wink:

Yes, I thought it would be a real challenge, but it appeared to
be very easy in the end. Everything is already in the language.
Now a ruby interpreter in unlambda, that would be a challenge!

Damn, now I have to write the COW one..
givent that brainf**k and OOk! are already there maybe we should start
a section on the wiki :slight_smile:

Yes, the "Ruby Comprehensive Esoteric language Archive",
why not?

Kristof

···

On Fri, 09 Jul 2004 13:24:11 +0000, gabriele renzi wrote:

gabriele renzi wrote:

Damn, now I have to write the COW one.. givent that brainf**k and OOk! are already there maybe we should start
a section on the wiki :slight_smile:

Now I just *have* to post my Brainfuck interpreter where all instructions can dynamically be changed and new ones can be added without problems:

···

begin
  require 'simplecc'
rescue LoadError
  def Continuation.create(*args, &block)
    cc = nil; result = callcc {|c| cc = c; block.call(cc) if block and args.empty?}
    result ||= args
    return *[cc, *result]
  end
end

class BrainfuckContext
  def initialize(code = nil, instructions = {})
    @data, @pointer, @jumps = Hash.new { 0 }, 0,
    @instructions = Instructions.merge(instructions)
    execute code if code
  end

  def execute(code)
    code.split(//).each do |instruction|
      instance_eval(&@instructions[instruction])
    end
  end

  def getc; STDIN.getc || 0; end

  Instructions = Hash.new { proc {} }.update({
    '>' => proc { @pointer += 1 },
    '<' => proc { @pointer -= 1 },
    '+' => proc { @data[@pointer] += 1 },
    '-' => proc { @data[@pointer] -= 1 },
    '.' => proc { putc @data[@pointer] },
    ',' => proc { @data[@pointer] = getc },
    '[' => proc do
      jump, jumped = Continuation.create(false)
      @jumps << jump
      unless jumped
        @depth ||= 0
        @depth += 1
        # make all instructions but ']' noops
        @old_instructions = @instructions.dup
        new_instructions = {
          '[' => proc { @depth += 1 },
          ']' => proc do
            @depth = [0, @depth - 1].max
            if @depth == 0
              # restore standard instruction table
              @instructions.update(@old_instructions) if @old_instructions
              @old_instructions = nil
                            jump = @jumps.pop
              jump.call(true) if jump and @data[@pointer] != 0
            end
          end
        }
        @instructions = @old_instructions.dup.clear.update(new_instructions)
      end
    end,
    ']' => proc do
      jump = @jumps.pop
      jump.call(true) if jump and @data[@pointer] != 0
    end,
    '#' => proc do
      data = @data.to_a.sort_by { |(key, value)|
        key
      }.map { |(key, value)|
        "#{key} = #{value}"
      }.join(", ")
      puts "#{@pointer} @ [#{data}]"
    end
  })
end

def bf(code)
  BrainfuckContext.new(code)
end

>I didn't even know there was a {} !
>Documentation (up to date) would seem to be a minor problem with ruby - am I
>being reasonable ? (To be fair, I've yet to read my 2 books from cover to
>cover, so I've probably missed it.) For instance, I believe theres no 1.8
>documentation. I'm still in love, though :wink:

http://www.rubycentral.com/book/

it feels a bit like "v1.0" documentation and tends to be a bit too
"for tradtional programmers" as a bridge to the ruby way of thinking
for my tastes. (i'd rather be explained the "accepted style" upfront,
personally.) but it is by far one of the best books on howto
programming, let alone learning ruby, i've read.

some where in there it explains about begin...end, then iirc talks
about blocks, then explains about { }. i would lump that together,
personally, but that's the "v1.0" thing. p.s. the "pragmatic
programmers" are pretty on the ball about improving the process of
programming; their other book is worth reading as well.

···

On Fri, 9 Jul 2004 21:02:32 +0900, gabriele renzi <surrender_it@rc1.vip.ukl.yahoo.com> wrote:

il Fri, 09 Jul 2004 12:51:27 +0100, Graham Nicholls > <graham@rockcons.co.uk> ha scritto::

you're reasonable but not in this thing.
blocks in ruby are in the form:

amethod do |vars|
body
end

or

amethod { |vars|
body
}

this is the only place where {} are used as syntax delimiters, and the
common idiom is to use do..end for multiline stuff, and {..} for
one-line blocks.

You can't use them in place of begin..end, like:

begin
print 10
end while true

{
print 10
} while true

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

zuzu wrote:

>> why the difference in scope?
>> why does 'do...end' pass into foo instead of bar?

Actually the difference is one of 'operator precedence' and not one of
scope, as far as {} can be called an operator. {} just binds very thight
to the call to bar, whereas do end binds loosely to the call of foo.
This means that

~ puts str.gsub { ... }

will do what you expected but

~ puts str.gsub do ... end

will call puts with a block. Hence the single line/multiline difference.

*lightbulb* word.

..."that's not intuitive!" :wink:

i would think that if you want to pass 'puts' a block, you should have
to more strongly define:
puts(str.gsub) do ... end

lots of words with spaces weirds me out, like applescript.

Thank you for your OT (not to me) pointers, I will put them on the list
of things to
read ! Perhaps you will be interested in my opinion afterwards :wink: ?

certainly. especially if you can finish 'science & sanity' by korzybski.
dretske i'm so-so on, but supposidly 'flow of information' is the
leading treatise on applying information theory to language... i
think his research is solid, but so far disagree with his conclusion
that knowledge is "all or nothing"; obviously he hasn't learned null-A
from korzybski.

···

On Fri, 9 Jul 2004 21:15:52 +0900, Kaspar Schiess <eule@space.ch> wrote:

yours,
kaspar

semantics & semiotics
code manufacture

www.tua.ch/ruby
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFA7o2oFifl4CA0ImQRAsDzAKCzLCTMaE/f9lvJ3dvWXoSjeDltxgCfewzT
dLMLTUzKpxUlwBhIsMvTREQ=
=mY7c
-----END PGP SIGNATURE-----

gabriele renzi wrote:

this is the only place where {} are used as syntax delimiters, and the
common idiom is to use do..end for multiline stuff, and {..} for
one-line blocks.

Ah, of course I had seen this.

You can't use them in place of begin..end, like:

begin
print 10
end while true

This is what I thought was being said. Thanks for clearing that up!
(Shame, though)
Graham

···

--
With Linux, the answer's always "Yes"