Fortress Specs Updated: 0.785

The Fortress specs have been updated.

http://research.sun.com/projects/plrg/fortress0785.pdf

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Impressive...

but very complicated. Most people complain about and can't grasp a language like C++, will they grasp Fortress?

Probably not, but probably not the point...

As much as I like the look of Fortress in comparison to other offerings in the programming language realm from big corporations in recent times, I kind of suspect that it is not going to be adopted nearly as widely as C++ or Java was. It's simply too different from the C-style paradigm.

But reading the specs and reading/hearing some of the discussion about the language from the creators, I don't think it's going to be marketed this way. It's meant to be a language that makes programming on big iron easy (with the parallelism, concurrency, contracts, etc.), as well as programming for scientific or abstract mathematical purposes easy (with extensive unicode support for mathematical characters, dimensions, etc.).

None of those are things the *average* C++/Java programmer really end up doing all that often.

However, as complex as the language might seem, I don't think it will be as bad as some people might anticipate. Using *all* of the features together would definitely require quite a mastery of the language, but many languages such as some ML dialects or Haskell for example also can be considered the same way, yet they remain quite usable on the whole.

you do know its stated goal i

you do know its stated goal is to take on FORTRAN, don't you? yes, completely different audience than that of java/C++...

I read the last spec, Is ther

I read the last spec, Is there any summary on that has changed?

don't think so

But what I noticed was:

  • improved and more examples
  • better introduction (and reordered chapters)
  • more detailed dispatch algorithm
  • added type inference algorithm
  • lists are now indexed with [] instead of <>
  • numeric types are now N/Z/Q/R8/16/32/64/128 and C16-256 (Int is gone)
  • dividing two integers always gives a rational number
  • the supertype of all numeric types is Number (was Num)
  • Object is the supertype of all types (was Any)
  • added a dimensions and units list
  • ranges are explained in their own section (also fixed mistakes: a#b and a:b were used incorrectly in some examples)
  • dimensions/units are put behind the type (e.g.: x:R64 Length)
  • added widening and coercion support for library writers
  • tuple expressions are evaluated in parallel
  • added section about early termination of threads
  • shared data: method localizeNoCopy() renamed to localize()
  • spawn takes a new parameter: 'guaranteed' which allows turning off guaranteed parallelism

I will stop here. :)

Thanks

Just what I needed.

Off by one

Fortress wishes to migrate FORTRAN users as Java did C users. Zero-based indexing seems a likely annoyance.

Disappointing lack of MathML. No hope of copy-pasting between Fortress output and MathCAD, Mathematica, Maple or vice-versa. How well Fortress shall integrate with these packages is a serious question for targeting science and engineering.

And then web browsers. Fortress cares about visual presentation, but ignores MathML. I don't get it. Will browsers need a Fortress plugin because it won't do MathML?

Otherwise things seem on track and the unit/dimension discussion is encouraging to see after 60 years of languages without units, the one place static type systems should be helping us today but aren't.

That's what IDEs are for

MathML input and output is a job for an IDE. The design of Fortress assumes that it will probably be used through an IDE which will make the source code look pretty and offer higher-level tools for editing code in a pretty form. Given this assumption, it's reasonable to believe that a decent Fortress IDE would allow copy-and-paste between Fortress and other systems like Mathematica.

It's already half an IDE spec...

...with excrutiating details on concrete syntax and user input encoding ("type this to get that"). Explaining how that will translate into MathML isn't asking much.

Besides, MathML covers semantics, distinguishing it from mere layout (TeX, PostScript). How mathematics interacts with programming is central to Fortress. Between that interface and layout typography are huge areas of MathML overlap. Then you have the notion of working with web browsers and math vendor software, whatever the merits of MathML.

So I don't see how Fortress can, or why it should want, to put off MathML. Avail the fine work by experts from Elsevier, INRIA, Univ. of Waterloo (Maple), IBM, American Mathematical Society, the OpenMath consortium, Wolfram Research (Mathematica), etc. Stand on their shoulders. Join their committees if appropriate. Fortress participation might expand the MathML envelope in important ways to everyone's mutual benefit.

