Open castarco opened 9 years ago
@punkka , @stefanmajoor I'll be thankful to read what's your opinion on this topic :) .
Prefix sharable methods are a big no-no I think, as it complicates the interface for the developer too much.
I think we need to define interfaces first, and that the different classes are much more of a fascade than that it really contains logic. I.e. BigComplex::multiply(BigNumer n) can call a class Multiply(BigComplex c, BigNumber n). In this way you can structure the logic, while keeping the simple interface for the developer.
Also a big question what needs to be answered is what happens when you mix the different types. (Does adding a decimal to an Integer always end up in a Decimal, or does it depend on the answer?
The question that then arises is how we ensure encapsulation, since the (for example) Multiply class don't have direct access to the private properties of the operands. Operating at high level usually adds a lot of CPU and memory overhead because intermediate objects creation and destruction (this is more evident with algorithms with a lot of intermediate computations, like number computations via series).
I think It will be difficult to design a clean API and at the same time keep low resources usage. It's clear that Decimal is too complex at this moment, and adding more methods (as I proposed) wont solve this. My reasons are different than yours (I don't think prefixed methods are complicated for the users of the library, but I think it implies a bloated class).
Your idea of extracting parts of the logic to other classes is a good one, but I'm not sure how to apply it.
I've posted a question in StackExchange. I hope someone enlightens me ^^U : http://programmers.stackexchange.com/questions/278380/how-to-avoid-big-class-complexity-while-keeping-encapsulation
Hi again, I've thought a lot on this issue, and I think I have a "solution", based on the ideas of @stefanmajoor . The idea adds overhead, but I think it will add also a lot of flexibility and potential to the library. I think the trade-off is worth.
What about adding Function
classes? I'm not talking about static methods, but typical methods on instances. It may seem weird, but this allow function composition and many other theoretical artifacts (like expressions, limits, integrals, differentiation...), and we can handle a "default" instance in a static property because the instances must/should be stateless. I'm not talking about making the constructor private since I prefer giving the flexibility of creating many function instances (mainly for testing purposes).
The function classes may have a common compute
method. This isn't exactly true, because we need to handle the n-arity of function arguments, and again, type hinting. Anyway, in this case creating type-specific methods isn't a big problem since the number of methods of the class will be very small, so it won't be as complex than if we try to do the same thing inside the number classes.
Probably Function
must be subclassed depending of the arity of its arguments, since we don't have parametric classes in PHP (like C++ templates, or Java Generics), we'll also need "manual" subclassing to ensure type-correctness.
Initially I wanted to do something like this in another separated repository (which I called MagicTheorist), but I'm not sure how to handle it now.
Hi,
Sorry for the delay but I'm looking to change job and it's taking a lot of my time. I'm not sure to fully understand your idea.
Could-it be possible to shematize or to diagram your solution ?
Hi @punkka ,
This days I haven't enough time to develop this library :( . But finally my idea is to keep only the Decimal
numbers, and maybe (but only maybe) also Float
, (and remove all the code related to infinite numbers).
This two classes (Decimal
and Float
) share a common feature: they serve as approximations, not to exactly represent numbers. Is because this that by default I don't "simplify" the trailing zeros in the representations, because it's possible that those zeros are there to indicate the precision of a previous measure (If I have 3.61, what does it mean? exactly 3.61 or a number between 3.610 and 3.615? If we know for sure that the following digit is a zero it's desirable to state it in our representation).
This leads us to another problem, we haven't unique representations for the "same" numbers, and we need to track additional info about the number precision (currently $scale
, but this may change), this makes more difficult to program uniform and clean interfaces to operate at the same time with these approximations and with "exact" representations (like integers or rationals) at the same time.
In any case, I think I'll move all the numerical functions outside the Decimal class in order to allow extending the library without burdening the main class.
I want to move all the theoretical stuff to other library "MagicTheorist". This new library will be slower (Is because this that I don't want to implement the theoretical stuff here), but much more flexible.
As a matter of fact, when I started to develop this library, my purpose was to use it in currency handling use cases, and I want to keep this possibility without hurting performance and simplicity.
EDIT : This idea is no longer proposed, a new issue will be posted if we arrive to a consensus in this thread.
Because we want to introduce new classes for big numbers (See #15, #27, #28 and #29), it would be necessary to create a
BigReal
interface or abstract class (more probably the second one) in order to allow interoperability between those classes.Currently, the class
Decimal have many defined methods, but almost all the methods use the
$scale`parameter, which is very specific for this type. Because it's desirable to use type hinting in the methods signatures, and because PHP doesn't allow classical method overliading (as in Java or C#), I propose to do a big refactor with the following steps:Decimal
class (de ''d'' is for Decimal), wheremethod
refers to the previous method name, for examplemul
oradd
.$scale
parameter, and hinting theBigNumber
type instead ofDecimal
. Those methods should have a switch-like control structure to map the calls to the specific-type methods :dMethod
forDecimal
rMethod
forBigRational
iMethod
forBigInteger
cMethod
forBigComplex
nMethod
for PHP's native types (see #16).BigReal
abstract class, and makeDecimal
to inherit fromBigReal
.Important Note: I'm talking about
BigReal
and not aboutBigNumber
because this way we have more flexibility . Number is a very general concept, and may be in the future we want to implement other number types (not only real or complex numbers, but... say finite fields, quaternions or whatever you can imagine).