Hacker News new | past | comments | ask | show | jobs | submit login
Translating math into code with examples in Java, Racket, Haskell, Python (2011) (might.net)
358 points by signa11 on May 28, 2019 | hide | past | favorite | 92 comments



I dream of material that would explain some advanced (for a regular person understanding of the word) math concepts using Python. Maybe it's because I've programmed more in my life than did math, but the "language" we use to write it is absolutely crazy: one letter variables everywhere, no structure, thousands of custom notations etc. I'm not criticising it, I realise it exists this way for a reason and if I wasn't so lazy I would have learnt it in school. But with my 31-year old brain oriented for looking at a sequential flow of code, it's quite difficult to learn math now.


There's a few books around for this, first is Jeremy Kun's book https://pimbook.org/ and is probably exactly what you're looking for: math from a programmer's perspective. There's also Discrete Math w/Functional programming https://cs.wheaton.edu/~tvandrun/dmfp/ in which most chapters translate theorems into algorithms or turn sets into types. Sussman also has two books translating Lagrange equations and differential eq into Scheme but both assume an undergrad physics background. Brown has a course in linear algebra using Python http://cs.brown.edu/courses/cs053/current/lectures.htm but you can do it with any math language library that builds matrices or write your own naive implementation as you go.

Of course the best way to do this would be to try and model the notation yourself (if possible) into function specs or algorithms, as you go through various math books. Then you'd really understand the notation even if you failed to implement it. You could try Pyret to do this https://papl.cs.brown.edu/2018/func-as-data.html#%28part._.A...


I tried something along these lines based on the computer algebra system SymPy [1,2]. The syntax is Python so feels a little weird for doing math, but the SymPy function names match very closely to the math verbs like solve, expand, simplify, factor, which is very good for learning.

For example, factoring a polynomial can be done by calling the `factor` function:

   >>> factor(x**2 - 5*x + 6, x)
   (x-3)*(x-2)
see https://live.sympy.org/?evaluate=factor(x**2%20-%205*x%20%2B...

Suddenly all the boring and fear-inducing math operations are available to you after a few simple calculations in a REPL! That's a huge win if you ask me ;)

______

[1] Printable math+SymPy tutorial https://minireference.com/static/tutorials/sympy_tutorial.pd... [2] Notebook version of [1] https://nbviewer.jupyter.org/github/minireference/SymPyTut/b...


At 31 years you are quite young still. Some of my peers studying maths are around your age or older than that.

Don't be afraid to dive into maths if you feel like it.

Anecdotally people >25 do better than younger people. Maturity appears to be an asset sometimes.

Yes, young people might think and learn slightly quicker, but older people tend to be less easily distracted and more focused on the task at hand.

Maths is not a race though, so I believe age is an advantage at the end of day.


Most of the structuring (and, therefore, syntax) around an 'enterprise' application, is about how easy it is to 'replace'/'change' functions based on future needs (or known, but yet un-realized requirements).

In mathematics, the driver for notation is: how succinctly can I express, what I want to express in this particular effort, yet allowing others to verify my work without mis-interpretation.

I am not sure if those two worlds are reconcilable, and mergeable, with worlds of structured and 'just-in-time' teaching.

I am going to also, claim, that style of presentation of mathematics is more appropriate for formulating vision, structure, strategy, architecture in formal technical/financial 'contracts'.

As I progress (perhaps, already at a sunset) of my career, I can see that lack of fluency in mathematics (both algebra and analysis) is a major impediment for transition into more highly compensated (and impactful) , yet, still technical roles for many of us, out there.


> As I progress (perhaps, already at a sunset) of my career, I can see that lack of fluency in mathematics (both algebra and analysis) is a major impediment for transition into more highly compensated (and impactful) , yet, still technical roles for many of us, out there.

Do you have an example off the top of your head? I'm assuming that by, "fluency in mathematics (both algebra and analysis)", you mean something beyond basic calculus and linear algebra.

My experience has been that software engineers at the staff, principal and architect levels don't really need to know advanced mathematics at all. From what I've seen they usually have a breadth of experience as generalists and a depth of experience in one or two particular specializations, which may or may not involve any advanced mathematics at all.


> mean something beyond basic calculus and linear algebra.

"Fluency" in mathematics, in my experience, isn't about being able to perform more complex computation, that's what computers are for. The key to fluency in mathematics is increased efficiency at equational reasoning.

Granted, I work in data science, but I've personally seen that more and more problems I have are solved writing out a few equations and reasoning about the problem than writing code. It's not about knowing, for example, what SVD is, but seeing how a variety of common problems trivially map to it. Or figuring out how to transform a business problem into a probability problem so you can quickly estimate your success. Many times now I have spent a few afternoons writing equations that simplified what would have been very large and unnecessarily complex programs.