XML syntax will hide under the IDE, but Fortress can't expect an IDE to fix systemic issues caused by today's design decisions. Now is the time for MathML compatibility design. Note that in MathML, Elements can use the definitonURL to override default semantics. There is really no excuse to ignore MathML.

Fortress won't happen very soon if it reinvents typography because that by itself constitutes a five year effort. Leave aside the task of improving FORTRAN and breaking new ground in programmable mathematics. Some time ago I suggested modifying an open source MathML editor to prototype an IDE.

Unless Guy Steele himself joins LtU to chat about his Fortress then I hope we won't see it posted again until the spec breaks 1.0 or software actually ships. A story for every 0.1 design rev is too frequent. Those who care can track Fortress on their own. Guy does participate in other groups like LL and lisp, so I don't know why he bypasses LtU. To his credit we exchanged private messages some while back and some of my feedback folded into the spec. Thank you, Guy. But I'm just one person with opinions whereas MathML is a world standard.

OK. All in all, I like the fact that someone as good as Guy Steele is actually doing something about scientific/math software under the aegis of semi-open-source. FORTRAN itself has come a very long way over the years. If Fortress plays its cards right, it can move the state of the art.

Guy Steele...

...is of course more than welcome to join LtU. Heck, I'd love to have him guest blog here.

a hacker's idol

I have a Steele Bust on top of my micro just like pianists have a Beethoven one on top of the piano. ;)

Interesting changes

I think it's very interesting to see how strongly that the design of the language has mutated in the time that I've been watching it. The original language design made it seem that high performance was the most important issue, forcing more programmer micromanagement of the size of integers, etc., but later incarnations have seemingly moved farther into "do the right thing with numbers" rather than just "do what's fastest," as long as you intentionally eschew use of the numbers of fixed size (e.g. Z32, a 32-bit integer.) No mention is made of what happens on overflow with fixed-size numbers; presumably they'll fail silently? At first, their section 2.9 called "automatic widening" looked like it addressed this issue, but, on closer reading, it looks like overflow is actually unaddressed.

As mentioned in the last Fortress thread, I've built a language called Frink that seems to fill the same niche. I've struggled with many similar design decisions, though, and this new version of the specification has introduced some new objections.

For example, they've introduced the operator per which is used as a synonym for division. I don't think they've thought this one through. As I mentioned in my LL4 presentation last year, in common English usage, per is ambiguous and context-sensitive. When you say miles per gallon, you expect it to mean the size of a mile divided by the size of a gallon. But when you write days per week, you expect to see 7, right? Well, if you follow the rule that per means division, you divide the size of a day by the size of a week, and get 1/7. Unexpected. Ambiguous. Dangerous. Requires reading minds.

A new slant in the latest specification: "Numerals containing a radix point are actually rational literals; thus 3.125 has the rational value 3125/1000." I'm not quite sure why that's valuable or desirable. It introduces illusory precision and an unnecessary performance hit. It would probably be better to attempt to track the number of significant digits; Mathematica purports to do this, but as you've seen if you've used it for a while, they really don't track very consistently. Sometimes they use less, sometimes they use more. It's a far harder problem to do well than it initially seems.

"In Fortress, dividing two integers using the / operator produces a rational number; this is true regardless of whether the integers are of type Z, Z64, N32, or whatever." I half-agree with this; the behavior that 1/2 == 0 should have no place in a modern language. But what is 6/2? It says that rationals are reduced to lowest terms. It's hard to tell from the documentation, but it seems that this is stored as a rational number, although it would probably be more efficient to reduce it to an integer when possible, as Frink does. It also appears that this rational number (type Q) is of arbitrary precision, and it doesn't look like the size can be specified by the user (which is probably reasonable to "do the right thing,") but this, combined with the interpretation of decimal numbers as rational, means that performance will certainly be impacted relative to hardware-implemented floating-point. Not bad, just slower.

