开发者

Is Mathematica an untyped language?

Unlike most programming languages, every value in Mathematica is an expression. Applying any operation to any expressions always yields anot开发者_开发技巧her expression. Consequently, Mathematica effectively has only one type. Mathematica does no static type checking and, arguably, doesn't even check types dynamically (at run-time).

For example, adding the integer expression 1 to the string expression "foo" in Mathematica results in the (nonsensical) expression 1 + "foo" but no error. In other cases, Mathematica provides feedback about nonsensical input but the checks that generate this feedback must be performed explicitly by the programmer.

Thus, is it fair to describe Mathematica as an untyped language as opposed to a statically or dynamically typed language?


Instead of "type", what Mathematica has is the concept of a "head", where any Mathematica expression possesses one. This is in line with their "everything is an expression" paradigm.

One can peer at the structure of a Mathematica expression through the functions FullForm[] and Head[]. For instance, Head[3]returns Integer,Head[2/3] returns Rational, Head[I] returns Complex, Head[.3] returns Real, Head[a] returns Symbol (assuming you had not yet assigned anything to a), Head["a"] returns String, Head[{2}] returns List... i'm sure you get the idea already.

The beauty of this is that one can write functions such that they can only accept arguments with specific heads. For instance:

f[x_Real] := x^2

f[3]
f[3]

f[3.]
9.

This discussion on patterns should give you ideas on how to set up functions such that they work only on objects with specific heads or sets of heads.


If we consider the phrases "statically typed" and "dynamically typed" as jargon referring to when a language checks the validity of operations against types, then I think it is fair to characterize Mathematica using the jargon "untyped" -- in the sense that it "never" checks whether an operation is valid for a type.

I do like Belisarius' use of the term "type-agnostic", however. I say this because while almost all type-checking in the language is idiomatic (i.e. implemented by the programmer, not the language), so is the concept of applying an operator to typed operands!

Consider the "nonsensical" example of 1 + "foo". I think it is fair to say that a significant fraction (approaching unity) of all Mathematica users trips over cases such as this as they are first learning the language. The problem is particularly evident when one is writing code in, say, the style of C. There is much discussion in Mathematica circles as to how to handle situations such as these.

On the other hand, this weakness is also Mathematica's greatest strength. Mathematica is optimized for creating new notations. Many, many notations have the concept of + that behaves very similarly to addition in elementary arithmetic. When building such a notation, it would very inconvenient if Mathematica stepped in and complained that the operands to + were not numbers. In such a higher-level application of Mathematica, the "nonsensical" example is not only "sensical", but actually crucial.

So, with that in mind, the question of type is frequently moot. Hence, I like Belisarius' "type-agnostic" characterization. Upvote him, I did ;)

Edit

I'll try to clarify what I had in mind when distinguishing between "untyped" and "type-agnostic".

Reading over the various answers and comments, I tried to figure out what the difference was between Mathematica and LISP. The latter is generally held up as an example of "dynamically typed", although the core LISP evaluator is very much like Mathematica with hardly any type-checking. The type errors we see in LISP programs are mostly issued by hard-coded checks in (typically built-in) functions. +, for example, will only accept numeric arguments even though the evaluator itself could not care less one way or the other. Having said that, the "feel" of programming in LISP differs greatly from the "feel" of Mathematica (for me, at least). The 1 + "foo" example really captures that difference.

While I broadly agree with "untyped" as the characterization of Mathematica, I still felt that something was missing. Assembler seems untyped to me, as does early FORTRAN and pre-ANSI C. In those cases, the bit pattern of arguments was all that mattered, and the programs would continue on blithely if I passed a string argument where an integer was needed. Mathematica certainly shares this untyped behaviour. But there is a difference: in assembler and FORTRAN and C, it is extremely rare for this lack of type-checking to result in a good outcome. As I mentioned above, in Mathematica it is possible and sometimes even common to rely upon this kind of behaviour.

Enter "type-agnostic". I liked its non-committal stance, sounding less drastic than "untyped". I felt it reflected the essentially untyped nature of Mathematica, but left some wiggle room for those language features that readily support idiomatic type-checking in the LISP, dynamic style (i.e. the "head" idiom and supporting functionality).

So, in short, I feel that Mathematica hovers between being completely untyped and being dynamically-typed. "Type-agnostic" captured that sentiment for me. YMMV :)

I readily confess that no-one is likely to reconstruct anything I've written in this response simply from inspecting the phrases "untyped" and "type-agnostic". Again I emphasize that I think that "untyped" is a fair characterization of Mathematica, but I also like the fact that "type-agnostic" begs a lot of the questions being addressed by the various responses to this SO question.


More from the practical, than the theoretical side of things, I believe you may say that Mathematica is more type-agnostic than untyped.

Moreover, you can construct easily a typed sub-language using things like (very basic example follows):

Unprotect[Set]; 

Set[a, x_] := If[Element[x, Integers], x, 0, 0];  

and then try:

a = 1; (*runs ok*) 

and

a = "caca"  (*assigns zero to a*)

Edit

Moreover, you may construct user-defined types as named patterns, and use them in the redefinition of Set above, instead of integers.
Type composition should work in the same way.


Mathematica does have some types, and it is dynamic. You have the types String, Integer, Real, Complex, List and Symbol. You can create functions operating on only one type by doing something like

f[x_Integer]:=x+1

to create a function which only operates on integers.

Mathematica is heavily based on patterns and substitutions; the types always seem to me to be another way to help you develop patterns. In the case of 1 + "foo", there is no pattern to evaluate a number added to a string, so the result is just the expression itself. In the case of 1 + 2, there is a pattern to add the numbers and it is evaluated. Mathematica's patterns and substitution rules can be much more complex, and it's best to read a book if you're interested.


The short answer: Untyped or typeless. This is how Wolfram Research describes the product themselves. See here.

Long answer: Jon, I think your question really hinges on what you mean by untyped. To appeal to the definitive resource that is Wikipedia "In contrast, an untyped language, such as most assembly languages, allows any operation to be performed on any data, which are generally considered to be sequences of bits of various lengths."

Reading the earlier answers, it seems the heart of the debate is what should a type checker when it encounters an error. The usual answer is to STOP evaluation and report some kind of error. From several earlier questions (1) and (2) on Stackoverflow, we can see that there isn't a graceful way of doing this built-in to Mathematica. (I would add the caveat that with more emphasis on compilation to C in version 8 that it is possible to write type checked code but I am unsure whether this should be counted as part of the main language.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