The mistake programmers make is thinking that math is just fancy computation, but mathematical reasoning is an entirely distinct way of reasoning about problems and computation is usually the least important part.

I used to also think that there was no reason for programmers to learn any math outside of enough calculus and linear algebra to compute basic things. But really understanding these areas and reasoning about them fluently (as well as other areas of mathematics) opens up many possibilities of problem solving that code it self does not.


I would outline 3 areas:

1) Modeling capacity/latency of complex system with queuing theory (basically creating spreadsheets that can 'calculate' how much servers you need with what I/O throughput/etc for our software)

2) When looking at tables in data-warehouse, as 'types' -- I felt I could benefit from leveraging modern type theory, where I could at least categorize schemas (filds/relations) into 'Automatically-transformable into target warehouse schema' vs 'human intervention is needed'.

Besides natural complexity, the papers in type theory use that fraction notation :-). For some reason difficult for me.

3) Various data de-anonymization proofing techniques, differential crypto, and tamper-proof logging.

Ability to read financial mathematics and NLP technique is something I do not need now, but I would have benefitted significantly in my past.


I've come to the conclusion that my brain's "algorithm"y, rather than "equation"y. My scores on (especially) spatial reasoning tests are excellent so one would think I'd have a leg up in mathematics, but trying to read typical "mathy" (equation-heavy) writing makes me feel the way I assume dyslexics do, even when it's something I'm pretty familiar with.

Algorithms, though? No problem. Programming in typical Algol-family languages & similar came easily to me. The "tough" early topics? Pointers, recursion? Not even a bump in the road, totally natural. To this day, though, the ones that look more like mathematical writing (Haskell) are really hard to read, let alone write. I can get all the concepts at play in a piece of Haskell and still not be able to keep the syntax or meaning of the code itself straight. When I do want or have to read mathematics of any complexity whatsoever, I only make headway by converting it to something more algorithmic as I go ("OK, so what does this term or whatever do to any other values passing through, here?")


You're not alone. The Math symbols are easy once you learn them (at least the subset I know), but it was challenging getting there.

My field has a lot of dense math that makes the pyramids look simple (ok I exaggerate, but there is a lot going on). The only way I've been able to really grok it is by writing software to do it. Now that I know what's going on, the math notation is useful in that it explains the problem in a succint way. I think Calculus via Python with nothing but the stdlib and Matplotlib would be a better way for me to learn to be honest.


Maybe you can start from a different angle. It might sound odd, but try taking a simple concept that you know, say calculating a restaurant tip or something and write it out in English + LaTeX. Build on this until you can do some more complicated problems, and soon I would bet you’ll read math as something a bit closer to code in your head. I had to do this a lot for classes in college, and forcing yourself into exposition is the math equivalent of rubber ducky programming. LaTeX will give you a feel somewhere between math and code that might feel a bit more natural.


About variable naming in math. I sometimes also think that it would be good to define sensibly named variables and then use them in subsequent equations much more often than is usually done. Math equations are traditionally very large and complicated, even though they could be broken down to pieces and then assembled piece by piece.

I think one argument against this is that in math you often want to reach down a few abstraction levels and reorder terms, factor out things etc. which requires peeking into the "internals of boxes". You can't abstract to the point where you only have two or three variables in one equation because to show the next step, you would need to make the expanded formulas of those variables interact (cancellations etc.).

Another is that math is quite a different way of thinking. Most professions don't do as much of this input/output-based, requirements-based thinking with lots of ad-hoc on-the-fly introduced abstractions that is usual in programming. For example engineers, doctors etc. just work very differently and consider many different levels of abstraction at the same time. They consider it normal to sprinkle in temperatures, voltage values etc. in supposedly high-level discussions. Programming is a product of the mind so we have an easier time with it for sure, as our abstractions are more reliable (even if they leak to some degree, they leak much much more in other disciplines).

Now, math is also a product of the mind, but tradition is quite different. Of course math is very abstraction-heavy but the abstractions are usually not generated by the practitioner on-the-fly, on-demand, the way you just write a function or introduce a class in programming. Rather they are widely-known definitions and conventions, which are mostly only created by the people developing new theory. Of course you do define some notations and variables in math, but I find it not as pervasive as in programming.

The closest you can get to programming-like variables in math writing that still somewhat adheres to math tradition is to place full words into subscript positions (index). For example, you can write out N_columns (as a subscript) or S_upper or L_dual or f_transform. This is also something I see more in CS papers than in non-CS math content.


You can use full words or even short multi-world phrases in math expressions. From a typesetting POV, write them in roman (upright) type, and enclose them in brackets whenever ambiguity arises (due to the possibility of separating spaces within a single variable, or the concurrent use of juxtaposition (of single letters) as a product or for other purposes within the same sorts of expression. This is very common in the applied sciences in general, and the convention is universally understood.


It may take some effort to realize this, but a mathematical formula is actually a picture, not text - more often than not it is intended to be seen - as a whole - rather then read, "word by word."


you will take single letter variables from my cold, dead, hands!

I'm more used to math than to code, and I find multiple-letter variables ridiculous when not unreadable.

In the ancient times, mathematicians used to write formulas using latin sentences. Even the simplest arithmetic result occupied a few lines of text. Are you proposing that we go back to that age?


" Even the simplest arithmetic result occupied a few lines of text. Are you proposing that we go back to that age? "

What if students learned "Force = mass * acceleration", and only later moved to "F = ma" once they'd gotten tired of writing it, instead of smacking students in the face with "F = ma" right out of the gate, to say nothing of all the other stuff we smack them with right away?


That's precisely how I learned that formula. In fact that's basically the pedagogy that's been presented to me for almost all the mathematics I've learned.

Sets? Define a set semantically, then replace "set" with S. Vector spaces? Define a vector space semantically, then replace "vector space" with V. Limits? Define a limit semantically, then replace the word with "lim".

Moreover mathematicians typically use jargon in a more reader-friendly way than simply throwing obtuse equations at them. Expressions, equations, inequalities and identities are complements to the proof, not the proofs themselves. Best practice holds that you present a theorem in plain language alongside the necessary notation, then break its proof down into as many atomic units (lemmas, propositions, corollaries, etc) as possible. Here is a blog post[1] from Terence Tao giving general advice for why that's useful. Tao has written a bunch[2] of these on the theme of emphasizing exposition and clarity.

Also contrary to popular belief, well-written mathematics papers actually have quite a lot of exposition in them. For a famous example, look at Yitang Zhang's proof[3] that there are infinitely many primes with 70 million numbers (or fewer) in between them. He spends a full five pages on introduction, background results used to develop the proof, and (most importantly) notation. He also includes a "sketch" of the proof in broad strokes so that a reader can follow his arguments at both a high level and in gritty detail.

That doesn't mean papers like Zhang's are accessible to most people. The jargon is still there and you can't really change that unless you want papers to become self-contained monographs. But the point is that what you're proposing - concepts defined in a straightforward way before moving on to dense notation - is already the general practice.

__________________________________

1. https://terrytao.wordpress.com/advice-on-writing-papers/crea...

2. https://terrytao.wordpress.com/advice-on-writing-papers/

3. http://annals.math.princeton.edu/2014/179-3/p07


Usually the problem is that the students don't understand the difference between force and energy, or the difference between mass and weight (or what is linear momentum). It is easy to remember that [in that class] a capital F means force.

Anyway, in sometimes it is useful to write more. For example teaching https://en.wikipedia.org/wiki/Consistent_and_inconsistent_eq... I try to write the full name of the classification at least for two clases. It is painful, but it is worth. I teach in Spanish, so we have also the problem that underdetermined is "indeterminado", so a capital "I" can mean "Inconsistent" or "[I]underdetermined" or in one of the following clases "Independent" (like in a linear independent set of vectors, yes they mix this too). So it is important to use the full name (or a long enough abbreviation) until you are sure that everyone can understand which "I" you are writing.


but even "force = mass * acceleration" uses those sneaky single-letter symbols that are not even letters! In appropriate, user friendly notation it would be "force equals mass multiplied by acceleration".

But this is not clear enough. What force? What acceleration? More precisely, what is the direction of the acceleration? The original statement of this law is less ambiguous: "Mutationem motus proportionalem esse vi motrici impressae, et fieri secundum lineam rectam qua vis illa imprimitur. "

Or, in plain english: "The alteration of motion is ever proportional to the motive force impress'd; and is made in the direction of the right line in which that force is impress'd"

There! we are good to go. Now write the fundamental theorem of calculus in english, readable by everybody, without those ugly, unreadable variables and fancy symbols...


I'm not seeking abstract philosophical purity, or trying to make the mistake of including a complete transitive concept closure in every equation [1]. I'm seeking pragmatic high-quality education that doesn't blow our student's cognitive resources on stupid shit instead of the stuff I want them to learn. By the time they get to physics, they know what multiplication and equality are. It's just the "force", "mass", and "acceleration" that they don't know yet, so we don't abbreviate them until they do.

[1]: AIUI, the actual problem the original "New Math" had. The original "New Math" tried to start students with set theory, because that was the foundations of mathematics, so obviously, the best place to start an education, right? (Hint: No.) This is why parents said they didn't understand "New Math". By comparison "Common Core" math is all-but-identical to what I learned in school 30 years ago.


I do not disagree with you. When you learn the stuff, it is perfectly OK to explain equations with words and even write equations with words. But this is akin to the comments of a program. Once you get down to work, in a professional setting, all mathematics uses single-letter variables

(and I may add that all programming should do the same).

I also agree with you that starting math with set theory is utterly ridiculous and even harmful. You should start with arithmetic and with geometry (obviously, using single-letter variables when needed).


Seems like this would be sensible, the multiplication symbol is one any student learning this should already be familiar with. To generalize, keep using well-learned symbols so things don't get out of hand in verbosity and slowly introducing new ones seems logical. I know when I was in school there were certain math and physics classes where I kept having to ask myself what a symbol meant that was introduced 5 minutes ago so writing it out fully would have been helpful often.


Gerry Sussman had the same idea and wrote a paper on it:

https://www.researchgate.net/publication/37597511_The_Role_o...


His SICP coauthor Hal Abelson also cowrote Turtle Geometry, which explores stuff like topology and the basics of general relativity in Logo. An underappreciated old book I'd like to see more like.


To be fair, when you actually look at Structure and Interpretation of Classical Mechanics (which is a great book), it's still math that a physicist recognizes, not so much an ALGOL-esque program. The Scheme system was extended to handle the math rather than the math brought to the language.

What they did was make all the math explicit, mostly by inserting all the necessary pieces of differential geometry that were glossed over in all other treatments.


A few personal observations:

1) A lot of frustration comes from bad expectations about how easy a math formulate should be to read. If I see 3 short lines of code, my gut tells me "this will be easy", and it's right. If I see 3 lines of math I feel like it should be easy but then get frustrated when 30 minutes later I'm still looking at the same 3 lines.

