login  home  contents  what's new  discussion  bug reports help  links  subscribe  changes  refresh  edit

FriCAS language (both interpreter and Spad) is imperative, basic operation is an assignment like

fricas
(1) -> a : Integer := 5
 (1)
Type: Integer
fricas
b : Integer := a + 2
 (2)
Type: Integer

FriCAS language is typed, each variable and expression have type, assigned value must have correct type. Above we explicitly declared a and b to be of type Integer. In same cases FriCAS can infer the correct type and allows use of variables without explicit declaration. Interpreter tries to assign reasonable type guessing user intent. Remark: this is quite different than type inference present in same languages.

Next element of FriCAS language are expression. In first approximation expressions can be viewed as tree of function calls with variables in the leaves. Remark: FriCAS treats various operators like functions. So * is a two argument function. The difference compared to ordinary functions is syntax, * is parsed as infix operator, but after parsing is indistingiushable from a function. So a+b*c is eqivalent to f(a, g(b,c)) where f denotes addition (+) and g denotes multiplication (*). Actually, FriCAS expressions are more complicated, one can use almost any part of FriCAS syntax inside an expression, but simple tree view is enough for basic understanding.

FriCAS supports overloading, that is one can give different definition of a function for various combinations of parameter types. For example, with declarations above a*b is multiplication of integers. However, if c is vector of integer, than a*c means multiplication of vector c by integer a which is a different operation despite having the same name. Remark: FriCAS treats various operators like functions. So * is a two argument function. The difference compared to ordinary functions is syntax, * is parsed as infix operator, but after parsing is indistinguishable from a function.

FriCAS types are parametric, for example Polynomial(Integer) is application of constructor Polynomial to parameter Integer. Polynomial(Fraction(Integer)) is a different type obtained using the same constructor, but with different parameter, that is Fraction(Integer), which is application of constructor Fraction to type Integer. Parameter usually are types, but it is also possible to use normal values as parameters.

Parametric types lead to parametric polymorphizm. This is similar to overloading, but conceptually and in implementation there is a difference. For example, writing a + b with integer a and b we use + declared in AbelianSemigroup?. When adding two polynomials we use the same declaration, but implementation is different. Choosing correct implementation is due to dispatch, from compiler point of view we have single operation, but at runtime support routines are responsible for calling correct version. Of course, users may worry that function calls in FriCAS need to do complicated things to find correct function and are expensive. However, FriCAS contains caching mechanism, first call may be quite expensive but usually subsequent executions of the same call have only very small overhead. Beside parametric polymorphizm there is also classical overloading. For example multiplication of vector by integer uses different declaration than multiplication of integers and FriCAS compiler choose proper declaration at compile time.

FriCAS has usual imperative constructs: sequence of operations, conditionals and loops. FriCAS allows also FunctionalProgramming: FriCAS functions are "first class", one can pass functions as arguments to other functions, store them in variables and data structures. One can define local functions with capture references to variables in surrounding environment. There are usual functional utilities like map.

FriCAS types are "first class": parametric types allow creating potentially infinite number of new types at runtime, types can be stored in variables and data structures. Types can be passed to functions as arguments.

FriCAS is strongly typed in sense that all variables and expressions have assigned type, function call is allowed only when arguments are of apropriate types. Strict type disciples sometimes does on allow to express desired and correct code. FriCAS allows holes in type checking, maininly via pretend construct. For example

fricas
a pretend PositiveInteger
 (3)
Type: PositiveInteger?

tells FriCAS that a which is declared as Integer should be treated as PositiveInteger in expression above. Use of pretend should be limited to cases when user knows that value is actually of appropriate type, but FriCAS can not infer this in authomatic way. Improper use of pretend is an error which may lead to wrong value or a crash.

Basic FriCAS types are implemented at lower level, currently in Lisp. To allow such implementation FriCAS allows direct calls to Lisp functions. Such calls are not type checked: FriCAS assumes on faith that argument have correct Lisp type and result is of correct FriCAS type. Note: FriCAS uses Lisp type declarations. Passing FriCAS value to Lisp function must respect declarations passed to Lisp. If user call to Lisp function cause type mismatch at Lisp level this may lead to trouble. In best case Lisp will report mismatch, but wrong result or a crash are also possible. Typical use of Lisp calls is via Spad wrapper: wrapper ensures that only correct types are passed to Lisp function and ensures correct FriCAS type for result.

 Subject:   Be Bold !! ( 15 subscribers )