ser / germane-software.com (Sean Russell) writes:

> Mikael Brockman <phubuh / phubuh.org> wrote in message
> news:<87n02a19ku.fsf / phubuh.org>...
>> No.  I claim that it's possible to write functional code in any
>> language, provided it is sufficiently expressive.  I don't claim Ruby
>> is a functional language.
>
> I cede this point.  You can write functional code in Ruby by simply
> avoiding all side-effects.  If you can avoid assignments, even better.
> And I have to apologise; I knew I was straying off the original topic,
> which was whether or not you could code *functionally* with Ruby, not
> whether or not Ruby was a functional language.  I tried to make that
> caveat at one point, but I think I failed.
>
>> > There *are* good, useful definitions of what constitutes a
>> > functional languages, and Ruby does not match the criteria for most
>> > of them.  Probably the most fundamental of all criteria is that the
>> > language does not allow side-effects, such as assignment.
>> 
>> I think that's a very poor criteria, since most language considered
>> to
>
> You may think it is poor, but it is about the *only* hard definition
> of a functional language that exists.  Yes, most "functional"
> languages violate this in one way or another, but they all *try* to
> adhere to it as much as possible.  They are functional languages
> inasmuch as Java or Python is an OO language.  Java still has
> primatives, so can't be considered a "pure" OO language; it justifies
> violating this rule for speed reasons.  Many functional languages
> violate the side-effects rule because IO is a pain in the arse without
> support for side-effects, but it is still a violation of the rule.

To resist succumbing to Layne's law, I'll accept your definition.

>> Arithmetic is indeed implemented as method calls, but that's an
>> implementation detail.  And that embodies my fundamental point:
>> paradigms are phenomena in the heads of the programmers, not
>> properties of the language.
>
> I'd disagree with you here, in as much as languages are the
> personification of paradigms, and if you can't classify a language by
> its paradigms, you might as well give up on classification.  And this,
> I believe, is silly, because this sort of classification is very
> useful.  There are times to use OO, there are times to use FP, and
> there are even times to use PP -- and the best language to use in each
> case is one that specializes in that particular paradigm.

I don't want to give up on classification.  I'd define a language of
paradigm X as a language that encourages one to think in paradigm X and
write programs of paradigm X.  If you're stubborn, or if you really need
to, you can use a language of paradigm X while thinking in paradigm Y,
but that's usually painful.

Ruby encourages one to think object orientedly in the large, but also
functionally in the small.  The programs that result in following the
grain of the language have object-oriented designs, and many of their
methods are written as functional pipelines.

So I'd say Ruby is a mostly-object-but-also-functional language.  But if
one wants to write Scheme code in Ruby, one is unstoppable.  One can
even make it look mostly like regular Ruby code, as long as one *thinks*
functionally.

>> They are both operations on an object.  The matter in which you
>> choose
>
> They're operations on a primitive: a list.  A list isn't an object in
> the OO sense.  You can call it an object, but it has no behavior, and
> it knows nothing about car and cdr.

It does have behavior.  When I car it, it gives me its first element;
when I cdr it, it gives me its tail; when I cons it with some other
item, it gives me a new list.  That's the behavior of a list as I see
it.  There's no concrete binding between the data and its operations,
but in my head, they're bundled up.

>> to see that is in your head.  You choose to see CAR and CDR as
>> non-methods; I can just as easily choose to see them as methods.
>
> Again, I point out that, to OO purists, calling a method is sending a
> message to an object, which reacts.  I don't see how you can claim
> that car or cdr, in any way shape or form, communicate with the list
> they're operating on.  They take information from, but never give
> information to.  They are not messages, and, therefore, not methods.

Here's an explicitly object-oriented definition of cons pairs:

| class Cons
|   def initialize (car, cdr)
|     @car, @cdr = car, cdr
|   end
| 
|   def car
|     @car
|   end
| 
|   def cdr
|     @cdr
|   end
| 
|   def cons (x)
|     Cons.new x, self
|   end
| end

Its methods, too, only take information.  They don't really
`communicate' with the object, either.  They just grab a variable and
shoot it right back.

| (define (cons a b)
|   (lambda (f)
|     (f a b)))
| 
| (define (car c)
|   (c (lambda (a b) a)))
| 
| (define (cdr c)
|   (c (lambda (a b) b)))

The only difference is that in the explicitly OO version, the OO nature
is codified.  Think about that, and compare it to static typing vs
dynamic typing.  I could say that the type of the argument to car is a
cons pair, but the program doesn't say anything concrete about `types'.
That's why someone said `All types are in the programmers' heads'.

  mikael