2) Once you understand a formula, I often decided I couldn't write it any better myself. It's most useful as a tool for thought and remembering, not necessarily as a tool for teaching.


There used to be a Coursera course called Coding the Matrix. It covered many linear algebra topics using Python. The course isn't available anymore on Coursera anymore, but you can still buy the textbook:

https://www.amazon.com/Coding-Matrix-Algebra-Applications-Co...


All of the course's video lectures are still available at:

https://www.youtube.com/channel/UCGVa4wp8SWGFtMe6hcdpHlg/pla...




I try to achieve this goal with "Thinking in Tensors, Writing in PyTorch" project: https://github.com/stared/thinking-in-tensors-writing-in-pyt... (very much a Work in Progress).

The idea is to have equations (in LaTeX) and code (in PyTorch) line-by-line, so it is easy to see how to use it in practice.

I think it may help to bridge the gaps between coders (but not experienced in maths) and mathematicians (but with little experience in practical programming).


I wrote a blog post describing the tensor product in terms of functional programming techniques in python https://jwkennington.com/blog/tensor-product-for-programmers...

I would also be interested in a "math for programmers" approach to deciphering formalism. I've studied a fair amount of linear algebra / differential geometry and could see how Python-definitions might help. I'm less familiar with other areas of mathematics


The article covers quite a few topics in set theory so that suggests that it does provide for advanced topics.

If you mean advanced proofs, again the article may be the right place to start.


I suspect what's jarring is the difference between programming in an imperative sense, where you write down steps to be taken to get a computation, and equations, like declarative programming. I once dated, in math grad school, a hardcore differential equations student, and she took Java, which she thought so very different than a world of equations. Made sense, I thought, having been exposed to imperative and declarative programming myself.


Math has a syntax to write imperative algorithms in too. Came up in the Discrete Math course I took, for things like finding GCD.


That sounds like something that could be done using a Jupyter Notebook and SageMath.


Agreed, i'm not sure whether one letter (immutable) greek variables are better than proper named variables.

Another consideration: A formal rule based math syntax could be checked by a computer (theorem prover).


Where widely understood, I consider a Greek variable to be vastly superior. The problem is how well it's understood. Delta is an example of a succinct variable which has a well defined meaning which to encapsulate in a named variable either requires a long name or leaving out some nuance (delta isn't 'change' which is ambiguous in English, but the difference between two measurable things.)

Keep in mind we use special single letter variables all the time, sometimes multiple for the same concept. Multiply, divide, add, subtract. You learned them all in early education along with everyone else, and now you have a universal set of symbols to express arithmetic concepts.

