Hacker News new | past | comments | ask | show | jobs | submit login
Fortran is easy to learn (craftofcoding.wordpress.com)
100 points by Bostonian on Jan 8, 2022 | hide | past | favorite | 122 comments



Ancient FORTRAN, as opposed to complicated modern Fortran/C++/Rust, has a huge advantage if you ever crash your spaceship on a resource rich alien world and have to build a programmable computer from scratch from first principles using only knowledge that a single human could memorize. Modern languages require nontrivial compiler theory to parse a sequence of language symbols into an Abstract Syntax Tree (AST), etc. But Ancient FORTRAN is essentially designed to be read in and translated just a few 80 column punch card lines at a time, much like assembly languages. Compilers were written that could fit inside computers with only a few thousand words of 16 or 18 bit memory. Magnetic Core memory from that era was often made by hand, by little old ladies weaving it in factories I've been told, and was used for the Apollo moon spacecraft and was extremely reliable:

  https://en.wikipedia.org/wiki/Magnetic-core_memory
Ancient LISP and BASIC variants also stand out in this regard of not requiring you to undergo years of training and theory to implement and fully understand.

Fabrice Bellard's minimalist but complete quickjs.c Javascript interpreter is presently about 54,000 lines of C:

  https://github.com/bellard/quickjs/blob/master/quickjs.c
Javascript is an enormous, complicated, designed-by-committee language, as are essentially all other languages we are forced to use. I do hope there is a renaissance of simpler technology, technology not driven by competitive egos but by a desire for the joy of simplicity and understanding. But such simpler technology won't be useful for building backend infra for Big AdTech ad-bidding exchanges so that we can be bombarded with ads for One Weird Trick to burn belly fat or whatever.


I would disagree on that. Parsing theory made it easier to write parsers, not harder. Separating the process into lexical and syntactic analysis makes for a much clearer structure than some ad-hoc parser. And writing a recursive descent parser for a language with an appropriate grammar is not hard and can be quite enjoyable.


I don't think recursive decent parsers is what people think of when it's about "parsing theory". In my mind the theory is more about classifying arbitrary languages that were not necessarily designed to be easily parsed by machines, and about models to parse them nevertheless.

If you write a recursive descent parser, you're probably parsing a language that was explicitly designed to be parsed with straightforward code, and that can mean the language is compromising on brevity and expressivity sometimes.


OTOH parsing with a recursive descent parser requires either a machine with a stack and the approriate calling conventions OR a lot of work to fake it. FORTRANs before F90 had no recursion (and you still have to explicitly declare that a function is recursive), and many early and easy architectures have no hardware stack.


If you like simple language cores look at chapter IV in "Early History of Smalltalk" for the one pager that became Smalltalk-72. http://worrydream.com/EarlyHistoryOfSmalltalk/


I’d Love to see you try given no resources other than what’s in your brain to build a Fortran punchcard interpreter from scratch.


In my undergrad computer science program, I implemented the rudiments of a very simple CPU using AND, OR, and NOT logic gates. I learned how to program microprocessors in assembly language. I learned how to implement a programming language interpreter. I implemented a compiler with a lex that tokenized its input stream and had a parser that built an AST from said tokens, and had a code generator that walked the AST and output a sequence of instructions. This was all covered in an undergrad CS program, not a Masters or PhD, so you don't have to be a genius at the level of John von Neumann to design programmable computational machinery from scratch using only the resources in your brain, because the geniuses like von Neumann already invented it in their brains instead, and good teachers at universities have found gentle ways to pass it from their brains into your brain.

The original FORTRAN '57 did not even have SUBROUTINE, FUNCTION, CALL, etc., for implementing subroutines. Those came with FORTRAN II in 1958, which was the main language Kemeny's original BASIC was based on in the early 1960s, but Kemeny changed FORTRAN II's DO loop to the easier to remember 'FOR I = 1 TO 42 ...'.

Knuth designed his original 1960s MIX computer using just pencil and paper, designed it to be easy to run programs using just pencil and paper.

If you yourself could not build a rudimentary BASIC or cut-down FORTRAN using only the resources in your brain and a sheet of paper with a pencil, you might be spending too much time working with overcomplicated programming tools that do not bring joy to your life.


Ignoring the presence of "(*, *)" in the Fortran program -- which is the equivalent of all of the format string and type complexities in the C, Python, and Julia programs -- is a serious deficiency of the argument here. As soon as you start writing something more complicated than Hello World: The Sequel, those complexities become something that language learners need to engage with.


Agreed. I'm a (very) long time Fortran user, and a more recent C, Python, and Julia user. I'd agree that scanf is a pain. The chomping/parsing bit can be, in all cases, hidden behind a convenience function, which if you like, you can name "read".

FWIW, I've been using Fortran since the mid 1980s, C from the mid 90s, Python from the mid 00s, and Julia since 2012 or so. All of these languages are fine for the example provided, and all are understandable. Each of these languages require some minimal boilerplate around the core algorithm to make it work. Specifics of input and output mechanisms would be language/dialect specific.

Really, each of them is fine for this trivial example. Its when you start getting into serious translation of the underlying math into something the language will understand, that the real difference stand out.

That's when both Fortran and Julia stand out. Both are designed to make this process as painless as possible. Fortran was designed and built almost 70 years ago. IO was very painful then, and while the language itself is very simple and easy to understand, the IO system is still quite similar to the early days.

The "(,)" notation combines units (file descriptors), and formatting. It is not different in intent than the scanf and other functions.

Why Fortran and Julia are so easy to use comes from the expressiveness of the language, the simple mechanism of writing code that looks close to the formulae in question. There is no fiddling with array indexing that doesn't start where the formula indicates. No allocating arrays of arrays to build matrices.

That is, it is simple to go from conception to working code very quickly. In a manner that really does look like the way you would do it on paper.

That's why Fortran is still in use, and growing. And why Julia is catching on quickly.