Pi is called out as a special value. It automatically extends itself to desired size. But why just pi? What about e and all other transcendental numbers? Is there a unified general principle or is this just a hard-coded special case? Tracking transcendental numbers with arbitrary precision is interesting, but it forces design decisions. This is why, in, say, Mathematica, you have to call N[expr] to get an actual numeric value for a symbolic expression containing pi or other transcendental numbers. Does Fortress plan to evaluate symbolically when pi is used, or is it still subject to the same old floating point errors and not really an improvement? (e.g. (pi + 1 quadrillion) - 1 quadrillion).

I notice that they say that units can have rational numbers as exponents. That's probably good.

The documentation insinuates that intervals may contain complex numbers. I'd be interested to see if they actually go that far. It's hard, and there's decidedly more than one way to do it (e.g. does a complex interval represent a rectangle in the complex plane or an ellipse with a given center and axes?) I'd bet all the money in my wallet that initial implementations will constrain intervals to real values, like Frink or Mathematica or Sun's interval libraries.

The precedence rules with differences between "tight" and "loose" associativity (i.e. whitespace is unexpectedly very significant!) still seem to be there. These seemed to be rather unpopular the last time we discussed them here. Their precedence rules for parsing units still violate standard mathematical precedence and the guidelines of the SI, which I think would be an insuperable objection for many people.

Overall, I'm not sure what I think of the changes. I haven't diff'ed the entire specification against the last one yet. The changes to make numeric values "do the right thing" is a positive change. It may not help lure die-hard performance freaks (which seemed to be the original audience) away from Fortran and the like, though. I believe that for most programs, it's better do to the right thing, than to do the wrong thing fast. These changes may actually widen their appeal. It's looking more like Frink every time. :)

Ambiguous per se?

... in common English usage, per is ambiguous and context-sensitive. When you say miles per gallon, you expect it to mean the size of a mile divided by the size of a gallon. But when you write days per week, you expect to see 7, right? Well, if you follow the rule that per means division, you divide the size of a day by the size of a week, and get 1/7.

Hmm.. I expect miles per gallon to mean a quantity of miles divided by a quantity of gallons (giving the number of miles for each gallon). Does dividing the size of a mile by the size of a gallon make sense? (What units?) Likewise, I'd expect days per week to be a number of days divided by a number of weeks, e.g. those in a full year: 365/52 = 7 (well, near enough), i.e. the number of days for each week. There may be a slight difference in meaning, but I'm not sure it's a dangerous ambiguity.

Reciprocal is ambiguity

I'm not sure why you ask if dividing one unit of measure by another makes sense, or what the units would be. You're effectively always dividing the size, (you could say "quantity," too,) not the count of things, as you say in your "number" sentence. (If you don't agree, I'll gladly trade your one gallon of milk for my two pints.) Quantity, taken to mean size and not cardinality, is the crucial factor. Only if everything has the same size can you divide the count.

What question are you trying to answer in your 365/52 example? You're dividing the size of a year by the number of weeks in a year, but it's not clear how this supports or contradicts the other part of the sentence.

Of course, any ambiguity where one perfectly common interpretation gives the reciprocal of another interpretation is dangerous. It's more than a "slight difference in meaning." That's why it's generally ill-advised to try and parse English sentences.

For example, note all the special-case convolutions, different interpretations of precedence, and different results that the Google calculator goes through when you enter different things like "days/week", "days per week", "1.0 days per week", "(1.0 days) per week". (Guess what each of these should return before you try them.) Yuck. An unmaintainable, unextensible, unpredictable forest of special cases. In some cases they give you a differently-arranged equation, that you have to rearrange, not a number, and they change precedence rules all around. They all come out to the same thing when you rearrange the terms ... 1/7.

But would a native English speaker still expect "days per week" to return 7? Probably. Best to leave it out.

(For even more fun with the Google calculator and wacky non-standard precedence rules, predict what you'll get when you compare "1/2 days/week" and "-1/2 days/week". Yikes!)

One needs to parse the Fortress specification to see if it's vulnerable to such unexpected precedence violations. They show just such a violation of standard mathematical precedence in their (revised since last time):

w: R64 AngularVelocity := 2 pi radian / 226 million year in sec example.)

