2 + Cats = 4 * Cute: How Math Works in Ruby
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 65 | |
Author | ||
License | CC Attribution - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/37608 (DOI) | |
Publisher | ||
Release Date | ||
Language | ||
Producer |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
Ruby Conference 201443 / 65
2
3
4
6
9
11
14
17
18
19
20
25
27
29
30
32
34
35
39
40
46
47
50
53
55
56
58
61
63
00:00
Cone penetration testMathematicsBitComputer-assisted translationVisualization (computer graphics)Algebra
00:27
Variety (linguistics)InternetworkingVideo gameReal numberSoftware developerComputer animation
00:50
WordRange (statistics)Multiplication signHash functionNumerical analysisMathematicsComputer animation
01:21
Range (statistics)Range (statistics)Default (computer science)Error messageArithmetic meanSocial classType theoryGoogolLecture/ConferenceComputer animation
01:50
Object (grammar)Glass floatMechanism designFloating pointMixed realityOperator (mathematics)Message passingType theoryNumerical analysisArithmetic meanElement (mathematics)Operator (mathematics)DampingCore dumpIntegerCodeReverse engineeringPoint (geometry)Parameter (computer programming)CASE <Informatik>Food energyObject (grammar)Entire functionSampling (statistics)Time zoneBit rateData managementComputer animation
03:21
DampingPoint (geometry)Numerical analysisType theoryComplex numberParameter (computer programming)Integer
03:58
Numerical analysisDivisorScaling (geometry)Direction (geometry)Vector spaceOrder of magnitudePressurePhysicalismVolume (thermodynamics)AreaCASE <Informatik>Mathematical objectDimensional analysisScalar fieldComputer animation
04:25
AreaVolumePressureVector graphicsVelocityMomentumPosition operatorForceDirection (geometry)Vector spaceVelocityVolume (thermodynamics)PressureMomentumRight angleScaling (geometry)Arrow of timeComputer animation
04:59
Vector spaceArrow of timeLengthFisher informationDirection (geometry)Cartesian coordinate systemRepresentation (politics)Order of magnitudePositional notationCASE <Informatik>Connectivity (graph theory)DivisorDiagram
05:32
MultiplicationDivisorScaling (geometry)CASE <Informatik>WeightNumerical analysisDirection (geometry)Order of magnitudeObject (grammar)MultiplicationRight angleDivisorRegular graphSound effectList of unsolved problems in mathematicsVector spaceCategory of beingMathematicsDiagram
06:09
Reduction of orderShared memoryObject (grammar)MultiplicationMultiplication signOperator (mathematics)Numerical analysisDescriptive statisticsExecution unitDivisorSocial classCASE <Informatik>2 (number)Arrow of timeVector spaceCartesian coordinate system
07:52
MathematicsReduction of orderComputer-assisted translationNeuroinformatikCodeObject (grammar)AdditionNumerical analysisReduction of orderLevel (video gaming)Default (computer science)Social classCASE <Informatik>Multiplication signPoint cloudComputer animation
09:02
Reduction of orderMultiplication signAdditionMultiplicationMathematicsComputer-assisted translationRight angleObject (grammar)ResultantData storage deviceCuboidPoint cloudReduction of orderNumerical analysisOscillationAuthorization1 (number)
10:44
Mathematical analysisComputer-assisted translationMathematicsDimensional analysisDependent and independent variablesMeasurementHecke operatorPoint (geometry)Mathematical analysisData conversionComputer animation
11:06
Dimensional analysisMathematical analysisMeasurementGravitationExecution unitData conversionMeasurementExecution unitMetreMathematical analysisDimensional analysis2 (number)Hecke operatorPoint (geometry)Computer animation
11:48
MetreMetre2 (number)Process (computing)Data conversionLine (geometry)Computer animation
12:12
GravitationDirection (geometry)Vector spaceWordMathematicsObject (grammar)Point (geometry)VacuumNormal (geometry)Numerical analysisGodSurfaceComputer animation
13:10
Exception handlingLibrary (computing)Multiplication signMereologySymbol tableCodeMathematicsLink (knot theory)BitProduct (business)Line (geometry)CubeUnitäre GruppeDimensional analysisLengthLecture/Conference
14:33
Inclusion mapMereologySymbol tableCode
14:56
Module (mathematics)Hausdorff dimensionSymbol tableLibrary (computing)Object (grammar)Numerical analysisModule (mathematics)
15:29
Module (mathematics)Hausdorff dimensionHeegaard splittingNumerical analysisArmDimensional analysisExecution unitPotenz <Mathematik>Division (mathematics)QuantumCASE <Informatik>Symbol tableBit rateElement (mathematics)MereologyLecture/Conference
16:15
Hausdorff dimensionExponentiationLibrary (computing)Potenz <Mathematik>Dimensional analysisMultiplicationAdditionSlide ruleSymbol tableStatement (computer science)Division (mathematics)Vector space
17:17
Hausdorff dimensionExponentiationExecution unitSymbol tableBinary multiplierMultiplicationAdditionExponentiationHash functionVideo gameKey (cryptography)Execution unitDimensional analysisMessage passingProcess (computing)Real numberPotenz <Mathematik>
18:15
Data conversionExecution unitMathematical analysisMathematicsData conversionExecution unitMathematicsObject (grammar)WhiteboardLie groupDimensional analysisMathematical analysisAdditionLine (geometry)GodCodeComputer animation
18:57
Social classHausdorff dimensionExponentiationCodeKritischer ExponentMultiplicationFunctional (mathematics)Exception handlingChemical equationNumerical analysisCanadian Light SourceNetwork-attached storagePoint (geometry)Mathematics
20:00
Data conversionUnitäre GruppeFloating pointCore dumpBlogLine (geometry)Library (computing)Point (geometry)Execution unitSlide ruleProduct (business)Data conversionComputer animation
20:54
SoftwareEvent horizonVideoconferencing
Transcript: English(auto-generated)
00:19
So, this talk is about math, well, it's about algebra
00:23
actually, and it's a little bit about cats. They're providing the visuals, so I thought it'd be rude not to mention the cats, they're quite central. So, I'm Chris Hoffman, in real life, and I'm on the internet, so I'm Yarmulganoska at a variety of places.
00:42
And I work for Optoro, and if you're a junior developer you should too, we're an e-commerce firm in DC, and we're quite fantastic. Yeah, so we're gonna be talking about numerical coercion. And it's kind of a scary thing, but it sounds scary. I mean, coercion, that's not a good word.
01:01
But it's not that frightening. Basically, it's how Ruby deals with unfamiliar math. So, does anyone know what would happen if we tried to multiply a number by a range or a hash or a fruit bet? So here, we're trying to multiply two times the range, one to three, and it says, that's Ruby's polite way
01:26
of asking, are you sure you know what you're doing? Because that doesn't work. But we can derive some meaning from the error. We get a type error, indicating that there's a fundamental incompatibility between what we want to do and what the classes support by default.
01:43
And it also tells us that the thing range can't do is to be coerced, which gives us a hint of where to look. So we do some googling, and then we eventually get to this, which is the rubylang.org core docs for Coerce on 2.1.2.
02:00
Now, the text is kind of useless here. It doesn't really tell you a lot. So I'll give you the TLDR. When you send the coerce message to a numeric object with y as the argument, it only takes one argument, Ruby expects the Coerce method to return an array of two elements, and it expects these elements to be compatible, and we'll explain what compatible means in a minute with some code samples,
02:22
because they are the actual useful portion of this documentation. So here, the integer receiver one is being asked to coerce 2.5, and in that case, 2.5 doesn't coerce to an integer, but one coerces to a float, so it returns an array of 2.5 and 1.0.
02:42
Here, the float 1.2 is being asked to coerce three, and three does coerce to a float, so it returns the array 3.0, 1.2. Here, the integer one is being asked to coerce the integer two, and that works out just fine. It doesn't actually need coercion, but it's useful to show the reversal behavior
03:02
of this operation. The first number in the array is going to be, the type of the first number in the array should be the type that you want the entire operation to coerce to, which is why here, sorry, we coerce to floats.
03:21
Some more examples involving some more of the esoteric numeric types in Ruby. Here, we're coercing the integer four with a complex, and it becomes the complex number four plus zero i. Here, we're coercing the rational four, and it becomes four over one.
03:41
Here, we're coercing, we want the rational 1.5 to coerce 4.5, and that coerces to a float. Here, we're coercing the float 4.5 to a complex, and it becomes a complex with a float as the first argument. So now we all have a basic understanding
04:00
of how numerical coercion works. We're gonna talk about vectors, as they are a great use case for numerical coercion. So vectors are a mathematical object that are ludicrously common in all the sciences. I actually don't know if you can do physics without vectors, like I'm pretty sure it's not possible unless you're, even in one dimension, you'd still need them.
04:21
So what they are is that they wrap a magnitude and a direction. So we're gonna have some examples of scalars and vectors. So things like population, area, volume, battery percent in all our phones, how loud I am, and the pressure that my voice is pushing against the microphone
04:40
are all non-directed numbers. Population doesn't have a direction. Volume doesn't have a direction. So these are called scalars. Things on the right-hand side, like velocity or acceleration or momentum, they do have a direction, and so they're vectors.
05:00
Vectors are routinely represented graphically as arrows because it makes it very easy to understand that two pieces of information are encoded here. The magnitude, which is the length of the arrow, and the direction, that's the direction the arrow is pointing in. There is a ubiquitous representation of vectors. And it also leads us to the most common notation
05:20
for vectors, which is not actually treating them as a magnitude and a direction, but treating them in orthogonal components, in this case, along an X and a Y axis. One of the other mathematical properties of vectors is they can be scaled, and that's why we're calling our non-directed numbers scalars, because they scale vectors.
05:40
They can be scaled by regular numbers, so basically integers, floats, rationals, and irrationals. This scaling only affects the magnitude and does not affect the direction, so it simply makes the vectors longer or shorter. In this case, we're scaling the vector on the left by a factor of 3 halves to produce the vector on the right.
06:01
So can we do that in Ruby? I mean, it sounds pretty simple. It sounds like a value object that encapsulates a couple of coordinates and has some interesting multiplication behavior. Oh look, it's a value object that has some weird behavior related to multiplication. It's almost like I share Sandy's ability to predict the future. Let's look at how this works.
06:22
So first, we're going to instantiate a vector class that has three units along the X axis and four units along the Y axis. I didn't specify that in this class, but let's just assume that it's a two-dimensional arrow like the one I was showing a little earlier. And we want to scale it by two. Two's a good number.
06:40
So here's what happens. We have the two times V, and then what happens there is that Ruby says, I don't know how to multiply two by a vector. Hopefully, or helpfully, rather. Well, hopefully and helpfully, actually. We've provided a coerced definition in our vector class.
07:03
So what happens is that V is asked to coerce two, and I'm just having reduce by multiplication here to store the operation of multiplication somewhere. Ruby doesn't actually use reduce to do this internally, but it's a nice Ruby land description of it.
07:20
So what happens when we coerce two is that we return an array of V and then the number. And the reason we do that is that Ruby then basically reduces with multiplication and passes, and calls multiplication on V and passes it to. And luckily, we've also defined a multiplication operation
07:40
that returns a new vector that is twice, in this case, twice as big. So here's that. Here is actually some code that makes the title of the talk
08:02
actually compute. So we have a Clouder object that contains a splatted array of cats. Don't worry, no cats were harmed in the making of this talk via splatting. It coerces by, when we give it a number, it takes that number and returns an array of that, and the number of aws, and the number of aws
08:23
is a map reduce with addition over each of the cats in the Clouder. We have a cat class to supply cats to the Clouder, and each of them allows humans to say one aw per cat, so they're relatively surly cats, or cats.
08:44
And then we have a cuteness class, which initializes with default quantity of cuteness, in this case being one, and then coerces just as though it's a number. So we say cats equals Clouder.new, cat.new, cat.new, we say cute equals cuteness.new, and then we compare two plus cats
09:01
and four times cute, and I will show how that works. So it's gonna be true, spoilers. But here's how it works, again with the helpful, colorful boxes. When we do two plus cats,
09:20
cats is then asked to coerce two, and it reduces with addition. Similarly on the right-hand side, the cuteness object is asked to coerce four, and reduces via multiplication. The definition for coerce on the Clouder object is to map reduce the aws for each cat, which is clearly shown in the red box,
09:40
in the big red box on the left-hand side. We're still reducing with addition, on the right-hand side, we are reducing the cuteness object, and that one's gonna resolve more quickly, because it's more simple. On the left-hand side, we still have the two, the one one array is indicating that we have two cats,
10:03
and each one has one aw, and it's reducing by addition. Similarly on the right-hand side, the quantity of cuteness has course to one, and it's still reducing by multiplication. This is the actual reduction of the number of aws
10:22
in the Clouder with addition, and on the right-hand side, you can tell it's just become straight-up math again, and this is gonna end pretty quickly. Then one plus one is two, and four times one is one, or four times one is four, rather, and then we get to two plus two, and then four equals four,
10:42
and then that's true, and because you've all been very good, here's a adorable remote-hogging cat. Now I'm gonna talk about dimensional analysis, another math thing. This is not dimensional analysis. The proper response to that picture is this,
11:02
because it's a black hole, and they're terrifying. Dimensional analysis is the simplification and conversion, it is the analysis of the dimensions of measurements. What the heck does that mean? So let's talk, let's give some examples of measurements. So some measurements are basically things you can measure, 60 miles an hour, eight feet, four inches,
11:23
which is how tall I am, 2.7 gigahertz, or 9.8 meters per second squared, which is how fast I fall when I jump at the Earth's surface. On Mars, it would be different. So measurement is anything with a unit, kind of makes sense, and dimensional analysis is the simplification
11:40
and conversion of measurements, either the simplification of a complex unit to a more simple one, hence simplification, or the conversion between units. So here's an example, we're converting 10 meters per second to kilometers per hour, and we do it in three steps. We first convert meters to minutes, that's the top line,
12:00
or we first convert seconds to minutes, that's the top line, and then we convert minutes to hours, and then we finally convert meters to kilometers. So this is a conversion process. Is that not showing? God damn it. There's some math there.
12:23
It's invisible. So here, we're determining how far a masked object will fall in a vacuum at the Earth's surface in the span of .01 minutes, or in normal people numbers, three quarters of a second, it turns out would fall about six feet. I will note one important thing here, even though you can't see the math. The negative sign in the answer
12:41
is actually very important, and it should not just be discarded. It indicates the direction of the vector. It's pretty cool in that we don't need to remember or know that gravity goes downward. The negative sign just falls out of the math. I think that's really cool.
13:00
It would be much cooler if we had actual SVGs. So where's the ruby? Here's the ruby. So this is a bit of a shameless plug, but I wanted to be able to do dimensional analysis in ruby the way it felt like doing it on paper,
13:22
so I wrote a library called Unitary that would allow you to do that. In here, we're setting up the speed to be five miles per hour, except we're writing it kind of weird. We're writing it as five being multiplied by the symbol MI, to denote miles,
13:44
divided by the symbol HR to denote hours, and that's really strange. I'm dividing and multiplying symbols here. That's craziness, and I'm doing it again on the next line to get what represents six hours, but then when we multiply speed times time,
14:02
we'll actually get 30 miles with this library. The hours will cancel out, essentially, which is even stranger. Symbols don't cancel out. That's crazy talk. The second example is also pretty simple. We have a length of two kilometers, and then if we square it,
14:22
we're comparing it to four kilometers squared, and then if we cube it, we're comparing it to eight kilometers cubed, and the math all works out, and here's how we did that, or I did that. The first part of the code is pretty much we require a bunch of stuff, and then we include something into symbol.
14:41
Don't ever do this in production. It's a hideously bad idea, but it's very, very cool. So we include some symbol, unless your rails are active support, and then just totally, yeah, do that, you're fine. So we include this module into symbol,
15:00
and as you can see, the first big headline method is we have a course method. So now when we try to multiply six by a symbol, Ruby at least has some idea of what to try to do, and what it does is it returns an array of two quantities, which are also objects introduced by this library, and the first quantity is gonna be quantity with,
15:22
so quantities in this library have a size and a dimension, and the size is the size, the number, sorry, five, or the number six or two, and then the dimension is gonna be derived from the symbol, but in this case, we have the first quantity
15:40
just having a number, it was basically a size and no dimension, so no unit, and then the second quantity having unit size, so one, and then the dimension. So because the course requires us to return an array of two elements, we're basically splitting the quantity into two parts and having on one hand the number
16:01
and on the other hand the unit. And then once it does that, we've also defined multiplication, division, and exponentiation on symbols to tell it how to combine them. This next slide is how quantities combine. It's a little complicated
16:20
and not the best written thing in the world. There's a large case statement, but when you combine it with itself, you're combining your size and the quantity's size and your dimension and the quantity's dimension. When you're combining it with just a numeric, you just multiply the size by the quantity, a la our vector friends earlier, and then when you're multiplying it by another symbol
16:42
or another dimension, then you just add to the current dimension. Similarly, we have division is defined simply as the inverse of multiplication and exponentiation is just defined as repeated multiplication.
17:01
The other cool thing is that you can't add miles per hour and megawatts. Like that doesn't make sense and similarly the library says it raises an incompatible dimension addition unless the dimensions equal each other. This is how dimensions course.
17:21
You can, yeah, they also return an array of two quantities and they, when you multiply a dimension, multiplies dimension when you give it a symbol, it multiplies it by a unit, and then when you multiply it by a numeric, it just multiplies it by a numeric. The cool thing is that it will cancel out, as you saw, the hour stuff.
17:43
So once it's done the multiplication, it has a process where it finds any, so the exponents are, the exponents are represented by a hash where the key is MI or HR and the value is the exponent there. So when it's miles per hour, that's a hash of MI to one, HR to negative one, and then when we multiply it by the six hours,
18:04
we then have hours and they reduce the addition so they turn into HR zero and then there's a pass after the multiplication that takes out all the zeros because they don't make sense in real life. So other coercion uses. There are many.
18:21
You can do unit conversion and dimensional analysis. You can do currency manipulation and conversion which is kind of unit conversion and dimensional analysis just with monies. You can do math or maths for any Brits in the room. And the last one is, I'm lying. There are no other uses for conversion, for coercion.
18:41
It is entirely for doing cool math in. The thing is that Ruby isn't very good at representing math the way we think of it in the real world or the way we write it on whiteboards. It's abysmal at it. We end up with these value objects and code like the stuff I just showed you that looks impenetrable and God, what are you doing here?
19:05
But wouldn't it be cool if we could do stuff like this? If we could compose functions with multiplication or could scale functions with numbers or could do chemical equations and just add two NAs and two CLs to get two salts
19:24
or it could do four dot dollars equals 6.5 dot euros. The cool thing is, with the exception of the first two and you would just need a little syntactic sugar to make that work, you can do all these things. You can do these, you can do more,
19:41
you can do things I haven't thought of. You can do things it would not occur to me to think of. I like math, I don't like chemistry and yet I came up with the chemistry example. I mean, there are way more things to do with numerical coercion than I've shown here.
20:01
The resources for it are relatively slim on the other hand. It is not the subject of the Ruby blogging industrial establishment and has relatively few blog posts. I couldn't find any from before 2012, though I guess it hasn't changed that much
20:20
so I could have gone earlier. A guy named Shamus Abshir has a conversions library that will pretty much let you do the thing that I wrote on the last line of the previous slide which is four dot dollars equals 6.5 dot euros. And his approach was a little different than mine. He just did active support style methods for just tacking on the unit to a numeric.
20:43
My library Unitary, which you shouldn't ever use in production, again, is available on GitHub as well and the docs are available where they are. And again, I'm Chris Hoffman and so go do course.