I don't think 1 based indexing is that useful. A lot of mathematics formulae start from 0 too and 1-indexing makes that more awkward.

Although I agree that some languages like Julia and say MATLAB feel more fluent to express mathematics.


Luckily, Fortran allows easily changing from one to the other. You simply define arrays as A(1:10) or A(0:9) and they will index from 1 or 0.

You can even do arbitrary indexing: fixed like A(-3:3) or dynamically like B(n1:n2). This may sounds useless but it's actually an excellent feature when writing eg convolution kernels.

I don't know of any other languages beyond Fortran and Julia that have arbitrary array indexing as a core feature (you can fake it in C in two lines I guess).


Wow that's incredible and really changes my opinion on Julia's indexing.

It is small but really makes things more elegant. I should definitely try Julia. I've spent a lot of time calculating awkward array index conversion formulae in my head and this could make things a lot more simple especially for weird cases.

I was under the impression that Fortran's only redeeming benefit was that it compiled well for numeric computing routines.


Again, to be clear, Julia does not have arbitrary indexing as in Fortran. It has an external package that can mimic arbitrary indexing of Fortran.


That's not a meaningful distinction. Julia is a powerful enough language that OffsetArrays don't need to be built in to work perfectly. Good languages don't need everything built in.


The comment above states: "...Julia that have arbitrary array indexing as a core feature...". Is an external package written in Julia considered a "core" feature of the Julia language? Why does the Julia community always twist the facts? Why cannot they accept the facts as they are? It would not reduce the value of their efforts, I guarantee you—decency and honesty always prevail.


Julia's docs say that it supports "Julia supports arrays with arbitrary indices": https://docs.julialang.org/en/v1/devdocs/offset-arrays/

So let's break that down.

The base standard library and "idiomatic" Julia are both largely written without the assumption of 1-based indexing, instead dispatching to what you think about as an array-oriented dsl, which is this interface: https://docs.julialang.org/en/v1/manual/interfaces/#man-inte...

It is very normal in Julia to implement such interfaces to do what you want. Julia uses these types of internal interfaces with multimethods in lieu of a lot of compiler intrinsics.

So I would say Julia and Fortran have different implementations of arbitrary indexing.

They are both oriented around core design features of each respective language.


Yes, Julia does support arbitrary indexing because base functions are written in terms of `firstindex`, `eachindex` and `lastindex` etc.

One can see it in the implementation of `filter!` for example https://github.com/JuliaLang/julia/blob/ab4e036b9209967b4273... :


External Julia packages can impliment core features. For another example, look at StaticArrays. Fortran is a brittle old language where everything supported must be built into the language. Julia isn't.


Again, twisting facts by some Julia novice about a topic they have no familiarity with. Fortran does not require features to be built-in. Look at all the intrinsic Fortran modules. But array-based indexing IS built-in to the language. Unlike Julia, you do not have to rely on an external package for it. Perhaps the Julia community's relatively young age has made it so arrogant, Machiavellian, and fact-twisting about other languages to prove their presence here and there. Other programming communities are old enough to put decency and honesty in their core values.


I also find it interesting that you assume I'm a Julia novice. I use Julia for my job, and have a few dozen commits to Julia (and several to packages)


