From d0d8e6476f0445bd9954bc2c15f79d873c19e399 Mon Sep 17 00:00:00 2001 From: Jon Michael Aanes Date: Mon, 17 Jul 2017 21:33:11 +0200 Subject: [PATCH] Bunch a' thoughts and documentation. --- analyze_structure.lua | 5 +++ function.lua | 6 +++- init.lua | 5 +++ library.lua | 11 ++++++- number.lua | 75 +++++++++++++++++++++++++++++++++++++++++++ pretty.lua | 7 ++++ table_type.lua | 3 ++ 7 files changed, 110 insertions(+), 2 deletions(-) diff --git a/analyze_structure.lua b/analyze_structure.lua index 3311e0d..1628a26 100644 --- a/analyze_structure.lua +++ b/analyze_structure.lua @@ -1,4 +1,9 @@ +-- pretty.analyze_structure +-- The datastructure analyzing module for pretty. + +-------------------------------------------------------------------------------- + local TABLE_TYPE do local thispath, was_loaded = ... and select('1', ...):match('.+%.') or '' diff --git a/function.lua b/function.lua index 907be62..b111ad2 100644 --- a/function.lua +++ b/function.lua @@ -1,4 +1,8 @@ ---[=[ The function formatting module for pretty. + +-- pretty.function +-- The function formatting module for pretty. + +--[=[ Thoughts on displaying functions in an informative way. How is one supposed to pretty print functions? Well, there are many different formats, and no "best" one, only "best for the purpose". Lets start at the diff --git a/init.lua b/init.lua index f4c759c..ea90943 100644 --- a/init.lua +++ b/init.lua @@ -1,4 +1,9 @@ +-- pretty.init +-- In case somebody loads `init.lua`. Just redirects to `pretty.lua`. + +-------------------------------------------------------------------------------- + local premodule = (...) if premodule == 'init' then premodule = '' end return require (premodule .. (premodule ~= '' and '.' or '') .. 'pretty') diff --git a/library.lua b/library.lua index c2f1ac6..f08dc20 100644 --- a/library.lua +++ b/library.lua @@ -1,5 +1,14 @@ --- TODO: Make lazy? It imports a lot of packages tbh. +-- pretty.library +-- Provides an API for accessing documentation for the Lua standard library, and +-- the LuaJIT extension libraries. + +-- FIXME: This is a large module to load from `function.lua` when `pretty` is +-- loaded. Could probably loaded lazily. +-- FIXME: Currently this module imports a bunch of packages, even though it may +-- never need to use them. Could probably load those lazily. + +-------------------------------------------------------------------------------- local function_library = {} diff --git a/number.lua b/number.lua index 3b43ec0..76bd564 100644 --- a/number.lua +++ b/number.lua @@ -1,4 +1,78 @@ +-- pretty.number +-- The number formatting module for pretty. + +--[=[ Thoughts on displaying numbers in an informative way. + +Numbers are such an intrinsic part of computer science, mathematics, science in +general and even finance industry, that it boggles they mind how different they +each treat numbers. This is one of the reasons that many programming languages +possess a huge number of number types: Integers both signed and unsigned, +rational number, floating point numbers, fixed point numbers, not to mention the +various Computer Algebra Systems (CAS), that exist. + +Lua has historically used floating point numbers, which can represent numbers in +a huge range, at the cost of non-uniform precision across that range. How can we +represent numbers in a intuitive and useful way? + +1. Native representation: We could use Lua's native way of representing + numbers. This is easy, as we just use the `tostring` function. + This is unsatifactory, if we're aiming for Lua-compatible output, as + `tostring` will produce `inf` (`1/0`) and `nan` (`0/0`), which are valid + identifiers, and does not guarentee that these variables are equal to their + respective values. + It's also unsatifactory when aiming for precision, as `tostring` truncate + the output if "close enough". +2. Unnecessary precision: We can use `string.format` with the format code + `%.99f`, to get a "precise" representation of the number. Unfortunantly, for + many "larger" (> 10⁻¹³?) numbers, some of the right digits will be 0, due + to floating point precision issues. We also run against the fact that π is + rounded and is only accurate 15 decimal digits. Do we really care about the + remaining digits, most of which are 0? +3. As required representation: We use as many digits as necessary for the Lua + parser to read the exact same number. Involves invoking `string.format` and + `tonumber` a lot. + This approach improves on 2. as we not only discard all those 0s and the + confusing unaccurate digits. Indeed, many "nice" numbers won't even possess + any decimal digits. Numbers feed directly into the interpreter would look + identical to the input, barring removal of trailing 0s. + And with that we achieved precision and a reasonable amount of consiseness. +4. Fractions: One issue with floating points have always been that the + precision is sorely limited. Some languages possess fraction types, but + such systems suffer from pathological cases, where memory usage spikes. + We can still exploit fractions despite using floating point numbers. When we + type `13/7` into Lua, we get a number back. This is the "canonical" + floating point representation of `13/7`, and every time we encounter this + number, we can use `13/7` to represent it. + This allows more consise representation of certain numbers, for example + numbers with repeating digits. It will also highlight patterns that a + decimal representation might not. + Unfortunantly it might also hide patterns, and it reduces the usefulness of + pretty as a calculator. +5. Reverse engineered number: Remember the concept of "canonical" + representation from 4.? We can expand that concept to also talk about more + general expressions like `math.sqrt(2)` or `2^-5`. Discovering those + expressions from a single number is pretty complex. + Again, this allows for very consise representations of numbers, and can find + hidden patterns all over the place. It's much easier to see the relation to + radians when we see `0.5*math.pi`, rather than `0.78539816339745`. + But again we lose the calculator aspect. +6. TODO: Write about `inf` and `nan`. +7. TODO: Write about rounding. +8. TODO: Write about unicode. + +We a bit of every one of the above methods. They each have their upsides and +their drawbacks. Which approach we use, depend on the number, and what is the +shortest representation. +If the chosen representation is different from the "as required approach", and +we're only pretty printing a single number value, then we also append the +approximate value given by the "as required approach" approach as a comment, in +case somebody was looking for that. +--]=] + +-------------------------------------------------------------------------------- + + -- Constants local MAXIMUM_INT = 2^53 -- The maximum double for where all integers can be represented exactly. @@ -61,6 +135,7 @@ local SPECIAL_NUMBER = { repr = function (a) return ('math.exp(%.0f)'):format(a) end, }, -- x = aπ + -- TODO: Add support for factions of π. { est = function (n) return n/math.pi end, real = function (a) return a*math.pi end, repr = function (a) return a == 1 and 'math.pi' or a..'*math.pi' end, diff --git a/pretty.lua b/pretty.lua index 385ab1d..2e21eba 100644 --- a/pretty.lua +++ b/pretty.lua @@ -1,4 +1,11 @@ +-- pretty.pretty +-- Main module of the `pretty` library. + +-- TODO: Maybe move table formatting into its own file? + +-------------------------------------------------------------------------------- + -- Ensure loading library, if it exists, no matter where pretty.lua was loaded from. -- Load the library component diff --git a/table_type.lua b/table_type.lua index 6a84761..7f33f58 100644 --- a/table_type.lua +++ b/table_type.lua @@ -1,4 +1,7 @@ +-- TODO: I don't like to have such tiny modules. Either merge into another +-- module or provide the funtionallity with another approach. + -------------------------------------------------------------------------------- -- Enum