Documentation * FAQ * Download * Frink Applet * Web Interface * Sample Programs * Frink Server Pages * Frink on Android * Donate
Frink changes almost every day. If your version of Frink is more than a few days old, you're probably out of date! (That doesn't mean that old programs will be invalidated, but that new, useful features and optimizations are added all the time.) If you'd like to be notified of major new releases via e-mail, please subscribe to the "Frink Language" project at freshmeat.net. (Link opens in new window.)
expressionContains[a,b] function to properly
match expressions. This manifested itself in a failure to reduce the
double derivative D[D[x,x], x].
URLEncode[str, encoding] to
encode a string to be used as part of a URL. The encoding should probably
be the string "UTF8" for most applications.
URLEncode function above to work, so this release is
required.
isSubset[setA, setB]
and isProperSubset[setA, setB] functions to perform
relation tests on sets.
This includes anti-aliased graphics with transparency, animation, image manipulation, integration with the Android's sensors, GPS, text-to-speech, and other features. For more details please see the Frink for Android page.
getSymbols[expr] which returns a set of symbols defined in the expression.
transformExpressionDebug[rulesetname, expr]
and transformExpressionDebug[expr] to transform an
expression and return the intermediate expressions and the
transformation rules used.
transformExpression...[rulesetname,
expr] functions can now also take an array of
strings for the rulesetname parameter which contains the names
of multiple rulesets to apply.
(_a:1)
Which creates a pattern called _a which, if it does not
appear, is assigned the value 1. For example, if you wanted
to match a quadratic equation, with optional coefficients for each of the
the terms, you could write your pattern as:
(_a:1) _x^2 + (_b:1) _x + _c
See the solvingTransformations.frink file for a concrete example of a transformation rule that solves quadratic equations.
The method for replacing the default value is pretty interesting and complicated. It actually undergoes all of the symbolic reductions that ordinary expressions undergo, so you can generally write your pattern the same way you write your equations. Again, all possible orderings of commutative/associative operators will be tested.
substituteExpression[orig, from,
to] to backtrack and try all patterns with conditions in
all possible orders.
isPositive[num] and
isNegative[num] functions which return true if
a number is a positive (or negative, respectively) dimensionless real
number, false otherwise.
transformations block to create a named set of
transformation rules which can be applied to an expression. See below.
Also see the solvingTransformations.frink file which demonstrates the use of this construct.
transformExpression[rulesetname, expr]
and transformExpressionTrace[rulesetname, expr]
to apply a named set of transformations to an expression.
transformExpressionTrace[expr] function
to transform an expression and return the intermediate steps as a list.
molarvolume to follow the accepted defintion (its units are
now m^3/mol.) This allows easy conversion of some quantities to and from
moles. For example, to find number of moles in 1 gallon of gas at STP,
you can use:
1 gallon / molarvolume
0.16888608262948273721
isUnit[expr] which returns true if the
specified expression is a unit of any type, including dimensionless
numbers.
eval[expression,
rethrows] where the rethrows argument is a
boolean flag indicating if we want errors to be thrown or just suppressed
and undef returned. If it is true, errors will be rethrown
as Java exceptions.
methods[object] function to list the methods
of an object.
f = newJava["java.awt.Frame", []]
sort[methods[f]]
In other words, this is a potentially severe bug and it is highly recommended that you update your version of Frink.
getPressureAltitude[pressure] and
getDensityAltitude[density] to StandardAtmosphere.frink.
In addition, fixed a potential problem with calculating molecular Hydrogen
densities below 150 km.
graphics.writeFormat... methods to allow a
filename argument of "-" which writes the image data to
standard output.
image.print[] and
image.printTiled[pagesWide, pagesHigh] methods
to an image to allow them to be easily printed to a printer.
image.show[] now displays images at their original
size by default.
See the Rendering Graphics section of the FSP documentation for more.
moonrise and moonset functions to predict
rising and setting times of the moon.
moonSecantAzimuth and sunSecantAzimuth
functions to handle wrapping around the circle.
signum[x] function to return a number
indicating the sign of its argument. More information in the Other Functions section of the
documentation.
Fixed an important bug which could cause underflow when raising a floating-point number to a large negative rational power. It is very strongly recommended to update.
.jnlp files for Java Web Start to hopefully
allow Frink to start properly even if you're offline or my servers are
down. I already had the offline-allowed setting enabled, but
found another switch dealing with shortcuts that would cause JNLP to throw
an exception if the server was unavailable.
x-x would be symbolically
simplified to 0. This affects date calculations in a subtle
way. A date can now be multiplied by zero, returning 0 s.
In short,
this is done by calling the replaceGraphics[g] method
on a graphics window. Thanks to Warren Schudy for the suggestions.
sleep[time] function which sleeps for the
specified amount of time. The argument time must have units
of time, for example 1 s or 4.9 minutes
or 1/30 s. This supports smooth animation.
x-x would be symbolically
simplified to 0.
Note that this change was rolled back later in the day because it caused premature simplifications of some expressions. Please obtain the current version.
x + 2x is transformed
into 3x.
x * 3x^2 is
transformed into 3 x^3.
This allows purely symbolic conversions to be performed. For example:
pack = 10 dog
tribe = 10 pack
tribe / dog
100
Hint: to avoid "undefined symbol" warnings, call
symbolicMode[true] which suppresses warnings about undefined
variables and changes some behavior when encountering undefined symbols
from fail-fast to a more tolerant deferred evaluation.
Note that at all times, dog is an undefined variable that is
manipulated purely symbolically. Also note that prefix, suffix, and
plural checking is not performed on local variable names, so
you can't write dog or dogs interchangeably
like you can if you define a concrete unit.
These changes should be essentially invisible to most programs, but may have an effect on variables that later contain interval arguments. The symbolic simplification will sometimes create a different result than the original formulation may have produced. In most cases, the resultant interval will actually be tighter than the previous result, such as in the case:
a = new interval[-2, 3]
a*a
[0,9]
Note that this interval is tighter than a naïve implementation
which would produce [-6,9]. This will also symbolically
simplify expressions such as x/x to 1.
isDefined[x] and
isVariableDefined[x] to test if an identifier is
defined in the current scope. The difference is that
isDefined[x] checks local variables and unit
definitions, while isVariableDefined[x] just checks
local variables.
These functions can be called with either a variable name or a string. For example:
isVariableDefined[a]
isVariableDefined["a"]
See the Testing Variables section of the documentation for more.
-> to allow more relaxed
conversion of undefined variables to give better symbolic behavior.
x is on the left-hand-side of an expression is:
solve[_left == _right, _x] :: freeOf[_left, _x] <-> solve[_right == _left, _x]
The condition follows the :: operator. This allows much
more powerful transformation rules to be written. For example, see
the solvingTransformations.frink
file which solves many algebraic equations with only a very small
number of rules.
Note that the syntax for anything dealing with transformation rules may change.
DFT[array, divFactor=-1, direction =
1] and InverseDFT[array, divFactor=-1, direction =
1] functions to make a Discrete Fourier Transform of the
specified array, or its inverse. These were previously only available in
the Fourier.frink
external file.
Note that the default value for divFactor has changed in
both of these files. If your code relied on the default value of
divFactor, you may need to specify it. See the Number Theory section of the
documentation for more information.
Re[x] and Im[x] (functions that return
the real and imaginary parts of a number return the number) with its
units rather than blowing up if the number wasn't dimensionless.
eulerPhi[n] function to calculate the
Euler's Totient of a number. See
the Number Theory section of the
documentation for more information.
3x sorts before the
expression y. This is necessary to make a variety of
symbolic transformations easier to write.
-> print "Unconvertable
expression:" before the expression if it's not convertible and not in
symbolic mode. This may make it more clear that the conversion failed.
If in symbolic mode, this returns the partially-converted expression,
which might succeed later after setting variables and
calling eval[] on it.
unit_ to the standard data file. This
allows you to use the original definition of a unit even if you've
"shadowed" it by declaring a local variable with the same name. For
example, if you define a local variable called g, that hides
the original definition of the gram. You can get the original definition
of the unit g by writing unit_g instead.
Note that this is not generally a problem when writing programs. If you realized that you shadowed a unit definition that you want later in the same function, just rename your variables and run the program again. It's only a problem in interactive sessions, where you're already at the top level and can't undefine the variable.
functions[] function to list the signatures of all
functions.
Warning: This release changes the behavior of the
abs[x] function when called with an interval
argument. It does not alter its behavior for any other
numerical types (e.g. real or complex numbers.)
The behavior of the abs[x] function has changed for
interval arguments. Previously, it returned a single scalar value instead
of an interval. To be precise, it used to return the absolute value of
the endpoint furthest from zero (which is a definition that goes back to
Ramon Moore's early texts on interval analysis.) However, this was
considered to be a surprising definition by many (including myself.) It
didn't follow the spirit of absolute value for real numbers, it chose one
endpoint arbitrarily as being more important than the other, discarded the
other endpoint and the "main/middle" value, and caused loss of information
and unexpected results when passing interval arguments to a program
initially written with real numbers in mind.
Thus, after surveying a large number of implementations of interval arithmetic and discussing this with the leading practitioners in the field, it was decided to change the implementation of this function to more closely follow the spirit of the definition of abs[x] for real numbers, and to follow a more modern convention that is widely used in interval arithmetic implementations. The abs[x] function now returns an interval (possibly with a main/middle value) which contains the interval that would be obtained by calling abs[x] on both endpoint (and the middle value) of the interval, with one exception. If the interval contains zero, then the lower bound of the new interval will be zero.
The previous behavior is now moved to a new function called
magnitude[x] which returns a scalar which corresponds to the
absolute value of the endpoint farthest from zero. For symmetry, another
function mignitude[x] has been added, which returns the
absolute value of the endpoint closest to zero.
This change should make the results of passing an interval to an equation designed for real numbers much less surprising.
Thanks to Alan Stebbens for the initial inquiry into this behavior, and to the respondents on the "Reliable Computing" mailing list and on the IEEE-1788 expert group mailing list, which is working toward defining an IEEE standard for interval arithmetic. Special thanks to R. Baker Kearfott, Arnold Neumaier, George Corliss, Ramon Moore, Dan Zuras and Richard Smith for directly answering questions related to these definitions.
Please see the Interval Arithmetic Status section of the documentation for more information about the new functions.
JavaObject:int) to
be mapped to that primitive type in a Java call.
graphics.write[] or when
calling leap-second-related functions like TAIMinusUTC. This
was due to calling some classes by name, and those names no longer matched
their obfuscated versions in the jar file available to the public.
g.font["SansSerif", 1 inch]. The
fix improves cases where the bounding box was wildly overestimated, and
caused everything to be drawn very tiny. However, there's really not
enough information available at the time that the bounding box is
calculated (because we don't know what other objects may be drawn) to
calculate an accurate bounding box. Thus, a zero-sized bounding box is
calculated, which may make constant-sized text be drawn off screen if it's
too big, but it eliminates the "everything drawn too small" problem.
graphics object (which can then be printed, saved to
a file, printed tiled across several pages, modified, drawn upon, etc.)
This gives the ability to modify images, add watermarks or text to
images, build collages or thumbnails, rescale images, overlay transparent
images on each other, and much more. See the new Images section of the documentation
to see how to load and display images.
graphics.write[filename, x, y,
insets] and graphics.write[filename, x, y,
insets] which allow you to control the borders around your
graphics when written to a file. The default is to only use 95% of the
width and height of the image file to allow a small border around the
image, but setting insets to 1 (which equals 100%)
forces 100% of the space to be used, that is, no border to be drawn. This
allows an image to be effectively re-rendered to different formats,
watermarked, or modified, without changing its size or introducing a
border.
GeneralPath to allow drawing of true
ellipses and circular arcs. This allows drawing of perfect circles with
transparent holes in the center, which was previously impossible.
Previously, circular arc segments could be approximated with cubic
Bézier curves, but this was an imperfect approximation.
More information is available in the GeneralPath section of the documentation.
GeneralPath class to allow these
new curve types, and to allow curves to calculate their own tight bounding
boxes.
marsday has been changed to use the
solar day instead of the sidereal day. Both definitions are
still available, as always, as marssiderealday and
marssolarday.
graphics.print[] and
graphics.printTiled[pagesWide, pagesHigh] now
also render the background color. The background color was not drawn
previously in an attempt to minimize ink usage, but this is easier than
drawing a colored rectangle for the background.
GeneralPath class
which allows drawing of complicated outlines and filled shapes, which may
be composed of straight lines and quadratic and cubic Bézier
curves. This allows filled shapes with transparent holes (such as the
letter "P") which were previously impossible to obtain.
Note: The GeneralPath functionality is only available under Java 1.2 and later.
More information is available in the GeneralPath section of the documentation.
(1/4)^(1/2). Previously, if intermediate results were too
big (such as when the numerator of the exponent became large enough,) this
could stop the program with an error due to overflow. This situation has
been fixed.
graphics.show[] method to suppress
printing "frink.graphics.PaintController" if it's the last method called
in a program.
TAIMinusUTC[date] returns this value. See the International Atomic Time
(TAI) section of the documentation for more details.
->) when the left-hand-side
is an interval and the right-hand-side is an array, like:
a = new interval[1.0 kg, 2.0 kg]
a -> ["lb", "oz"]
[(2 lb, 3.2739619495804129157 oz), (4 lb, 6.5479238991608258314 oz)]
Previously, this would return strange results in a strange format that didn't make much sense. Thanks to Mark Feeney for reporting the problem.
graphics.writeFormat[filename, format,
width, height] methods so that if filename is
the string "-" then the image file data is written to
standard out.
graphics.printTiled[pagesWide,
pagesHigh] method to allow a graphics object to be printed to
a printer at extremely large sizes and tiled across several pieces of
paper.
graphics.stroke[width] to
change the width of the stroke used to draw lines, polygons, or other
outlines. (Note that the stroke width can not be changed in Java 1.1.)
array.remove[index] :
Removes the item with the specified index from an array and returns its
value.
array.removeRandom[] : Removes a
random element from an array and returns its value.
More information is available in the Array Methods section of the documentation.
randomSeed[seed].
To obtain repeatable results with a program that generates random numbers,
sometimes it is desirable to use the same random sequence. This function
seeds the random number generator with a known value. The seed must a
number from -263 to 263-1 (both inclusive.)
graphics.text[text, x, y,
horizontalAlign, verticalAlign] to allow text to be drawn
with its sides aligned to the right, left, top, bottom, centered, etc.
See the Graphics with Text
section of the documentation for more information.
Please see the Graphics section of the documentation for detailed information on this major update, including sample programs. This update consists of over 7000 lines of new code, with a large number of new features and capabilities.
input[] function) to return empty strings instead of null
strings when the user cancels or closes the dialog. The null strings
caused problems in many cases, such as simply checking to see if it's true
or not.
frink.gui.FrinkStarter class that
caused errors like "cannot load file --swing" when you were actually
passing a flag.
setRestrictiveSecurity(true) method to the
frink.parser.Frink class to easily enable the most
restrictive security. See the Embedding Frink section of the
documentation for more information.
frink.gui.InteractivePanel) is now the "Main-Class" of the
jar file.
I pondered over this, and figured that if there were platforms (like handheld devices) where you don't have Java Web Start or you downloaded the .jar file and didn't have any way to specify how to start it, or you didn't know what you were doing, and just randomly started it by double-clicking or using the platform's "launch" command or something, it would use the least common denominator to start and display itself, which is AWT and not Swing. So, sorry, if you're just randomly clicking on the .jar file, it may not look as pretty as it (briefly) did, but it should work on more platforms. The differences are probably purely aesthetic.
nextPrime[n] function to return the next
prime number greater than n. The value of n may
be any real number. This uses a "wheel factoring" method to completely
avoid checking composites with small factors.
basetiming.frink to something awful and 1980's era DOS-like
BASETI~4.FRI.
# August 19, 1969 AD 04:54 PM #
# 18 February 3102 BC 06:00 Ujjain #
#1582-10-04 23:59:59 UTC# (Julian) is followed
immediately by #1582-10-15 00:00:00 UTC# (Gregorian) Note
that if a date is specified between these dates, behavior will be
undefined.
Ujjain timezone for use in ancient Indian astronomy
calculations. See IndianAstronomy.frink for more information.
setDimensionNameDelimiters[string,string]
function which changes the text printed around the dimension name (default
is parentheses). For example, when you enter "1 K", the
result is displayed as 1 K (temperature). Setting
setDimensionNameDelimiters["UN[", "]"] makes this output as
1 K UN[temperature].
showDimensionName[bool] function which
switches display of the names of dimensions on and off. For example, when
you enter "1 K", the result is displayed as 1 K
(temperature). Setting this flag to false suppresses
the "(temperature)" display. For more information, see the Setting Number Formats section
of the documentation.
frink.parser.Frink.getVariableAsDouble(String variable, String units)units to be either null or
the empty string. This tries to return the value of the variable as a
dimensionless number. And it must be a dimensionless number or an
exception will be thrown. See the documentation on Frink's integration methods for more
information. Thanks to Alberto Di Lullo for the suggestions.
secantAzimuth function to calculate the time that
a planet will pass through a given azimuth as seen from a location on
earth.
list = newJava["java.util.ArrayList", [] ]
ulist = callJava["java.util.Collections", "unmodifiableList", list]
ulist.size[]
This problem occurs because ulist is an instance of the
inner class
java.util.Collections$UnmodifiableRandomAccessList in which,
for some reason, the class has no access specifier and is thus "package
private" which, due to the aforementioned bug in Java's handling of
method invocation, is considered not accessible (even though the
method is public) when using reflection, but would be perfectly fine to
call from compiled code. Sigh. There may be a nasty workaround to try
and call this method via an interface specification, but I'm not sure.
For more information, see the discussion in the entry for 2007-06-28. I already implemented some nasty
workarounds to try and fix part of these bugs.
Thanks to Rowan Worth for the bug report.
100 m -> "ft"
and returned undef in these situations. The excessive
security check has been modified. Thanks to André Sihera for the
report.
deepCopy[x] function to perform a recursive
deep copy of all the parts of a container class. The function can be
called with any expression type. The function currently deep copies
everything contained in arrays, dictionaries, and sets, and all of the sets
contained within them. It is thus useful for copying nested data
structures, multi-dimensional arrays (which are arrays of arrays, etc.) and
prevents modification of the original or the copy from changing the other.
It does not currently deep copy Java objects, Java arrays, nor
objects created from a class specification, although it may do some of
these in the future.
symbolicMode[true]
f[x] := sin[x] + 4
f[y^2]
4 + sin[y^2]
\u0966-\u096f.
९८७६५४३२१०
9876543210
approxLog2[0].
10.0^32000.5
sqrt[n,digits] in root.frink. This now
uses adaptive working precision and smart initial guesses to produce
results more rapidly.
6_0). Thanks to Neal Crook for the bug
report.
feed_face\\16
0xfeed_face
0b0001_0101_0000
Thanks to Neal Crook for the suggestion.
FrinkVersion[] function to return the current
version of Frink from within a program. (You can also find out the
current version from the command-line by running:
frink -v
or
frink --version
binomial[m,n] to calculate
binomial coefficients. This is of the number of ways m things
can be chosen n at a time, with order being
unimportant. This is sometimes called "m choose n" or "m C n". This is
equivalent to m!/(n!*(m-n)!) although calculating that way often leads to
way-too-big numbers. For example, binomial[10000, 9998] is equal to
49995000, but if you calculated it naively, you'd have to calculate
10000! which is a 35660-digit number, and divide it by another huge
number, which could be inefficient and slow.
->
operator, Frink will now make more suggestions for factors to multiply or
divide by. Notably, it will look for squares and square roots of existing
units and suggest those as well. For example:
(8 pi 1 erg/cm^3)^(1/2) -> gauss
Conformance error
Left side is: 1.5853309190424043 m^(-1/2) s^-1 kg^(1/2) (unknown unit type)
Right side is: 1/10000 (exactly 1.0e-4) s^-2 kg A^-1 (magnetic_flux_density)
Suggestion: multiply left side by permeability^(1/2)
For help, type: units[permeability]
to list known units with these dimensions.
Thanks to Anne Archibald for the suggestion.
watt
1 m^2 s^-3 kg (power)
watt^(1/2)
1 m s^(-3/2) kg^(1/2) (unknown unit type)
The exponents of base dimensions can now be either integers or rational numbers. (Previously, only integers were allowed.)
This change was necessary to support some systems of units such as the
Gaussian and Heaviside-Lorentz systems of units, which build on the
"cgs" (centimeter-gram-second) system of units, but have very different
definitions of electromagnetic quantities than the International System
of Units (SI). For example, in the Gaussian system, electric current has
dimensions of cm^(3/2) g^(1/2) s^-2, and working
natively with this system requires fractional exponents.
While it does not usually make sense to have fractional exponents in
many systems of measurement nor in physical measurements, it is sometimes
necessary in some fields, quantum physics being another example. I have
also seen the use of fractional exponents in physical equations, such as
the square root of volumetric flow ( m^(3/2) s^(-1/2) ).
In the future, enabling fractional exponents may require a flag, but it may not. The reason for having a flag would be to detect certain types of errors as early as possible.
Thanks to Anne Archibald for a very edifying discussion of the needs of handling Gaussian units properly.
a/b where the numerator a was a large integer
(magnitude greater than 231). This did not happen in the cases
where the values of the expressions could be immediately evaluated at
compile time, but happened when more complex expressions involving
uncommon operators or functions were encountered, like
2^40 / 40!.
The error manifested itself by printing
NotAnIntegerException and halting the program. This bug did
not cause silent errors, nor did it ever produce incorrect
answers; if you encountered it, the program halted with this error
message.
Also note that multi-line mode requires that you click the "Go" button to execute the statement. Hitting the return key just moves the cursor to a new line.
array.pushFirst[x] and
array.popFirst[] methods to allow pushing and popping
from the front of an array.
== or !=
operators. Previously, this would return an error. Comparing complex
numbers using other relational operators, such as <, will
still return an error, as the complex numbers are not a well-ordered field.
EulerMascheroniConstant to the standard data file.
array.lexicographicPermute[]
to produce all the permutations of the elements in the array in
lexicographical order. This is in contrast to the
array.permute[] method which returns the permutations
in no particular order (and does thus not require them to be comparable.)
update method in
FrinkCanvas.
sunApparentRA and
sunApparentDecl into a single
sunApparentRADecl function.
xxxSiderealTime to the more accurate
xxxSiderealAngle.
apparentLocalSiderealTime function which was
completely broken in two different ways.
hourAngle function to calculate the hour angle of
an object.
parallacticAngle function to calculate the
parallactic angle of an object.
moonPositionAngle and
moonPositionAngleRelativeToZenith functions that calculate
the position angle of the moon's bright limb relative to the North Point
of the moon and the zenith respectively.
paint methods in the guitoolstest.frink file.
metretes and fixed the
definition of oldhollandcable (from a prefix to a unit
definition) in the standard data file.
Thanks to John G. Malecki for spotting these problems.
sum[x]
function to add the elements of a list or an enumerating expression.
this member variable to objects created from
classes. This was necessary to be able to pass the current object as a
parameter to functions.
EnglishToChinese, Chinese, FromChinese to imply
simplified Chinese instead of traditional Chinese. This probably
reflects modern practice more closely. Traditional Chinese will likely
not work.
charList[str] to return a list of characters
in a string.
isInteger[num] function which returns true if
a number is a dimensionless integer, false otherwise.
It now supports calculation of the following at different altitudes:
6.3 hour -> [0, "weeks", "day1", "hours", "minutes"]
This is still an error, but now it produces a more helpful error message. Thanks to Eric Hill for the bug report.
eval[] and unsafeEval[] are passed an
array, all elements of the array will now be evaluated and the
result will be returned in an array. This greatly simplifies things like
reading from a file and turning strings into numbers.
newJavaArray[classname, length] method to allow
creation of arrays of Java objects or Java primitives. See the Creating Java Objects section
of the documentation.
collapseIntervals[bool]
function to control the collapse of degenerate intervals (those with the
same upper and lower bound) into a single real number.
As an important note, this fixes the case where you couldn't create an external process through introspection, for example:
runtime = callJava["java.lang.Runtime", "getRuntime", []]
process = runtime.exec["ls"]
println[process.available[]]
The above wouldn't work in the past because the process
object wasn't usually an instance of java.lang.Process, but
of a subclass like UNIXProcess (on Linux) or
ProcessImpl (on Windows), and the aforementioned Sun bug
caused failure when trying to invoke methods on these classes, which were
declared private, even though the methods were public and
the calls would work fine in normal Java code. So now you can really
call external processes from Frink, if you want.
chars[x]
function to return an array of Unicode character codes even when passed a
single-character string.
partitionCount[n] to return the number of
ways that the positive integer n can be partitioned.
for, do...while, and
while loops. This allows for cleaner breaking out of nested
loops. See the Loops section of the
documentation for examples.
length[set] function return a value much
more efficiently for sets.
Warning: This release fixes a significant bug that was introduced recently.
Fixed a major bug that was introduced recently when multiplying by zero. I had added an over-eager optimization that turned this case into 0 (without dimensions) at compile-time, which worked for many cases, but this broke dimensional analysis. For example, the case below would produce a conformance error:
4 s + 0 s
If that produces an error, make sure you update your version of Frink!
It should, of course, produce 4 s (time).
You would also see the loss of units in something like:
0 s
If this produces 0, and not 0 s (time), then you should
update.
Many thanks to Jared Updike for informing me of the bug.
sin[x] when x is an undefined variable will
immediately halt with an error. (If you've set
symbolicMode[true] then this will return the unevaluated
expression sin[x] and will not generate a warning.)
"Fail-fast" behavior prevents traditional programs from running along merrily and building (potentially huge) symbolic expressions if you forgot to define a variable. For most programs, you'll want to know immediately if you forgot to define a variable's value. This behavior had been altered with this month's symbolic algebra changes.
JDE[day] function to take a
dimensionless value (the JDE value in days) and create a date object from
it:
JDE[2451545.0]
AD 2000-01-01 04:58:56.170 AM (Sat) Mountain Standard Time
x+0 to
0.
x^x.
symbolicMode[bool] flag to suppress a variety
of warnings that are normally presented to the user when running in
ordinary programming mode. When set to true, warnings for
undefined symbols and functions are suppressed.
frink.gui.FrinkStarter class that allows
selection of starting in command-line mode (with no arguments) in AWT GUI
mode (with --gui or --awt or -open
filename command-line arguments), or in Swing GUI mode (with
--swing command-line argument.)
sin[x] to not always throw
fatal exceptions when passed arguments that can't immediately be
evaluated. If these functions cannot evaluate their arguments, they check
to see if any of the arguments contain undefined symbols, and, if so,
return the original expression quietly. If the arguments are of the wrong
type entirely, they will still throw an exception. This is an attempt to
allow symbolic manipulation of these functions, while trying to preserve
some "fail-fast" behavior for ordinary programs. In the future, this
behavior may be further altered by a "symbolic mode" flag.
D[_f[_u], _x] <-> D[_u, _x] D[_f[_u], _u]
rationalAsFloat[true] function to force
display of rational numbers as floating-point. Setting this to
true will display all rational numbers as floating-point
approximations. They will continue to be represented internally as
floating-point numbers for accuracy. For more information, see the Setting Number Formats section
of the documentation. Thanks to Robert Munafo for the suggestion, as well
as several good suggestions for improving the documentation.
rationalAsFloat, showApproximations, setPrecision) in a
restricted context. This prevents, say, users of the web
interface from messing up the display settings for all users. Note that
someday these flags might be on a per-interpreter basis, but that'll be
significantly slower.
setPrecision[digits]
function, which allows the user to set the number of digits of precision in
floating-point calculations. I kept this function as somewhat of a
secret due to the possibility listed above. For more information, see the
Setting Precision section
of the documentation.
transformExpression[expr] function
pre-evaluate its arguments like most normal functions.
The new frink.jar file can now be compiled to a stand-alone executable using the experimental gcj 4.3 eclipse-merge-branch. (Unfortunately, it's compiled without optimization, because that pegs the CPU for over 72 minutes, and then blows out my system after trying to use over a gigabyte of virtual memory. Anyone want to donate me a new computer with tons of memory? Or try compiling it with -O3?) Thanks to Reuben Thomas for the suggestions and error reports.
Hint: If you install the gcj package linked above, the command line to compile with full optimization will be something like:
gcj -O3 --main=frink.parser.Frink -o frinkx.exe frink.jar
Note: Yes, the executable has been stripped to reduce its size (original was about 48 MB.) I may further compress it with an executable packer which will reduce the size to less than 5 MB at the cost of slightly slower startup time.
showUndefinedSymbols[false]
_x + _x <-> 2 _x
The <-> operator seperates the two sides of a
transformation rule.
The above implements the usual mathematical equivalence x+x=2x. A
variable preceded with an underscore like _x is a pattern
that matches any expression. (If you just have a variable
called, say, x in a rule, it will match only the literal
symbol x.) The fact that the above expression has
_x in two places on the left-hand side enforces that the
same pattern has to be the same on both sides of the addition
operator.
All defined patterns can then be applied by the
transformExpression[expr] function:
transformExpression[y+y]
2 y
Note that it also works with arbitrary expressions on either side:
transformExpression[2x + 2x]
4 x
You can define more transformation rules, and they will all be applied. Below are a couple of the most common transformation rules:
0 _x <-> 0
1 _x <-> _x
0 + _x <-> _x
_x * _x <-> _x^2
_a _x + _b _x <-> (_a+_b) _x
_x^_a * _x^_b <-> _x^(_a+_b)
If you play with this a bit, you'll see that the structure of the expression is matched, and the structure has to match exactly.
More work needs to be done with matching all orderings of addition and multiplication operators, which are commutative, and the syntax may change, but this is a huge, huge step forward for Frink!
Homework: Using the above examples, define transformation rules
to take the derivatives of expressions, like: D[sin[2x],x]
You can do it for many types of expressions, but not all.
frink.jar file and added
some apparently-unused inner classes that were preventing compilation with
some picky tools like gcj. These missing classes may have also prevented
execution on some odd JVMs, at least in theory. Thanks to Reuben Thomas
for the information.
The exact workings of this may change, but you can now specify arbitrary
patterns beginning with the underscore character _ and with
an optional name. For example, to transform instances of x +
x (where x is any pattern) into 2x, you
can try the following code:
substituteExpression[x+x, _y + _y, 2 _y]
2 x
The pattern _y + _y matches any pattern where both
sides of the + operator are the same pattern, and replaces
that pattern in the first expression x+x with 2
x.
Or, more generally, to handle sums of products of similar variables:
substituteExpression[3x+4x, _z _y + _x _y, (_z+_x)_y]
7 x
Using the same rule:
substituteExpression[(z-3) x+4x, _z _y + _x _y, _y (_z+_x)]
x (1 + z)
That may seem simple, but it's an amazingly powerful feature that will allow arbitrary mathematical transformations. More information and features to come, and more easy specification of transformation rules to come.
+ operator to also allow string concatenation gets in the way
of doing this universally. Sigh. I need to choose a different string
concatenation operator. I knew I'd regret that choice.
parseInt[str, base] to
parse a string into an integer, treating the string as being in the
specified base. This is faster, but less flexible, and more sensitive,
than using something like eval[str\\16] for the same
purpose.
arccosh[x]
or acosh[x]. This function works for complex and
interval arguments.
set datatype useful. You can now construct sets,
add elements to a set (using the put method), test for
containment, and more. For more information, see the Sets section of the documentation.
showUndefinedSymbols[bool] to
control whether or not "(undefined symbol)" should be shown after all
undefined symbols. This would be annoying in symbolic calculations. This
function may change.
approxLog2[x] function to return a double
and return a much better initial estimate for integers. This will help
the initial estimate in many numeric algorithms.
collapseIntervals[bool] function to indicate
whether or not degenerate intervals (that is, those with equivalent lower
and upper bounds) should be collapsed into a single real number. The
default is false. This feature is still somewhat
experimental, but it should allow you to see what may happen with
different rounding directions in interval arithmetic, and see how
numerical error propagates as a result of different rounding directions.
substituteExpression[orig, from,
to] function to allow substitution of parts of an
expression with other expressions. This is part of the upcoming symbolic
mathematical capabilities. The name and behavior of this function may
change.
+ ) in several ways:
Note that the following changes may affect existing programs! It's very doubtful that anyone expects or codes for the old behaviors, but these changes could affect some oddly-written programs.
Slightly altered the semantics so that two units (i.e. numbers) which are added together in the midst of a string concatenation will get added first before the string is concatenated. This altered/fixed the case where string concatenation was always done first. For example:
s = 1
println["Next=" + s + 1]
now outputs Next=2 instead of the old behavior, which was
to print Next=11. (See how the promotion to string and
then string concatenation was done first.)
If you want the old behavior, you can get it by coercing one of the units to a string explicitly using the string interpolation rules. Either of the following works to give the old, weird behavior:
println["Next=$s" + 1]
println["Next=" + "$s" + 1]
date = now[]
offset = 1 year
println["1 year from now is about: " + date + offset]
1 year from now is about: AD 2008-04-11 10:07:45.100 AM (Fri) Mountain Daylight Time
The previous behavior was to do a string concatenation of the date and time, without separators, which is probably never what anyone wanted. And yes, it may have been best to have a completely different string concatenation operator in the first place.
expressionContains[a,b] and
freeOf[a,b] functions to support
symbolic calculations. These functions determine if the expression
a either contains or is free of expression b. The names and
behaviors of these functions may change.
gcd function if one of the
arguments was zero.
?rich
[metrichorsepower, electrichorsepower, Richter[n]]
??rich
[metrichorsepower = 588399/800 (exactly 735.49875)
m^2 s^-3 kg (power),
electrichorsepower = 746 m^2 s^-3 kg (power),
Richter[n]]
Note that this now displays the Richter[n] function which
converts energy values to/from their equivalent on the Richter scale.
This facility will make interactive calculations more friendly, and somewhat reduce the need to go to the documentation to find information about functions. This will also reveal some functionality that you may not have known about, such as the Richter function which must be implemented as a function because it's not linear.
Note that user-defined functions display their proper named arguments,
while built-in functions may display something like arg1.
This may change, or it may not, as Frink checks to see if a function has
named arguments and performs several optimizations if there are no named
arguments.
numerator[num] and
denominator[num] functions to return the numerator and
denominator of a rational number (or any number).
left[str,len] and
right[str,len] convenience functions to give
the left or right side of a string.
childCount[expr] and
child[expr, index] functions to support
symbolic calculations. These functions give information about the
structure of an expression and any child expressions. The names and
behaviors of these functions may change.
indexOf[string, substring] function to
find the first index of a given substring within a string. This returns
-1 if the substring is not found.
dict.clear[] to clear the contents of a dictionary.
length[dict] function return a value much
more efficiently for dictionaries.
earth...) from the sun.frink astronomical
library to its own new file, navigation.frink.
If you have programs written to use the above functions, they may require modifications:
East and West defined at the top of
the sun.frink file, changing your use
statement to instead include navigation.frink will
automatically give you the proper sign convention. Otherwise, you will
need to verify that your sign convention uses negative numbers for west
longitudes and positive for east.
Note: The sun.frink sign convention was chosen to
match the one that is widely used in all astronomical
calculations, by the International Astronomical Union, etc. It would
be nice to rewrite all the astronomical algorithms to follow the same
sign convention as geodetics, but that's really fraught with peril.
Sigh.
earthBearing and resultantLatLong) used
spheroidal calculations which would cause small errors and asymmetries
between the forward and reverse calculations. The calculations are now
symmetrical. These functions have replaced the old functions of the
same name, with the old functions being renamed to
lowAccuracy... You should be able to use the updated
functions without modification, as long as you note the sign convention
change.
Even the previous ellipsoidal calculation in the function
earthDistance has been replaced with the new algorithm.
The new algorithm will be more accurate as it uses an iterative
procedure to reduce error on the ellipsoid (most calculations on an
ellipsoid cannot be expressed in a closed form.) Currently,
convergence limit is set at 1 microdegree, which corresponds to about
.1 mm on the earth's surface. The previous calculations could have a
relative error on the order of earth's flattening squared.
earthDistanceAndBearing which returns a list
containing [distance, initBearing, finalBearing] as the
calculations for distance and bearing would repeat many of the same
calculations. If you're calculating both distance and bearing, this
function will be more efficient than calling earthDistance
and earthBearing.
update tag to the JNLP specification files
(used for Java Web Start and available only in Java 6) as it caused
problems in Java 1.5 and before (it said that the file was missing a
<jnlp> tag when it wasn't.) Thanks to the lovely Tara Stewart for
the bug report.
Added a couple of sample scripts to run Frink in command-line mode. You will need to edit them to match the paths on your system!
There is more information on startup options in the Running Frink section of the documentation.
update tag to the JNLP specification files
(used for Java Web Start and available only in Java 6) to tell Frink to
check for updates in the background while launching and then automatically
update if there's a newer version. I'm not sure how well this works, so
let me know if you have problems with Java Web Start.
set data type.
new dict
for new array. The syntax for accessing elements of an array
and of a dictionary is otherwise identical:
a = new dict
b@0 = 123
b@100 = 301
showApproximations[bool] function
which switches display of floating-point approximations for rational
numbers on and off. For more information, see the Setting Number Formats section
of the documentation.
gcd algorithm, as it was tested to be
faster than the new algorithm for larger numbers, especially on some
platforms.
i^4 is now exactly 1.
factor function for the first time.
break statement to break out of the
currently-executing loop. This applies to for,
do, and while loops. Labeled breaks may come
later.
gcd function to be about 10% faster.
This will improve the speed of Frink's gcd function and
improve performance when reducing rational numbers to simplest terms.
messageDigest[str,
algorithm] to calculate a variety of cryptographic hashes of
various strings. The algorithm parameter is a string
containing one of any hashing algorithms your Java platform supports, which
probably includes: "MD2", "MD5", "SHA-1", "SHA-256", "SHA-384",
"SHA-512". See the Cryptographic Functions
sections of the documentation for code samples.
modDiv[n,m,
modulus] to perform the integer modular division
n/m mod modulus which returns the integer result
if one exists, otherwise returns undef.
modInverse[n,modulus] to
find the integer modular inverse of n to the base
modulus and returns the integer result if it is invertible,
otherwise returns undef.
array.permute[]
to produce all the permutations of the elements in the array.
Warning: Older versions of Java may contain incorrect daylight saving time conversion for the U.S. in 2007 and beyond. Read below for more details.
If you use Frink to perform calculations with dates in the future, especially dates in the U.S.A., I would like to strongly urge you to make sure that your version of Java is updated to match U.S. daylight saving time changes. These changes were signed into law as part of the Energy Policy Act of 2005 and will take effect in 2007.
In short, "Clocks will be set ahead one hour on the second Sunday of March instead of the current first Sunday of April. Clocks will be set back one hour on the first Sunday in November, rather than the last Sunday of October."
Sun claims that this change has been made to the following Sun Java releases:
However, at the time of this writing, the latter three are apparently unavailable for download from Sun's web site.
In practice, I have apparently seen this change to be made in some earlier versions of the 1.5 branch, but they would probably know better than I would if the problem was only half-fixed in earlier releases. Updating is recommended.
There is also a (beta) timezone updater tool if you're not allowed to update to any of these VMs.
Failure to update your VM may cause significant errors in converting to or from any U.S. timezones. No changes to your Frink jar files or Frink programs will be necessary when your Java environment is up to date.
Note that Java 6 (also known as 1.6) has very recently been released and is available for download.
If anyone notices any unexpected changes in any Frink behavior under Java 6, please let me know!
randomGaussian[mean, sd] to return a
normally-distributed (i.e. "bell curve") random floating-point value with
the specified mean and standard deviation.
randomFloat[lower, upper] to return a
uniformly-distributed random floating-point value in the specifed range.
array.shallowCopy[]
to perform a shallow copy of the elements of an array. Arrays are normally
passed by reference, and this allows them to be copied easily and
efficiently.
Important Fix: Fixed a problem in the makefile introduced when checking in yesterday's changes. This may have caused certain files not to be packaged correctly and could have broken Frink entirely. Please download Frink again if you experienced problems with yesterday's build.
Turkey_Lira to Turkey_New_Turkish_Lira.
The symbols changed are:
| Country | Old Symbol | New Symbol |
|---|---|---|
| Azerbaijan | AZM | AZN |
| Mozambique | MZM | MZN |
| Romania | ROL | RON |
| Turkey | TRL | TRY |
earthradius_equatorial,
earthradius_polar, and earth_flattening in the
standard data file to use the WGS84 datum, which is most commonly used in
modern maps.
eval[string] more robust in the face of errors
thrown from low levels of Java, such as divide by zero errors.
Now, any Throwable is caught and the function returns undef
when an exception is caught.
java.vm.name.
If the VM did not have a property with this name, initialization of the
base converter class would fail and Frink would not display larger numbers
(absolute value 231 or larger) properly. This was a problem in
some Java 1.1 environments, notably on Nokia handhelds. Be sure that when
you install Frink on these environments, it says version 3.4 or 3.04 or
later. Thanks to Francis for the bug report!
return statement
was the last statement in the function. This is now much faster. It
improves the speed of calling such functions from 3% up to 700%.
sin[x]. This
gives a small speedup and a reduction in runtime memory usage.
arccsch[x] or
acsch[x], defined as ln[sqrt[1 + 1/x^2] + 1/x].
This function works for complex and interval arguments.
format function was not an integer.
arcsinh[x]
or asinh[x]. This function works for complex and
interval arguments.
use statements to look for files in an
internal library shipped within the jar file. (In directory
/lib/). This library is currently empty, but this paves the
way for a distribution of Frink with a larger standard library of code
implemented in Frink.
array.removeValue[value] now returns
true if the value is found and removed, and
false if no matching item was found. See the
Array Methods section of the
documentation for more.
futureboy.homeip.net to
futureboy.us. It appears that this may make pre-existing
Java Web Start icons ask you if you want to make file associations or
create icons. If you answer "yes," it looks like it won't bother you
again.
File |
Interrupt Calculation menu item.
It's possible that this causes problems on platforms with minimal Java support and no support for threading. If this is the case, please let me know.
version tag of Java Web Start
JNLP files to hopefully work around bugs in Sun's implementations where
the latest installed version of Java is not used. See below on how to fix
this manually.
Note that when Frink first starts up as a widget, it might appear to hang. This is because Sun's Java installation pops up a dialog box behind other windows that asks you if you want to trust the Frink applet. You may have to hunt for this window. You can choose to "always trust" the application so you don't have this problem repeatedly. This was supposedly fixed in Java 1.5, but it still seems flaky.
I should note that installing Frink via Java Web Start (outlined here) is still in all ways a better way to install Frink than via a widget. It's resizable, automatically updates itself when Frink changes, and more. But the kids these days seem to like these widgety dealies.
Many thanks to the lovely Tara Stewart and the lovely Adam Singer for showing me how a Mac works, updating their Java settings, letting me screw with their computers, helping me test this stuff, and making dinner while I screwed around.
deltaT[now[]] returns 65.184 seconds,
due to the leap second introduced at the end of 2005. (Frink planned for
this change in the 2005-08-30 release.) Be sure to set your clocks back
one second!
The current value of delta-T, the difference between Terrestrial Dynamical Time and UTC is now 65.184 seconds. Astronomers take note.
deltaT[now[]]
65.184 s (time)
-v or
--version command-line flag actually works. Thanks to Bill
Poser for the bug report.
-v or --version command-line flag to
print out the Frink version and exit. The format of this version string
may change in the future.
BigInteger.ONE
from the new factoring code. This yet again fixes some
incompatibility problems with some Java 1.1 distributions. I
didn't realize that these variables weren't required to be public until
Java 1.2, and all of the Java distributions that I'd tested with made them
public, even on PersonalJava 1.1. But not on the Sharp Zaurus.
The choice of using pack200 compression should be automatic and transparent. Note that pack200 compression is only chosen if you're using Java 1.5 or later. If you're using something older, downloads should still work as before.
The advantage of using pack200 compression is that the size of the file you have to download is reduced from 615 kB to 220 kB. This should happen automatically the next time you launch Frink from your Java Web Start icon.
If you haven't used Java Web Start to install and automatically update Frink, you can do so here.
The pack200 compression scheme is a little screwy, and requires repacking the original jar file. This may cause issues on some platforms that I haven't detected. If you have any problems with downloading Frink or running Frink on any platform, or if you get verification errors, please let me know as soon as possible.
(1/4)^(1/2) :
(-27)^(1/3) now
returns the real number -3.0 instead of the complex number
(1.5 + 2.598076 i) that it returned
previously. Both of these are valid cube roots, (all numbers can be
said to have three cube roots, at least 2 of which are complex,) but now
the "principal" real cube root is returned for real negative bases.
Please note that if an inexact floating-point number is substituted for
the exponent (e.g. (-27)^.333333333), this will
(correctly) return a complex number if the base is negative. This
means that exponentiation may be somewhat "discontinuous" in the
complex plane for negative bases (you're actually picking a different
root at nearby points,) so if continuity matters to you, you might need
to either make conscious adjustment of the root you desire, or just
force the exponent to be a floating-point number before exponentiation.
(Say, by multiplying by 1.0.)
(1/4)^(1/2) now returns
the exact rational 1/2, instead of 0.5.
Currently, this is only true for exponents with denominators of 2, which
will hopefully be improved when I add routines to find exact integer
roots, if such exist, for roots other than 2.
isPrime[x] to automatically use a faster
Lucas-Lehmer test if x is of the form 2n-1 (i.e.
Mersenne numbers). Note that the Lucas-Lehmer test is sufficient to
prove primality for numbers of this form, regardless of their
size. If Frink says that a Mersenne number is prime, it is.
factor[num] to detect Mersenne numbers
(that is, those of the form 2n-1) and use certain properties of
these numbers to speed factorization when n is composite. This
currently performs some recursive subdivision of the number, detecting
some known factors rapidly. This makes factoring some Mersenne numbers
much, much faster.
It should be noted that any calendar dates before October 15, 1582, (the date that the first countries switched from the Julian to the Gregorian calendar) should be treated as suspect when converting a Julian day to a Julian date or Gregorian date or vice versa. Not to mention the glitches in the proleptic leap year rules projected backwards, the fact that there was no year zero, and the fact that there was no Julian calendar before 4 AD. I need to figure out and state my policies as to what calendar dates before this mean (and probably make all the options of interpretation user-configurable.)
array.removeValue[value] method to
remove the first item having the specified value from the array. See the
Array Methods section of the
documentation for more.
new operator, e.g.
new Something instead of
new Something[] .
arctan[x,
y] to work with all combinations of intervals and real
numbers. This was an enormous pain. Thanks to G. William Walster for his
assistance in making this much less painful.
format[x, divideBy,
decPlaces] function to allow intervals to be formatted to the
specified number of decimal places.
format[x, divideBy,
decPlaces] function to be a string representing a more
complex expression (previously, it only allowed unit names.)
-> and in the format[x, divideBy,
decPlaces] function. This has the result that some complex
formatting done through the web-based interface will not work. This may
be weakened in the future.
0 -> m . Thanks to
the lovely David Rysdam for the report.
eval[string] return undef if
something goes wrong during parsing. Previously, it would throw an
exception and halt evaluation.
floor[x],
arccos[x], arcsec[x], and
arctan[x] to work with intervals.
mod operator to work with intervals.
This added a huge amount of power. All of a sudden, almost all of the astronomical calculations in my sun.frink libraries work with fuzziness and uncertainties.
infimum[x],
supremum[x], and mainValue[x]
functions to work on date intervals.
tan[x],
csc[x], sec[x], and
cot[x] to work with intervals and all of their
inflection points.
sin[x] and
cos[x] to work with intervals and all of their
inflection points.
sqrt[x], ln[x],
log[x], and exp[x] to work with intervals.
frink.errors.FrinkEvaluationException
when something goes wrong in the course of parsing or executing. If
you're integrating Frink into another program, you'll have to catch this
exception. This hopefully makes it easier to detect and handle error
cases. Previously, the error message just appeared in the output string,
which made it difficult to distinguish from normal program results.
See the documentation on Frink's
integration methods for more information.
infimum[x],
supremum[x], and mainValue[x] to
return the lower, upper, and main (middle) bounds of an interval. If these
functions are called with a unit that's not an interval, these just return
the unit.
< == >, etc) to
work with intervals. These operators try to Do The Right Thing when
applied to intervals. If you compare intervals that do not overlap, they
return the appropriate result. If, however, the intervals do
overlap, they terminate the program with an error similar to the following:
Comparison expression: Using operator > to compare intervals [2, 3] and 2.5.
This operator is only defined if there is no overlap between intervals.
Please modify your program to use interval-aware comparison operators.
CLT (certainly-less-than) and
PGE (possibly greater-or-equal).
1^x to always return the exact integer 1.
So what's interval arithmetic? It's a way of tracking errors or imprecise values automatically throughout your calculations. Check out the new section in the documentation about it.
Internally, the math libraries were rewritten extensively to allow rigorous interval arithmetic.
Currently, only the mathematical operators + - * / ^ are
implemented for intervals. The notation may also change in the future,
but it's already quite usable for many programs and calculations.
min[array] and max[array]
functions to return the smallest and largest items in an array
respectively.
new expressions to go just about anywhere in
expressions. These were somewhat limited before.
1.234e100 + 1 the answer would be calculated and
stored with all 100 digits, most of which were almost certainly illusory
digits of precision, and far more digits than were specified in the
original number. The result is now only calculated and stored to the
number of digits of working precision (by default 20, but you can
increase this by using the setPrecision[digits]
call.) Note that this does not affect integers or rationals,
which are still calculated with all of their digits.
mod function also
produces less digits of illusory precision when working with
floating-point numbers.
length[expr] function now returns the number of
items in an enumerating expression.
eval[] now disallows defining of functions in
untrusted code. (You can still do this in unsafeEval[]).
This may be relaxed in the future--it may be beneficial to allow users to
define functions that are marked as being defined in a restricted context
and would only be allowed to be called in the same restricted context.
But that'll take work. What this means for users of the web-based
interface is that they won't be allowed to define functions any more.
--sandbox command line option which enables Frink's
internal sandbox mode for untrusted code. See the Command-Line Options section of
the documentation for more.
<, >, =,
<=>, etc.) to make better comparisons when numbers were
really large or really small. Previously, there could be issues if
floating-point numbers were larger than about 10308or when
comparing very large and very-nearly-identical rational numbers or
comparing some numbers of different types (e.g. integers and rationals)
when the numbers were very large and almost identical.
Double.compareTo() which did not
exist before Java 1.2. This may have caused problems doing comparisons on
some handheld devices.
Numeric hierarchy so that they
would support the above.
.frink file extension and the
text/frink MIME type with the Frink program you just
downloaded. This simply allows you to edit files with the .frink file
extension by double-clicking them. This will not run the files,
but simply open them in editing mode. Java Web Start will also
never change the MIME associations used by your browser... the
MIME associations are only made for the operating system. If you don't want
this behavior, choose "no" when prompted by Java Web Start. (You can also
prevent associations from ever being made by setting your Java Web Start
preferences wherever that may reside on your system. In Windows, It's in
the Control Panel.)
hubbleconstant and H_0 units for the
expansion rate of the universe. These are based on WMAP data.
afghani, baht, balboa, birr, bolivar, boliviano, cedi, dalasi, denar, deutsche_mark, dobra, dong, drachma, euro, fin, florin, forint, gold_cordoba, gourde, guarani, hryvna, indonesia_rupiah, israel_new_shekel, italy_lira, kina, kroon, kuna, kwanza, lari, lat, lek, lempira, leone, lev, lilangeni, litas, loti, luigino, markka, metical, moldova_leu, morocco_dirham, naira, nakfa, new_dinar, new_dollar, new_shekel, ngultrum, norway_krone, nuevo_sol, ouguiya, pa'anga, pataca, peseta, pula, punt, quetzal, rand, real, riel, ringgit, rubel, ruble, rufiyaa, rupiah, schilling, somoni, switzerland_franc, taka, tenge, tolar, tughrik, vatu, yen, yuan_renminbi, zloty
Type sort[units[currency]] to get a list of all currencies
sorted by name, or ?currencyname to figure out what
country each of these comes from. Do you know?
-> operator where the
right-hand-side was a function that used a "return" statement. This may
have previously thrown a "Return used outside a function" error. For
example, 10 kilotons TNT -> Richtersovereigns_yyyy (with the trailing
"s") work properly. Before I just had sovereign_yyyy
entered twice. Thanks to the lovely Berrian (Eno)-(Van Fleet) for filing
a bug report so Zen-like and subtle that it was like it wasn't a bug
report at all. And thanks for the lovely comments about Frink.
randomBits[numBits] .
Fixed a bug in the function JacobiSymbol[a,n] which
returned the wrong value in some cases when a was negative and
within the range [-2147483648, -1]. (Values were correct for other values
of a.) Thanks to Aaron Bertram for the bug report.
I'd like to note, as an interesting aside, that I remembered that Sun had a similar bug in their calculation of the Jacobi Symbol. (I don't use their algorithm, by the way, so Frink's Jacobi symbol calculations will work properly in any JVM.) It took Sun three years to release a fix since the bug was first reported. (It was reported against Java 1.3.1, and not fixed until 1.5.) Many of their primality tests were broken due to this. (So much for your secure communications!)
To contrast, I got the bug report this morning, and I was ashamed that I didn't have time to fix it before I left for work. I had to wait until I got home to release a fix.
setEngineering[boolean] function to switch
back to the old "engineering" format. See the Setting Number Formats section
of the documentation for more details.
--nounits or -nu command-line option to
start Frink without parsing the standard units file.
/g modifier) where repeating the match may
cause null pointer exceptions.
flatten[list] function to allow enumerating
expressions to be passed in.
for loop of the form:
for [a,b] = enumeratingExpression[]
ARGS global variable which contains the values of
any command-line arguments following the name of the program.
There are some oddities and inconsitencies in NIST's data (and it's certainly not the first time I've found mistakes in NIST data.) For example, dividing their definition of electron mass in kilograms, their definition of the "unified atomic mass unit (u)", and the electron mass in u do not yield values that are self-consistent. They're close, but off in some significant figures. These sorts of errors and inconsistencies seem to go all through their data--values that are derived from other values, such as the fine structure constant α, or the Rydberg constant, show more precision than the values they are derived from, and the values derived from multiplying their published values aren't self-consistent.
editDistance[str1, str2] function
to calculate the edit distance or Levenshtein distance between two
strings. This can be used for a wide variety of purposes, including
performing fuzzy spelling checks, detecting plagiarism, or finding
correlations between strands of DNA. More information is available in the
Other String Functions
section of the documentation.
editDistance[str1, str2] function
allowed fuzzy spelling suggestions to be suggested in the hints provided by the
web interface. If a misspelled unit is entered in the web-based
interface, it will suggest alternates which have edit distances less than
1/3 the length of the longer word. (This matching is done in a
case-insensitive manner.)
min[arg1, arg2] and
max[arg1, arg2] functions. More
description can be found in the Other
Functions section of the documentation.
lines[] function. The
security check was deferred until the enumerator was actually accessed.
This meant that an enumerator could "leak" out of a secure context and its
security may not have been checked until later, when, say, its contents
were printed. I now check security repeatedly at several points. Many
thanks to 31337 |-|Ax0r Clayton O'Neill for discovering this bug,
and many more thanks for reporting it (and not exploiting it!)
-Xnative-big-math argument to the Kaffe executable. See the
Performance Tips section of the
documentation.
Re[x], Im[x], and
abs[x].
This allows you, say, to get a list of all of the hexadecimal values of the Unicode characters in a string. The following translates a string to Japanese and then gets the Unicode codepoints for each character in the translated string.
hex[char["Year of the beagle" -> Japanese]]
[30d3, 30fc, 30b0, 30eb, 72ac, 306e, 5e74]
This improves performance enormously. On a 800 MHz Pentium III, it originally took 808 seconds to print the numbers from 1 to 10000 in the AWT interface. After the change, it takes 0.3 seconds, a factor of 2700 times faster! Similarly, performance is improved greatly on handheld devices. On a Symbian 7 emulator, the time was improved from 2432 seconds to 45 seconds, faster by a factor of 54.
class
specification to use less memory.
use statement now searches paths relative to the
file being included. This allows code libraries that consist of files
which include other files to work in a straightforward fashion, whether
the file is local, or included from another file, or part of a remote
library fetched by an HTTP or other URL. See Including Other Files section
of the documentation for more information about the search order.
for loop: if the enumerating
expression evaluates to undef, it's treated as the empty list
and returns without an error, and without evaluating the body of the
loop. Previously, it threw an exception.
NullPointerException if an unknown timezone name
was specified.
China as a timezone alias for
Asia/Shanghai, as China has only one (big) time zone. Thanks
to Mike Kordik for the suggestion.
"\\t" wouldn't
work right. (It's supposed to turn into one backslash followed by a "t"
(that is, \t ). Any single character following a backslash
that isn't a special character just becomes that character. Added more
documentation to the Strings section of
the documentation.
split[pattern, str] to run
faster when the pattern is a simple string.
parseInt[str] to parse a string into an
integer. This is faster, but less flexible, and more sensitive, than
using eval[str] for the same purpose.
class specification.
.jar file might only get reloaded the
second time after it changes if the web server gives a redirect
response.
split[pattern, str] to be either a regular
expression or, now, a string.
NullPointerException that occurred if a class
didn't have any class-level methods or variables.
input[x]
function was calling methods (getWidth() / getHeight()) that
don't exist on Java 1.1 platforms. This caused the input function to not
work on Java 1.1 platforms. This was unfortunately introduced in the
2004-04-23 update. Thanks to a mysterious being who calls himself "Casual
Programmer" for the bug report.
trim[string] function to remove whitespace
from both ends of a string.
new as
the name of the function. More documentation and discussion is in the classtest.frink
sample which documents object-oriented programming.
new,
for example:
jupiter = Sphere.new["Jupiter"]
jupiter = "Sphere".new["Jupiter"]
See the end of classtest.frink for a sample.
string
or dict. The complete list and documentation is found in the
Constraining to Built-in
Types section of the documentation. For example,
var name is string
DimensionListConstraintSource for memory
usage.
isStrongPseudoprime[num,
base]
function to deterimine if a number is a strong pseudoprime to a specified
base.
mod operator.
Eventually, FFT routines will be ported to Java and more highly optimized (pre-caching of sines and cosines, possible real transforms, possibly caching of swaps and butterflies, and probably implemented entirely in machine-precision floating-point for speed.)
class keyword:
class keyword to
share class-level variables efficiently with their metaclass instance.
isA(String type) method to FrinkObject interface
to allow objects to claim to be of a certain type.
TestClass, the following will ensure
that the value assigned to the variable a is always an
instance of TestClass.
a is TestClass = new TestClass[]
Environment objects to
allow for more flexibility in construction, and better error reporting.
input[] window to be the same size as the
parent window, or the minimum size necessary to contain the prompt,
whichever is bigger. Also made the input window resizeable. This should
prevent too-small input boxes and still work on handheld devices. Thanks
to Kip Barros for the suggestion.
BigInteger.toString() (this only recognizes Kaffe right now, but Kaffe can use the
incredibly fast GMP libraries for
its BigInteger work, making it thousands of times faster than Sun's
implementation for large integers.
oldToString[integer] and
newToString[integer] functions to test the speed of
integer formatting using, respectively, the method implemented by the VM's
version of BigInteger, and my own hand-written recursive
divide-and-conquer algorithm. You generally won't use either of these,
but my version is orders of magnitude faster than Sun's for large numbers,
and just as fast for small numbers.
Re[x] function (to return real part of a complex
number.) It wasn't working correctly before for complex numbers due to a
stupid cut-n-paste.
JacobiSymbol[a,
n] function to calculate the Jacobi symbol of two
numbers. This is used in factoring and primality testing.
format[x, divideBy,
decPlaces] function to be a string, which prints the value of
the string after the result.
input[] box. Thanks to Jon Hoskin for the bug report.
1/2
1/2 (exactly 0.5)
1/11
1/11 (approx. 0.09090909090909091)
frink.ipk file (these are
really just .tar.gz files,) without warning you or changing
the filename. If you have problems with the installer, you should try
downloading with another browser.
BigInteger.ONE and
BigInteger.ZERO from the code. This fixes some
incompatibility problems with some Java 1.1 distributions. I
didn't realize that these variables weren't required to be public until
Java 1.2, and all of the Java distributions that I'd tested with made them
public, even on PersonalJava 1.1. But not on the Sharp Zaurus. Thanks to
Karl Heinz Kremer for the report.
frink.gui.InteractivePanel
and frink.gui.FullScreenAWTStarter
to specify size of the initial GUI window. You can specify either width
or height or both. The syntax would look something like:
java -cp frink.jar frink.gui.InteractivePanel -width
500 -height 400
Thanks to Karl Heinz Kremer for testing this on the Sharp Zaurus.
class var x = 10Classname.variable Note that this now
essentially allows "clean" global variables.
conforms operator to take a string on the
right-hand side. This string is taken to be the name of a dimension list.
units[x] was a variable name
and improved error messages.
sqrt[-1] now returns i and not
the inexact 1.0 i.
M-; work for inserting comments.
do...while loop.
getBit[num,
bit] function to test bits in the binary representation
of an integer.
bitLength[num] function
to return the length of bits in the base 2 representation of a number.
factor[num] function. Factoring now first tries
trial division, then the Pollard p-1 algorithm, then the Pollard
rho algorithm.
/e switch to
evaluate the right-hand-side as a Frink expression.
new array
which is now the recommended syntax.
Important Changes: Several major changes were made to the command-line options and syntax for Frink. These may require you to change your startup scripts. Please read below for details.
-e option is now
required to execute a command-line argument as a Frink expression. The
-f option to specify a filename to interpret is now
deprecated and unnecessary, and has slightly different functionality,
although it will still work the same in most cases. See the Command-Line Options section of
the documentation for more.
{{ |x| x mod 2 == 0 }}
is now written as:
{ |x| x mod 2 == 0 }
Programs using the old notation will still work, (for some unspecified time,) but will produce a warning. This syntax is now identical to Ruby's, and is more concise and less noisy.
gcd[x,y] function to return the greatest common
divisor of two integers.
!! to ||| to allow chained
factorials. If you use your own data file, you'll have to change it.
isPrime[x] and factor[x] functions
explicitly raise an error on non-positive arguments, and return reasonable
values for 1.
ln[x] and common log (base 10)
log[x] to handle and produce complex numbers.
exp[x] function for real and complex numbers.
Re[x] and Im[x] functions to
return real and imaginary parts of a complex number.
sinh[x], cosh[x], and
tanh[x] hyperbolic functions.
sin[x]
cos[x]
tan[x]
sec[x]
csc[x]
cot[x]
arcsin[x]
arccos[x]
arctan[x]
arcsec[x]
arccsc[x]
arccot[x]
now[] function without the
square brackets.
USD_ as a possible prefix for historical US dollar
conversions. See the Historical U.S. Price Data
section of the documentation for more information. Changed to bootstrap
the loading if someone requests a unit starting with the incorrect
lowercase usd_ for help purposes.
GBP_ as a possible prefix for historical British
pound conversions. See the Historical British Price
Data section of the documentation for more information.
subst[fromStr, toStr] and
subst[fromStr, toStr, options] to allow
building of search-and-replace expression with variable interpolation on
the left-hand-side. See Search and
Replace in the documentation for more.
SelfDisplayingExpression interface which
Expressions can implement if they want to display themselves in a certain
way. Modified formatters to use this.
\u00D7 )
× and INVISIBLE TIMES ( \u2062 ) as synonyms for
multiplication. I'll be digging through more Unicode tables and putting
in Unicode synonyms for other operators.
There was actually a great adventure a couple of days ago where I predicted the moon crossings and noticed that the next rare predicted crossing would happen in two hours and managed to contact Keith Winstein at MIT to run over and verify. Many thanks to Keith Winstein and Ken Olum for providing location information for the corridor, and helping to verify predictions. It's a good story. If you're interested in the predictions (or the story,) please contact me. Thanks also to Stuart J. Goldman and his interesting article "Sun Worship in Cambridge" in the November 2003 Sky & Telescope magazine.
4 miles / 10 hours which explains
normal mathematical rules of precedence and suggests 4 miles / (10
hours). See this section of the
FAQ for more information.
new operator to create new objects by name.
Currently, the only object that can be constructed is dict,
but the underlying architecture to make this happen will allow for
arbitrary objects to be constructed in a very flexible fashion.
undef to Java
null.
java.util.Enumeration to allow their use as a Frink
EnumeratingExpression.
inchmercury and irregular plural
inchesmercury. Thanks to Howard Tanner for the suggestions.
f = newJava["java.awt.Frame", "Whee!"]
f.setSize[200,200]
f.show[]
??moon-style help
messages.
0xFFFF notation for hexadecimal numbers and
0b1111 notation for binary numbers. I refuse to use
the normal convention that numbers beginning with a zero are treated as
octal. That madness has to end.
1000! (approx. 4e+2567) that will be cached. If
you regularly need factorials larger than this, performance will be
degraded. Please let me know if this is the case.
??moon
moonlum = 2500 m^-2 cd (illuminance),
moondist = 0.002569555301823481845 au,
moonmass = 73.483E+21 kg (mass),
moonradius = 0.000011617812472864754024 au,
moongravity = 1.62 m s^-2 (acceleration)]
More information can be found in the Integrated Help section of the documentation.
parseDate[string] function to parse a date
from a string.
?horse which
produces a list of unit names that contain the word "horse" can be
converted to a list of those units and their values:
?horsepower -> watts
[horsepower = 37284993579113511/50000000000000
(approx. 745.6998715822702),
brhorsepower = 745.7,
boilerhorsepower = 9809.5,
waterhorsepower = 746.043,
metrichorsepower = 588399/800 (approx. 735.49875),
electrichorsepower = 746]
More information can be found in the Integrated Help section of the documentation.
Rankine as a synonym for degreesRankine
and its family, because Rankine has its zero at absolute zero, and this
usage works for both the size of a degree and absolute temperatures.
var keyword (you can still use it if you
want) when specifying formal arguments of a function. More information
can be found in the
Constraining Function
Arguments section of the documentation.
octal,
binary, hexadecimal, duodecimal,
and so on up to base 20. More information can be found in the All Your Base Conversions...
section of the documentation.
conforms operator to be allowed to take a
named DimensionList on the right-hand side, for example:a conforms lengthvar t is time = 0 seconds
More description can be found in the Constraints on Variables section of the documentation.
var avar a = initVal
More description can be found in the Declaring Variables section of the documentation.
persistent=boolean directive to Frink Server
Pages.
println[] function.
timezone[] function with no arguments to return
the name of the default timezone.
JD[] and MJD[] functions to be able
to take a unit with dimensions of time and create a date object from it.
This makes the functions self-symmetrical.
fmt = ### yyyy-MM-dd hh:mm a (E) zzzz ###
# 2003-06-12 02:25 PM Mountain # -> [fmt, "Japan"]
FrinkEnumeration interface to give a bit more
flexibility and improve error-handling capabilities.
-I
command-line option to specify include paths that will be searched when a
use statement is encountered.
\u20ac).
\u00a5) to be used as
fundamental currency as well as an identifier.
\u0163) to be used as
fundamental currency as well as an identifier.
String.intern() for all identifiers found by the
lexer to slightly improve runtime and decrease memory usage.
for loop where you're
assigning to a single variable. This makes very tight loops run about 1.7
times faster.
for
loop to reflect the preferred use of the format for i = 1 to 10
http://futureboy.us/frink/bitLength[x] function to return the number of bits
in the minimal two's-complement representation of an integer,
excluding a sign bit.
modPow[] and randomBits[]
functions. More description can be found in the Other Functions section of the
documentation.
to codeword most
commonly used in for loops) for the case where indices are
dimensionless integers, which should be the most common case.
input functionality to allow input from a
wider array of user interfaces.
input[prompt, defaultValue] function to
allow default values in prompts.
sort
function to use a method that would be available in Java 1.1.
random functions so they would work on Java
1.1.
for loop. This
makes some tight loops run about 3-4 times faster.
-> conversion
operator.
deltaT[date] to get the offset to be added to
Universal Time to get Dynamical Time.
JDE[date] and date ->
JDE date formatter to parse Julian Day (Ephemeris) which is the
Julian Day with respect to Dynamical Time, not Universal
Coordinated Time.
Dynamical
Time (TD) and Terrestrial Time (TT). You can now
parse dates correctly for any date using these formats. For example:#1992 October 13 00:00 TD# (from example 25.a in Meeus.)
dateformats.txt.
use statement.
select[list, regex] function to
allow a regular expression as the second argument. This expects the
list to contain all strings and returns all of the strings that match the
regular expression.
use statement try to load the specified file from a
location relative to the working directory or as a fully-qualified URL.
See Including Other Files
section of the documentation for more.
?name where name is part of the
name of a unit to be looked up. This is not case-sensitive. See the
Integrated Help section of the
documentation for more information.
! and function
factorial[x].
=!=. This only affects you if you use your own units
file.
while loop no
longer require parenthesis.
for loop
able to be written as for a = 1 to 10for a 1 to 10
for and while
loops.
.sis file so that Frink
can be easily installed on Symbian devices like the
Sony Ericcson
P800 smartphone, and the
Nokia 92x0 Communicator
and the Nokia 7650. The installer is now built as part of the Frink
release process, so the SIS version will be up-to-date with the latest
Frink.
Huge thanks to the lovely David Bergman of Remote Proximity for his immense enthusiasm and efforts in porting Java to these small devices.
centillion.)
centuries and
juliancenturies to units file.
JD[date] and MJD[date]
functions to return a value of the specified date as a Unit containing the
time since JD 0, or MJD 0, referenced to UTC. To convert this to a number
of days, divide by day. This function is often unnecessary
as dates and times can be added and subtracted directly.
units[x] function to
work appropriately if x is a variable.
dict keyword to create dictionary to
dict[] function. This means that dict no longer has to be a
weird reserved word.
units[force] work as expected. Thanks to Anthony Crowson for
the bug report.
substr[string, startPos,
endBefore] and substrLen[string,
startPos, len] functions to take substrings. See
the Substrings section of the
documentation for more information.
:-> operator. This will catch the errors (if the
right-hand side is a string or list of strings) at compile-time at the
expense of some flexibility at runtime. It's probably for the best this
way. Some cases (such as if the right-hand-side is a function or raw
symbol) cannot be checked at compile-time and will produce errors at
runtime. Thanks to Anthony Crowson for the bug report.
eval[] and unsafeEval[]
functions to evaluate a non-string argument.
1 m^2 s^-3 kg A^-1 (electric_potential):->
operator:
electric_potential :-> "volts"
See the Setting Display Units section of the documentation for more. Thanks to Anthony Crowson for suggestions.
use statement to include other
files. For the moment, this can only include files in its classpath until
I get the security implications worked out.
units.txt file that I
put in yesterday in response to Anthony Crowson's report.
Environment.outputln.
x/x is simplified to 1
x^0 is simplified to 1
x^1 is simplified to x
(x^y)^z is flattened if y and z are numeric.
eval[]
statements.
eval[] statement and created unsafeEval[]
function.
lines[URL] and
read[URL] functions try to set the charset encoding
from the Content-Type header in an HTTP request. This should
often eliminate the need for using the two-argument version for
well-behaved websites, but will not fix the case where the encoding is set
in an HTTP <META> tag, or if the header is sent out incorrectly.
ln[2]
to only be evaluated once.
abs[x] function to take absolute value.
sec[x], csc[x], cot[x],
arcsec[x], arccsc[x], and arccot[x]
functions.
--encoding
str command-line switch to allow you to specify the
character encoding of your Frink program files. Frink programs can now be
more directly written in any language and encoding system.
The encoding is a string representing any encoding that your version of
Java supports, e.g. "UTF-8", "US-ASCII",
"ISO-8859-1", "UTF-16", "UTF-16BE",
"UTF-16LE". Your release of Java may support more charsets,
but all implementations of Java are required to support the above. Check
the release notes for your Java implementation to see if other charsets
are supported.
FSPRoot which gives
the root directory containing FSP pages.
char[x]
function to convert back and forth between Unicode character code and the
actual characters.
base[x, b] which returns a string
representing the integer x in base b.
base2[x] ... base36[x]
functions which return a string representing the integer x in the
specified base. These are useful on the right-hand-side of the
-> operator.
uppercase[str] or uc[str]
and lowercase[str] or lc[str]
functions to convert a string to upper- or lowercase. These functions try
to do the right thing with Unicode, possibly making the string longer in
some cases.
1_234_567_890
frink.expr.AddExpression[x (undefined symbol), y (undefined
symbol)], you'll see x + y (with maybe a few
"undefined symbol" warnings depending on my mood of the day.)
[key, value] pairs in an
enumerating context.
conforms operator not blow up if the items on both
sides aren't units--just returns false.
{{ || 2+3
}} ) or even nonexistent argument lists, if the body is a single
line (e.g. {{ 2+3
}} )
timezones[]
function to list all known timezone names.
now[] function
to return the current date/time. This is a bit slicker than the old way,
which was to call eval["##"]
lines[URL,
encoding] function to read from a file or a URL where you
need to specify the encoding of the file. The encoding is a string
representing any encoding that your version of Java supports, e.g.
"UTF-8", "US-ASCII", "ISO-8859-1",
"UTF-16", "UTF-16BE", "UTF-16LE".
Your release of Java may support more charsets, but all implementations of
Java are required to support the above. Check the release notes for your
Java implementation to see if other charsets are supported.
read[URL,
encoding] function to read from a file or a URL where you
need to specify the encoding of the file. See the previous note for more
information about encodings.
e be the base of the natural logarithm
(2.718281828459...) This supplants the former definition which was the
charge on an electron. This is now electroncharge. Fight it
out, mathematicians and physicists.
dimensions[] function to return an enumeration of all
DimensionList names.
"$1.99" is not a candidate for variable replacement
because variables must begin with a letter. This makes it less
error-prone (and somewhat faster) to have literal dollar amounts in
Frink Server
Pages, which internally treat literal blocks of HTML as a
triple-quoted string and thus candidates for replacement.
/e modifier to regex substitution expression to
allow $0 match to match the whole pattern, even if it's not
parenthesized.
/e modifier to regex substitution expression which
treats the right-hand-side of the substitution as an expression. The
values on the left-hand side in parentheses are put into the variables
$1 , $2 , etc.
lyrics = """Oh, Danny Boy,
The pipes, the pipes are calling
From glen to glen and down the mountainside"""
Truth class to return false for undefined symbols
or the empty string.
StringInterpolator.
sqrt[x] function.
NOR, NAND, IMPLIES and
XOR operators.
Truth.isTrue() to force
truth-testing in all contexts.
round[x,y] to round x to the nearest
multiple of y.
a.push[x] and
a.pop[].
-u [unitsfile] command-line option to allow
you to specify your own alternate units file.
random[min, max] to select a random integer between
min and max (inclusive).
-> operator.
next statement to allow you to skip to the next
iteration of while or for loops before reaching
the end of the body. This is not necessary, just some nice syntactic
sugar.
\uXXXX where XXXX is a
4-digit hexadecimal number. For example, the Unicode symbol for the Greek
lowercase mu is \u03BC.
for construct.
frink.gui.InteractivePanel.
->
could take an unbracketed comma-separated list on the right-hand
side. This made default arguments in function definitions not work.
pow() function.
random[int] to generate random numbers
between 0 (inclusive) and the value of int (exclusive.)
square or sq and
cubic or cu to raise the unit on their
right-hand-side to the second and third power. Thanks to the lovely
Marcus Downing for the suggestion. (I had linear as a no-op,
but took it out.)
squared and cubed operators to
modify all the multiplicative units to their left. This has a precedence
between multiplication and addition, so 3 feet squared is
equivalent to (3 feet)^2. I tried to get the operator
square to work in both contexts but decided that this was
less arbitrary and better English. (Okay, actually I gave up because I
couldn't get the conflicts resolved.)
/g modifier to make it work
better (yet again.) It now returns an array of arrays if evaluated in a
non-enumerating context, and saves its values so it isn't evaluated
multiple times.
flatten[list] to flatten the elements of a
list of lists into a one-dimensional list. This is useful in the pattern
match above if you want the results returned in a flat list.
units[] function to list the names of all known
units.
units[unit] function to list the names of all
of the units with the same dimensions as unit, or with a specific
dimension list (e.g. acceleration, time, velocity, etc.)
unit[string] function to return the unit with
the given name.
random[list] to select a random element
from a list.
-> able to take an
unbracketed comma-separated list on the right-hand side. It saves
a few keystrokes. Tweaked some precedence rules to make this possible.
(Note: this was later repealed as it made default arguments in
function definitions not work.)
%r/.../g so
that it made more sense and can be used in more places.
<=> to compare the
magnitude of 2 expressions (it works for strings, dates, and units.)
sort[list] and sort[list,
proc] functions to sort lists. The second form takes a
user-defined comparison routine.
See the Sorting section of the
documentation for samples. This uses a quicksort algorithm.
reverse[list] function to reverse the order
of items in a list.
dict keyword. See the
Dictionaries section of the
documentation for a sample.
keys[dict] function to return an enumeration
of the keys contained in a dictionary (in no particular order.)
select[list, proc] which returns the elements of
list for which proc returns true.
read[URL] function which reads the entire
contents of an URL into a string.
/g-modified regular expression
matches to make the implementation more logical. This implies that if
you're going to use the /g modifier, you gotta use it in a
loop, and you can't use it in a simple if statement. This may be revised.
+10.
split[regex, str] function to split a
string into an array based on a regular expression separator.
join[separator,
array] function to join the elements of an array into a
string with the specified separator.
line =~ %s/pattern/replacement/opts
/g pattern-match modifier and allowed patterns to
match multiple times in a single line by using the for loop.
[first, second] = [1,2].
regex[] functions to create a regular expression
object from a string.
lines[URL]
function to read from a file or a URL.
array[] function to turn a enumerating expression
into an array.
for loop for
iterating over the contents of an enumerating expression.
return statement in a function.
Fahrenheit and Celsius functions to
F[x] and C[x]. This means that to convert
Fahrenheit to Celsius, you can enter the shorter F[98.6] -> C
conforms operator to see if two units are conformal
with each other.
Fahrenheit[x], Celsius[x], and
Reaumur[x] to convert to/from these temperature scales.
# 2002-01-03
10:00 AM New York #. This allows easy conversions between all the
timezones Frink knows about, and is a major improvement in timezone
handling. See main documentation for examples.
dateformats.txt, as all
date formats now allow a freeform timezone to be specified at the end.
dateformats.txt file.
1/3
(approx. 0.3333333333333333) ) I like and dislike this... it
shows you the true, exact, representation, and also puts it into terms you
may better understand, but it's a bit cluttered. I'll decide if I like it
before I rewrite the affected documentation.
year mod day -> days to find out how much
the length of the year actually differs from 365 days.
int[x] or trunc[x] functions which
truncate the decimal part off a number.
div operator, defined as x div y ===
floor[x/y]. I'm not sure that floor[] is sensible and
the correct rounding method to complement our definition of mod; I may
change this definition.
floor[x], ceil[x],
recip[x], round[x], and modulus operator
(% or mod).
-> operator, like ## ->
Germany to get the current time in Germany.
->). This makes all of the language
translation pairs work as advertised.
->) in quotes; this both evaluates the value in quotes and
appends the quoted value so that you can eliminate some redundancy in
formatting. For example, you can say 10 feet ->
"meters"3.048
meters", as opposed to the "3.048" you would get if
the right-hand-side was unquoted.
2^13466917 - 1. (A decimal number of over 4
million digits.) This now works quickly (the exponentiation is performed in
only 0.13 seconds,) but the algorithm to convert that gigantic binary
number to decimal for display is still really slow for very large numbers
(it takes over 14 hours.) So, you can calculate really large values, but
if you want to see the results, you'll have to wait. (Note: the
arbitrary-precision 2.^13466917 is very fast, if you don't
need to see every digit.)
Comments/questions to Alan Eliasen.