Julia's compiler is made to be extendable. GPUCompiler.jl which adds the .ptx compilation output for example is a package (https://github.com/JuliaGPU/GPUCompiler.jl). The package manager of Julia itself... is an external package (https://github.com/JuliaLang/Pkg.jl). The built in SuiteSparse usage? That's a package too (https://github.com/JuliaLang/SuiteSparse.jl). It's fairly arbitrary what is "external" and "internal" in a language that allows that kind of extendability. Literally the only thing that makes these packages a standard library is that they are built into and shipped with the standard system image. Do you want to make your own distribution of Julia that changes what the "internal" packages are? Here's a tutorial that shows how to add plotting to the system image (https://julialang.github.io/PackageCompiler.jl/dev/examples/...). You could setup a binary server for that and now the first time to plot is 0.4 seconds.

Julia's arrays system is built so that most arrays that are used are not the simple Base.Array. Instead Julia has an AbstractArray interface definition (https://docs.julialang.org/en/v1/manual/interfaces/#man-inte...) which the Base.Array conforms to, and many effectively standard library packages like StaticArrays.jl, OffsetArrays.jl, etc. conform to, and thus they can be used in any other Julia package, like the differential equation solvers, solving nonlinear systems, optimization libraries, etc. There is a higher chance that packages depend on these packages then that they do not. They are only not part of the Julia distribution because the core idea is to move everything possible out to packages. There's not only a plan to make SuiteSparse and sparse matrix support be a package in 2.0, but also ideas about making the rest of linear algebra and arrays themselves into packages where Julia just defines memory buffer intrinsic (with likely the Arrays.jl package still shipped with the default image). At that point, are arrays not built into the language? I can understand using such a narrow definition for systems like Fortran or C where the standard library is essentially a fixed concept, but that just does not make sense with Julia. It's inherently fuzzy.


I wasn't sure. I googled it and it was in the Julia docs but I didn't look at the details to see if it is first-class.

The fortran version is super neat, especially in conjunction with stack allocated multidimensional variable length arrays.


Much of Julia language is written in Julia. So the 'external package' is just an extension you install/use if you wish. A distinction without a difference.


Ada and many BASICs also permit using arbitrary ranges. Ada even takes it further, any range over a discrete type can work including characters and arbitrary enumerations.


Ada has adopted it from Modula-2/Pascal.


A lot of formulae start from 1 too. And in linear algebra, most of them do.

It's like driving on the left side of the road instead of the right side of the road. Inconsistency is what makes it painful.


I am convinced a good fraction of the off by one errors in C like languages comes from 0 indexing. The ith element is found after traversing i+1 elements and that fact leads to mistakes all the time. With 1 indexing the numbers line up.


I agree. There's far less of a cognitive load for developers associated with representing an expression as written, if you don't need to mess with indices, in order to accommodate the language and its vagaries.

One should not need to adjust the way one expresses an algorithm, because of opinionated language design decisions. Put another way, languages designed for scientific/engineering computing won't have a hard/fixed opinion about things that shouldn't be worried about.


Indeed, polynomials, for instance, start with a power of zero. At the same time, there is a reason why the natural numbers begin with 1, and, in practical terms, there is a certain convenience in the count (size) being the same as the last index.


The natural numbers don't start with 1... The convention is inconsistent, but for many mathematicians, especially including logicians, they start with 0. It is best not to use the term "natural numbers" at all.

By the way, your point about polynomials works in favour of the convention that 0 is a natural number.


Try thinking of being the zeroth person in a line. Or your child being in the zeroth year of her life.


How many lions are in my room at the moment? Hopefully zero.


But zero sheep is not a flock.

(Besides, there's uncountably many things you have zero of in you room.)


> But zero sheep is not a flock.

So one isn't a natural number?

> (Besides, there's uncountably many things you have zero of in you room.)

;) Exactly. Zero is the most natural number.


So, on your scale, which is the first natural number?


> Why Fortran and Julia are so easy to use comes from the expressiveness of the language, the simple mechanism of writing code that looks close to the formulae in question

Why would it not in any other languages?


Some other languages have attempts to emulate it (like some matrix classes in c++ and numpy), but it is not that great. You can make it look close in some places at the cost of more complexity elsewhere. It also feels bolted on with more or less opaque data structures manipulated by ad hoc functions. There always are strange edge cases where the library fights against the language. The TKR (type, kind, rank) concepts are at the very core of the variable model in Fortran, and n-dimensional matrices are first class variables just like scalars, and are much more natural to use. Elemental functions are very useful and trivial to implement in Fortran. Coupled with the great array syntax and easy user-defined operators, it makes writing complex numerical expressions very satisfying and elegant. Granted, some other parts of Fortran are far from elegant.

I am not saying it makes other languages unusable (I use numpy arrays quite frequently; Python and Fortran are very complementary), but definitely less natural and elegant.


With Python+Numpy, my issues are or were:

  1. The matrix multiplication syntax used to be bad. But it became possible at some point to write A @ B for the product of A with B. And that seems fine to me.

  2. The code seems more natural when you write `sin(array([1,2,3]))` instead of `np.sin(np.array([1,2,3]))` -- which you can achieve by running `from numpy import *`, but doing this is discouraged by a lot of people.

  3. The convention in Linear Algebra is that indexing starts from 1, not 0. This sometimes makes translating from a language which follows the more usual convention difficult.
Overall though, I think only 3 is unfixable, but this is usually a minor problem. Usually, Python+Numpy doesn't seem any worse than Matlab syntax-wise.

I find the experience of using Pandas to be much worse. Sympy also feels abrasive because of needing to write `m12 = var('v12')`.


Well, ignoring the presence of "(,)" in Fortran is exactly what one should do.

Recall that FORTRAN stands for FORmula TRANslator.

FORTRAN is built for math. It makes math expressions — particularly, linear algebra stuff — easy to write, and running very, very fast. There are much better tools for text processing (there's perl, python, pandas, and everything in between). But for raw math, there's Fortran.

That's why everything is still powered by Fortran.

Yes, from Matlab to your fancy neural network, numpy, scipi, scikit-learn, etc., the actual computational core - BLAS/LAPACK is Fortran-based.

That's why Matlab feels like Fortran. And that's why numpy semantics are different from python's: because it is heavily inspired by Matlab, and, like Matlab, wraps FORTRAN code in a friendly manner.

But in the end, it's FORTRAN all the way down. Even in Julia.

(And that's how I ended up fixing a minor bug in Google's FORTRAN sparse svd package, PROPACK[1], in 2019. Well, PROPACK was written before Google existed, but they have hired the author for a reason. The bug was only in the way an error message displeased the internal memory leak checker; in other words, FORTRAN text I/O was an issue. Stay away from that, and it's the best tool for the job.)

[1] http://sun.stanford.edu/~rmunk/PROPACK/


> But in the end, it's FORTRAN all the way down. Even in Julia.

That's not true. None of the Julia differential equation solver stack is calling into Fortran anymore. We have our own BLAS tools that outperform OpenBLAS and MKL in the instances we use it for (mostly LU-factorization) and those are all written in pure Julia. See https://github.com/YingboMa/RecursiveFactorization.jl, https://github.com/JuliaSIMD/TriangularSolve.jl, and https://github.com/JuliaLinearAlgebra/Octavian.jl. And this is one part of the DiffEq performance story. The performance of this of course is all validated on https://github.com/SciML/SciMLBenchmarks.jl


Is the recursive comparison against OpenBLAS using ReLAPACK or the normal(?) one? I don't remember the story on building with that or know the different algorithms.

Does Julia not use OpenBLAS at all now?


Julia defaults to OpenBLAS but libblastrampoline makes it so that `using MKL` flips it to MKL on the fly. See the JuliaCon video for more details on that (https://www.youtube.com/watch?v=t6hptekOR7s). The recursive comparison is against OpenBLAS/LAPACK and MKL, see this PR for some (older) details: https://github.com/YingboMa/RecursiveFactorization.jl/pull/2... . What it really comes down to in the end is that OpenBLAS is rather bad, and MKL is optimized for Intel CPUs but not for AMD CPUs, so when the best CPUs are now all AMD CPUs, having a new set of BLAS tools and mixing that with recursive LAPACK tools is either as good or better on most modern systems. Then we see this in practice even when we build BLAS into Sundials for 1,000 ODE chemical reaction networks (https://benchmarks.sciml.ai/html/Bio/BCR.html).


The question was whether the comparison was against OpenBLAS built with recursive LAPACK routines (not the default, I've now checked). I don't know whether that would use the same algorithm.

I don't see great attraction in "flipping" to MKL. (In general I switch BLASes by dynamic linking if necessary.) I'm puzzled by the value of "rather bad" for OpenBLAS, at least for BLAS [1], but it seemed OK against MKL for LAPACK-based R benchmarks I measured on sandybridge. That said, I don't understand why people avoid AMD's BLAS/LAPACK (BLIS/libflame with enhancements intended for merging) on AMD systems. In this context: BLIS studiously avoids Fortran for some reason, even for test the Fortran interface.

I have nothing against Julia, incidentally; I have the original Dylan book.

1. https://git.sr.ht/~fx/blis/tree/performance/docs/Performance...


It doesn't look like you're measuring factorization performance? OpenBLAS matrix-matrix multiplication is fine, it just falls apart when going to things like Cholesky and LU. Also it falls apart on smaller problems, like <100x100 cases.

> not the default, I've now checked

Whatever the Julia default build is doing, so probably not the recursive LAPACK routines then if that's how it's being built. If there's a better default that's worth an issue.

> That said, I don't understand why people avoid AMD's BLAS/LAPACK

There just isn't a BLIS wrapper into Julia right now, and it's much easier to just write new BLAS tools than to build wrappers IMO. It makes it very easy to customize to nonstandard Julia number types too. But I do think that BLIS is a great project and I would like to see it replace OpenBLAS as the default. There's been some discussion to make it as easy as MKL (https://github.com/JuliaLinearAlgebra/BLIS.jl/issues/3).


OK, no, I measured level 3 BLAS, and it sounded like a blanket dismissal of OpenBLAS. I'm surprised at it falling apart at all, but I haven't considered its LAPACK much and I value understanding from measurement. The set of R LA benchmarks I ran on sandybridge in response to theories about the Microsoft R distribution did include Cholesky. (I think the operations are a thin wrapper over LAPACK ones.) In that case OB was actually better than MKL for Cholesky with the versions I had then, so I'm puzzled. Probably I should revisit that sometime.

OB seems to me a better general default than BLIS, though its threading implementation may not be robust. BLIS is even broken on POWER9, and I don't remember whether the dynamic micro-architecture selection ever added for other than x86.

For really small matrices on x86, I'd front BLAS with libxsmm, but I don't remember where it starts winning, or know the threshold for BLIS' non-packed kernels.

Anyway, thanks for the info. I should be embarrassed never to have made time to look seriously at Julia.


Yeah no worries. You might want to join in the community at least because this kind of discussion is par for the course on the Slack. You might find a nice home here!

> though its threading implementation may not be robust

That's one of the main issues I have with it. Its poor threading behavior coupled with a bad default (https://github.com/JuliaLang/julia/issues/33409 one of my biggest pet peeve issues right now) really degrades real user performance.


> Even in Julia.

Unless you're using [Octavian.jl](https://github.com/JuliaLinearAlgebra/Octavian.jl) or such for your linear algebra in place of BLAS. But yes, it is always interesting how many people do not know how much of modern software is built on Fortran!


This is a reasonable argument, but it implies that FORTRAN is in fact not a good language for beginners; almost all beginners care about IO / text processing, and almost none care about linear algebra. (Especially if one is talking about beginners-in-general, as opposed to engineering types who are learning to use programming as a tool.)


Sure, but that still means FORTRAN is an easy language if your intro to programming isn't centered around text processing.

And for many people, it isn't/hasn't been/doesn't have to be.

That's the author's take as well:

>The idea of introductory languages is not necessarily that they are suited to commercial endeavours, but rather that they are (i) easy to implement algorithm in, (ii) readable, and (iii) do not contain things that will confuse and bewilder.


Have you ever thought it was because the tutorials you read were geared towards a type of programmer that had different goals from a computational programmer?


What high performance BLAS do you have written in Fortran? I don't know of one (though I think I could write one with decent performance on simple targets). It seems the rule that this will come up whenever Fortran is pushed, though I don't want to disparage Fortran after so long.


Yeah it's funny because they are all C these days.


Well, C plus assembler, or maybe non-standard machine-specific intrinsics, for the ones I know. They at least seem to need control over prefetching.


As a data processing language, IDL/GDL is even closer to Fortran. It's essentially a vectorized, interpreted, simplified Fortran. In many ways I still prefer it to Python these days.


First: Very convenient to provide a numerical program to showcase.

Mainly:

> Certainly things like I/O are still problematic for the novice programmer in these languages.

Poor I/O basically killed my interest in programming in most languages when I was a novice. BASIC was great for this. QuickBasic was, and probably still is king. People new to programming want to do fun stuff, and it's very hard to do without I/O. Me and most of my peers spent a fair amount of their hobby programming writing very simple games, or doing fun graphics stuff (drawing lines, circles, etc).

After doing this for a while in BASIC and QB, "serious" languages like C/C++ were pure Hell. I could literally do none of the cool things I used to with only a rudimentary command of the language. Did not know about Perl/Python until much later.

In my opinion, if you want learning languages to be fun, provide one where:

- Text I/O are no-brainers

- You can easily respond to keypresses (i.e. detecting if a button was pressed and not having to wait till the user hits Enter).

- Rudimentary graphics: Plotting a point, drawing a line and circle. Coloring it as desired.

- Easy way to generate random numbers.

Teach people these things, and they can have a lot of fun with loops, conditionals, and functions.


I remember some people i know learning programming using DarkBASIC which had a custom fullscreen IDE[0] very reminiscent of QBASIC, though unlike QBASIC it was focused on making games (especially 3D games). It provided out of the box commands for graphics, sound, music, etc (IIRC you could place and animate a 3D model with a couple of lines of code and the examples were simple 3D games[1]) and had integrated hypertext help that taught the basics of programming, among others[2]. Also had a CLI (inside the IDE) for quickly trying out stuff.

It was later replaced by DarkBASIC Pro (which was eventually open sourced years later) but that one used a more traditional IDE that was kinda reminiscent of a simplified Visual C++ 2005 and had a more complex language.

[0] https://i.imgur.com/UKZtMue.png

[1] https://i.imgur.com/lslPht6.png

[2] https://i.imgur.com/TqrSzEe.png


That's exactly why it took me ages to finally get into other programming languages besides QBASIC and Visual Basic, and primitive ES3 era JavaScript. I'd try to learn C, but it was immediately obvious that there would be a long road to doing anything interesting. If I could easily do I/O with QBASIC, it was hard to justify spending hours reading a bunch of boring books to do the same thing with C/C++.

Looking back, I think QBASIC/QuickBasic had it right in contrast to other learning languages. You don't need a DSL, turtle graphics, drag-and-drop code blocks, or any of that stuff to teach programming. Just make the hurdle to getting useful input and output minimal, and the prospective programmer can take it from there.

On the other hand, I do wish I had been able to pick up things like C much earlier in life. Only recently did I actually learn C++ in my 30s, even though part of me wanted to learn it when I was 9. I think that things like QBASIC can also be a sort of trap because if the I/O is so easy then it can be difficult to leave it for something that actually is better but not in an obvious way to a novice.


Fortran is great for computational programmers (ie. scientists) who can code things up without worrying about certain details that you need to keep straight in other languages. A lot of the things you're talking about are for general programming for which Fortran is not well suited. May be your initial interest in programming comes from games essentially which is why Basic appealed to you. For a fortran programmer, the initial interest comes from "what tool does my advisor use to calculate light propagation in semi-ionized media" and for that Fortran excells.

When evaluating what is good for beginners it helps to remember not all beginners approach programming from the same place. Traditionally computational scientists were a distinct and equal in size subset of the users of computer resources in academic and industry research centers accross the nation, specifically distinct from computer scientists. Today they are smaller total fraction but that history continues to inform how they approach computation and mentor new scientists learning to use computers for science, which diverges from the way computer scientists do both in approach and requisite mental model.


> A lot of the things you're talking about are for general programming for which Fortran is not well suited.

The article is about teaching programming in general, not teaching it for computational needs:

> in any respects modern Fortran is an exceptionally good language to teach programming in

> Partially it is because modern Fortran is easy to read and comprehend, which is an important factor for the individual learning to program for the first time.

> The idea of introductory languages is not necessarily that they are suited to commercial endeavours, but rather that they are (i) easy to implement algorithm in, (ii) readable, and (iii) do not contain things that will confuse and bewilder.

You can also see his prior blog posts where again he is speaking about learning programming in general - not limited to computation.


This is pretty much embodied by creative coding environments[0] like Processing (https://processing.org/) which is how I got my start in programming and incredibly fun

[0] https://en.wikipedia.org/wiki/Creative_coding


Output (text output) isn't bad in C, but indeed input is another story (either lacking like keypresses, or when a convenience like scanf() is provided, it is full of traps for beginners).

Its origin is really showing: UNIXes and their line-oriented terminals. No notion of a screen-oriented console, let alone a graphical one, unlike most BASICs aimed at personal computers.


> Output (text output) isn't bad in C

It's still poor compared to most languages I've used. String formatting is not simple for beginners. In Python you can do:

    print(num_eggs)
where num_eggs is an integer. In C you have to do:

    printf("%d", num_eggs);
One is much simpler than the other.

And on top of that, I detest languages that force you to manually enter newlines by default. Probably over 90% of use cases require a newline, so why not have the function add it by default, and either provide another print function or optional parameter for the times when you don't want a newline? The "I forgot to add a newline" headache is extremely annoying. Whereas in languages that add it by default, I rarely find myself saying "Ouch. I actually didn't want a newline there."


I had the same experience going from qbasic to c++, but then I found the SDL library that could do all these things (input, graphics, time, ...) and I could have fun writing simple games again!


Easy dependencies are also a huge boon for fun, I remember having a lot of frustration with python in that regard.


GFA Basic on the Atari ST was great in all respects you mentioned.


Something tells me you have more ideas on how to make a language or programming environment more welcoming, and less intimidating for new learners. Please go on :-)


Never thought of it beyond what I wrote - mostly voicing my own personal frustrations with learning languages. I finally had to learn C/C++ in university, and was quite good at it, but avoided programming until I learned Perl some years later.

I do think that if one is an engineering student (not necessarily CS/CompE), then it's more useful to teach how to do useful stuff (e.g. automation) in languages like Python. In my day most schools used either C/C++ or Java - both of which are not very useful for people whose primary job is not coding. Engineering students would take that one course and that's it. However, I suspect most engineers will benefit greatly if they knew Python. Lots of tedious stuff to automate.

Even if the introductory course uses Python, I think they should cover useful tasks for automation - handling directories, and perhaps some basic network related stuff via requests. If you can't squeeze it into one course, make another one and make it mandatory. It'll be more useful than many engineering courses they'll take.


A minor quibble: The article leaves out the commands needed to actually run the program. Also, just for grins, the first language I learned:

    10 INPUT "Height above sea level(m)", H
    20 D=SQR(2*6367.45*(h/1000.0)
    30 PRINT "Distance to horizon", D
    RUN


Yes, if you read the first Dartmouth BASIC documentation you immediately understand that Kurtz and Kemeny were designing a language that students could teach themselves, with the goal of them being able to transition to Fortran.


Amusingly, my physics and math classes all used FORTRAN, but my teachers were OK with me translating the programs to BASIC so I could run them on my crude MS-DOS computer. I had a copy of the IBM FORTRAN compiler, but it was this cumbersome beast that required two diskettes -- one contained the compiler and the other contained the linker, or something like that. And the complete compile/link workflow took several minutes. BASIC, and then Turbo Pascal, were game changing because you could run a program instantly.

BASIC even had crude array math via the MAT statement though I don't recall the details.

I got to my senior year, second semester, and had a meeting with my advisor to make sure I had met all of my graduation requirements. He looked at my record and said: "Hey, you were supposed to take a programming class. But you know how to program, don't you?" I said yes. He checked the box to waive that requirement for me. Then I started breathing again.


I'm not sure that's a minor one in the case of Fortran, I've seen enough Fortran code to know that every codebase has its own special set of flags that it needs to compile correctly (or the need to dig up an old, unmaintained compiler...). Also missing from the Fortran code is `implicit none` (and let's not talk about good old fixed format or the mess with comparison operators or common blocks or ...).


One nice thing about the INPUT facility in BASIC is that it's truly designed for interactive use out-of-the-box and does its own error recovery on inputs that are incomplete or fail to parse. With other languages (FORTRAN, C/C++) you generally have to implement that part manually.


Minor quibble: You omit units from the output.


Fortran seems to be undergoing a minor renaissance at the moment. Modern Fortran is a fun read and the FPM tool is an attempt at creating an ecosystem similar to cargo for Rust.

  * https://www.manning.com/books/modern-fortran
  * https://fpm.fortran-lang.org/en/index.html


Until recently the best Fortran compilers were proprietary, I guess having gfortran catching up and those adopting LLVM not wanting to be left behind has helped.


That may depend on what you mean by "best". GNU Fortran has always been portable and generally decently competitive with proprietary ones speed-wise over the years and architectures. Also often more reliable. I wish it got properly funded.


The best buck for money on HPC clusters, those supercomputers using Intel and IBM proprietary compilers, which are now based on LLVM on more recent versions, thus also need to support Fortran to finish the toolchain transition.


I thought in the past was at issue. Anyway if you mean "bang for money", GCC is usually zero money, and is more reliable in my experience of research computing support. I've had long experience measuring its output. Fairly recently I ran the Polyhedron Fortran benchmarks, which seemed to be used to market proprietary compilers. In the bottom line, gfortran was essentially equal to ifort (then-current releases and roughly equivalent options on SKX). It's infinitely faster than ifort on ARM and POWER, of course. I could have improved the results for gfortran by individual attention to the codes (some of which were somewhat broken anyway). In HPC the quality of compiled code, within reason, often isn't actually the bottleneck anyway.


Not sure why the Fortran code is that much simpler, I mean if you don't want to futz around with the IO stuff, C++ can be lot more straightforward.

  #include <iostream>

  int main(void)
  {
      float height, dist;
      std::cout << "Height above sea level(m): ";
      std::cin >> height;
      dist = sqrt(2*6367.45*(height/1000.0));
      std::cout << "Distance to Horizon " << dist << " km\n";
  
      return 0;
  }


There's still some cryptic stuff in the Fortran example. I don't know what (*,*) or :: mean. It's even more cryptic than printf or chomp or float.


   write (*,*) "hi"
means write to standard output (the first asterisk) using a default format (the second asterisk) chosen by the compiler. I agree it's a bit obscure. An alternative is

   print*,"hi"
The :: just separates the type of variable from the variable names. The code shown compiles and runs the same if the :: is removed, but there are cases where the :: is needed.


It's not clear to me that, once you explain all this, you end up saving any time vs. the Python version. And once your students want to do anything besides "read a number and perform a simple calculation on it", Python is likely to start winning out very rapidly.


I don't think the point was to score which language was best.


Fortran, my first real language. I haven’t looked at any since 1993. I wrote whole interactive term screen engineering tools with it. I had a whole system/scheme for how I did line numbering (3xxx for formats, 2xxx for gotos, etc). Some of what I cobbled together is still being used for nuclear fuel assembly design work flow.

I have no idea which year’s flavor of Fortran is shown… are implicit variable types based on what letter the variable starts with still a thing? I notice the “real :: …” in the listing…

I thought it was kind of quaint feature as I started learning “real languages” after that. All these years later, I kinda thinks it’s clever/original now.


So I don't doubt that "modern Fortran" is a nice language, but last I'd heard, it also effectively didn't exist in the wild; Fortran remains king of numerical computation by virtue (largely if not exclusively) of having a vast number of packages already written spanning decades of use... but not, generally, spanning to new versions of the language. So is it good enough to use the language in spite of its ecosystem?


No.

I write Fortran professionally and it is a real pain in the dick to get anything done. It has some nice SIMD and matrix operation syntactic sugar but that is about it.

If you want to get anything useful done you are better off writing in another language.

The Fortran ecosystem is running on fumes from the inertia of these massive legacy code bases that no one wants to pay to rewrite. But then complain that it is expensive to get anything done in them.


This surprises me. I wrote a lot of Fortran doing research and found it very strong for numerics. Having first class multidimensional arrays with debuggers being able to understand slicing operators is a nice boost for productivity, because half the time is often spent figuring out why two results don’t agree. The main missing feature was generic functions and that’s where I think Julia brings some real advantages to the table. But SIMD, multicore, MPI and GPU support is afaik. still more mature on Fortran and that’s where it counts when programming cluster applications.


I agree with you that Fortran is running on more than just legacy here. At the same time, I also think Julia has caught up a lot as far as SIMD, multicore, MPI and GPU.

For SIMD, Chris Elrod's LoopVectorization.jl [1] is an (IMHO) incredibly impressive piece of work (which incidentally provides the foundation for I think the first pure Julia linear algebra library competitive with BLAS).

Multithreading is pretty easy with things like `@spawn`/`@sync` and `@threads for` in the base language, as well as super low-overhead multithreading from the Polyester.jl [2] package (which LoopVectorization also uses to provide a version its vectorization macro that'll also multithread your loops in addition to SIMD-vectorizing them).

MPI.jl [3] has been totally problem free for me, though I wouldn't be surprised if the Fortran bindings still have an edge somewhere, and Cuda.jl [4] seems to provide pretty seamless GPU support which should play nicely with MPI.jl's Cuda-aware MPI [5], but I don't work as much with GPUs myself.

[1] https://github.com/JuliaSIMD/LoopVectorization.jl

[2] https://github.com/JuliaSIMD/Polyester.jl

[3] https://github.com/JuliaParallel/MPI.jl

[4] https://github.com/JuliaGPU/CUDA.jl

[5] https://juliaparallel.github.io/MPI.jl/latest/usage/#CUDA-aw...


What about debuggers? For Fortran there are some powerful commercial debuggers available, incl. Parallel debugging and even reverse debugging (being able to step backwards based on snapshots).


It depends a bit on what you want, but https://rr-project.org/ works really well with julia


I tend not to use debuggers very much myself so not speaking on a ton of expertise, but I think it's probably safe to say the Fortran ones are going to be a lot better on that front. There are a few options for debuggers so far, but no parallel ones that I know of yet.


What Fortran standard have you used? About your specific pain, you need to visit a doctor, it is unrelated to Fortran or programming in general.


It's true that many of the famous Fortran libraries such as Lapack are Fortran 77 or close to it. However, there are lots of projects using modern Fortran, especially at universities and national labs, in the areas of astrophysics, computational fluid dynamics, earth science, climate and weather prediction, and electronic structure and quantum chemistry. A list of GitHub Fortran codes by category is at https://github.com/Beliavsky/Fortran-code-on-GitHub .


From the article:

> The idea of introductory languages is not necessarily that they are suited to commercial endeavors, but rather that they are (i) easy to implement algorithm in, (ii) readable, and (iii) do not contain things that will confuse and bewilder.


As for FORTRAN in the wild, there are many simulations used by the US government still in use, example like Enhanced Surface-to-Air Missile Simulation (ESAMS).

Would it be a good language to use outside of specialized needs? Probably not.


I'm not questioning Fortran in the wild, I'm questioning modern Fortran in the wild. Are those simulations Fortran 2008, or FORTRAN 77 that nobody dares touch?


There's modern stuff being written in astro(nomy/physics) (I can attest to some of the codebases listed in https://github.com/Beliavsky/Fortran-code-on-GitHub#astrophy... being modern, at least in terms of development), but I'd say C++ likely does have the upper hand for newer codebases (unless things have changed dramatically last time I looked, algorithms that don't nicely align with nd-arrays are still painful in Fortran).

I've also heard rumours of Julia and even Rust being used (the latter because of the ability to reuse libraries in the browser e.g. for visualisation), but the writers of these codebases (and the Fortran/C/C++/Java) are unusual—Python and R (and for some holdouts, IDL) are what are most people write in (even if those languages call something else).


As much as C11, C++11, Java 11, C# 8, Python 3, and later exist in the wild.

After a certain threshold is very hard to get people to move on when the IT managed compilers just work, and coding isn't a full time activity.


I feel like this post is full of details papered over to prove its point. Others have brought up the fortran details, and with an extremely limited knowledge of fortran, I'll focus on a python detail. You absolutely doesn't need an import statement to perform a sqrt, as you can raise a number to a fractional exponent ( sqrt(x) = x * (1/2)).


    x ** (1/2)
You mean, and one could make a point about that being a non-standard way of raising exponents for a complete novice


In Python 2 you have to use x**(1/2.0) unless you from __future__ import division.


I believe that in Python 1.3 you have to use pow(x, 1/2.0), but that's hardly relevant.


There are several orders of magnitude more people using Python 2 than Python 1.3.


Python 2.7 is 12 years old at this point. Twelve years! That's the difference between Windows XP and Windows 2.1. It's completely unsupported software. There may be people still using it (sadly, embarrassingly), but anyone choosing to teach it to new programmers - what this article is about - is sabotaging them. Its quirks are irrelevant here.


This makes no sense. C is almost 50 years old, English is a bit over 1000 years old, and Euclidean geometry is something like 2500 years old. It's not embarrassing to use any of them. If Python 2 users are failing to successfully organize among themselves well enough to maintain their interpreter, which is licensed in a way that guarantees that they can do that, I guess that's sort of embarrassing, but trying to shame them for using it isn't going to help them organize better.


Comparing Python 2.7 - a release of software - with programming languages (Python is 30 years old and I'm not complaining about the use of it), human languages, and systems of mathematics makes no sense.

When discussing teaching C to beginners, no one is insisting on bringing up considerations for the C compilers of 1972 or their dialects. When discussing teaching new speakers of English how to ask someone their name, no one says, "yes, but in old English you'd need to say 'Hwæt hātest þū?'". I can't really come up with a pithy dismissal regarding Euclid, but not to get too metaphysical, the idea that Python 2.7, C, or English - human constructs - are comparable to Euclidean geometry, which is a sort of immutable construct of logic and/or human cognition, is just plain bizarre. Ideas are timeless; software isn't. I don't begrudge us for using Unix per se - it's a damn fine idea after all - but as elegant as it is, there's no good reason to be running V7 these days.

Or, to return to a different OS: again - in the year 2000, Windows 2.1 was 12 years old. Would you have said then, "there's nothing wrong with using Windows 2.1; after all, English is 1000 years old and we still use it?"


Maybe the fact that you're looking for pithy dismissals instead of seeking to learn something from the conversation suggests that conversing with you is not worthwhile.

Whether 1/2 gives you 0 or 0.5 is not an issue of the implementation; it's an issue of the language semantics.

Software is applied mathematics. It doesn't break down or wear out like an old car. There's nothing wrong with using Windows 2.1 if you like it, but it wasn't very good in the first place, and there are legal problems with copyright law that prevent you from fixing its problems and making it run well on modern hardware.


Software is applied mathematics, but much of it in fact does wear out, because it doesn't exist in isolation. It runs on and uses hardware that wears out and moves forward - do Python 2.7 or the native extensions written for it work well on Apple Silicon? It relies on ecosystems - libraries, developers, users, operating systems, compilers, networks - that move forward. This is especially true of operating systems and programming languages, because they're the basis for the ecosystems which stand on them.

And so the problems with using Windows 2.1 are precisely the same as those with using Python 2.7 - you miss out on ever-mounting additional features that make your life easier; you miss out on an ecosystem which is no longer compatible with it; you miss out on security or bug fixes and need to deal with those issues yourself; you miss out on newer, faster, more reliable or efficient or even just existent hardware (could I find a printer for a Windows 2.1 box if I wanted to?); if you're working with other people, you'll find them harder to find and need to train more and more of them as they're increasingly unfamiliar with the dated system.

And all of these effects stack - you don't just lose out on upgrades for Python, you lose out on new features or bug fixes or security updates for the libraries you use that have stopped supporting Python 2.7 too, and so on. Your world gets smaller and smaller as the rest of the world gets bigger and bigger.

If you're maintaining a legacy system, and you don't want to risk changing it in any way unless absolutely necessary, because you're a bank or controlling medical or nuclear equipment or something, then that's something to weigh. But in any case, by refusing to upgrade when the rest of the world has moved on, you're racking up a technical debt that will grow by the day.


I would say Fortran is a pretty great language for teaching beginners in numerical analysis courses. The only issue I have with it is that, similar to using C+MPI (which is what I first learned with, well after a bit of Java), the students don't tend to learn how to go "higher level". You teach them how to write a three loop matrix-matrix multiplication, but the next thing you should teach is how to use higher level BLAS tools and why that will outperform the 3-loop form. But Fortran then becomes very cumbersome (`dgemm` etc.) so students continue to write simple loops and simple algorithms where they shouldn't. A first numerical analysis course should teach simple algorithms AND why the simple algorithms are not good, but a lot of instructors and tools fail to emphasize the second part of that statement.

On the other hand, the performance + high level nature of Julia makes it a rather excellent tool for this. In the MIT graduate course 18.337 Parallel Computing and Scientific Machine Learning (https://github.com/mitmath/18337) we do precisely that, starting with direct optimization of loops, then moving to linear algebra, ODE solving, and implementing automatic differentiation. I don't think anyone would want to give a homework assignment to implement AD in Fortran, but in Julia you can do that as something shortly after looking at loop performance and SIMD, and that's really something special. Steven Johnson's 18.335 graduate course in Numerical Analysis (https://github.com/mitmath/18335) showcases some similar niceties. I really like this demonstration where it starts from scratch with the 3 loops and shows how SIMD and cache-oblivious algorithms build towards BLAS performance, and why most users should ultimately not be writing such loops (https://nbviewer.org/github/mitmath/18335/blob/master/notes/...) and should instead use the built-in `mul!` in most scenarios. Students should leave the course knowing generally how BLAS is implemented but also how to use it most effectively. There's very few languages where such "start to finish" demonstrations can really be showcased in a nice clear fashion.


FORTRAN is pretty easy to learn. One of my first programming gigs was, basically, writing a CGI program to present scientific reports on an OpenVMS system that used Apache. I had zero to do with the setup and FORTRAN was used because they had license for that compiler. This was the late 90s and it was a FORTRAN 90 compiler.

It was fairly easy to learn the language and port the C/Perl/TCL CGI things I normally did. In fact, I ended up writing library much like Don Libes cgi.tcl that was somewhat popular back then.

Surprisingly one of my favorite data projects (https://retrosheet.org) has tools that will output data in a format that makes it really easy to read in FORTRAN. So, I still use it quite a bit to do some heavy lifting with my baseball research.


There is a very useful function in Julia, named Base.prompt (I don't remember if it's exported or not, but better be safe

  height_str=Base.prompt("Height above sea level(m): ")
  height =Parse(Float64, height_str)


TIL! I wonder why it isn't exported. There's also apparently a `Base.getpass`, that doesn't echo the entered characters and returns a `SecretBuffer`.


My FORTRAN 77 experience in college also included the control lines in the file to have the operating system of the CDC Cyber 172/6600 (a hybrid of two Control Data Corporation super computer/mainframe). The first lines of the file outlined the account submitting the file, where the input & output would be, and some other items to just make the compile/run happen.


That is what I learned FORTRAN on too, a CDC cyber something (a year earlier). I do not even remember what happened to my text book for that class. And my first job was in FORTRAN a year later (which I messed up royally).

As someone else mentioned, I have been thinking of getting back into FORTRAN.


Is elisp the simplest? (entered on *scratch*)

    (setq r 6367.45
          h (/ 42.0 1000))

    (sqrt (* 2 r h))

    23.12716584452146


Have always been intrigued by Fortran but never made an effort to learn it. I do get the article's point about easy text I/O, but what about data structures? I have a hobby project I'd like to port (from PHP prototype) to a compiled language so, what about things like dynamic arrays, DAG's, associative arrays... would I have a hard time trying to implement/use those in Fortran?


Fortran excels in array computation but I was advised against using it for graph structures. I think with Modern Fortran it would be not so onerous go handle, but maybe because good libraries already exist in other languages.


Thank you, that makes sense indeed. What I'm liking about 'modern' C++ for example, is the ability to populate nested data structures like (std::map containing std::vector containing ojb instances) using literal initializers, in a sort declarative-style programming. Useful especially for testing & prototyping. Rust, OTOH, seems rather intimidating to me.


FORTRAN is the only programming languages that made me sick. I understand contemporary iterations are more human-friendly, but even COBOL is less ugly.


"The determined Real Programmer can write FORTRAN programs in any language."

That Python example in there :)


Teach those kids properly:

  perl -e 'print(sqrt(<>*12.7349))'


Is it easy to remember?




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: