From: William James
Subject: Alternatives
Date: 
Message-ID: <c76c61a2-108c-40c8-8170-02e325c9f63f@v22g2000pro.googlegroups.com>
Writing some stuff in Paul Graham's _On Lisp_ in Ruby.


=begin

(defun our-remove-if (fn lst)
  (if (null lst)
      nil
    (if (funcall fn (car lst))
      (our-remove-if fn (cdr lst))
      (cons (car lst) (our-remove-if fn (cdr lst))))))

=end

def remove_if list
  list.inject([]){|col,elt|
    col << elt unless yield elt
    col }
end


=begin

2.4 Functions as Properties

(defun behave (animal)
  (funcall (get animal 'behavior)))

(setf (get 'dog 'behavior)
      #'(lambda ()
	  (wag-tail)
	  (bark)))

=end

$behaviors = {}

def behave animal
  $behaviors[ animal ].call
end

$behaviors[ :dog ] = proc{ wag_tail; bark }


=begin

2.6 Closures

(defun make-adderb (n)
  #'(lambda (x &optional change)
      (if change
	  (setq n x)
	(+ x n))))

=end

def make_adderb n
  proc{|x,*change|
    return x + n  if change.empty?
    n = x }
end

addx = make_adderb( 1 )

p addx[ 8 ]
addx[ 99, true ]
p addx[ 8 ]


=begin

It's even possible to return a group of closures which share the
same data objects. Figure 2.1 contains a function which creates
primitive databases. It takes an assoc-list (db), and returns a
list of three closures which query, add, and delete entries,
respectively.

Each call to make-dbms makes a new database--a new set of
functions closed over their own shared copy of an assoc-list.

> (setq cities (make-dbms '((boston . us) (paris . france))))
(#<Interpreted-Function 8022E7>
#<Interpreted-Function 802317>
#<Interpreted-Function 802347>)

	(defun make-dbms (db)
  (list
   #'(lambda (key)
       (cdr (assoc key db)))
   #'(lambda (key val)
       (push (cons key val) db)
       key)
   #'(lambda (key)
       (setf db (delete key db :key #'car))
       key)))

=end

def make_dbms db
  [ proc{|key| db.assoc(key).last},
    proc{|key,val| db << [key,val]},
    proc{|key| db.delete_if{|pair| key == pair.first}} ]
end

cities = make_dbms [[:boston, :us], [:paris, :france]]

puts cities[0].call(:boston)
puts cities[0][:paris]
cities[1][:london, :england]
puts cities[0][:london]

From: Rob Warnock
Subject: Re: Alternatives
Date: 
Message-ID: <pbmdnd1pzcyrIZLUnZ2dnUVZ_s_inZ2d@speakeasy.net>
William James  <·········@yahoo.com> wrote:
+---------------
| Writing some stuff in Paul Graham's _On Lisp_ in Ruby.
+---------------

Wrong newsgroup: Try "comp.lang.ruby".


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Kenny
Subject: Re: Alternatives
Date: 
Message-ID: <490fcd20$0$20284$607ed4bc@cv.net>
Rob Warnock wrote:
> William James  <·········@yahoo.com> wrote:
> +---------------
> | Writing some stuff in Paul Graham's _On Lisp_ in Ruby.
> +---------------
> 
> Wrong newsgroup: Try "comp.lang.ruby".

Oh, I don't know. Paul Graham would love it. He is on record in re 
proposed changes to Arc: "anything that makes the code terser".

Mr Graham with the K crowd and many others think that an important 
dimension. I decided it must be when, well, go look at your code 
everyone. The code you wrote without a flamewar in mind. Here are the 
first dozen I found:

     (if (null info)
         (pqhtml
          (:princ "No matching suppliers"))
       (pqhtml
        ((:div :style "font-size: small;")
         (if (> (wsv^ "toppage") 1)
             (pqhtml ((:input :type "button"
                        :value "Prior Page"
                        :onClick (nsfmt^ "toppagenext('~a',-1);"))))
           (pqhtml ((:input :type "button"
                      :value "Prior Page"
                      :disabled "yes"
                      :onClick (nsfmt^ "toppagenext('~a',-1);")))))
         ((:input :type "button"
            :value "Next Page"
            :onClick (nsfmt^ "toppagenext('~a',1);"))))
        (:hr)
        ((:div :style "overflow:auto; height:400px;")

Ooooh. White space, gratuitous line breaks to give each keyword-value 
pair its own line. Long datanames. But lotsa macrology to hide boilerplate.

Does Ruby have macros?

kt
From: ·······@eurogaran.com
Subject: Re: Alternatives
Date: 
Message-ID: <3f500f4a-632c-450d-a499-c98523fbea2f@g17g2000prg.googlegroups.com>
His Kennyness wrote:
> Does Ruby have macros?
>
> kt

I suspect William is being attracted by Lisp: First he was just
plainly making Ruby propaganda. Now he tries to reproduce Lisp code in
Ruby. Next step is reproducing Ruby code in Lisp. Eventually adopting
Lisp.
Only we all have to suffer him in the meantime.
Where is Gavino when we really need him?
From: ········@gmail.com
Subject: Re: Alternatives
Date: 
Message-ID: <a179b588-cee9-4fee-8451-7a7176d429c1@b31g2000prf.googlegroups.com>
On 4 Nov, 03:09, William James <·········@yahoo.com> wrote:
> Writing Ruby

Ah, you want to get the same down-vote score as JH.

Good luck!
From: budden
Subject: Re: Alternatives
Date: 
Message-ID: <260dee78-df6f-4486-aece-a22f349a821b@g17g2000prg.googlegroups.com>
Hi, William,

What do you think about this:
http://shootout.alioth.debian.org/u32q/benchmark.php?test=all&lang=sbcl&lang2=ruby

You can see, code compactness is (mostly) on the side of the Ruby.
Memory consumption is not measured correctly (minimal SBCL image is
about 25Mb). But the speed... No comments...
From: ··········@mail.ru
Subject: Re: Alternatives
Date: 
Message-ID: <aafdfb48-07b9-486c-b02d-441c080c02f5@s9g2000prg.googlegroups.com>
On 4 ÎÏÑÂ, 07:18, Kenny <·········@gmail.com> wrote:
> Rob Warnock wrote:
> > William James  <·········@yahoo.com> wrote:
> > +---------------
> > | Writing some stuff in Paul Graham's _On Lisp_ in Ruby.
> > +---------------
>
> > Wrong newsgroup: Try "comp.lang.ruby".
>
> Oh, I don't know. Paul Graham would love it. He is on record in re
> proposed changes to Arc: "anything that makes the code terser".
>
> Mr Graham with the K crowd and many others think that an important
> dimension. I decided it must be when, well, go look at your code
> everyone. The code you wrote without a flamewar in mind. Here are the
> first dozen I found:
>
>      (if (null info)
>          (pqhtml
>           (:princ "No matching suppliers"))
>        (pqhtml
>         ((:div :style "font-size: small;")
>          (if (> (wsv^ "toppage") 1)
>              (pqhtml ((:input :type "button"
>                         :value "Prior Page"
>                         :onClick (nsfmt^ "toppagenext('~a',-1);"))))
>            (pqhtml ((:input :type "button"
>                       :value "Prior Page"
>                       :disabled "yes"
>                       :onClick (nsfmt^ "toppagenext('~a',-1);")))))
>          ((:input :type "button"
>             :value "Next Page"
>             :onClick (nsfmt^ "toppagenext('~a',1);"))))
>         (:hr)
>         ((:div :style "overflow:auto; height:400px;")
>
> Ooooh. White space, gratuitous line breaks to give each keyword-value
> pair its own line. Long datanames. But lotsa macrology to hide boilerplate.
>
> Does Ruby have macros?
>
> kt

Again macros that don't give any advantage against OOP.

Here is Smalltalk:

SUCounterTest>>renderContentOn: html
   | id |
   id := html nextId.
   html paragraph: [
      html span
         id: 'counter_' , id;
         with: count.
      html space.
      html anchor
         onClick: (html updater
            id: 'counter_' , id;
            callback: [ :render | self increase; renderCountOn:
render ]);
         with: '++'.
      html space.
      html anchor
         onClick: (html updater
            id: 'counter_' , id;
            callback: [ :render | self decrease; renderCountOn:
render ]);
         with: '--' ]

Yes, in this case pqhtml macro can do some work at compile time - but
this doesn't matter for convinience of its usage.

Dear Lispers, can you design a DSL (but true DSL!) in Lisp for
generating XML (or HTML) that will give great (small) advantage over

1) Python/Ruby/Perl/Lisp functions with keywords:
 div(span('some text', style="span-style"),
     style="kuku", onClick="alert('kuku')")
2) Given Smalltalk OO code
?
From: Kenny
Subject: Re: Alternatives
Date: 
Message-ID: <4911c979$0$14321$607ed4bc@cv.net>
··········@mail.ru wrote:
> On 4 ����, 07:18, Kenny <·········@gmail.com> wrote:
> 
>>Rob Warnock wrote:
>>
>>>William James  <·········@yahoo.com> wrote:
>>>+---------------
>>>| Writing some stuff in Paul Graham's _On Lisp_ in Ruby.
>>>+---------------
>>
>>>Wrong newsgroup: Try "comp.lang.ruby".
>>
>>Oh, I don't know. Paul Graham would love it. He is on record in re
>>proposed changes to Arc: "anything that makes the code terser".
>>
>>Mr Graham with the K crowd and many others think that an important
>>dimension. I decided it must be when, well, go look at your code
>>everyone. The code you wrote without a flamewar in mind. Here are the
>>first dozen I found:
>>
>>     (if (null info)
>>         (pqhtml
>>          (:princ "No matching suppliers"))
>>       (pqhtml
>>        ((:div :style "font-size: small;")
>>         (if (> (wsv^ "toppage") 1)
>>             (pqhtml ((:input :type "button"
>>                        :value "Prior Page"
>>                        :onClick (nsfmt^ "toppagenext('~a',-1);"))))
>>           (pqhtml ((:input :type "button"
>>                      :value "Prior Page"
>>                      :disabled "yes"
>>                      :onClick (nsfmt^ "toppagenext('~a',-1);")))))
>>         ((:input :type "button"
>>            :value "Next Page"
>>            :onClick (nsfmt^ "toppagenext('~a',1);"))))
>>        (:hr)
>>        ((:div :style "overflow:auto; height:400px;")
>>
>>Ooooh. White space, gratuitous line breaks to give each keyword-value
>>pair its own line. Long datanames. But lotsa macrology to hide boilerplate.
>>
>>Does Ruby have macros?
>>
>>kt
> 
> 
> Again macros that don't give any advantage against OOP.
> 
> Here is Smalltalk:
> 
> SUCounterTest>>renderContentOn: html
>    | id |
>    id := html nextId.
>    html paragraph: [
>       html span
>          id: 'counter_' , id;
>          with: count.
>       html space.
>       html anchor
>          onClick: (html updater
>             id: 'counter_' , id;
>             callback: [ :render | self increase; renderCountOn:
> render ]);
>          with: '++'.
>       html space.
>       html anchor
>          onClick: (html updater
>             id: 'counter_' , id;
>             callback: [ :render | self decrease; renderCountOn:
> render ]);
>          with: '--' ]
> 
> Yes, in this case pqhtml macro can do some work at compile time - but
> this doesn't matter for convinience of its usage.

Oh, golly, don't be confused. That post was about code brevity, not a 
demonstration of the power of macros.

And don't be confused either by specific cases of macrology. Ruby, 
Python, Perl, and K have amazingly cool, terse, neato constructs for 
programming data, so many times there will be nice ways for those 
languages to keep up (almost) with macros. But then they /really/ come 
up short on the other cases. The thing about Lisp macros is, they cannot 
fall down.

Folks would know this if they had used a language with Lisp-like macros 
(Lisp or Arc). If one has not used a language with macros one should 
probably give them a try and not worry so mush about Usenet debates.

> 
> Dear Lispers, can you design a DSL (but true DSL!) in Lisp for
> generating XML (or HTML) that will give great (small) advantage over
> 
> 1) Python/Ruby/Perl/Lisp functions with keywords:
>  div(span('some text', style="span-style"),
>      style="kuku", onClick="alert('kuku')")
> 2) Given Smalltalk OO code
> ?

In all these bake-offs the anti-Lispers are making a fatal error: tiny 
little bits of code. As I said, if the specific task lends itself to the 
neato constructs of Ruby or Python then the deeper difference between 
the way they get terse code and the way Lisp gets terse code gets lost. 
ie, They are just bad experiments.

Probably better to do a damn serious exercise with the language on your 
own and spend less time on Usenet if one's mind is open. If not, Usenet 
is precisely where one should be.

kzo
From: Franccesco
Subject: Re: Alternatives
Date: 
Message-ID: <15f790c6-bc3b-4052-8abb-8f3cb6609f36@v13g2000pro.googlegroups.com>
On 5 nov, 17:27, Kenny <·········@gmail.com> wrote:

> In all these bake-offs the anti-Lispers are making a fatal error: tiny
> little bits of code.

And where is the big code for Lisp? Ein?

Nobody sees it.

It is secret.

You know, for constructing nuclear weapons and things like that.

Or maybe indefinitely "under rapid development".
From: Kenny
Subject: Re: Alternatives
Date: 
Message-ID: <49145c43$0$4876$607ed4bc@cv.net>
Franccesco wrote:
> On 5 nov, 17:27, Kenny <·········@gmail.com> wrote:
> 
> 
>>In all these bake-offs the anti-Lispers are making a fatal error: tiny
>>little bits of code.
> 
> 
> And where is the big code for Lisp? Ein?
> 
> Nobody sees it.
> 
> It is secret.
> 
> You know, for constructing nuclear weapons and things like that.
> 
> Or maybe indefinitely "under rapid development".

I was actually going to recommend Cells. It is a reasonable amount of 
code but exercises Lisp (and Python, where Philip Eby has done something 
inspired by Cells) pretty seriously. It is also a fine entry in the 
functional reactive programming horse race, a way cool fun productive 
paradigm, so at the same time whatshisface could gain admission to the 
yearly FRP Conferences to be held in Monte Carlo.

Then we get a real comparison and a real contrib to Ruby hence the 
world. Without macros Rubycells will not look as slick, but that's OK, 
the bang is in the functionality.

peace,kxo
From: ··········@mail.ru
Subject: Re: Alternatives
Date: 
Message-ID: <1a1af4fa-9fcd-4b22-834f-8f1c85c859cb@v39g2000pro.googlegroups.com>
On 6 ÎÏÑÂ, 13:13, Kaz Kylheku <········@gmail.com> wrote:

> With this function-based approach, you can't stream the HTML, because you're
> stuck with generating the HTML bottom-up; the nested function calls generate
> the inner pieces before the outer ones. The outermost div is called last, and
> only then are the pieces integrated to form the outermost div block.

Again performance issue.
Here comes interesting moment: We can bypass this problem just with
lambdas, and it looks like this (in Ruby):

html(:style => 'default-div', :id => 'dsl') {
    span(:style => 'span-style') {
        print "first"
        }
    span(:style => 'second') {
        print "second span"
        }
    }

,but Python has no good lambdas. So, bye, function approach:

from __future__ import with_statement

class Tag:
    def __init__(self, name):
        self.name = name

    def __enter__(self):
        pass

    def __call__(self, **kwargs):
        print("<%s %s>" % (self.name,
                           ' '.join(['%s="%s"' % (k, v) for k, v in
kwargs.iteritems()])))
        return self

    def __exit__(self, *args):
        print("</%s>" % self.name)

def html_element(name):
    return Tag(name)

def define_html_element(name):
    globals()[name] = html_element(name)

map(define_html_element, ['div', 'span', 'form', 'input'])

with div(style = 'default-div', id = 'dsl'):
    with span(style='span-style'):
        print("first")
    with span(style='second'):
        print("second span")

And we can begin HTML streaming.

Let's call this approach "hack with generators" (though it is not a
hack and doesn't use generators, but sounds great)


> Moreover, the arguments to div, when it is finally called, are canned character
> strings. The div function cannot do much more with the pieces other than
> catenate them together.  What if I want some function that I can use in place
> of div that will walk the HTML tree and do something interesting to it? That
> function will have to parse HTML strings.

At least two options for Python here:
1) use XSL
2) use ElementTree instead of strings

 each of this options is better than writing code walker in Lisp

> Of course, we haven't proved that you need macros; it's possibly doable in a
> functional language with lazy evaluation (normal argument passing), if you have
> some tools to influence the actual evaluation order.
>
> You might be able to hack it using Python generators.  But Python generators
> are not regular functions.  Python generators use some special syntax which
> cannot be developed in Python itself.  Before the benevolent dictator declared
> ``let there be generators'', they were not possible to implement in any way
> other than as a patch to the Python source code. Back to macros!

That's right. Generators use special syntax. With_statements use
special syntax. And you cannot even imagine Lispy DSL for generating
XML that will be better than this special syntax.
From: Vsevolod
Subject: Re: Alternatives
Date: 
Message-ID: <c66af8a2-8647-4232-bb0a-0596a8c34f3f@a29g2000pra.googlegroups.com>
On Nov 7, 11:14 pm, ··········@mail.ru wrote:
> Again performance issue.
> Here comes interesting moment: We can bypass this problem just with
> lambdas, and it looks like this (in Ruby):

> That's right. Generators use special syntax. With_statements use
> special syntax. And you cannot even imagine Lispy DSL for generating
> XML that will be better than this special syntax.

If you leave performance aside (and that's a huge thing, because, if a
big part of what your application does is generating HTML -- and
that's what all dynamic web applications do today,-- you need to
regenerate every static part of a page on every request to it). So, if
you leave performance issues aside, could you please explain how is
the Ruby/Python code with print statements all over it is more
elegant, than, for example, the CL-WHO variant?
(with-html-output
  (:div :style "default-div" :id "dsl"
      (:span :style "span-style" "first")
      (:span :style "second" "second span")))
From: Keith H Duggar
Subject: Re: Alternatives
Date: 
Message-ID: <836b3d04-29a0-498b-961d-6bf20bd7a050@s9g2000prm.googlegroups.com>
Vsevolod wrote:
> ··········@mail.ru wrote:
>
> > Again performance issue.
> > Here comes interesting moment: We can bypass this problem just with
> > lambdas, and it looks like this (in Ruby):
> > That's right. Generators use special syntax. With_statements use
> > special syntax. And you cannot even imagine Lispy DSL for generating
> > XML that will be better than this special syntax.
>
> If you leave performance aside (and that's a huge thing, because, if a
> big part of what your application does is generating HTML -- and
> that's what all dynamic web applications do today,-- you need to
> regenerate every static part of a page on every request to it). So, if
> you leave performance issues aside, could you please explain how is
> the Ruby/Python code with print statements all over it is more
> elegant, than, for example, the CL-WHO variant?
> (with-html-output
>   (:div :style "default-div" :id "dsl"
>       (:span :style "span-style" "first")
>       (:span :style "second" "second span")))

That seems to have too much semantically important juxtaposition
that with-html-output must parse. I would have thought a "Lispy"
HTML DSL would look more like:

(with-html-output
  (div ((style "default-div") (id "dsl"))
     (span ((style "span-style")) "first")
     (span ((style "second")) "second span")))

no? Because, for example, attribute values are always name-value
pairs so why not represent those pairs directly as sexps and let
Lisp parse the AST rather than rolling some juxtaposition parser
within with-html-output?

KHD
From: ······@corporate-world.lisp.de
Subject: Re: Alternatives
Date: 
Message-ID: <5a55c2b4-f9c4-44ac-9783-bd28be3ac827@z6g2000pre.googlegroups.com>
On 8 Nov., 17:30, Keith H Duggar <······@alum.mit.edu> wrote:
> Vsevolod wrote:
> > ··········@mail.ru wrote:
>
> > > Again performance issue.
> > > Here comes interesting moment: We can bypass this problem just with
> > > lambdas, and it looks like this (in Ruby):
> > > That's right. Generators use special syntax. With_statements use
> > > special syntax. And you cannot even imagine Lispy DSL for generating
> > > XML that will be better than this special syntax.
>
> > If you leave performance aside (and that's a huge thing, because, if a
> > big part of what your application does is generating HTML -- and
> > that's what all dynamic web applications do today,-- you need to
> > regenerate every static part of a page on every request to it). So, if
> > you leave performance issues aside, could you please explain how is
> > the Ruby/Python code with print statements all over it is more
> > elegant, than, for example, the CL-WHO variant?
> > (with-html-output
> >   (:div :style "default-div" :id "dsl"
> >       (:span :style "span-style" "first")
> >       (:span :style "second" "second span")))
>
> That seems to have too much semantically important juxtaposition
> that with-html-output must parse. I would have thought a "Lispy"
> HTML DSL would look more like:

HTML has a different syntax than Lisp. I might be useful
to have an extra parser that walks over S-Expressions.
The WITH-HTML-OUTPUT macro could call that parser
and pass the s-expression representing some HMTL.
The macro can then generate code that outputs the
HTML to an output stream.

>
> (with-html-output
>   (div ((style "default-div") (id "dsl"))
>      (span ((style "span-style")) "first")
>      (span ((style "second")) "second span")))
>
> no? Because, for example, attribute values are always name-value
> pairs so why not represent those pairs directly as sexps and let
> Lisp parse the AST rather than rolling some juxtaposition parser
> within with-html-output?

IF you want DIV and SPAN to be a macro or function, your syntax
example would be wrong.
Example: If DIV and SPAN would be macros, then the typical choices
would be:

(with-html-output
  (div :style "default-div" :id "dsl"
    (span :style "span-style" "first")
    (span :style "second" "second span")))

See above for comparison.

But usually one might add an extra layer of parentheses around the
options:

(with-html-output
  (div (:style "default-div" :id "dsl")
    (span (:style "span-style")
       "first")
    (span (:style "second")
       "second span")))

The DIV macro would then have a definition similar to:

(defmacro div ((&key style id) &body body) ... )

SPAN then would similar to:

(defmacro span ((&key style) &body body) ... )

You can see that the expressions above map very nicely to the macro
parameter lists.

>
> KHD

CL-HTTP would use something like (I haven't tried to run this snippet,
but the syntax is mostly right) this:

(with-division (:style :default-div :id :dsl)
  (with-division (:inline-p t :style :span-div)
    (print 'first))
  (with-division (:inline-p t :style :second)
    (print 'second)))

WITH-DIVISION is a macro and there is no extra parsing needed, since
it is just the
normal Common Lisp syntax. It can be expanded and compiled to
efficient code
that does write to streams and does not need to create large result
strings.
From: Vsevolod
Subject: Re: Alternatives
Date: 
Message-ID: <b8701a0a-e76d-4ee5-b728-9c9996654364@h23g2000prf.googlegroups.com>
On Nov 8, 6:30 pm, Keith H Duggar <······@alum.mit.edu> wrote:
> (with-html-output
>   (div ((style "default-div") (id "dsl"))
>      (span ((style "span-style")) "first")
>      (span ((style "second")) "second span")))
>
> no? Because, for example, attribute values are always name-value
> pairs so why not represent those pairs directly as sexps and let
> Lisp parse the AST rather than rolling some juxtaposition parser
> within with-html-output?

Key-value pairs in Lisp are often represented with the use of keywords
(e.g. in lambda lists and plists). It has the advantages of utilizing
the ubiquitous keyword package and a simpler syntax (less
parenthesis). There's also an alternative form:
   ((:div :style "default-div" :id "dsl")
      ((:span :style "span-style") "first")
      ((:span :style "second") "second span")))
used by those, who prefer a more articulated separation of arguments
and tag content. But both of them are lispy enough in my point of
view. The idea is to make it uniform, but not overly, i think. Some
simple semantics is good: like the semantics of an s-expression --
(function args),-- not just (some values). :)
From: Matthias Buelow
Subject: Re: Alternatives
Date: 
Message-ID: <6ndn7jFl40njU1@mid.dfncis.de>
··········@mail.ru wrote:

> Here is Smalltalk:
[...]

How would you verify this (code/data)? It's relatively easy to do if
it's in s-expr form. Not so easy if it's in Smalltalk, or any other
language with a more complicated syntax. Furthermore, you'd have to
parse it into an internal representation first (which isn't necessary if
it's in Lisp.) That's the biggest one I think; otherwise, you could also
write a sh-script for generating HTML.
From: Alex Mizrahi
Subject: Re: Alternatives
Date: 
Message-ID: <4912dbbf$0$90273$14726298@news.sunsite.dk>
 ea> Dear Lispers, can you design a DSL (but true DSL!) in Lisp for
 ea> generating XML (or HTML) that will give great (small) advantage over

 ea> 1) Python/Ruby/Perl/Lisp functions with keywords:
 ea>  div(span('some text', style="span-style"),
 ea>      style="kuku", onClick="alert('kuku')")


DSL approach might have couple of advantages:
 * better performance -- all constant parts can be compiled into
   constant strings at compilation time. joining lots of small strings
   might be sort of expensive performance-wise, and sometimes even function
   calls might be rather expensive.
 * with DSL you have more chances to verify correctness of structure of
   your code at compile time (i think you can also do that in languages with
   advanced type system   and static type checking).
 * in DSL you have clear separation between dynamically injected strings
   and HTML pieces, so you can automatically escape those strings etc.

   with a simplistic implementation via functions you will have everything
   as string, so you can't do this automatically. you might choose to have
   intermediate representation building sort of DOM, but then you'll have
   even more overhead.
 * but, huh, how DIV with two SPANs will look? probably you'll need
   a construct to join adjacent elements:

    div(span('some text', style="span-style")
        + span('other text', style="span-style"),
       style="kuku", onClick="alert('kuku')")

   in general, HTML generation does not map well onto function calls --
   it is sort of ugly, and DSL can fix that.

but actually HTML generation is not the biggest reason to have DSLs.
i think there are more advantages for query languages. and of course,
this makes more sense in bigger code pieces, where you can see synergy
between several DSL -- for example, you directly output results of
query into HTML. and often, these advantages from DSLs are rather small,
but a bit here and a bit there -- and whole picture changes.

 ea> 2) Given Smalltalk OO code ?

i dunno how Smalltalk OO code works, but i guess some points above
apply to it too. 
From: Isaac Gouy
Subject: Re: Alternatives
Date: 
Message-ID: <3bd6035c-2c00-44f2-9baa-c33b71da928c@w24g2000prd.googlegroups.com>
On Nov 4, 8:59 am, budden <········@mtu-net.ru> wrote:
...
> What do you think about this:http://shootout.alioth.debian.org/u32q/benchmark.php?test=all〈=sb...
...
> Memory consumption is not measured correctly (minimal SBCL image is
> about 25Mb).

How interesting!

On x86 Ubuntu, System Monitor reports 1.9MiB for the SBCL fannkuch
program memory use and the benchmarks game shows 5,572KB.

http://shootout.alioth.debian.org/u32q/benchmark.php?test=fannkuch&lang=sbcl&id=2


On x64 Ubuntu, System Monitor reports 33.1MiB for the SBCL fannkuch
program memory use and the benchmarks game shows 38,024KB.

http://shootout.alioth.debian.org/u64q/benchmark.php?test=fannkuch&lang=sbcl&id=2


Any idea what's going on?
From: George Neuner
Subject: Re: Alternatives
Date: 
Message-ID: <8gt4h41gb08k4ospmtnbl7h00jf40db04r@4ax.com>
On Wed, 5 Nov 2008 19:04:29 -0800 (PST), Isaac Gouy <······@yahoo.com>
wrote:

>On Nov 4, 8:59�am, budden <········@mtu-net.ru> wrote:
>...
>> What do you think about this:http://shootout.alioth.debian.org/u32q/benchmark.php?test=all?=sb...
>...
>> Memory consumption is not measured correctly (minimal SBCL image is
>> about 25Mb).
>
>How interesting!
>
>On x86 Ubuntu, System Monitor reports 1.9MiB for the SBCL fannkuch
>program memory use and the benchmarks game shows 5,572KB.
>
>http://shootout.alioth.debian.org/u32q/benchmark.php?test=fannkuch&lang=sbcl&id=2
>
>
>On x64 Ubuntu, System Monitor reports 33.1MiB for the SBCL fannkuch
>program memory use and the benchmarks game shows 38,024KB.
>
>http://shootout.alioth.debian.org/u64q/benchmark.php?test=fannkuch&lang=sbcl&id=2
>
>
>Any idea what's going on?
>

I haven't looked at the shootout pages - I don't really care - but
questions about memory use are complicated by virtual memory.  At a
minimum you have to distinguish between the reserved set, the
committed set, the paged-in set, and the algorithm's working set (all
of which may change over time) in order to fairly compare memory use
between programs intended as "benchmarks".

All of these numbers are available, but rarely are they all reported.

George
From: Isaac Gouy
Subject: Re: Alternatives
Date: 
Message-ID: <608cf437-2978-4d4f-921a-8714602095b0@q30g2000prq.googlegroups.com>
On Nov 5, 8:50 pm, George Neuner <········@comcast.net> wrote:
> On Wed, 5 Nov 2008 19:04:29 -0800 (PST), Isaac Gouy <······@yahoo.com>
> wrote:
>
>
>
> >On Nov 4, 8:59 am, budden <········@mtu-net.ru> wrote:
> >...
> >> What do you think about this:http://shootout.alioth.debian.org/u32q/benchmark.php?test=all?=sb...
> >...
> >> Memory consumption is not measured correctly (minimal SBCL image is
> >> about 25Mb).
>
> >How interesting!
>
> >On x86 Ubuntu, System Monitor reports 1.9MiB for the SBCL fannkuch
> >program memory use and the benchmarks game shows 5,572KB.
>
> >http://shootout.alioth.debian.org/u32q/benchmark.php?test=fannkuch&la...
>
> >On x64 Ubuntu, System Monitor reports 33.1MiB for the SBCL fannkuch
> >program memory use and the benchmarks game shows 38,024KB.
>
> >http://shootout.alioth.debian.org/u64q/benchmark.php?test=fannkuch&la...
>
> >Any idea what's going on?
>
> I haven't looked at the shootout pages - I don't really care - but
> questions about memory use are complicated by virtual memory.  At a
> minimum you have to distinguish between the reserved set, the
> committed set, the paged-in set, and the algorithm's working set (all
> of which may change over time) in order to fairly compare memory use
> between programs intended as "benchmarks".
>
> All of these numbers are available, but rarely are they all reported.
>
> George


Does anyone have a suggestion about what's going on with the numbers
that are reported?

For the same sbcl fannkuch program, for the same input values, top
shows

x86 Ubuntu
VIRT 523m
RES 5572
SHR 3628

x64 Ubuntu
VIRT 8243m
RES 37m
SHR 4160

Programs in other languages show a only modest increase in memory use
going from x86 to x64 - so what's going on with sbcl?
From: Juho Snellman
Subject: Re: Alternatives
Date: 
Message-ID: <87ej1opyf3.fsf@vasara.proghammer.com>
Isaac Gouy <······@yahoo.com> writes:
> Does anyone have a suggestion about what's going on with the numbers
> that are reported?
> 
> For the same sbcl fannkuch program, for the same input values, top
> shows
> 
> x86 Ubuntu
> VIRT 523m
> RES 5572
> SHR 3628
> 
> x64 Ubuntu
> VIRT 8243m
> RES 37m
> SHR 4160
> 
> Programs in other languages show a only modest increase in memory use
> going from x86 to x64 - so what's going on with sbcl?

The VIRT is just due to sbcl reserving a larger default heap on x86-64
(0.5GB vs 8GB). We use the larger default larger address spaces are
the main reason to go 64-bit. The increase in RES is probably due to
sbcl's internal gc page tables, which will basically become larger
when the heap size increases, and which are touched at process startup
(hence being resident).

It should be pretty easy to frob things so that the whole page table
doesn't need to be touched at startup. Alternatively runnign with a
smaller heap size (e.g. --dynamic-space-size 500) should result in
roughly the same space usage as on x86.

And to answer the point made a couple of posts upthread, it's quite
correct for the resident set size to be smaller than the image size:
most of the lisp image is just mapped into memory, but not actually
accessed during the execution of a small benchmark.

-- 
Juho Snellman
From: Isaac Gouy
Subject: Re: Alternatives
Date: 
Message-ID: <ed5dfa02-2df6-45be-a5bf-b4fc490625bb@r36g2000prf.googlegroups.com>
On Nov 6, 9:16 am, Juho Snellman <······@iki.fi> wrote:
> Isaac Gouy <······@yahoo.com> writes:
> > Does anyone have a suggestion about what's going on with the numbers
> > that are reported?
>
> > For the same sbcl fannkuch program, for the same input values, top
> > shows
>
> > x86 Ubuntu
> > VIRT 523m
> > RES 5572
> > SHR 3628
>
> > x64 Ubuntu
> > VIRT 8243m
> > RES 37m
> > SHR 4160
>
> > Programs in other languages show a only modest increase in memory use
> > going from x86 to x64 - so what's going on with sbcl?
>
> The VIRT is just due to sbcl reserving a larger default heap on x86-64
> (0.5GB vs 8GB). We use the larger default larger address spaces are
> the main reason to go 64-bit. The increase in RES is probably due to
> sbcl's internal gc page tables, which will basically become larger
> when the heap size increases, and which are touched at process startup
> (hence being resident).
>
> It should be pretty easy to frob things so that the whole page table
> doesn't need to be touched at startup. Alternatively runnign with a
> smaller heap size (e.g. --dynamic-space-size 500) should result in
> roughly the same space usage as on x86.
>
> And to answer the point made a couple of posts upthread, it's quite
> correct for the resident set size to be smaller than the image size:
> most of the lisp image is just mapped into memory, but not actually
> accessed during the execution of a small benchmark.
>
> --
> Juho Snellman


Thank you for taking the time to give a comprehensive answer.
From: ··········@mail.ru
Subject: Re: Alternatives
Date: 
Message-ID: <4a21f1f4-968c-40f3-80ab-c27f7249e4a8@w39g2000prb.googlegroups.com>
On 5 ÎÏÑÂ, 23:57, "Alex Mizrahi" <········@users.sourceforge.net>
wrote:
>  ea> Dear Lispers, can you design a DSL (but true DSL!) in Lisp for
>  ea> generating XML (or HTML) that will give great (small) advantage over
>
>  ea> 1) Python/Ruby/Perl/Lisp functions with keywords:
>  ea>  div(span('some text', style="span-style"),
>  ea>      style="kuku", onClick="alert('kuku')")
>
> DSL approach might have couple of advantages:
>  * better performance -- all constant parts can be compiled into
>    constant strings at compilation time. joining lots of small strings
>    might be sort of expensive performance-wise, and sometimes even function
>    calls might be rather expensive.
>  * with DSL you have more chances to verify correctness of structure of
>    your code at compile time (i think you can also do that in languages with
>    advanced type system   and static type checking).
>  * in DSL you have clear separation between dynamically injected strings
>    and HTML pieces, so you can automatically escape those strings etc.
>
>    with a simplistic implementation via functions you will have everything
>    as string, so you can't do this automatically. you might choose to have
>    intermediate representation building sort of DOM, but then you'll have
>    even more overhead.
>  * but, huh, how DIV with two SPANs will look? probably you'll need
>    a construct to join adjacent elements:
>
>     div(span('some text', style="span-style")
>         + span('other text', style="span-style"),
>        style="kuku", onClick="alert('kuku')")
>
>    in general, HTML generation does not map well onto function calls --
>    it is sort of ugly, and DSL can fix that.
>
> but actually HTML generation is not the biggest reason to have DSLs.
> i think there are more advantages for query languages. and of course,
> this makes more sense in bigger code pieces, where you can see synergy
> between several DSL -- for example, you directly output results of
> query into HTML. and often, these advantages from DSLs are rather small,
> but a bit here and a bit there -- and whole picture changes.
>
>  ea> 2) Given Smalltalk OO code ?
>
> i dunno how Smalltalk OO code works, but i guess some points above
> apply to it too.

Let's put aside performance/compile-time-checks for now and
concentrate on usability:
DIV can have any number of SPANs

# warning: toy example
def html_element(name):
    'ha! mixing &key and &rest'
    def inner(*args, **kwargs):
        return '<%s %s>%s</%s>' % (name,
                                   ' '.join(['%s="%s"' % (k, v) for k,
v in kwargs.iteritems()]),
                                   ''.join(args),
                                   name)
    return inner

def define_html_element(name):
    globals()[name] = html_element(name)

map(define_html_element, ['div', 'span', 'form', 'input'])

print div(span('first', style='span-style'),
          span('second', ' span', style='second'),
          style='default-div',
          id="dsl")

It seems that HTML/XML generation maps perfectly well into function
calls. No need for macros here. And almost every book on Lisp has
chapter "Generating HTML with macros".

Query languages? Synergy between several DSLs? Great!

Dear Lispers, can you design a DSLs (imaginary) for
generating XML and for querying that together will give any advantage
over ordinary Python+SQL code? Please give an example of its usage.
From: Kaz Kylheku
Subject: Re: Alternatives
Date: 
Message-ID: <20081106135353.819@gmail.com>
On 2008-11-06, ··········@mail.ru <··········@mail.ru> wrote:
> print div(span('first', style='span-style'),
>           span('second', ' span', style='second'),
>           style='default-div',
>           id="dsl")
>
> It seems that HTML/XML generation maps perfectly well into function
> calls.

One problem is evaluation. All of the arguments to DIV are evaluated before it
is called. So if you're generating a long HTML, nothing happens until the end.

Those macro-based Lisp HTML generators are often directly coupled to HTTP
streams. Because they are macro-based, they have full control over the order of
translation of the S-expression to the HTML. HTML streaming can begin before
everything is evaluated.

With this function-based approach, you can't stream the HTML, because you're
stuck with generating the HTML bottom-up; the nested function calls generate
the inner pieces before the outer ones. The outermost div is called last, and
only then are the pieces integrated to form the outermost div block.

Moreover, the arguments to div, when it is finally called, are canned character
strings. The div function cannot do much more with the pieces other than
catenate them together.  What if I want some function that I can use in place
of div that will walk the HTML tree and do something interesting to it? That
function will have to parse HTML strings.

See, everything /seems/ easy, if you flunked computer science and haven't made
up for it in later years by learning how to think.

Of course, we haven't proved that you need macros; it's possibly doable in a
functional language with lazy evaluation (normal argument passing), if you have
some tools to influence the actual evaluation order.

You might be able to hack it using Python generators.  But Python generators
are not regular functions.  Python generators use some special syntax which
cannot be developed in Python itself.  Before the benevolent dictator declared
``let there be generators'', they were not possible to implement in any way
other than as a patch to the Python source code. Back to macros!
From: Matthias Buelow
Subject: Re: Alternatives
Date: 
Message-ID: <6njsdmFm1r9aU1@mid.dfncis.de>
William James wrote:
> Writing some stuff in Paul Graham's _On Lisp_ in Ruby.
[...]

I think for any aspect of Lisp, you can find some other language that
does it just as well or maybe even a little better. More interesting,
however, would be if there is a language that does everything Lisp can
do just as well. If it exists, I haven't seen it yet. So far, Lisp
(Common or otherwise) offers the best "package".
This isn't to say that I think Lisp is the "Silver Bullet"... that would
be naive. IMHO there will never be a single solution that covers all.
From: Jon Harrop
Subject: Re: Alternatives
Date: 
Message-ID: <Q7ednX9z49uZWYnUnZ2dnUVZ8judnZ2d@posted.plusnet>
Matthias Buelow wrote:
> William James wrote:
>> Writing some stuff in Paul Graham's _On Lisp_ in Ruby.
> [...]
> 
> I think for any aspect of Lisp, you can find some other language that
> does it just as well or maybe even a little better. More interesting,
> however, would be if there is a language that does everything Lisp can
> do just as well. If it exists, I haven't seen it yet. So far, Lisp
> (Common or otherwise) offers the best "package".
> This isn't to say that I think Lisp is the "Silver Bullet"... that would
> be naive. IMHO there will never be a single solution that covers all.

What problems can Lisp solve more easily than F#, OCaml, Haskell, Erlang,
Scala etc?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?u
From: William James
Subject: Re: Alternatives
Date: 
Message-ID: <gf2p9701v95@enews2.newsguy.com>
Jon Harrop wrote:

> What problems can Lisp solve more easily than F#, OCaml, Haskell,
> Erlang, Scala etc?

Hey!  Why doesn't anybody ever give Ruby any credit?
From: Kenny
Subject: Re: Alternatives
Date: 
Message-ID: <49151bec$0$4876$607ed4bc@cv.net>
William James wrote:
> Jon Harrop wrote:
> 
> 
>>What problems can Lisp solve more easily than F#, OCaml, Haskell,
>>Erlang, Scala etc?
> 
> 
> Hey!  Why doesn't anybody ever give Ruby any credit?

No macros, lame OO model, interpreted, one-trick pony (Rails) which is 
not even all that good. Your fifteen minutes is up.

hth,kzo
From: Jon Harrop
Subject: Re: Alternatives
Date: 
Message-ID: <F6WdnRFUBtuRBYjUnZ2dnUVZ8sTinZ2d@posted.plusnet>
Kenny wrote:
> William James wrote:
>> Hey!  Why doesn't anybody ever give Ruby any credit?
> 
> No macros, lame OO model, interpreted, one-trick pony (Rails) which is
> not even all that good. Your fifteen minutes is up.

No static typing, no performance...

What can Ruby do that modern FPLs cannot?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?u
From: Brian Adkins
Subject: Re: Alternatives
Date: 
Message-ID: <m2d4h5ebq2.fsf@gmail.com>
Jon Harrop <···@ffconsultancy.com> writes:

> Kenny wrote:
>> William James wrote:
>>> Hey!  Why doesn't anybody ever give Ruby any credit?
>> 
>> No macros, lame OO model, interpreted, one-trick pony (Rails) which is
>> not even all that good. Your fifteen minutes is up.
>
> No static typing, no performance...
>
> What can Ruby do that modern FPLs cannot?

Develop database backed web applications in a fraction of the time ...
From: Jon Harrop
Subject: Re: Alternatives
Date: 
Message-ID: <mvmdnf5JTu8yYovUnZ2dnUVZ8v6dnZ2d@posted.plusnet>
Brian Adkins wrote:
> Jon Harrop <···@ffconsultancy.com> writes:
>> What can Ruby do that modern FPLs cannot?
> 
> Develop database backed web applications in a fraction of the time ...

...that are notoriously unreliable.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?u
From: Brian Adkins
Subject: Re: Alternatives
Date: 
Message-ID: <m24p2geo2f.fsf@gmail.com>
Jon Harrop <···@ffconsultancy.com> writes:

> Brian Adkins wrote:
>> Jon Harrop <···@ffconsultancy.com> writes:
>>> What can Ruby do that modern FPLs cannot?
>> 
>> Develop database backed web applications in a fraction of the time ...
>
> ...that are notoriously unreliable.

You have *no* idea what you're talking about, but that's not really
news, now is it? :) 

Fortunately, "A man with experience is never at the mercy of a
man with a theory."

Have you even written a web app with a FPL? I seriously doubt it, but
if you have, please show me some that you've written in a FPL that
have uptime even close to my Ruby/Rails apps below.

I predict you will not do this, but will instead continue to spout
about that which you know little to nothing about. On the other hand,
I would love to hear some success stories regarding FPLs in the web
arena. I have no religious affection for Ruby/Rails, it's just a great
tool currently.

* Notice the start time of 2007 in several of the processes
  below! Others have been up since Jan, Feb, Mar, etc.

$ ps -ef | grep mong
PID  STIME   CMD
23982 2007   /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e production -p 8040 -a 127.0.0.1 -P log/mongrel.8040.pid
23985 2007   /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e production -p 8041 -a 127.0.0.1 -P log/mongrel.8041.pid
21996 2007   /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e production -p 8060 -a 127.0.0.1 -P log/mongrel.8060.pid
30457 Jan21  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e production -p 8050 -a 127.0.0.1 -P log/mongrel.8050.pid
30460 Jan21  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e production -p 8051 -a 127.0.0.1 -P log/mongrel.8051.pid
 3626 Feb14  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e production -p 8020 -a 127.0.0.1 -P log/mongrel.8020.pid
 3630 Feb14  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e production -p 8021 -a 127.0.0.1 -P log/mongrel.8021.pid
18010 Mar05  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e production -p 8030 -a 127.0.0.1 -P log/mongrel.8030.pid
18013 Mar05  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e production -p 8031 -a 127.0.0.1 -P log/mongrel.8031.pid
25470 May24  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e production -p 8070 -a 127.0.0.1 -P log/mongrel.8070.pid

$ uptime
10:29:38 up 512 days,  2:21
From: Kaz Kylheku
Subject: Re: Alternatives
Date: 
Message-ID: <20081109201054.954@gmail.com>
On 2008-11-09, Brian Adkins <···········@gmail.com> wrote:
> Have you even written a web app with a FPL? I seriously doubt it, but

I don't suspect Harrop has ever flipped a bug database record from
"assigned" to "fixed" in any software organization.
From: Jon Harrop
Subject: Re: Alternatives
Date: 
Message-ID: <766dnX6NSrWo_4XUnZ2dnUVZ8tDinZ2d@posted.plusnet>
Brian Adkins wrote:
> Jon Harrop <···@ffconsultancy.com> writes:
> 
>> Brian Adkins wrote:
>>> Jon Harrop <···@ffconsultancy.com> writes:
>>>> What can Ruby do that modern FPLs cannot?
>>> 
>>> Develop database backed web applications in a fraction of the time ...
>>
>> ...that are notoriously unreliable.
> 
> You have *no* idea what you're talking about, but that's not really
> news, now is it? :)

Ruby's reputation has nothing to do with me.

> I predict you will not do this, but will instead continue to spout
> about that which you know little to nothing about. On the other hand,
> I would love to hear some success stories regarding FPLs in the web
> arena.

Google search, Wink and MSN Live AdCenter all use functional programming.
The last two use code in OCaml and F#, respectively.

> I have no religious affection for Ruby/Rails, it's just a great 
> tool currently.
> 
> * Notice the start time of 2007 in several of the processes
>   below! Others have been up since Jan, Feb, Mar, etc.
> 
> $ ps -ef | grep mong
> PID  STIME   CMD
> 23982 2007   /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
> production -p 8040 -a 127.0.0.1 -P log/mongrel.8040.pid
> 23985 2007   /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
> production -p 8041 -a 127.0.0.1 -P log/mongrel.8041.pid
> 21996 2007   /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
> production -p 8060 -a 127.0.0.1 -P log/mongrel.8060.pid
> 30457 Jan21  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
> production -p 8050 -a 127.0.0.1 -P log/mongrel.8050.pid
> 30460 Jan21  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
> production -p 8051 -a 127.0.0.1 -P log/mongrel.8051.pid
>  3626 Feb14  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
>  production -p 8020 -a 127.0.0.1 -P log/mongrel.8020.pid
>  3630 Feb14  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
>  production -p 8021 -a 127.0.0.1 -P log/mongrel.8021.pid
> 18010 Mar05  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
> production -p 8030 -a 127.0.0.1 -P log/mongrel.8030.pid
> 18013 Mar05  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
> production -p 8031 -a 127.0.0.1 -P log/mongrel.8031.pid
> 25470 May24  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
> production -p 8070 -a 127.0.0.1 -P log/mongrel.8070.pid

How intensively have those processes been used?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?u
From: Brian Adkins
Subject: Re: Alternatives
Date: 
Message-ID: <m2k5bbcyxw.fsf@gmail.com>
Jon Harrop <···@ffconsultancy.com> writes:

> Brian Adkins wrote:
>> Jon Harrop <···@ffconsultancy.com> writes:
>> 
>>> Brian Adkins wrote:
>>>> Jon Harrop <···@ffconsultancy.com> writes:
>>>>> What can Ruby do that modern FPLs cannot?
>>>> 
>>>> Develop database backed web applications in a fraction of the time ...
>>>
>>> ...that are notoriously unreliable.
>> 
>> You have *no* idea what you're talking about, but that's not really
>> news, now is it? :)
>
> Ruby's reputation has nothing to do with me.
>
>> I predict you will not do this, but will instead continue to spout
>> about that which you know little to nothing about. On the other hand,
>> I would love to hear some success stories regarding FPLs in the web
>> arena.

Prediction fulfilled. I appreciate that; now I can go back to ignoring
your posts.

> Google search, Wink and MSN Live AdCenter all use functional programming.
> The last two use code in OCaml and F#, respectively.

Yawn...

>> I have no religious affection for Ruby/Rails, it's just a great 
>> tool currently.
>> 
>> * Notice the start time of 2007 in several of the processes
>>   below! Others have been up since Jan, Feb, Mar, etc.
>> 
>> $ ps -ef | grep mong
>> PID  STIME   CMD
>> 23982 2007   /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
>> production -p 8040 -a 127.0.0.1 -P log/mongrel.8040.pid
>> 23985 2007   /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
>> production -p 8041 -a 127.0.0.1 -P log/mongrel.8041.pid
>> 21996 2007   /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
>> production -p 8060 -a 127.0.0.1 -P log/mongrel.8060.pid
>> 30457 Jan21  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
>> production -p 8050 -a 127.0.0.1 -P log/mongrel.8050.pid
>> 30460 Jan21  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
>> production -p 8051 -a 127.0.0.1 -P log/mongrel.8051.pid
>>  3626 Feb14  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
>>  production -p 8020 -a 127.0.0.1 -P log/mongrel.8020.pid
>>  3630 Feb14  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
>>  production -p 8021 -a 127.0.0.1 -P log/mongrel.8021.pid
>> 18010 Mar05  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
>> production -p 8030 -a 127.0.0.1 -P log/mongrel.8030.pid
>> 18013 Mar05  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
>> production -p 8031 -a 127.0.0.1 -P log/mongrel.8031.pid
>> 25470 May24  /usr/bin/ruby1.8 /usr/bin/mongrel_rails start -d -e
>> production -p 8070 -a 127.0.0.1 -P log/mongrel.8070.pid
>
> How intensively have those processes been used?

I asked you first. Show me your apps, and I'll be glad to continue the
dialog.
From: Brian Adkins
Subject: Re: Alternatives
Date: 
Message-ID: <m2abc7cxde.fsf@gmail.com>
Jon Harrop <···@ffconsultancy.com> writes:

> Google search, Wink and MSN Live AdCenter all use functional programming.
> The last two use code in OCaml and F#, respectively.

Google search uses primarily C++, Python & Java.

Wink is currently advertising for:
----------------------------------
Front End Web Developer
Senior Front-End Engineer
Senior Software Engineer
Senior Product Manager
Search Engine Developer
Senior Operations Engineer

Not *one* mentions OCaml. They are looking for PHP/JavaScript
programmers for the front end and Java/C++ programmers for the back
end though. Perl, Python & Ruby are favorably considered.

And wrt MSN Live AdCenter, get serious.
From: Jon Harrop
Subject: Re: Alternatives
Date: 
Message-ID: <cpydnVpy2vRq4YXUnZ2dnUVZ8oydnZ2d@posted.plusnet>
Brian Adkins wrote:
> Jon Harrop <···@ffconsultancy.com> writes:
>> Google search, Wink and MSN Live AdCenter all use functional programming.
>> The last two use code in OCaml and F#, respectively.
> 
> Google search uses primarily C++, Python & Java.

Map-reduce.

> Wink is currently advertising for:
> ----------------------------------
> Front End Web Developer
> Senior Front-End Engineer
> Senior Software Engineer
> Senior Product Manager
> Search Engine Developer
> Senior Operations Engineer
> 
> Not *one* mentions OCaml. They are looking for PHP/JavaScript
> programmers for the front end and Java/C++ programmers for the back
> end though. Perl, Python & Ruby are favorably considered.

The 120kLOC of OCaml code that underpins Wink was written by OCaml
consultant extraordinaire Gerd Stolpmann. Wink Technologies have also
kindly open sourced part of the OCaml infrastructure that was built to
support their enterprise web apps:

http://groups.google.com/group/fa.caml/browse_thread/thread/7bd2ae0a9415340d

http://groups.google.com/group/fa.caml/browse_thread/thread/b364c5890ed1fbc2

> And wrt MSN Live AdCenter, get serious.

Listen to Microsoft's AdCenter team:

"F# was absolutely integral to our success"

"We couldn’t have achieved this with any other tool given the constraints of
the task"

http://research.microsoft.com/fsharp/slides/FSharp-Intro-techdays-2008-02-11.pptx

This is not my domain so perhaps I am mistaken but I cannot find a single
billion dollar web app written in Ruby. I found "Enterprise Ruby" which is
a product designed to address Ruby's reliability problems but
their "Clients" page only says "Coming soon!".

If you want more examples of hugely successful network-intensive software
written in OCaml and F# look at distributed management software in
XenEnterprise (written in OCaml and bought by Citrix for $0.5bn) and
TruSkill in Halo 3 (written in F#, one of the most successful computer
games ever).

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?u
From: Brian Adkins
Subject: Re: Alternatives
Date: 
Message-ID: <m21vxjcqxn.fsf@gmail.com>
Jon Harrop <···@ffconsultancy.com> writes:

> Listen to Microsoft's AdCenter team:
>
> "F# was absolutely integral to our success"
>
> "We couldn’t have achieved this with any other tool given the constraints of
> the task"

F# marketing speak from Microsoft? How unusual. The latter statement
reveals more about their *team* and you (if you believe it) than the
technology.

> This is not my domain

Agreed

> so perhaps I am mistaken but I cannot find a single
> billion dollar web app written in Ruby.

So? For someone with a supposed Phd, you sorely lack a sense of
relevance.

Whether there is or isn't a "billion dollar web app written in
Ruby" is irrelevant to me. It has zero effect on my productivity or my
income.

(see "This is not my domain" above)

More to the point, if you believe that the use of a particular
technology in a billion dollar system is an indication that the
technology is the best tool for *any* system, you are naive and/or
ignorant.

> If you want more...

I don't.
From: Rainer Joswig
Subject: Re: Alternatives
Date: 
Message-ID: <joswig-2CEB7D.20523510112008@news-europe.giganews.com>
In article <··············@gmail.com>,
 Brian Adkins <···········@gmail.com> wrote:

> Jon Harrop <···@ffconsultancy.com> writes:
> 
> > Listen to Microsoft's AdCenter team:
> >
> > "F# was absolutely integral to our success"
> >
> > "We couldn’t have achieved this with any other tool given the constraints of
> > the task"
> 
> F# marketing speak from Microsoft? How unusual. The latter statement
> reveals more about their *team* and you (if you believe it) than the
> technology.
> 
> > This is not my domain
> 
> Agreed
> 
> > so perhaps I am mistaken but I cannot find a single
> > billion dollar web app written in Ruby.
> 
> So? For someone with a supposed Phd, you sorely lack a sense of
> relevance.
> 
> Whether there is or isn't a "billion dollar web app written in
> Ruby" is irrelevant to me. It has zero effect on my productivity or my
> income.
> 
> (see "This is not my domain" above)
> 
> More to the point, if you believe that the use of a particular
> technology in a billion dollar system is an indication that the
> technology is the best tool for *any* system, you are naive and/or
> ignorant.
> 
> > If you want more...
> 
> I don't.

Brian, you are going to be totally off-topic discussing Ruby vs. F#
on comp.lang.lisp. You might want to consider moving this discussion
to another newsgroup (comp.lang.ruby, ...) or to private conversation.

Please try to stay on-topic.

-- 
http://lispm.dyndns.org/
From: Brian Adkins
Subject: Re: Alternatives
Date: 
Message-ID: <m2wsfbbad1.fsf@gmail.com>
Rainer Joswig <······@lisp.de> writes:

> Brian, you are going to be totally off-topic discussing Ruby vs. F#
> on comp.lang.lisp. You might want to consider moving this discussion
> to another newsgroup (comp.lang.ruby, ...) or to private conversation.
>
> Please try to stay on-topic.

You're absolutely right - my apologies. Rather than the two options
you suggested, I think lowering his gnus score is best :)
From: Rainer Joswig
Subject: Re: Alternatives
Date: 
Message-ID: <joswig-8AC279.21243410112008@news-europe.giganews.com>
In article <··············@gmail.com>,
 Brian Adkins <···········@gmail.com> wrote:

> Rainer Joswig <······@lisp.de> writes:
> 
> > Brian, you are going to be totally off-topic discussing Ruby vs. F#
> > on comp.lang.lisp. You might want to consider moving this discussion
> > to another newsgroup (comp.lang.ruby, ...) or to private conversation.
> >
> > Please try to stay on-topic.
> 
> You're absolutely right - my apologies. Rather than the two options
> you suggested, I think lowering his gnus score is best :)


Thanks.

-- 
http://lispm.dyndns.org/
From: ······@gmail.com
Subject: Re: Alternatives
Date: 
Message-ID: <478cccb5-35ad-48fe-a89a-3d98892a977c@1g2000prd.googlegroups.com>
Rainer Joswig wrote:
> Brian, you are going to be totally off-topic discussing Ruby vs. F#
> on comp.lang.lisp. You might want to consider moving this discussion
> to another newsgroup (comp.lang.ruby, ...) or to private conversation.
>
> Please try to stay on-topic.

please note that your own post of trying to tell other's what to do,
is off topic.

in my 13 years of using newsgroup, i find that people like you
contribute the most to so-called newsgroup noise.

This class of people includes, all those troll-criers, those who tell
others about how it should be top-post/bottom-post, those who tell
others how they should quote their messages, those who says how
message should be ascii only, or plain text only, those who tell
others how lines shouldn't be some 80 char each... etc.

one aspect of verifying this is to check if newsgroup noise has
improved in the past decade. You'll find that it is not better, if not
worse.


For a collection of essays regarding these issues, see:

• Netiquette Anthropology
http://xahlee.org/Netiquette_dir/troll.html

Here's a plain text excerpt of one of the essay

------------------------------------
http://xahlee.org/UnixResource_dir/writ/troll_ignorance.html
On Ignoring Trolls

Xah Lee, 2002-09

Dear troll readers,

I resent your uncouth advice on dealing with trolls. To the average
intellects rampant here, the “gospel of ignorance” seems to be the
sage advice for dealing with trolls, but has anyone noticed that it is
a rhetorical advice and never worked?

Alas, it is never going to work, because, like corruption or thievery
or mistrust, it takes a single cell to thwart the whole system, where
society necessarily became law-laden, lock-decorated, and mistrustful,
and that is the nature of things.

I have been more and more viewing things from a Artificial Life↗ or
Dynamical Systems↗ point of view. Ignoring trolls is indeed a above-
average advice, because it is a form of education, of the probable
theorization of how troll operates. However, it is a bit valueless if
one do not understand the core of the problem, or never took time to
think and analyze the complete picture. There are indeed many
perspectives and questions to be asked on the subject of troll. For
example, why do trolls troll? What is their ilk, if any? What caused
their disposition? Apparently a simple first question like this
already calls for researches that likely no sociologist has undertook.
Immediately the question begs how do we define a “troll”. As with
“intelligence”, i'm sure it is elusive. Of the liberally or literally
endowed, one can probe on the writing styles of good trolls, such as
mine. Now, have you observed, that certain trolls tend to exhibit
phantasmagoric reconditeness in their produce? Say, the Erik Naggum
fellow (or Richard Stallman, Linus Torvald, Larry Wall), who has i'm
sure in various times been labeled a troll, and a big monstrous one at
that. As you can see, a clear definition of troll now becomes
painfully necessary. Just exactly who is troll and who is not? Is it
by intent or by result?

