Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Complex enhancements #5440

Merged
merged 6 commits into from Dec 1, 2018
Merged

Complex enhancements #5440

merged 6 commits into from Dec 1, 2018

Conversation

Sija
Copy link
Contributor

@Sija Sija commented Dec 22, 2017

@RX14
Copy link
Contributor

RX14 commented Dec 22, 2017

I agree with @larubujo. Complex isn't even comparable to itself. It makes little sense for it to descend from Number given Number's current interface.

@Sija
Copy link
Contributor Author

Sija commented Dec 22, 2017

Complex isn't even comparable to itself.

Hmm, I beg to differ:

describe "==" do
it "complex == complex" do
a = Complex.new(1.5, 2)
b = Complex.new(1.5, 2)
c = Complex.new(2.25, 3)
(a == b).should be_true
(a == c).should be_false
end
it "complex == number" do
a = Complex.new(5.3, 0)
b = 5.3
c = 4.2
(a == b).should be_true
(a == c).should be_false
end
it "number == complex" do
a = -1.75
b = Complex.new(-1.75, 0)
c = Complex.new(7.2, 0)
(a == b).should be_true
(a == c).should be_false
end
end

@RX14
Copy link
Contributor

RX14 commented Dec 22, 2017

@Sija

The Comparable mixin is used by classes whose objects may be ordered.

Complex is not ordered.

@Sija
Copy link
Contributor Author

Sija commented Dec 22, 2017

@RX14 true, yet it's still a Number. All other numeric classes (BigInt, BigFloat, BigRational, BigDecimal) in stdlib derive from Number. IIRC Ruby does the same.

@larubujo
Copy link
Contributor

ruby undefines methods for complex. not such thing in crystal. what do you win with complex < number? what can you do now that you cant before?

@RX14
Copy link
Contributor

RX14 commented Dec 22, 2017

@Sija yes complexes are numbers. That doesn't mean it has to inherit Number per se.

If it doesn't fit in the interface for Number, it's not a Number regardless of if it's a number. Yes that points to our number hierarchy being inconsistent with pure mathematics but i'm not sure how important that is in the real world, or if it's worth adding many new interfaces for it like I think Rust has done.

@straight-shoota
Copy link
Member

@Sija A complex number is a number in real world (no pun intended). But it does not adequatly qualify as an instance of Number which expects operations that are simply not applicable to complex numbers.
Now, this could mean we need to think about if the features of Number might need a change. But at the current state, it just makes no sense to let Complex inherit from Number.

@Sija
Copy link
Contributor Author

Sija commented Dec 23, 2017

Fair points, thanks! I understand that, OTOH I see Complex extending Number with arithmetic operations and equality operator, making me ask myself what's the actual difference between them API-wise—spaceship <=> operator?

Perhaps every Number class descendant should inherit Comparable as opt-in instead? Are they any other incompatibilities between their APIs?

What about two other points listed?

src/complex.cr Outdated
# raises otherwise.
def to_f64
unless @imag.zero?
raise Exception.new "The imaginary part should be exactly zero"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message should simply describe what's wrong, not how it should be, for example: Complex number with non-zero imaginary part can't be converted to real number.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed, thanks!

@ghost
Copy link

ghost commented Dec 23, 2017

Going crazy with algebra is probably useless but having Number without <=> and having Conparable as a separate Module makes sense to me.
Finite fields have no ordering as well (F_2={0,1}) and are actually used for coding/ decoding information.
Ruby has Comparable as a module as well although they include it in number directly.
Having conparable as a separate include in every number class that supports it makes sense to me.

In practise for me a number is an element of a field and a field has no inherent ordering.

Someone else might argue though that a pointer to a variable is a number and arguing from this perspective a number is not necessarily a field (you can’t multiply pointers) but you certainly can compare and order their addresses.

Copy link
Contributor

@RX14 RX14 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I seriously think this is a badly thought out PR trying to shoehorn a Complex into being something it's not: a single-dimensional dumber.

# raises otherwise.
def to_f64
unless @imag.zero?
raise Exception.new "Complex number with non-zero imaginary part can't be converted to real number"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But what's the point of these methods then? Why not just provide an assert_real! and an assert_imaginary! method and let people use c.real? What's the usecase of a number conversion method that raises all the time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But what's the point of these methods then? Why not just provide an assert_real! and an assert_imaginary! method and let people use c.real? What's the usecase of a number conversion method that raises all the time?

Somehow that's what Ruby does, so I guess all of your questions should be directly answered by digging into the Ruby land, their decision making and API designing process.

I seriously think this is a badly thought out PR trying to shoehorn a Complex into being something it's not: a single-dimensional dumber.

And what's the point of of your criticism? I don't see any constructive arguments, only your personal opinions which you hold dearly to the point of putting yourself on airs.

If it doesn't fit in the interface for Number, it's not a Number regardless of if it's a number. Yes that points to our number hierarchy being inconsistent with pure mathematics but i'm not sure how important that is in the real world, or if it's worth adding many new interfaces for it like I think Rust has done.

AFAIK the only thing from Number API it doesn't fit is <=> operator which IMO shouldn't be included there from default.

@Sija
Copy link
Contributor Author

Sija commented Aug 17, 2018

Could this PR be re-reviewed?

@Sija
Copy link
Contributor Author

Sija commented Aug 31, 2018

I reverted the change making Complex a Number descendant.
Could this be re-reviewed?

@Sija
Copy link
Contributor Author

Sija commented Nov 16, 2018

🏓

src/complex.cr Show resolved Hide resolved
@RX14 RX14 requested a review from bcardiff November 22, 2018 16:01
@Sija Sija force-pushed the complex-enhancements branch 2 times, most recently from 9c6a363 to 9d869eb Compare November 22, 2018 16:42
@Sija
Copy link
Contributor Author

Sija commented Nov 22, 2018

No idea why Travis failed...

@RX14
Copy link
Contributor

RX14 commented Nov 27, 2018

There's an incorrect sign on the imaginary part, no idea how that happened given the specs are run in the exact same docker container. Nothing could be different between circle and travis!

@Sija
Copy link
Contributor Author

Sija commented Nov 28, 2018

[...] no idea how that happened given the specs are run in the exact same docker container. Nothing could be different between circle and travis!

I broke CI :( what did I do wrong...? 💭 🐛🔨

src/complex.cr Outdated Show resolved Hide resolved
@RX14 RX14 added this to the 0.27.1 milestone Dec 1, 2018
@RX14 RX14 merged commit e00cf8c into crystal-lang:master Dec 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants