Why I don't use Ruby.

S

Sean Russell

James Britt said:
For me, the question is whether Ruby allows one to do proper functional
programming, not that it forces one to do so.

Actually, I'm going to backtrack. By the definition of FP that I
chose -- no assignments, no side effects -- I'll agree that it
possible to do functional programming in Ruby. Although this still
doesn't make Ruby a functional programming language, I'd agree that it
is enough to satisfy the "functional programming" clause.

--- SER
 
S

Sean Russell

Sean O'Dell said:
You can have variables in a functional language, but what you can't have are
globals that act statefully, causing any functions you write to return
different values when passed the same parameter values. You can have
(pseudocoded):

function myfunc(a)
b = anotherfunc(a)
return sin(b)
end

Technically, in a purely functional language, you also shouldn't be
able to reassign a new value to 'b', once you set it. This has
nothing to do with the scope, and indeed, there are no such things as
"variables" in *purely* functional languages, because they shouldn't
vary. What you can have is aliases for values. Haskell, for example,
allows you to use "let" and "where" to assign values to aliases that
look alot like variables, but are immutable.

--- SER
 
M

Mikael Brockman

Sean O'Dell said:
I don't remember closures from my LISP days, but perhaps that's a memory
issue.

Ancient Lisps, such as Emacs Lisp, lack closures. They have anonymous
functions, but they're dynamically scoped. Dynamical scoping is
occasionally useful, but it mostly sucks. Non-ancient Lisps, starting
with Scheme, use lexical scoping.
I/O has always been an exception, but I think you have to have
exceptions to get variance into the program and I/O is a common programming
paradigm and a great way to introduce variance.

Note that there are purely functional languages with I/O: Haskell,
Clean, Miranda, and probably more.

mikael
 
Z

zuzu

Technically, in a purely functional language, you also shouldn't be
able to reassign a new value to 'b', once you set it. This has
nothing to do with the scope, and indeed, there are no such things as
"variables" in *purely* functional languages, because they shouldn't
vary. What you can have is aliases for values. Haskell, for example,
allows you to use "let" and "where" to assign values to aliases that
look alot like variables, but are immutable.

--- SER

how are variables in ruby "mutable" then? ruby assignment merely
labels objects.

a = 42
a = 64

here, ruby created a Fixnum object with a return value of 42, and
assigned it the label "a".
next, ruby creates another Fixnum object, this one with a return value
of 64, and points the label "a" to it instead.
the Fixnum object with a value of 42 still exists... but if it goes
unused the garbage collector will eventually stroll along and trash
it.

i should double-check this, but i think ruby allows for anonymous
(unlabeled) objects just as it allows for anonymous functions. but
referencing such objects would require tricks of introspection and
asking objects "who's willing to reply to this message?"

-z
 
L

Lennon Day-Reynolds

Ruby objects are mutable in the sense that you can do the following:

a = []
a.add(1)

The internal state of 'a' has been changed, which is a no-no in
functional languages. Of course, most of them do so anyway for tasks
like I/O, and use some sort of abstraction (which often looks eerily
like an 'object') to hide those side-effects from the programmer.

Lennon
 
Z

Zach Dennis

Take the following code (this is conceptual thought, not working code):

class MyObject
def initialize
@myobj = MyEventHandler.new();
@myobj.event(){ |evt|
puts( evt.getID() ); }
end
end

m = MyObject.new();


I would like to get rid of the { |evt| ... } block and instead pass in a
proc created by an outside method. I would like to do this to clean up my
code because my proc is of decent size. Any ideas? Thanks,

Zach
 
J

Joel VanderWerf

Zach said:
Take the following code (this is conceptual thought, not working code):

class MyObject
def initialize
@myobj = MyEventHandler.new();
@myobj.event(){ |evt|
puts( evt.getID() ); }
block = ...
@myobj.event(&block)
 
S

Sean O'Dell

Technically, in a purely functional language, you also shouldn't be
able to reassign a new value to 'b', once you set it. This has
nothing to do with the scope, and indeed, there are no such things as
"variables" in *purely* functional languages, because they shouldn't
vary. What you can have is aliases for values. Haskell, for example,
allows you to use "let" and "where" to assign values to aliases that
look alot like variables, but are immutable.

I think that's an implementation feature, not a fundamental property of a
functional language. There's no reason a functional language can't have use
memory space lexically any way it sees fit. The outcome is the same: nothing
stateful affects function performance, so you get consistent return values
for your input.

I think those sorts of properties are assigned after observing existing
implementations, and don't really describe the core nature of a "functional
language."

If I implemented a language that was functional in nature, except that, within
a function you could overwrite your own variable values, programmers using
the language are virtually unaffected. They simply have to treat their own
variables slightly differently, but all the benefits of functional
programming are unchanged.

Sean O'Dell
 
S

Sean O'Dell

Ruby objects are mutable in the sense that you can do the following:

a = []
a.add(1)

The internal state of 'a' has been changed, which is a no-no in
functional languages. Of course, most of them do so anyway for tasks
like I/O, and use some sort of abstraction (which often looks eerily
like an 'object') to hide those side-effects from the programmer.

You can modify values, as long as the value isn't a global (stateful data).
The key is that the function has to represent the modification, so that when
you call it with a given set of values, it always does the same thing.

You can say:

function
a = array
add(a, 1)
end

...because anytime you call add, it does the same thing to the array you give
it, and your function always does the same thing. But you can't do this:

$a = array

function
add($a, 1)
end

...because your function now uses a variable which can be modified by other
functions, so if you called function more than once, it's possible to get two
different results. Functional programming doesn't allow this, and this is
really, I think, the very heart of functional programming.

Sean O'Dell
 
Z

zuzu

Ruby objects are mutable in the sense that you can do the following:

a = []
a.add(1)

The internal state of 'a' has been changed, which is a no-no in
functional languages. Of course, most of them do so anyway for tasks
like I/O, and use some sort of abstraction (which often looks eerily
like an 'object') to hide those side-effects from the programmer.

Lennon

hmm... on the surface i understand and agree.

however, here's my line of thought: you are referring to the internal
state of the _object_, treating it as "data". this is a quite common
model, and i'm not throwing it out wholesale. however, objects are
actually a unique beast; the whole is greater than the sum of its data
and functions. for sake of argument, let us *not* think of objects as
data. the function .add(1) simply transforms the return function of
the array...

my hypothesis here is that referential transparency (statelessness)
attempts to resolve the problem of the data in memory values from
changing. for example, in C:

int value = 47; /* a memory space of size integer is defined, and a
data value of "47" is stored inside that memory. tell the compiler
that all references to "value" point to that memory address within
this scope. */
value = 52; // null the data in the memory address at "value" and
write inside it the value of "52"

this seems like a bad thing because who knows why that memory address
sometimes will return "47" and othertimes will return "52" without
actually stepping through the program. and even then, any programmer
will have to guess as to what the original programmer's intentions
were in doing so. hence people like referential transparency because
it says "all values simply represent the process of other processes of
some original value." (of course, that original value is where
referential transparency breaks down, such as with I/O, because again
only the users knows why the hell they enter the data they do when
they do.) the nice thing about FP is that it's timeless; you don't
need nor care about when, just how.

from this point of view, does an object in a pure OO environment
constitute an arbitrary change in a memory value, or can the process
be reversed without using a clocktick as a reference? if the process
can so be reversed, i would argue something immutable / referentially
transparent is going on, at least within "ruby space".

-z
 
S

Sean O'Dell

Take the following code (this is conceptual thought, not working code):

class MyObject
def initialize
@myobj = MyEventHandler.new();
@myobj.event(){ |evt|
puts( evt.getID() ); }
end
end

m = MyObject.new();


I would like to get rid of the { |evt| ... } block and instead pass in a
proc created by an outside method. I would like to do this to clean up my
code because my proc is of decent size. Any ideas? Thanks,

Something like this:

class MyObject
def initialize(&handler)
@myobj = MyEventHandler.new();
@myobj.event(handler)
end
end

handler = proc { |evt|
puts( evt.getID() ); }

m = MyObject.new(handler);



Sean O'Dell
 
S

Sean Russell

gabriele renzi said:
In this view you can consider lisp as having one object (the list) and
some basic methods to work on that (car/cdr). If we had method call in
ruby like:

Once again, if you remove the semantic difference between a "method"
and a "function", you render both useless. A method is a message sent
to an object, which then reacts and exhibits some behavior. A
function is something that operates on some (optional) argument -- the
functionality is in no way bound to the object. One would say that
given:

Ruby:
class Obj
def foo ; end
end

Haskell:
foo :: Obj

In Ruby, Obj *knows* about, and is intimate with, foo, which in turn
knows about Obj[1]. In Haskell, foo() knows about Obj, but Obj knows
nothing about foo.

Pure functional languages violate your statement:
if you consider that an Object is some state+some data+some methods

because (a) pure functional languages have no state, and (b) there are
no objects in the classical sense; just primatives, which have no
associated behaviors. This is one of the beauties of functional
languages: you're always working with primatives. Ultimately,
everything in an FP is a pair, a tuple, a string, or a number of some
sort.


