[BLOG] A different perspective on Ruby.

J

Joe Van Dyk

=20
Hmmm, prefix, postfix, or infix? Functional or object-oriented?
These are bottomless questions.
=20
One justification for sqrt(5) would be that "sqrt", works on more than
one class of objects (Fixnum, Bignum, Rational, etc). So does "abs" for
that matter, and I'm not crazy about 5.abs. As a method, sqrt would
have to be defined in every applicable class, either with new code or as
an included module. This spreads the definition out, which complicates
maintainence.
=20
Another reason is that the prefix style, sqrt(5), is somewhat closer to
the typical mathematical notation. I can't think of any unary
mathematical operations that are naturally postfix, unless you count
C++'s post-decrement and post-increment.
=20
This is all just criticism of library design, which is very much a
matter of style and taste. The "standard" library could stand some
attention to smooth out these style bumps, possibly by allowing either
prefix or postfix styles whenever possible. Then questions of style
would be forwarded to the programmer.

I think the guy's point was "omg, they said everything was an object!=20
"hi".length =3D=3D 2 and stuff! But not sqrt(5)! Like, omg you farking
farktards are farking dumb! So much for POLS!!!1"
 
J

johng

|"It's 5.abs for absolute value, but Math.sqrt(5) for square root."
|
|Good point. That bugs me too. abs is a *function*, not logically a
|method.
The definition of abs is not questionable; it returns self, negated
when self is negative, for all numeric value. On the other hand,
natural sqrt() may return float or integer, or something else. That's
the reason for sqrt() being a function in Math module.

I may be missing something, but why does it matter what the return
type is?

What is wrong with always returning a float just like Math.sqrt does?

-alternatively, although I prefer the first option-

Why couldn't the implementation of sqrt "cast" the result to an
instance
of the current self's type? So, if you ask an integer to sqrt, you get
an
integer back?

Like I said, maybe I am missing something, but it seems that
sqrt is a verb applied to numbers.

John.
 
E

ES

Le 27/5/2005 said:
|"It's 5.abs for absolute value, but Math.sqrt(5) for square root."
|
|Good point. That bugs me too. abs is a *function*, not logically a
|method.


I may be missing something, but why does it matter what the return
type is?

What is wrong with always returning a float just like Math.sqrt does?

-alternatively, although I prefer the first option-

Why couldn't the implementation of sqrt "cast" the result to an
instance
of the current self's type? So, if you ask an integer to sqrt, you get
an
integer back?

Like I said, maybe I am missing something, but it seems that
sqrt is a verb applied to numbers.

Well, essentially this is all that is required:

irb(main):018:0> class Fixnum
irb(main):019:1> def method_missing(sym, *args, &block)
irb(main):020:2> return Math.send sym, self, *args, &block
irb(main):021:2> end
irb(main):022:1> end
=3D> nil
irb(main):023:0> 100.sqrt
=3D> 10.0
irb(main):024:0>

It is obviously not very robust but it took about eight seconds
to implement.

E
 
L

Logan Capaldo

On 5/26/05 said:
Another reason is that the prefix style, sqrt(5), is somewhat closer to
the typical mathematical notation. I can't think of any unary
mathematical operations that are naturally postfix, unless you count
C++'s post-decrement and post-increment.

Just to get offtopic, factorial is one.
 
J

Jim Weirich

I can't think of any unary
mathematical operations that are naturally postfix,

Factorial !
One justification for sqrt(5) would be that "sqrt", works on more than
one class of objects (Fixnum, Bignum, Rational, etc).  So does "abs" for
that matter, and I'm not crazy about 5.abs.  As a method, sqrt would
have to be defined in every applicable class, either with new code or as
an included module.  This spreads the definition out, which complicates
maintainence.

Actually, I think you have this backwards. It would be much more convenient
to have sqrt as a member function in order to implement it differently in
different classes. Numeric could hold the standard definition, but if a
subclass needed to redefine it, it could do so with little effort.

Look at the code in complex.rb to see how it handles enhancing sqrt to handle
complex numbers:

alias sqrt! sqrt
# ...
def sqrt(z)
if Complex.generic?(z)
if z >= 0
sqrt!(z)
else
Complex(0,sqrt!(-z))
end
else
if z.image < 0
sqrt(z.conjugate).conjugate
else
r = z.abs
x = z.real
Complex( sqrt!((r+x)/2), sqrt!((r-x)/2) )
end
end
end

If sqrt were a member function, the generic test could be completely avoided.
Although the original sqrt would still have to be enhanced to handle negative
values, it would only have to test for < 0, rather than the rather fragile
test for Integer, Float and Rational.
 
M

Martin DeMello

why the lucky stiff said:
And where do you stand in regard to .succ?

succ is definitely a method rather than a function, IMO - I can't see
myself using it in a mathematical rather than a 'programming' context.

martin
 
R

Robert Klemme

Glenn said:
+1

Hmmm, prefix, postfix, or infix? Functional or object-oriented?
These are bottomless questions.

One justification for sqrt(5) would be that "sqrt", works on more than
one class of objects (Fixnum, Bignum, Rational, etc). So does "abs"
for that matter, and I'm not crazy about 5.abs. As a method, sqrt
would have to be defined in every applicable class, either with new
code or as an included module. This spreads the definition out,
which complicates maintainence.

This is not true, for two reasons:

First, there is indeed a place to put functions that have the same
implementation for all numeric types - so it does not have to spread:
Fixnum.ancestors => [Fixnum, Integer, Precision, Numeric, Comparable, Object, Kernel]
Bignum.ancestors => [Bignum, Integer, Precision, Numeric, Comparable, Object, Kernel]
Float.ancestors
=> [Float, Precision, Numeric, Comparable, Object, Kernel]
Numeric}
Bignum
Float
Fixnum
Integer
Numeric

Second, it's most likely that you actually *want* different
implementations for performance and optimization reasons (see the recently
discovered bug with exponentiation).
Another reason is that the prefix style, sqrt(5), is somewhat closer
to the typical mathematical notation. I can't think of any unary
mathematical operations that are naturally postfix, unless you count
C++'s post-decrement and post-increment.

Well, this can remain in place as a simple forward to not break
compatibility

def Math.sqrt(n) n.sqrt end
This is all just criticism of library design, which is very much a
matter of style and taste. The "standard" library could stand some
attention to smooth out these style bumps, possibly by allowing either
prefix or postfix styles whenever possible. Then questions of style
would be forwarded to the programmer.

True.

Kind regards

robert
 
G

Gene Tani

The rant-writer likes ruby. From his python rant:
===========8<
Though, I must admit, Python has the least inconsistencies of any
language I've ever used, excepting maybe Ruby.
 
G

Glenn Parker

Jim said:
Factorial !

Indeed, but this may be the exception that proves the rule.
Actually, I think you have this backwards. It would be much more convenient
to have sqrt as a member function in order to implement it differently in
different classes. Numeric could hold the standard definition, but if a
subclass needed to redefine it, it could do so with little effort.

There is no backwards or forwards here.

The world is full of code and data, and we prefer languages that give us
flexibility in how we choose to organize these things. There are always
conflicting goals that we, as designers, must reconcile one way or
another. The main conflict I see is the beauty/elegance/clarity of a
library's internal organization versus the beauty/elegance/clarity of
the code where that library is used. I tend to favor the latter, on the
theory that consumers normally shouldn't have to care too much about the
internals, but it's a tug-of-war.
 
J

Jim Weirich

Glenn Parker said:
There is no backwards or forwards here.

As long as we are only talking asthetics, then I agree that either choice
is co-equal, neither is backwards or forwards. In fact, I would tend to
agree that sqrt(n) is more asthetically pleasing than n.sqrt.

However ...

But if we are talking maintenance (cf. "[sqrt as a method] spreads the
definition out, which complicates maintainence"), then I think it is clear
that the method implementation is (1) no more "spread out" that the
current implementation, (2) simpler to extend to for new types (e.g.
Complex). It is the stand-alone function (not method) implementation that
complicates maintainence. That is the part I thought was backwards.
 
J

Jonas Hartmann

Gene said:
The rant-writer likes ruby. From his python rant:
===========8<
Though, I must admit, Python has the least inconsistencies of any
language I've ever used, excepting maybe Ruby.

actually he seems to like both languages cause in the ruby rant he
refers to python and in the python rant he refers to ruby.

his choice of language is bad, some examples are stupid, and even me,
being quite a newbish, wonders why he rants about that, but some
examples are really good.

btw. isnt there a way to extend integer, fixnum and bignum with .sqrt ?

(just adding the method .sqrt arg, that again runs the sqrt method
which is possibly part of Kernel or Object, I am just guessing - is
that right?)

greetings

Jonas
 
J

Jonas Hartmann

Jim said:
Glenn Parker said:



As long as we are only talking asthetics, then I agree that either choice
is co-equal, neither is backwards or forwards. In fact, I would tend to
agree that sqrt(n) is more asthetically pleasing than n.sqrt.
oh no! its not at all!

n is an Integer object and sqrt is a method on that object so it must
be n.sqrt - you could as well implement the third square root of 8 by
typing 8.sqrt 3 (I am not such a big math-guy... so maybe you could
just send over the whole exponent - 8^(1/2) => 8.sqrt is equal to
8.sqrt .5 is equal to 8.sqrt(0.5) is equal to 8.sqrt(1/2) and so on...
well just my ideas on sqrt method - exuse me if its bs ;-(
However ...

But if we are talking maintenance (cf. "[sqrt as a method] spreads the
definition out, which complicates maintainence"), then I think it is clear
that the method implementation is (1) no more "spread out" that the
current implementation, (2) simpler to extend to for new types (e.g.
Complex). It is the stand-alone function (not method) implementation that
complicates maintainence. That is the part I thought was backwards.
 
J

Jonas Hartmann

Florian said:
What about 5.-@ ?

what should that do?

5 substract at?

(I read some parts of Why's and I cannot read out your example to get
what it does...)
 
E

ES

Le 27/5/2005 said:
actually he seems to like both languages cause in the ruby rant he
refers to python and in the python rant he refers to ruby.

his choice of language is bad, some examples are stupid, and even me,
being quite a newbish, wonders why he rants about that, but some
examples are really good.

btw. isnt there a way to extend integer, fixnum and bignum with .sqrt ?

(just adding the method .sqrt arg, that again runs the sqrt method
which is possibly part of Kernel or Object, I am just guessing - is
that right?)

Yes, I already posted this. Something like this is all
that is needed (untested):

# Slightly more robust
class Numeric
alias_method :_old_mm, :method_missing

def method_missing(symbol, *args, &block)
Math.send symbol, self, *args, &block

rescue NoMethodError
_old_mm symbol, *args, &block
end # method_missing
end # Numeric
greetings

Jonas

E
 
C

Christoph

Glenn said:
Another reason is that the prefix style, sqrt(5), is somewhat closer
to the typical mathematical notation. I can't think of any unary
mathematical operations that are naturally postfix, unless you count
C++'s post-decrement and post-increment.

Pretty much all non alphabetical unitary operators are typically
used in postfix notation (at least if "upper and lower postfix"
counts as post fix too) and the usage of these operators is
actually quite common in some specialized areas of math.


/Christoph
 
J

Jason Foreman

[...]
n is an Integer object and sqrt is a method on that object so it must
be n.sqrt - you could as well implement the third square root of 8 by
typing 8.sqrt 3 (I am not such a big math-guy... so maybe you could
just send over the whole exponent - 8^(1/2) =3D> 8.sqrt is equal to
8.sqrt .5 is equal to 8.sqrt(0.5) is equal to 8.sqrt(1/2) and so on...
well just my ideas on sqrt method - exuse me if its bs ;-(

I assume by "third square root" that you mean cube root? To me, third
square root would mean sqrt(sqrt(sqrt(8))).

I think you'd want something like 8.root(3), not 8.sqrt(3). Square
root has a very precise meaning.

Also beware, 1/2 =3D=3D 0 because of integer math.

</offtopic>


The article does raise some interesting questions, but certainly lends
itself no credibility due to the presentation. And I'm certainly not
going to become a 'Pythonista' due to this kids rant. You can easily
pick a few elements of any language and pick on them to your hearts
content, but it really just comes down to getting things done, and
Ruby does that for me.


Jason
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top