The issue of how to deal with trolls is in fact a stupid question not
realized. If one traces the origin of troll, she'll find that it is a
human phenomenon, not particular to newsgroups. The word trolling has
somewhat specific meaning in the beginning. According to the Jargon
File (http://catb.org/~esr/jargon/index.html), it originally means the
act of message posting that ensures fire, knowingly or not. Today, the
word troll is both verb and noun, and is applied loosely to any
outsider. If you don't like someone's manner, he is a troll. If you
don't like a gadfly, he is a troll. If you don't like a philosopher,
he is a troll. If you don't like a inquirer, he is a troll. If you
don't like a humorist, he is a troll. If you don't like a teacher, he
is a troll. If you don't like witches, they are, well, witches and
must be witch-hunted. Thusly, from weirdo to witch, from teacher to
philosopher, from gadfly to firebrand, from loner to gay, they are all
trolls online at your call. Quick spun the guild of killfilers and
troll-criers. Anyone who has contrariwise things to say or the manner
of saying it is a troll.

Before the internet, there are epithets of weirdo, geek, oddball,
screwball, crank, kook, crackpot, jester, queer, fruitcake, firebrand,
gadfly, hell-raiser, rabble-rouser, outsider, loner, desperado, witch.
Their owners exist everywhere, from your highschool to your workplace.
As you can see, trolls were not born with the internet. It was with us
from the dawn of time. It is of course oblivious to the mainstream.
After all, who like witches?

Now what about the process aspect? I'm sure all of you who read me
have at least ten years of living experience. Of these years, 2/3 of
the time your eyes must be open. So, you must have some inkling of the
general situation of human activities. In conglomerations, people do
all kinds of things; and throughout a life time, view changes,
behavior changes, life-style changes. What is it, that has every
online discussion groups plagued with the troll phenomenon? Of course
both troll and troll-dealers are responsible, but what made them tick?
Now coming back to our original sagacious advice of ignoring trolls,
why would it _never_ work? Could you now see the complexity of the
problem? From a process point of view, troll-criers feed trolls
because that made them both happy. Spatting and babbling is a inherent
part of discussion. Do you honest think there should or would be a
pure society filled with perfect logicians who have unilateral goals
and impeccable manners? Good trolls, such as myself, ENJOY trolling.
Troll-feeders, enjoy spitting on their targets. (it's a human need.)
Troll advisers, enjoy giving troll-dealing advice. Bleeding-hearts,
enjoy speaking out for so-called trolls. The more open a forum, the
more diversity. Nothing can be less natural.

I don't know if i should have some conclusive remarks about troll. You
see, i'm beginning to view things as a process, a ever changing
dynamic system, a Artificial Life system model. The human-simpletons
are just little insignificant entities in a environment of billions of
them, each effecting local happenings in a diverse and extreme complex
way with some simple but fuzzy needs, along which some emergent
phenomena arise, among them trolling.

PS i as a troll is rather special because i tend to put a final say on
things, in contrast with one-liner trolls i myself despise. (In a
sense i'm a anti-troll, untroll, or a atrocious atroll.) At first i
balked at being branded a troll. Now i revel it. I as a troll is
rather recent, beginning and getting worse about in 1998. I have been
using online discussion medium since 1990. Perhaps one day i'll write
“how i became a troll”. It is bound to be a tragedy.

    I'll find a day to massacre them all,
    And raze their faction and their family...
          —William Shakespeare, in Titus Andronicus

  Xah
∑ http://xahlee.org/

☄
From: Don Geddis
Subject: Re: Alternatives
Date: 
Message-ID: <878wrqm9a5.fsf@geddis.org>
·······@gmail.com" <······@gmail.com> wrote on Mon, 10 Nov 2008:
> Rainer Joswig wrote:
>> Brian, you are going to be totally off-topic discussing Ruby vs. F#
>> on comp.lang.lisp.
>> Please try to stay on-topic.
>
> please note that your own post of trying to tell other's what to do,
> is off topic.

So is your post, Mighty Xah!  Whereas I, on the other hand ... oh, damn it.
_______________________________________________________________________________
Don Geddis                  http://don.geddis.org/               ···@geddis.org
From: ······@gmail.com
Subject: Re: Alternatives
Date: 
Message-ID: <410eb1a5-e7aa-48e0-a659-2804c50b33e4@d10g2000pra.googlegroups.com>
Rainer Joswig wrote:
> >> Brian, you are going to be totally off-topic discussing Ruby vs. F#
> >> on comp.lang.lisp.
> >> Please try to stay on-topic.

Xah Lee wrote:
> > please note that your own post of trying to tell other's what to do,
> > is off topic.

Don Geddis wrote:
> So is your post, Mighty Xah!  Whereas I, on the other hand ... oh, damn it.

So, you did get my point?

For reasons on why i started to post off topic too, see:

• Why Can't You Be Normal?
http://xahlee.org/Netiquette_dir/why_cant_you_be_normal.html

• How Shall I Respond
http://xahlee.org/Netiquette_dir/how_shall_i_respond.html

  Xah
∑ http://xahlee.org/

☄
From: Jon Harrop
Subject: Re: Alternatives
Date: 
Message-ID: <Erydnevk4t2DL4XUnZ2dnUVZ8q2dnZ2d@posted.plusnet>
Rainer Joswig wrote:
> Brian, you are going to be totally off-topic discussing Ruby vs. F#
> on comp.lang.lisp. You might want to consider moving this discussion
> to another newsgroup (comp.lang.ruby, ...) or to private conversation.

Or we could ask whether Lisp is more widely used for significant web apps
than Ruby? I'd wager it probably is.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?u
From: Jon Harrop
Subject: Re: Alternatives
Date: 
Message-ID: <Erydnejk4t1ZLIXUnZ2dnUVZ8q2dnZ2d@posted.plusnet>
Brian Adkins wrote:
> Jon Harrop <···@ffconsultancy.com> writes:
>> Listen to Microsoft's AdCenter team:
>>
>> "F# was absolutely integral to our success"
>>
>> "We couldn’t have achieved this with any other tool given the constraints
>> of the task"
> 
> F# marketing speak from Microsoft? The latter statement reveals more about
> their team and you (if you believe it) than the technology.

I suppose you think Microsoft are secretly using Ruby but giving F# all the
credit?

>> This is not my domain
> 
> Agreed

But you claim this is your domain and, yet, I have provided infinitely more
examples than you have. What can this mean?

>> so perhaps I am mistaken but I cannot find a single billion dollar web
>> app written in Ruby. 
>
> So? For someone with a supposed Phd, you sorely lack a sense of
> relevance.

You challenged me to provide "some success stories regarding FPLs in the web
arena". If you cannot handle the facts, you should not have asked for them.

> Whether there is or isn't a "billion dollar web app written in
> Ruby" is irrelevant to me...

In other words, you have no idea.

> More to the point, if you believe that the use of a particular
> technology in a billion dollar system is an indication that the
> technology is the best tool for *any* system, you are naive and/or
> ignorant.

Strawman argument.

>> If you want more...
> 
> I don't.

I'm not surprised.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?u
From: Kaz Kylheku
Subject: Re: Alternatives
Date: 
Message-ID: <20081110122214.705@gmail.com>
On 2008-11-10, Jon Harrop <···@ffconsultancy.com> wrote:
> Brian Adkins wrote:
>> Jon Harrop <···@ffconsultancy.com> writes:
>>> Google search, Wink and MSN Live AdCenter all use functional programming.
>>> The last two use code in OCaml and F#, respectively.
>> 
>> Google search uses primarily C++, Python & Java.
>
> Map-reduce. 

Note how this is not called ``map-fold-left'' or ``map-inject''. :)

> Listen to Microsoft's AdCenter team:
>
> "F# was absolutely integral to our success"
>
> "We couldn?t have achieved this with any other tool given the constraints of
> the task"

Couldn?t have done what? Replaced random apostrophes with question marks?
From: Matthias Buelow
Subject: Re: Alternatives
Date: 
Message-ID: <6nk4adFm8040U1@mid.dfncis.de>
Jon Harrop wrote:
> What problems can Lisp solve more easily than F#, OCaml, Haskell, Erlang,
> Scala etc?

Is this question supposed to have anything to do with my posting or have
you just picked the nearest one to your mouse cursor to post it to?
From: Jon Harrop
Subject: Re: Alternatives
Date: 
Message-ID: <p7ednY1O7ea7d4nUnZ2dnUVZ8s_inZ2d@posted.plusnet>
Matthias Buelow wrote:
> Jon Harrop wrote:
>> What problems can Lisp solve more easily than F#, OCaml, Haskell, Erlang,
>> Scala etc?
> 
> Is this question supposed to have anything to do with my posting or have
> you just picked the nearest one to your mouse cursor to post it to?

You stated "if there is a language that does everything Lisp can
do just as well...I haven't seen it yet". Either you haven't seen because
you haven't looked, or you looked and found tasks better suited to Lisp. I
optimistically assumed the latter and asked what tasks you thought were
better suited to Lisp.

So which is it? Have you not done the study or do you have results to share?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?u
From: Jon Harrop
Subject: Re: Alternatives
Date: 
Message-ID: <uqadneGdMYDpfInUnZ2dnUVZ8q7inZ2d@posted.plusnet>
William James wrote:
> Writing some stuff in Paul Graham's _On Lisp_ in Ruby.

Some literal translations to OCaml/F#:

> =begin
> 
> (defun our-remove-if (fn lst)
>   (if (null lst)
>       nil
>     (if (funcall fn (car lst))
>       (our-remove-if fn (cdr lst))
>       (cons (car lst) (our-remove-if fn (cdr lst))))))
> 
> =end
> 
> def remove_if list
>   list.inject([]){|col,elt|
>     col << elt unless yield elt
>     col }
> end

let remove_if f list =
  [ for elt in list do
      if not(f elt) then yield elt ]

> 2.4 Functions as Properties
> 
> (defun behave (animal)
>   (funcall (get animal 'behavior)))
> 
> (setf (get 'dog 'behavior)
>       #'(lambda ()
> (wag-tail)
> (bark)))
> 
> =end
> 
> $behaviors = {}
> 
> def behave animal
>   $behaviors[ animal ].call
> end

let behave _ = invalid_arg "behave"

> $behaviors[ :dog ] = proc{ wag_tail; bark }

let behave = function
  | `Dog -> wag_tail(); bark()
  | animal -> behave animal

> 2.6 Closures
> 
> (defun make-adderb (n)
>   #'(lambda (x &optional change)
>       (if change
> (setq n x)
> (+ x n))))
> 
> =end
> 
> def make_adderb n
>   proc{|x,*change|
>     return x + n  if change.empty?
>     n = x }
> end
> 
> addx = make_adderb( 1 )
> 
> p addx[ 8 ]
> addx[ 99, true ]
> p addx[ 8 ]

let make_adderb n ?(change=false) x =
  if change then n := x;
  !n + x

let addx = make_adderb(ref 1)

addx 8
addx ~change:true 99
addx 8

> It's even possible to return a group of closures which share the
> same data objects. Figure 2.1 contains a function which creates
> primitive databases. It takes an assoc-list (db), and returns a
> list of three closures which query, add, and delete entries,
> respectively.
> 
> Each call to make-dbms makes a new database--a new set of
> functions closed over their own shared copy of an assoc-list.
> 
>> (setq cities (make-dbms '((boston . us) (paris . france))))
> (#<Interpreted-Function 8022E7>
> #<Interpreted-Function 802317>
> #<Interpreted-Function 802347>)
> 
> (defun make-dbms (db)
>   (list
>    #'(lambda (key)
>        (cdr (assoc key db)))
>    #'(lambda (key val)
>        (push (cons key val) db)
>        key)
>    #'(lambda (key)
>        (setf db (delete key db :key #'car))
>        key)))

That's a really awful example but here you go:

let make_dbms db =
  object
    method find key = List.assoc key !db
    method add key value = db := (key, value) :: !db
    method remove key = db := List.filter (fun (k, _) -> k <> key) !db
  end

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?u