Would we be better off if every occurrence of '+' was replaced with 'sum'? I don't think so, but that doesn't necessarily mean that loading up with single letter variables that people aren't familiar with is better. It's entirely to do with how familiar the target audience is with them. A library targeted for use by scientists might see benefit to more of them, while one targeted towards being accissible to many people might not.


Single letter variables (including Greek ones) are great when they stand for something, or are well-known so they don't need to stand for anything.

If you stick to convention and use stuff like A for array, i for index, r for root, δ for small change (a delta), ε for error, Σ (Greek S) for sum, Π (Greek P) for product, etc.

It's only when you start using variable names as if they were free variables when they really aren't that you get into trouble with comprehension, especially from people not in your field.


It think this is somewhat similar to: many chinese characters vs ASCII. Neither is the superior notation. I prefer to write words by concatenation of multiple ASCII letters instead of one letter symbols, but that's due to my cultural background.


https://projecteuler.net/

Some problems with solutions in different languages. Each problem leads to the next one.


Agreed. I think the internet needs a 'math as code' wiki site.

Math is so easy! and its a joy to work with when programming, but the way its written, the notation, is often baffling to me.


> Mathematics is a purely functional language.

It is not. E.g. x ∈ ℕ ∧ x > 2 ∧ x < 5 ∧ x % 2 = 0 implies x = 4. This is not something pure functional languages can express directly. In math we make common use of relations, of which functions are a special case, but not the common one and certainly not the only one. But even when we do work with functions, a functional PL does not suffice. E.g. writing f(t) = t + 1 ∧ x ∈ ℕ ∧ f(x) = 3 is equivalent to writing x = 2. Also, we commonly employ objects that are not computable.

This is just one of the many mathy myths that plague the FP community. Yes, there are some similarities between FP and mathematical notation, but FP and imperative are much closer to one another than either is to mathematics.


I'm not sure what point you're trying to make. You can certainly express those statements in both FP and imperative languages, and you can prove the equivalences you mention in FP languages like Agda, Coq, and F*.


An example of

> E.g. x ∈ ℕ ∧ x > 2 ∧ x < 5 ∧ x % 2 = 0 implies x = 4.

in Agda would be this, I think:

  _ : ∀ { x : ℕ } → x > 2 → x < 5 → (x % 2) ≡ 0 → x ≡ 4


The type level of dependently typed languages or other languages that allow directly expressing relations (including Java's JML) can do that. That's little to do with pure FP.


In some sense it does though. Type Theories (and their associated pure FP languages) often have the exact same algebraic structure as different classes of logic. To my understanding, JML uses Hoare Logic, which is a great tool for proving correctness of imperative languages, but is not quite as expressive. For example, Hoare Logic cant really deal with Higher-Order things. That's not to say Coq/Agda are perfect though. They do struggle with more "extensional" properties, such as function extensionality.


> but is not quite as expressive

It's as expressive.

> For example, Hoare Logic cant really deal with Higher-Order things.

1. It can. 2. It doesn't matter so much, as there are no higher order "things" but rather higher-order ways to describe things. For example, in mathematics higher-order systems can be described as either higher-order ODEs or equivalent first-order ODEs. In other words, "order" is a feature of the signifier, not the signified. For example, things that would be higher-order in Agda are first-order in TLA+ (and you don't need to go that far: formal set theories are usually first-order, yet you need higher-order typed logics to describe the same things).

> They do struggle with more "extensional" properties, such as function extensionality.

Well, that's because they're constructive. There are type-theory-based proof assistants that more easily support classical mathematics, like Lean.


First, while you can express those statements in programming languages, they will either be expressed differently in order to have the same meaning or, if expressed in a similar way, have a different meaning (even ignoring that many such statements are not computable at all). This merely shows that math is not an FP language.

Second, you can prove those equivalences in any language that allows you to directly express relations, be it the type-level language of Agda, Coq or F*, or the contract language of an imperative language -- this is nothing to do with FP, but with a language that can express relations.


Yes, well said. Math is not any form of programming, and programming is not math. Studying the relations between the two can be very helpful, and the difference itself is interesting. One may have specific reasons to us FP to cleanly decouple from certain kinds of side-effects, but there’s nothing un-mathy about mutability, and there are times when it’s a fine choice.


I mean, that’s exactly what the Curry-Howard Isomorphism says: that math and programming are equivalent.

Both can express and are equivalent to Turing machines.