I just think that any language which reinvents standard and unambiguous mathematical rules of precedence better think long and hard about why they're doing it, and then think again.

Besides, it's hardly more work or less legible (especially to international users) to type "/" instead of "per". It also follows the guidelines of the SI, which means that programs will read and write better internationally.

A little type-checking removes a lot of ambiguity

I'm not sure why you ask if dividing one unit of measure by another makes sense, or what the units would be. You're effectively always dividing the size, (you could say "quantity," too,) not the count of things, as you say in your "number" sentence. (If you don't agree, I'll gladly trade your one gallon of milk for my two pints.) Quantity, taken to mean size and not cardinality, is the crucial factor. Only if everything has the same size can you divide the count.

When discussing "per" statements you are never dividing "size". What is the "size" of a mile, or of a gallon? These are different units of measure, and their "sizes" are not directly comparable or divisible (in PL terms, they are values of different types). What is divisible is the number (or count, or cardinality if you prefer) of these things relative to some other (common) unit of measure (since both values will have the same type: "number per common unit"). Thus we compute "miles per gallon" by dividing a number of miles travelled by the the number of gallons required to travel those miles. This is a case of computing "miles per trip / gallons per trip", with "trip" being the common unit of measure that both miles and gallons are counted against.

The problem with your "days per week" example is that you are using incorrect common units of measure. You compute "days per week" as "days per day / days per week", and of course get "weeks per day" as your answer. Effectively you have used "common units per number" as the type of the values you are dividing. If instead you used "days per year / weeks per year" you would get the correct result, since the type of the values you divide has the (correct) form "number per common unit", and the common units on the denominators of each side of the division cancel correctly.

Type-checking doesn't work for reciprocals of dimensionless nums