[1] The exception to this are mixins, which are generally ignorant of
the objects on which they are operating.

--- SER
 
S

Sean Russell

Mikael Brockman said:
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.
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.
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.
They are both operations on an object. The matter in which you choose

They're operations on a primative: 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.
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.

--- SER
 
J

James Britt

Sean said:
Technically, in a purely functional language, you also shouldn't be
able to reassign a new value to 'b', once you set it. This has
nothing to do with the scope, and indeed, there are no such things as
"variables" in *purely* functional languages, because they shouldn't
vary. What you can have is aliases for values. Haskell, for example,
allows you to use "let" and "where" to assign values to aliases that
look alot like variables, but are immutable.

--- SER
Indeed. People learning XSLT are often bit by the use of the word
'variable' when used to refer to things that in fact may not vary. One
then has to learn new ways of accumulating values, or incrementing
counters, or rewriting code where one might have otherwise used variable
variables.

James
 
G

gabriele renzi

il Sat, 10 Jul 2004 05:32:59 +0900, zuzu <[email protected]> ha
scritto::

how are variables in ruby "mutable" then? ruby assignment merely
labels objects.

a = 42
a = 64

ruby is not a pure functional language, and actually allows this.
In pure FP you have the ability to actually replace every expression
with itìs actual value, this is impossible if an expression (i.e. a
variable name) can be changed.
 
M

Mikael Brockman

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.


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.
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'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.
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
 
G

gabriele renzi

il Sat, 10 Jul 2004 06:18:56 +0900, "Sean O'Dell" <[email protected]>
ha scritto::

..
I think that's an implementation feature, not a fundamental property of a
functional language. There's no reason a functional language can't have use
memory space lexically any way it sees fit. The outcome is the same: nothing
stateful affects function performance, so you get consistent return values
for your input.

no, referential transparency seem to be at the core of the definition
of pure OO. I'm not an expert anyway, but you could like to take a
look at a recent thread in comp.lang.smalltalk about this, look for
"is smalltalk a functional language".

I think those sorts of properties are assigned after observing existing
implementations, and don't really describe the core nature of a "functional
language."

If I implemented a language that was functional in nature, except that, within
a function you could overwrite your own variable values, programmers using
the language are virtually unaffected. They simply have to treat their own
variables slightly differently, but all the benefits of functional
programming are unchanged.


you won't have the ability to handle the code with the 'sobstitution
model' that is, I think, the model commonly used to describe FP
 
M

Martin DeMello

Sean Russell said:
Once again, if you remove the semantic difference between a "method"
and a "function", you render both useless. A method is a message sent
to an object, which then reacts and exhibits some behavior. A
function is something that operates on some (optional) argument -- the
functionality is in no way bound to the object. One would say that
given:

Ruby:
class Obj
def foo ; end
end

Haskell:
foo :: Obj

In Ruby, Obj *knows* about, and is intimate with, foo, which in turn
knows about Obj[1]. In Haskell, foo() knows about Obj, but Obj knows
nothing about foo.

I'd say that the difference between a function and a method is that a
method has a distinguished argument, 'this', *within whose scope it
runs*. It's not a matter of Obj knowing about foo, or foo knowing about
Obj, it's a matter of Obj defining its own personal scope within which
foo is run.

martin
 
M

Mikael Brockman

Martin DeMello said:
Sean Russell said:
Once again, if you remove the semantic difference between a "method"
and a "function", you render both useless. A method is a message sent
to an object, which then reacts and exhibits some behavior. A
function is something that operates on some (optional) argument -- the
functionality is in no way bound to the object. One would say that
given:

Ruby:
class Obj
def foo ; end
end

Haskell:
foo :: Obj

In Ruby, Obj *knows* about, and is intimate with, foo, which in turn
knows about Obj[1]. In Haskell, foo() knows about Obj, but Obj knows
nothing about foo.

I'd say that the difference between a function and a method is that a
method has a distinguished argument, 'this', *within whose scope it
runs*. It's not a matter of Obj knowing about foo, or foo knowing about
Obj, it's a matter of Obj defining its own personal scope within which
foo is run.

At least one standard's committee disagrees with you; ANSI Common Lisp's
methods aren't like that.

The concept of object orientation is like Wittgenstein's `game' --
intuitively understood by many, properly captured in words by none.

mikael
 
S

Sean Russell

zuzu said:
how are variables in ruby "mutable" then? ruby assignment merely
labels objects.

a = "immutable string"
b = a
a.gsub!( /^im/, "" )
puts a # => "mutable string"
puts b # => "mutable string"
a = 42
a = 64

Besides the previous example, you're re-assigning a value to "a".

--- SER
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top