That is not what the Curry-Howard Isomorphism -- AKA propositions-as-types -- says. Propositions-as-types is the observation that the typing rules of certain type systems follow the inference rules of certain logics (largely because they were designed this way), and that in general typing rules and inference rules can be made to mimic one another, so that a type system can represent propositions in some logic, and type checking represent proof-checking.

That arbitrary mathematical proofs can be equivalently made by Turing machines (and conversely, that predicate calculus is Turing complete) is a lemma by Turing, published in the same 1936 paper in which he introduced the notion of computation, Turing machines and proved what today is known as the halting problem.


Can you provide an example of mutability in, say, high school or undergraduate math?


any sum with an index of summation requires mutability


"requires" is a strong word. the only explicit definition ive seen given for n-ary summations and products products was recursive.


I don't think so. For example, sum of first 5 integers:

    sum i = 1 to 5 of i -> 1 + 2 + 3 + 4 + 5 = 15
Nothing mutable there. In functional programming this is done with a `fold`, which doesn't use mutation.


We're talking about notation. Anything could be described in any Turing complete language. It's uncommon to have something similar to mutation in ordinary mathematical notation, but summation is one example where it's used.


I don't know much about this area. What about "x ∈ ℕ ∧ x > 2 ∧ x < 5 ∧ x % 2 = 0 implies x = 4." can't be expressed in common languages? Don't lots of solver systems have support for sets, and deriving facts from statements about them?


Just in case somebody might benefit from finding out how easy it is in python with z3

  >>> from z3 import Int, solve
  >>> x = Int('x')
  >>> solve([x > 2, x < 5, x % 2 == 0])
  [x = 4]


The argument here is that you used a program to solve an equation. You did not write your program in that way. Indeed, you are using operator overloading/fancy syntax to make this work.

If anything, this seems to support the original claim.


I also found this sidetrack to be a bit of a straw man. A large proportion of physics is devoted to dynamics: the study of change. There are mathematical descriptions for dynamics whereby a thing is updated x ↦ x + v * dt, v ↦ v + a * dt. You can think of a classical particle's position both as a thing that gets updated and as a function of time (time is definitely updating whether you like it and model it or not).

Many numerical algorithms for differential equations update a field in place. Sometimes you need to be very careful in your description of how something gets updated in order to avoid data conflicts. If you define it as a function then you have a single option if you want to do this "in place": sparse matrix representation of the updated values and a write of the updated values into the memory. As an example, memory requirements for line relaxation in multigrid can be done as an O(1) operation instead of as the O(n^1/d) operation of a sparse copy.

A mathematical function does not always return the same value. There are stochastic differential equations and random variables. For the sake of formality, they are frequently treated as discrete samples taken from a random distribution, but the naive approach of acting like the output of some function ε is random maps nicely into computers. If you are not "abusing notation" by using the functional notation, then the sample can be different every time you "take" it. Either way, you are not returning the same value each time.

It is useful to be able to describe certain mathematical operations as updates instead of as pure functions. Mathematics certainly isn't incapable of doing this. There is a lot of value in functional descriptions as well. If you are a purist on either side, you are just ignoring valuable things for the sake of your ideal.


Not to mention that whole fields of mathematics deal with numerical algorithms: Computational algebraic geometry, number theory, numerical mathematics etc.


Nice article, I was wondering why Julia wasn't featured considering its support for math syntax. I wondered whether this could have been an old article, but there is no date in the article.

I checked the RSS feed and couldn't find the article in it. I cross-checked the oldest article in the feed with the index of articles on the site, this article seems to be written before Dec 2014. This makes sense for why Julia isn't included.


Don't forget the Internet Archive!

The first version is from Nov. 14: https://web.archive.org/web/20111114185849/http://matt.might... The article index from Nov. 8 does not include the article: https://web.archive.org/web/20111108003034/http://matt.might...

So we can say with confidence that this should have a [2011] tag and was published sometime Nov 8 - Nov 14 in 2011.


It's frustrating when Internet articles don't include publication dates. It's not like it's paper where someone didn't think to record the date. The date certainly exists in the database, filesystem, etc, the author just chooses not to show it, forcing forensics to figure out when it's from.

(I was reading another article from his site yesterday after it was linked on lobste.rs and was also trying to figure out how old it was.)


Why would the date "certainly" exist in the database or filesystem? The file might be one file created in 2001 and modified every date after containing every post in it like a mail spool file. It might be a record in a database table with no date column. If it was a single file, then the creation time could be weeks or months before the publication time, and the modification time could be the last time an edit or tweak was made, rendering both useless for this purpose. I think it's more likely not to have a useful date anywhere unless someone went out of their way to put one in.

