If you don't do math it's difficult to understand, but try writing without the alphabet and expressing the same concepts. Possible but clunky
If you don't do math it's difficult to understand, but try writing without the alphabet and expressing the same concepts. Possible but clunky
Suppose you write a function that uses a variable ω_0, and somebody else wants to change it. Unless they have the same keyboard setup as you, they will have to just copy-past it everywhere. And what if you have several variable with special names?
I can not effectively use my computer for anything without customizing the keyboard a little. I need to make the capslock key into an extra control key. I need to set up a compose key so I can type accents when writing in Spanish (even if I didn’t do that, what about writing people's names?). Even sticking with English, I need to type curly quotes and apostrophes, and em- and en- dashes, plus, now and then, symbols like ™ or ©. And I need to be able to type Greek letters when talking about physics or math. So, since my keyboard is already set up to handle all this, and it is easy to do so, for me it is delightful that I can use ω in my Julia code. The math looks more like math, equations take more familiar forms (which makes it easier to spot errors), and the code can be made more expressive. So, for me (but clearly not for everyone) this is not a “special” setup.
Current solution for most people is google + clipboard
For example, to type the word "cliché" here, I googled it, then copied it, then pasted it.
May be instead of arguing for Unicode, community needs to come up with a unambiguous smaller set of symbols languages should support.
Ill-considered backward 'compatibility' with block-drawing character sets for mathematical typesetting. (Fucked if I know which character set, but presumably the same one they found U+23B2 '⎲' and U+23B3 '⎳' in.)
Tell me what does ":" mean?
Now if I tell you the language is Typescript, what does "?" mean?
I personally believe semantic overloading causes a lot of problems, but we are so steeped in the existing limitations that we don't recognise it is a problem.
Language overloads things. Pretty much period. I doubt programming will get away from that.
We are so short of semantic operators that languages start to use single letters like "s", "q", " u" as operators or modifiers - which I find ugly (although the best compromise).
I have experienced how the wrong Unicode character can ruin my day - but that is what tooling and editors and best practice are there to help with.
Keyboards are the main problem now I think (in the past it was your OS, your editor, and your tooling). I regularly type Unicode characters from my handheld devices, but hardly ever from my qwerty entry devices (I can't easily find ¡, ∆, ↑ or ç as examples).
So...I don't see how this changes my point. The list of symbols that is a program will have many of those symbols in need of context to understand. Do you really think programming can escape that?
Edit: I am sympathetic. I like lisp for having fewer signifiers than other languages.
You should dream bigger. A better world is possible but only if people really want to throw out all the shitty designs from the ancient past
How should we do this?
I am imagining that we have a "char-bank" that lives on a little touch display at the left of my keyboard. I can add chars to my bank by highlighting them and pressing a 'yank' key. I can scroll up and down through my charbank and type the chars with a tap or rearrange them with touch-and-hold similarly to apps on a phone's homepage.
If I want to map a char to my keyboard, I can press and hold a "map" key, tap the char, and press the key I want to map it to. If I want to map the char directly from the screen I highlight it and press the map and yank keys together.
Vim/Kakoune users could have their help menu _be_ the keyboard. Every action changes all of your keys to whatever is possible. Sort of mind blowing.
Come to think of it, i bet someone has done this with Vim & LED Keycaps. Huh
Wow, this is an amazing idea. Think of all the other unimagined possibilities if we had real innovation in human-computer interface tech
I personally find it also helpful to make the distinction between the maths and its implementation, though I accept that others would vehemently disagree iwth me.
As they say, it's already way too easier to write code than to read it. A programmer should make every effort to make code more readable.
An editor should make it relatively easy to enter special symbols (especially if you can specify a limited set); it is totally solvable problem.
An editor can only help you so far with reading code...
The use of greek letters in academic writing has a single purpose: Compact notation. It has nothing to do with abstract readability.
The compactness of the notation is a major factor in overall readability. Long variable names make it harder to see the overall structure of an expression. When operators, numerical constants and parentheses mostly are represented with one or two characters each but variable names are all much longer, then the only thing you can tell about a long line of code at first glance is what variables it uses as inputs. Mathematical pretty printing can help with some operators (eg. fractions) and make it more visually apparent what's being grouped together by parentheses, but even then long variable names will still detract from the ability recognize the structure of an expression.
(a*(1+exp(1i*theta[0,:]))+foo(x))/((b-cosh(bar(x))+(b+sinh(y[:,-1])).
The sort of thing where it just _looks_ far nicer on a page with like _real fractions_ -- where missing a bracket or changing the order of two brackets can _totally_ bugger you. Yes, changing the form of the expression a bit can make it "far nicer" or simpler -- for example, by defining intermediate terms -- but sometimes there's something to be said for <expression x> matches <equation y> in the paper.Another example where I think ASCII actually _is_ limiting is for entries of matrices directly. I mean, we try, but I'm not convinced we succeed. For an example (picked at random), hands up if you think this is a nice Euler angle transformation, where cphi/sphi etc are the cosine and sine of phi? No matter how you write it, it's going to be ugly.
alpha = [cpsi*cphi-ctheta*sphi*spsi cpsi*sphi+ctheta*cphi*spsi spsi*stheta;
-spsi*cphi-ctheta*sphi*cpsi -spsi*sphi+ctheta*cphi*cpsi cpsi*stheta;
stheta*sphi -stheta*cphi ctheta];I'd probably go with something like:
double cf = cos(phi),sf = sin(phi);
double cp = cos(psi),sp = sin(psi);
double ct = cos(theta),st = sin(theta);
alpha = [ cp*cf-ct*sf*sp cp*sf+ct*cf*sp sp*st;
-sp*cf-ct*sf*cp -sp*sf+ct*cf*cp cp*st;
st*sf -st*cf ct];
but I agree it would look better with: alpha = [ cψ*cϕ-cθ*sϕ*sψ cψ*sϕ+cθ*cϕ*sψ sψ*sθ;
-sψ*cϕ-cθ*sϕ*cψ -sψ*sϕ+cθ*cϕ*cψ cψ*sθ;
sθ*sϕ -sθ*cϕ cθ];
Either way, I don't think Euler angles are ever going to be "nice". # this assumes that ϕ, ψ, and θ have already been set
my \cϕ = ϕ.cos; my \sϕ = ϕ.sin;
my \cψ = ψ.cos; my \sψ = ψ.sin;
my \cθ = θ.cos; my \sθ = θ.sin;
my \alpha = [ cψ×cϕ−cθ×sϕ×sψ, cψ×sϕ+cθ×cϕ×sψ, sψ×sθ;
−sψ×cϕ−cθ×sϕ×cψ, −sψ×sϕ+cθ×cϕ×cψ, cψ×sθ;
sθ×sϕ, −sθ×cϕ, cθ];
I'm not sure if using × helps or hurts in this case since I'm not really experienced in this area.These all work because Unicode defines ϕψθ as "Letter lowercase"
say "ϕψθ".uniprops;
# (Ll Ll Ll)
---I would like to note that I used the Unicode "Minus Sign" "−" U+2212 so that it wouldn't complain about not being able to find a routine named "cϕ-cθ". (A space next to the "-" would have also sufficed.)
Blech; looks like a letter and normalizes cross products. Better to use "·" (U+B7)[0]:
alpha = [ cψ·cϕ−cθ·sϕ·sψ, cψ·sϕ+cθ·cϕ·sψ, sψ·sθ;
−sψ·cϕ−cθ·sϕ·cψ, −sψ·sϕ+cθ·cϕ·cψ, cψ·sθ;
sθ·sϕ, −sθ·cϕ, cθ];
Minus sign is a nice-to-have, though.0: Also "∧" (U+2227, wedge), the real other vector product[1], but that doesn't matter for scalar multiplication.
my &infix:< · > = &infix:< × >;
(After all `×` itself is just an alias of `*` in the source for Rakudo.)If you need more control you can write it out
sub infix:< · > (+@vals)
is equiv(&[×]) # uses the same precedence level etc.
is assoc<chaining> # may not be necessary given previous line
{
[×] @vals # reduction using infix operator
}
I made it chaining for the same reason `+` and `×` are chaining.---
I don't know enough about the topic to know how to properly write `∧`.
It looks like it may be useful to write it using multis.
# I don't know what precedence level it is supposed to be
proto infix:< ∧ > (|) is tighter(&[×]) {*}
multi infix:< ∧ > (
Numeric $l,
Numeric $r,
) {
$l × $r
}
multi infix:< ∧ > (
Vector $l, # need to define this somewhere, or use List/Array
Vector $r,
) {
…
}
If it was as simple as just a normal cross product, that would have been easy. [[1,2,3],[4,5,6]] »×« [[10,20,30],[40,50,60]]
# [[10,40,90],[160,250,360]]
# generate a synthetic `»×«` operator, and give it an alias
my &infix:< ∧ > = &infix:< »×« >;
[[1,2,3],[4,5,6]] ∧ [[10,20,30],[40,50,60]]
# [[10,40,90],[160,250,360]]
Of course, I'm fairly confident that is wrong.I don't often write complicated formulae, but I do find it easier to use the original symbols if possible. Its one less thing to think about when comparing the source code with a mathematical description of the algorithm.
for some reason the entire Unicode "No" (Number, other) category is not included in the admissible character list for identifiers
Using these one letter variables forces the reader of the code to either be already familiar with the concept, which that letter refers to, or keep the whole calculation in their head, until the final result, to hope, that they then can make sense of it. It is implicitly requiring outside knowledge. It is shutting out many potential readers of the code.
It might still be saved/helped though, if good prose comments are given, that help the reader understand the meaning of the one letter symbols. Whenever I have seen this one letter code salad, I have seen few if any comments, as if the author of the code expects me to magically know, what each symbol stands for.
Lets say omega was a vector of weights. Why not name it "weights"? That is much better naming than "omega" or that character, that most cannot easily input and need to copy paste from somewhere.
(_ < 5)
Instead of this:
(e: Int) => (e < 5)
It’s just a trivial example so I understand if someone wants to have the same comfort. I am not a mathematician so I am not sure what is best here so I’d cut them some slack.
For example, suppose we have a function whose job is to calculate two vectors of weights and do something unless they are equal but opposite. Personally, I would rather read something like
v = someCalculation()
w = someOtherCalculation()
if (v ≠ -w) {
doSomething()
}
where we use short names for the local variables and vector-aware unequality and negation operators, than read something like weights1 = someCalculation()
weights2 = someOtherCalculation()
if (not(vector.equals(weights1, vector.negate(weights2)))) {
doSomething()
}
The longer but still arbitrary names for the vectors add no value here and the longhand function names for manipulating them are horrible compared to the short and immediately recognisable vector notation.In general, I think there could be advantages to using a broader but still selective symbol set for coding, as long as we also had good tool and font support to type and display all of the required symbols. I would be hesitant about including Greek letters in that symbol set, but that’s because several letters in the Greek alphabet look similar to other common letters or symbols, not because I think calling a value ω_0 is a bad idea if that’s how practitioners in the field would all write it mathematically.
When you're writing code for physics, then yes - absolutely: It is intended for other physicists, and the prerequisite is precisely that you have outside knowledge. When they use a symbol like ℏ in a journal article, it is expected that the reader knows it is Planck's constant[1]. Why should they have a different expectation when writing code? To a physicist, -ℏ^2/(2 * m) is a lot more recognizable than -planck^2/(2 * mass).
To be clear: The chances that a person who doesn't recognize these symbols will need to read and understand your code are virtually nil.
Within a context, single character symbols are very useful. To take a different example, what if I insisted that people should write:
2 add 3 add 7
instead of:
2 + 3 + 7
Would anyone reasonably argue that the former is more readable? We all accept that it's OK that a reader is familiar with the '+' sign. While ℏ is not readable to most, it is likely readable to anyone who is expected to read the code.
The thing that really is annoying when writing physics code is the need to explicitly write * for multiplication, and not being able to write fractions the way you would on paper.
[1] divided by 2π
G_{ab} = 8 \pi T_{ab}
does not benefit from being converted in code to, einstein_tensor[index1][index2] = 8 * PI * stress_energy_tensor[index1][index2]
For a practitioner of physics, this is just unhelpful and takes more effort to comprehend. In the spirit of The Humble Programmer, we have unwisely spent the mental energy of the reader. If you actually expand out the Einstein tensor in terms of the Levi-Civita connection and spell it out instead of using the canonical symbol \Gamma and respectively g for the metric tensor then you will just make an incomprehensible wall of text--especially if you inline the summation. What is added by expanding the variable names? A practitioner has gained nothing and lost familiarity and compactness while a layperson has learned nothing about general relativity except the names of the objects. Don't apply best practices uncritically: they are always premised on context.That being said, formulae would benefit greatly from editors that allow the formula to be visualized next to the code. Sort of like compiling latex; if IntelliJ or some other IDE would actually render the code as a formula in some pane next to the code, that would be the greatest benefit to comprehension of a formula.
You can do that in a general function, where the general concept is expressed, where it would still help me to understand your code and search for concepts and terms online, in case I do not understand what is going on.
However, in many contexts it wont be merely an "einstein_tensor", but something that has a meaning in the specific context. Ask yourself what you are doing with that einstein_tensor. What is it used for? Is there a real-world equivalent to the thing you are looking at in the code? Those are the names you should choose in a non-general context and that is why naming things is hard.
Here is a more appropriate example, spot the bug in this Tolman-Oppenheimer-Volkoff equation:
let radial_derivative_of_pressure = - (pressure + energy_density) * (4. * PI * pressure * radius_squared + mass_potential) / (radius_squared - 2. * mass_potential * radius)
vs (with the same bug) let dp_dr = - (p + rho) * (4. * PI * p * r2 + m) / (r2 - 2. * m * r);
Of course you have to look up the TOV equation to do so, even most domain experts would need to compare to a formula. One of these is much easier to compare and it isn't the spelled out version.Your questions are unhelpful. It is merely the radial derivative of pressure. It is going to be used to be passed to a general purpose ODE integrator which just needs the radial derivative of pressure to integrate pressure for some range of radii. There is a real world equivalent: dp/dr; it is a known entity with exactly that symbol. Naming is not at all hard in this case: dp_dr or dpdr even dp_by_dr. Any other choice and you are just creating problems due to uncritical application of the belief that variable names should be descriptive while ignoring the fact that there is a well known ubiquitous language to describe these entities.
The closest thing in other business domains is common acronyms. Nobody is going to spell out GDPR in the implementation of their cookie banner. Nobody spells out HTTP, or JSON, or XML. Spelling them out won't help anyone trying to read the code, it just creates line noise.
Mathematicians are used to using one letter variables. Using a set of unwritten naming rules, mathematicians almost always know what concepts the variables are referring to (in a mathematical context).
So, I'd say if the code is only to be maintained by mathematicians, one letter variables for mathematical concepts only, would be an advantage.
The danger comes when you start using them for everything.
> Using a set of unwritten naming rules
Simplest being things like using upper case Greek for certain sets and lower case Greek for its elements. Or, in Statistics, using Greek letters for parameters and English equivalents for their estimates.
So, if I were programming something to do something in that realm, I would write:
for my $ω ($Ω) {
# ...
}
where what Ω represents would be clear from the subfield of Math that is relevant to the program.Then, of course, you get people like one of my former professors who liked to invent notation on the fly and would quickly and up cycling through Greek (π, Π), Hebrew (פ), Blackboard (ℙ), and reach out for Sanskrit (?). (Symbols used here for illustration, this was a long time ago and we didn't even know if he was correct as we had no way of checking with no intarwebs back then.)
A typical program contains thousands and thousands of "named things", so you're naturally going to see a proliferation of names. That just doesn't seem to be that necessary in math once you're working in a particular context (e.g. statistics).
Currently learning some dsp. One of the biggest barriers to entry has been the inscrutable variable names inherited from the field’s math connections.
Which are? I suspect the reasons are a combination of the price of paper and ink, the history of teaching using chalkboards. None of those mean we can’t make the canonical version of an equation the expanded representation.
Why do we all know e=mc2 and not energy = mass * lightspeed^2.
The broader the base of people that have to interact with a formula, the less mathy the terminology tends to be. Think of trigonometry. Instead of greek letters the sides of a triangle and the functions get real world names. Sine(angle) = opposite / hypotenuse. Sure when you write that out you use sin ϴ = O/H but that’s just a compressed representation of human-readable variable names.
So per your point - I'm not qualified to re-define mathematical notation so I won't go very far with it, but taking the formula you mentioned, Gaussian distribution density function (not focusing on the fact that I had to re-write it in pseudocode to represent it in a text format):
f(x) = 1/(σ * sqrt(2*pi))*e^(-1/2*((x-μ)/σ)^2)
I would suggest a couple changes:- change σ to `standard_deviation`, or if you don't like snake_case I could handle `stddev`
- change μ to `mean`.
- change x to `input` - there may be a better name than that, and x is pretty widely used in math so I'm not married to this one.
- e should probably stay the same - e means e no matter the mathematical context, while μ means different things in different fields of math.
f(input) = 1/(standard_deviation * sqrt(2*pi))*e^(-1/2*((input-mean)/standard_deviation)^2)
This doesn't make it more or less readable, but it does mean I don't have to _just know_ or look up that μ is `mean` to parse it.