When discussing "per" statements you are never dividing "size".
Not even when saying "pints per gallon"? Which have the same dimensions?
What is the "size" of a mile, or of a gallon? These are different units of measure, and their "sizes" are not directly comparable
This part of the sentence is correct. I agree. You cannot meaningfully compare them (in the sense of generating an ordering.) Frink will produce an error. Presumably, Fortress will too. You can't add or subtract them, either.
or divisible (in PL terms, they are values of different types).
This part of the statement is certainly incorrect. They are, of course, divisible. (If they weren't, it would throw physics into a cocked hat. c=299792458 m/s would become meaningless because you can't divide meters and seconds, and you'd force us to write Universe 3.0.) It's almost like saying that you can't divide a real number by an integer, or multiply a matrix by a scalar, because in PL terms, they're different types. But actually, short reflection reveals that an integer and a real are both numbers, that is, they share a common superclass, just like gallons and miles are specializations of a more general supertype--a unit of measure (called a "unit" in Frink, and now Fortress.) The matrix/scalar argument also shows that as long as you have well-defined rules, you can multiply or divide very different things. (Although some would argue that a matrix or an interval are simply a "different kind of number.")

There are well-known rules that are thousands of years old for handling multiplication and division of units of measure with different dimensions. The result may, and likely will, have yet different dimensions. Programatically and conceptually, this is simple.

What is divisible is the number (or count, or cardinality if you prefer) of these things relative to some other (common) unit of measure (since both values will have the same type: "number per common unit").
I don't follow this. First, you said that you can't divide these things because they have different units of measure, now you're saying that they do have the same units of measure? What is the "common unit of measure" when, say, calculating density, that is, g/m3? Or, similarly, what are you physically counting when you "count" density or velocity? Keep in mind that physical things being measured are not units of measure.
Thus we compute "miles per gallon" by dividing a number of miles travelled by the the number of gallons required to travel those miles.
Again, I agree wholeheartedly, but this seems to be at odds with your previous statement that these are not divisible.
This is a case of computing "miles per trip / gallons per trip", with "trip" being the common unit of measure that both miles and gallons are counted against.
I'm not sure I follow here. Your intended precedence is unclear, but if I guess your intent correctly, it appears that you've simply introduced an algebraic tautology, that is, a/b = (a/c) / (b/c). This is obvious, but introducing (any value for) c gives no additional information nor insight into the measurement. In addition, it reiterates the point that you're dividing by a third unit that necessarily has yet again different units of measure from "miles" or "gallons", which you previously incorrectly stated was impossible. In fact, it introduces an infinite regress in which one is forced to forever try to find a new "common unit of measure" c that simultaneously has the same dimensions as both, (which you stated as a prerequisite for divisibility) which is of course impossible, since a and b have different dimensions from each other.

A physical thing being measured is independent of a measured quantity (as you can see by factoring c out of the equation above); this is the entire intent of measurement systems. A gram is a gram whether it was measured as a gram of iron or a gram of water; a velocity is a velocity whether it was measured on photon A or photon B or neutrino C. A meter is a meter. (Nobody's allowed to make relativity arguments here.) You cannot divide one rock by another rock; you can divide measured masses of rocks. If we couldn't factor out the thing being measured, we'd never be able to compare measurements made on different things. If you wish to disagree, please start by telling me what the dimensions of "trip" are in SI units. :)

I must also add that, to compare sizes, it is not strictly necessary to postulate a "base" unit that other things are eventually counted in terms of. While Frink does that for computational efficiency, I also considered an unrooted, undirected graph where the nodes are units (e.g. "gallon" and "pint") and the edges indicate the multiplicative factor to convert between the size of these units. (e.g. to convert gallons to pints, multiply by 8. When converting joules to watts, multiply by 1 second.)

The problem with your "days per week" example is that you are using incorrect common units of measure.
As noted above, it apparently doesn't matter what the "common" units of measure are arbitrarily chosen to be. Again, I think you're confusing a particular thing being measured with a measurement. The value of "c" is irrelevant. It's the measurement a/b that is the only comparable thing. I should again clarify that I was discussing the value that a native English speaker expects to see when asked what value that "days per week" would be expected to return. I'm not saying that the use of per in English is logical, or unambiguous. I'm saying that it is ambiguous, and not always a synonym for dividing the left side by the right. A purely dimensionless example is "dozen per gross".
You compute "days per week" as "days per day / days per week", and of course get "weeks per day" as your answer.
No, again, I refuse to compute the english sentence "days per week," because it's ambiguous. :) Again, I'm not sure what rules of precedence you've intended here and in the following example; the only way you'd get that answer is if you chose "per" to mean division, but at a higher precedence than division. This is apparently not the case in Fortress. I don't know what Fortress would return--due to their loose/tight binding rules, it probably depends on whitespace.

If you're meaning "per" to be a synonym for division, and follow normal mathematical precedence (division and multiplication are at the same precedence and performed left to right) this should be parsed as ((days/year)/weeks)/year which is days/(year2 * weeks), which has dimensions of time-2.

If instead you used "days per year / weeks per year" you would get the correct result, since the type of the values you divide has the (correct) form "number per common unit", and the common units on the denominators of each side of the division cancel correctly.

If you're meaning "per" to be a synonym for division, but at a higher precedence, (which is the only way the last part of your sentence becomes true) then this becomes (days/year)/(weeks/year) or simply (days/weeks). Again, the algebraic tautology, which introduces no new information. Introducing "year" added zero information content.

You almost make it sound convincing, but you've forgotten again that in Fortress, and the Google Calculator, and Frink, that any unit such as "day" and "year" or "days" and "years" always indicate the size of a day, or a year, (all appear to reduce these in terms of base SI units.) So (days/year)=1/365.x and (weeks/year)=0.0191. The result is still 1/7. The programming language can't read your mind to guess that you intended something different. To make it more interesting, try putting them into variables and see if the program you envision can read your mind and return 7:

a = day
b = week
a per b

What if it's "1 day"? "1.0 day"? If you can make this return the "expected" value (7) in all such cases, without messing up other uses of "per" indicating left/right, please describe your algorithm.

In any case, to address the subject line of your posting, type-checking does not resolve the ambiguity when dividing units with the same dimensions (which was the case I noted as being ambiguous); the result in both cases a/b and b/a is a dimensionless number, and type-checking doesn't help you to see if you got the right answer or the reciprocal of the right answer.

You almost make it sound conv

You almost make it sound convincing, but you've forgotten again that in Fortress, and the Google Calculator, and Frink, that any unit such as "day" and "year" or "days" and "years" always indicate the size of a day, or a year, (all appear to reduce these in terms of base SI units.) So (days/year)=1/365.x and (weeks/year)=0.0191. The result is still 1/7.

But how does the language know that I mean 1 day? (Or 1 week?) Being able to reduce "year" singular to 365 days seems safe, but it shouldn't assume that "days" plural means 1 day. The calculation has been changed from "x days per year" to "1 days per year", which is obviously incorrect as it is x we are trying to calculate. But in order to solve for x, we need to know more information: i.e. a common period of time for which we know the number of days and years (e.g. one whole year). Then we can write:

x days     365 days
------  =  --------
1 years     1 years

and solve as x = 365 days. Likewise, we can solve our "days per week" by doing:

x days     365 days
------  =  --------
1 weeks    52 weeks

which solves to x = 7 days (approx). "Per" is still just normal division here.

Disambiguation based on name doesn't work

But how does the language know that I mean 1 day? (Or 1 week?)

Presumably, because you didn't tell it otherwise. I don't think it's reasonable to expect a language to read my mind and know that I meant "x days" or "14 days" when I wrote "days". If there's an unknown factor in there somewhere, it must be explicitly stated.

Being able to reduce "year" singular to 365 days seems safe, but it shouldn't assume that "days" plural means 1 day.

Nice try, but disambiguation based on name or plurality doesn't work with many names. It doesn't work for the most common ones, actually. For example, the SI symbols m, kg, s, cd, A, etc. are written the same way in the singular and plural. That is, you're never allowed to pluralize them by adding an "s" or whatever.

Thank you for the days...

I don't think it's reasonable to expect a language to read my mind and know that I meant "x days" or "14 days" when I wrote "days". If there's an unknown factor in there somewhere, it must be explicitly stated.

But you are assuming that it means 1 day! That is what I am saying is wrong, as it is this number that we are trying to calculate (days per week; the number of days in 1 week). The language shouldn't have to read your mind, it should throw an error if you haven't specified a number of days (or it could allow an unbound logic variable so we can solve for the value), rather than defaulting to 1 day. Trying to calculate "days per week" by dividing the size of 1 day by the size of 1 week doesn't make any sense (to me, at least :-). Likewise, I don't see anything meaningful in dividing the size of 1 mile by the size of 1 gallon. Is there an example of usage of "per" with this interpretation? My understanding of "per" is that "x per y" generally means "a number (quantity) of x for each unit of y", e.g. miles per gallon, inches per foot, doughnuts per lunchbreak. If you specify x, then you are asserting a fact ("my car does 28 miles per gallon", or "there are 12 days in a week") rather than performing a calculation.

However, I can't say I'm overly enthusiastic about use of "per" to mean division so I won't devote any more time trying to defend it.

Inverse acres

Ha! A chance to use my favourite units joke.

So what's an inverse acre? It's miles per gallon, obviously (L / L^3) and thus a perfectly appropriate unit of measurement for fuel efficiency.

I don't know how Frink handles this case, but it strikes me as an interesting problem in trying to type-check unit calculations. In the miles per gallon case, inverse acres is probably inappropriate because the miles and the gallons refer to different substances. (On the other hand, there is a good physical intuition as to why inverse acres is an appropriate measurement, albeit with the wrong size for most practical purposes; I generally find gigaoveracres to be more practical.)

A similar issue arises with, for example, measurements of concentration, or map scales. (Say ml/l, cm/m). These are "dimensionless" but it should be a type error to multiply a concentration by a distance or a map scale by a concentration. Shouldn't it? It would almost certainly indicate a programming error.