(Which they should do, it's useful)


Well, we are fortunate that the author covered four languages. That said, seeing the same in Julia and also Common Lisp would be great. I am coming up on my 36 year anniversary for using Common Lisp, so even though I really love Haskell and Racket, and I am enjoying learning Julia, I would vote for adding CL.

This might be a good community project - the article on github and allow people to do pull requests adding their favorite language.


Thanks for doing the sleuthing on that, I (and surely others) had been wondering about the same :).


I see that there are other comment questioning the same, I saw that only after posting this else I would have added this as comment to it.


That's also supported by the fact that examples are given using Python 2, not Python 3. Not a hard and fast rule, but it's a helpful heuristic.


I would think Clojure vs. Java would be used given immutability. I like both Haskell and Racket for math, especially this article on geometric algebra with Haskell:

https://crypto.stanford.edu/~blynn/haskell/ga.html

I am personally learning Shen[1] because Lisp, optional typing (great type system), and the formal work done within it, and for it in proving, verification and other related endeavors. It seems to tick the Haskell, Lisp, Prolog and logic boxes for me. Its portability is great[2], however, it is still young and building libraries. I am thinking on trying to mimic the DL work done by Dragan Djuric[3] for Clojure in Shen. We'll see how that goes...

[1] http://www.shenlanguage.org/ [2] https://shen-language.github.io/ [3] https://dragan.rocks/


APL is an executable mathematical notation - in fact, it was designed by Iverson for describing algorithms on paper (in 1958 IIrC), and then the team working on it implemented it in software, because ... it was a well specified way to describe algorithms.

I highly recommend reading [0], which contains the simplest (IMO) description of the simplex algorithm, which is both mathematical and executable. If you find that inspiring, [1] is also worth a read.

[0] https://www.jsoftware.com/papers/DFSP.htm

[1] http://www.eecg.toronto.edu/~jzhu/csc326/readings/iverson.pd...



I like Julia for all of the libraries, the Lisp underneath, however, from the article:

"Many of the encodings are as immutable, purely functional data structures (even in imperative languages), a topic unfortunately omitted from many computer science curricula."

Julia and similar PLs don't express math like APL, J[1], Haskell[2], Scheme[3] or even Clojure can with immutable structures and function composition to name a couple. Sure you can write it in Julia, but I don't think the article is about creating math output in the Latexify.jl example, but how to code these math structures where certain languages can express them out of the box in an easier manner.

[1] https://www.jsoftware.com/books/pdf/

[2] https://www.amazon.com/Haskell-Logic-Programming-Second-Comp...

[3] https://mitpress.mit.edu/sites/default/files/titles/content/...


