6 ms·
My favorite feature of Raku: Integer division and decimal literals both return `Rat`, a rational fraction type. Even though everyone knows floats suck, nobody i
by pie_flavor 3y ago
My favorite feature of Raku: Integer division and decimal literals both return `Rat`, a rational fraction type. Even though everyone knows floats suck, nobody is actually moving away from them except Raku. If you want a float literal you specifically have to use scientific notation.
- moonchild 3y agoIt's actually an awful misfeature, because those Rats will automatically turn into floats when the rational representation gets too big: > WHAT 1/10 (Rat) > WHAT 1/100000000000000000000 (Num) (There is FatRat, which does not so 'promote', but it is not the default.)
- cosmojg 3y agoHa, it's like best-effort typing. The interpreter gives you a precise rational if it can, and it throws you a float if it can't. I suppose that, in a language as dynamic as Raku, the idea is that you should never need to keep track of types anyhow, but this might be nicer if this value ends up being your user-facing output, depending on the application.
- moonchild 3y agoThere is no reason why it could not continue to use the exact representation and operations if it wished (and that's what FatRat does). It's just an ill-conceived concession to performance.
- librasteve 3y agoand yet, raku is the first serious attempt to unify Int-Rat-Num-Complex types into a cooperative Numeric space --- which I think is a good design given its untyped default approach
- moonchild 3y agoCommon lisp and scheme have had proper numeric towers without this problem for decades.
- librasteve 3y agook - but raku has a reinvention of Numeric that is less esoteric, and more practical ... what you mention is that an Int isa Rat isa Real isa Complex isa Numeric ... and thus in Scheme or Lisp, then the Number Tower class model is one of subsetting features as you go down to an Int which is counter to the reality in your computer than an Int is just a 64-bit register in raku, for example, an Int is not an isa (grand)child of Complex (and so doesn't carry that overload) ... but yes it is a Real so raku separates Real from Complex and Int from Rat and you can go eg. my $x = 1 ~~ Rat; #False and this is aligned with literals - 1 vs 1.1 and then you play nice if things overflow see https://docs.raku.org/assets/typegraphs/Numeric.svg https://docs.raku.org/assets/typegraphs/Numeric.svg
- lizmat 3y agoNewer versions of Rakudo allow you to tune this behaviour dynamically through the $*RAT-OVERFLOW dynamic variable (which defaults to Num for the described behaviour). See: https://docs.raku.org/language/variables#$*RAT-OVERFLOW https://docs.raku.org/language/variables#$*RAT-OVERFLOW*
- librasteve 3y agoI disagree that graceful degradation from Rat to Num (ie double) when Real numbers over- or under-flow is a misfeature. We could (and have) debate whether FatRat should be the default, but imo the right expectation for an untyped language should be that very large or small numbers are represented with a floating point representation that (i) uses the FPU that's right there and (ii) sacrifices precision in the mantissa for accuracy. Since Raku has (gradual) types, you can easily specify what you want and throw an error.
- lizmat 3y agoAnd for 1.5 years now, you can have the FatRat behaviour by simply adding `INIT $*RAT-OVERFLOW = FatRat` to your program.
- nwellnhof 3y agoAFAIU, it's not only very large or small numbers that are affected, but any rational number with a denominator larger than 2*64. For most applications it's completely unpredictable when the switch to Num happens.
- lizmat 3y ago`INIT $RAT-OVERFLOW = CX::Warn` will produce a warning whenever a switch to Num happens. `INIT $RAT-OVERFLOW = Exception` will throw an exception whenever a switch to Num would happen. If you want to define your own behaviour, you can. For instance: class ZeroOrInf { method UPGRADE-RAT(Int $nu, Int $de) { $nu > $de ?? Inf !! 0 } } INIT $*RAT-OVERFLOW = ZeroOrInf would either convert the value to `Inf`if too large, or to `0` if too small.
- librasteve 3y agoNearly, the docs say "To prevent the numerator and denominator from becoming pathologically large, the denominator is limited to 64 bit storage." (https://docs.raku.org/type/Rat https://docs.raku.org/type/Rat) Please bear in mind that in raku (like perl and other untyped scripting languages) it is normal to say: my $x = 1; say 1 + $x; #2 say 'a' ~ $x; #'a1' My point is that when the type is automatically inferred/coerced like this, is is very natural that small/whole Numerics are Int, that medium/fractional/decimal Numerics are Rat and that large/exponential Numerics are Num (ie double). And that you can freely perform maths operations mixing the various Numeric types at will. my $y = 1; say 1 + $y; #2 Int say 1.1 + $y; #2.1 Rat say 1e27 + $y; #1e27 Num And, in raku, if you want to control the type, then just use the type system like this. my FatRat $r; I also think from a 2nd order point of view that a denominator of 2*64 means you are dealing with quite a small number 5e-20 ish), although admittedly that is a matter of taste and machine performance. It makes most sense in my view to go with Rat (which is stored as an Int (uint64) for the numerator and an Int for the numerator. That way (i) you get to use all those transistors that you bought for your FPU and (ii) you do not get a surprise as Rat operations perform slowly without warning. --- And yes - @lizmat has pointed out the various pragmas to let you control the behaviour you want if you disagree.
- kstrauser 3y agoI'm not sure what I think about that. I know when to use decimal/rational types vs floats, but my own Python code has a whole lot more float() calls than Decimal()s. Floats are almost always what I want unless I'm directly working with money.
- zelphirkalt 3y agoAre they almost always what you want? Like, what kind of code do you work on? I personally find, that I need floats quite rarely and rationals usually are just fine, when I write Scheme. And when I write Python, floats also don't come up that often, except for in places where I would rather like to have exact numbers than inexact ones, always making me doubt, whether what I calculate here might have too big error in it.
- kstrauser 3y agoIt's mostly in calculating percentages, measuring timing, computing the interval to wait to satisfy a rate limit, that sort of thing. None of those require the extra overhead of an exact datatype in the contexts I'm using them.
- 59nadir 3y agoIt's funny that you're talking about this in a Python context, because pretty much every few lines will be 50-100x overhead. I take your point that Python would probably slow this type of thing down even more than it should, but still... Python is the exact type of language where this type of generalization to something slower but "more correct" makes sense in my opinion. For what it's worth I agree with you when it comes to languages where 50+x overhead isn't an ever-present fact; you should generally have to opt in to using decimal types and the like.
- dragonwriter 3y ago> My favorite feature of Raku: Integer division and decimal literals both return `Rat`, a rational fraction type. Even though everyone knows floats suck, nobody is actually moving away from them except Raku. Scheme’s numeric tower has a handled exact expressions with exact representations correctly for decades, so I guess its true that is not “moving away from” unnecessary and error-prone use of inexact floats where not explicitly requested, but only because it was never there to move away from.
- db48x 3y agoThere are older languages just waiting for the people who dislike IEEE 754 floats to notice them too, like Common Lisp and Scheme. They have a numeric tower which includes both rational and complex rational numbers: > (+ 5/3 4/5) 37/15 > (expt #C(0 1) 2) -1 > (expt #C(3/2 1/2) 2) #C(2 3/2) And of course they all support arbitrary precision numbers as well: > (complex (fact 10) (fact 20)) #C(3628800 2432902008176640000) > (/ (complex (fact 10) (fact 20)) 29) #C(3628800/29 2432902008176640000/29) Composition is a wonderful thing.
- melagonster 3y agoRaku contain so many cool things.
- fuzztester 3y agoExamples? Also, related and recent: Ask HN: Are you using Raku? Pros / cons? https://news.ycombinator.com/item?id=36922692 https://news.ycombinator.com/item?id=36922692 Question inspired by starting to watch this: Raku for Beginners, at TPRC 2023: https://youtu.be/eb-j1rxs7sc https://youtu.be/eb-j1rxs7sc
- sekia 3y agoYup, literally: https://docs.raku.org/type/Cool https://docs.raku.org/type/Cool
- DougBTX 3y agoLove it: > The following built-in types inherit from Cool: Array Bool Complex Cool Duration Map FatRat...
- duped 3y agoFloats are fine, people just don't want to understand computers it seems
- petre 3y agoRacket begs to differ. Also does things right. > (/ 1.0 3.0) 0.3333333333333333 > (/ 1 3) 1/3 > (- (+ 0.1 0.2) 0.3) 5.551115123125783e-17