Can you explain it better? I do agree with Haskell due to laziness by default and arrow types for example, but against Scheme and Clojure the only aspect seels like it would be the more strict rebinding/shadowing rules (which doesn't limit what you can express, just that you can also express non-mathematical expressions).

Primitive types (like pretty much all languages) are immutable and structs in Julia are immutable by default (which includes pretty much every math type like complex numbers), and all math operators are non mutating (in fact mutating operators should have a ! in the name).

Function composition is just as simple in this scenario:

f(x) = x + 2

g(x) = 2x

h = g ∘ f

h(3) == 10


@ddragon your points are well taken. I will look further into Julia. I still think when I wrote "out of the box" with APL in mind as far as expressing math, or J for that matter if you learn the ASCII symbols. I've seen other examples since your post on Julia that show similar math expressiveness, but they seem to rely on libraries or the syntactic sugar provided by the libraries. I haven't tried your example, but it looks like vanilla Julia. My familiarity with Matlab makes Julia an easy choice for me too.

Here is a simple example in J:

+/ % #

The above is an average function in J. It is a fork, where you fold right over the input (+/), and divde (%) by the tally (#) or count of items, so that

(+/ % #) 4.5 3 2 12

produces 5.375 as the average of the input vector. Notice the array-based language deals with singular quantities or scalars, vectors, and multi-dimensional arrays as fundamentals of the PL.

You could also define it as:

average =: +/ % #

for those who make the readability argument, however, you learn math symbols and read math papers full of them, and not lengthy verbal descriptions of these math formulas (average is equal to the "sum all of the input elements, and divde by the count or tally of input items").

The fact that a highly-functional APL program can fit on one screen negates the argument that you need readability, so that when you pick up or someone else picks up, your 110K lines of JavaScript code they can make a change. You may have to do a refresh read in APL and J, but because it is terse, you can deal it pretty quickly. Well-commented code in the 100k to 1 million lines of code scale will never allow one person to see the whole picture.

The work by Aaron Hsu in APL is amazing. Here is a link to the slides from a talk he gave. It's a bit lengthy but I found it very interesting and appropriate to this topic:

https://sway.office.com/b1pRwmzuGjqB30On

The YouTube link to the talk is here:

https://www.youtube.com/watch?v=9xCJ3BCIudI


Idk why apl or haskell would be any better.


I'm not as opinionated on Haskell, but APL is both a programming language AND executable math notation. It's just the notation is different than what most are already used to.


> Explicit sequences tend to be wrapped in angle-brackets, so that:

s = <s1, s2, ... sn> (Please note that in LaTeX, one should use \langle and \rangle for angle brackets--not less than and greater than.)

The article is pretty good overall, but I find this an little odd. I don't think I've ever seen sequences denoted with angle brackets. You usually see those used for denoting an inner product. I've only ever seen sequences denoted with parentheses, like (a_n) = (a_1, a_2, ..., a_n).

It's kind of humorous to me that we can sort of fingerprint the textbooks/lecturers people learned from by the idiosyncrasies of their notation.


Not sure what the point of translating math into code is. Just because we represent something with code doesn't mean it is computable. It's also technically incorrect to say math is translated into code. The mathematical symbols are being swapped with codey things, but the underlying semantics are quite different. For example, we might say the symbol 'oo' is infinity, but infinity itself is something that cannot be embedded in a finite program. So, we might be coerce a parser to realize that 1/oo=0 with a background ruleset, but the identity itself was derived by our minds accessing the mathematical world of forms that is completely inaccessible to finite computational mechanisms.

It seems like this effort is going to increase a lot of overhead to do math, and obscures the role of thinking through the math conceptually. There seems to be a Principia Mathematica 2.0 idea in the programming world that we just need to reduce mathematics to code and it'll become easily accessible and usable. I'm not convinced that will be the case.


You and I read the article very differently. Based on your comment, it sounds like you interpreted the article as implicit advocation for the idea that mathematics should be represented in a programmatic (i.e. computable) way.

I didn't pick up any ideology in my reading. My interpretation of the article is that the author wanted to provide tips on how to implement mathematics, for two reasons:

1. People have to implement nontrivial mathematics from time to time, and

2. Most mathematics doesn't concern itself with obstacles to implementation, because it doesn't have to.


That's true, and numerical analysis can be quite helpful for mathematical insight. However, I've never found the math to code part to be tricky. It's mostly an after thought compared to the conceptualization itself. So the emphasis on coding math suggests a reversal of priorities. In my experience, focusing on the coding part becomes very inefficient, especially with combinatorial problems. No matter how tricky I get with the implementation, a combinatorial explosion is still a combinatorial explosion. Coming up with a neat analytic solution ends up being super efficient in comparison.


>infinity itself is something that cannot be embedded in a finite program

I am not sure what you mean by infinity here, but there are many ways in programming to handle infinite streams in an otherwise finite program. Python's itrrtools.count and the ability to map and filter over it would be a basic example.

Indeed I could argue that every game's or webserver's event loop is embedding infinity in a finite program.


What you are describing is a potential infinity. I'm talking about an actual infinity.


How is ∞ more "actual" than Python's itertools.count or float('inf') ?


The symbol is not an actual infinity. The abstract concept we access with our minds is an actual infinity. That's the point. The abstract principle cannot itself be embedded in a program or symbol. All we can do is describe it with rules we infer from observing it. Like a painting of a tree will never be the tree itself, and we will not be able to infer everything about the tree just by looking at the painting.


>> completely inaccessible to finite computational mechanisms.

I assume you have already proven we ourselves are an infinite computational mechanism?


We can imagine infinity and its implications. E.g. what is the largest number? After thinking about it a bit, we realize there is no such thing. In that sense, we are not like finite computational devices. A computer cannot make the same kind of inference. It has to have the answer given to it.



This is great, but I'd love to see more Mathy languages added like APL, Mathematica, and Matlab/Octave.


Despite the title, this article does a real disservice to Python.

For the purpose of constructing a generator, the author wrote:

> In an object-oriented setting like Python or Java, streams can be constructed from an interface

Yikes. itertools was introduced in, let's see... 2003?


Python has both generator functions and generator expressions. A generator function is like this:

    def int_generator():
        i = 0
        while True:
           yield i
           i += 1
A generator expression looks like a list comprehension (a Python construct based on the set-builder notation in Math) and is used in situations where you don't really need to materialize the list - for example when you are just iterating over it in a `for` loop:

    for n, square in ((i, i * i) for i in int_generator()):
        print(f"{n}² = {square}")
        time.sleep(1)




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: