Mathematica 是一种无类型语言吗?
与大多数编程语言不同,Mathematica 中的每个值都是一个表达式。对任何表达式应用任何运算总是会产生另一个表达式。因此,Mathematica 实际上只有一种类型。 Mathematica 不进行静态类型检查,甚至可以说,甚至不动态检查类型(在运行时)。
例如,在 Mathematica 中将整数表达式 1
添加到字符串表达式 "foo"
会产生(无意义的)表达式 1 + "foo"
但没有错误。在其他情况下,Mathematica 提供有关无意义输入的反馈,但生成此反馈的检查必须由程序员显式执行。
因此,将 Mathematica 描述为一种非类型语言而不是静态或动态类型语言是否公平?
Unlike most programming languages, every value in Mathematica is an expression. Applying any operation to any expressions always yields another 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
Mathematica 拥有的不是“类型”,而是“头”的概念,任何 Mathematica 表达式都拥有一个“头”。这符合他们的“一切都是表达式”范式。
人们可以通过函数
FullForm[]
和Head[]
查看 Mathematica 表达式的结构。例如,Head[3]
返回Integer
,Head[2/3]
返回Rational
,Head[I]
返回Complex
,Head[.3]
返回Real
,Head[a]
> 返回Symbol
(假设您尚未将任何东西分配给a
),Head["a"]
返回String
,Head[{2}]
返回List
...我相信您已经明白了。这样做的好处在于,人们可以编写函数,使其只能接受具有特定头的参数。例如:
这个关于模式的讨论应该为您提供有关如何设置函数以使其仅起作用的想法具有特定头部或头部组的物体。
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[]
andHead[]
. For instance,Head[3]
returnsInteger
,Head[2/3]
returnsRational
,Head[I]
returnsComplex
,Head[.3]
returnsReal
,Head[a]
returnsSymbol
(assuming you had not yet assigned anything toa
),Head["a"]
returnsString
,Head[{2}]
returnsList
... 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:
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.
如果我们将短语“静态类型”和“动态类型”视为术语,指的是语言检查类型操作的有效性,那么我认为使用术语“无类型”来描述 Mathematica 是公平的——在这个意义上它“从不”检查操作对于类型是否有效。
不过,我确实喜欢贝利萨留使用“类型不可知论”这个术语。我这样说是因为虽然语言中几乎所有类型检查都是惯用的(即由程序员而不是语言实现),但将运算符应用于类型化操作数的概念也是如此!
考虑
1 + "foo"
的“无意义”示例。我认为可以公平地说,所有 Mathematica 用户中很大一部分(接近统一)在第一次学习该语言时都会遇到此类情况。当一个人用 C 语言风格编写代码时,这个问题尤其明显。Mathematica 圈子里有很多关于如何处理此类情况的讨论。另一方面,这个弱点也是 Mathematica 最大的优点。 Mathematica 针对创建新符号进行了优化。很多很多符号都有
+
的概念,其行为与初等算术中的加法非常相似。在构建这样的符号时,如果 Mathematica 介入并抱怨+
的操作数不是数字,那将非常不方便。在Mathematica这样一个更高层次的应用中,“无意义”的例子不仅是“有意义的”,而且实际上是至关重要的。因此,考虑到这一点,类型问题常常没有实际意义。因此,我喜欢贝利撒留的“类型不可知”特征。支持他,我这么做了;)
编辑
我会尽力澄清在区分“无类型”和“类型不可知”时我的想法。
阅读了各种答案和评论,我试图找出 Mathematica 和 LISP 之间的区别。后者通常被视为“动态类型”的示例,尽管核心 LISP 求值器非常类似于 Mathematica,几乎没有任何类型检查。我们在 LISP 程序中看到的类型错误主要是由(通常是内置)函数中的硬编码检查引起的。例如,
+
只接受数字参数,即使求值器本身并不关心其中一种方式。话虽如此,LISP 编程的“感觉”与 Mathematica 的“感觉”有很大不同(至少对我来说)。1 + "foo"
示例确实体现了这种差异。虽然我大体上同意“无类型”作为 Mathematica 的特征,但我仍然觉得缺少了一些东西。对我来说,汇编程序似乎是非类型化的,就像早期的 FORTRAN 和 ANSI C 之前的那样。在这些情况下,参数的位模式才是最重要的,如果我在需要整数的地方传递一个字符串参数,程序就会轻松地继续运行。 Mathematica 当然也有这种非类型化行为。但有一个区别:在汇编程序、FORTRAN 和 C 中,缺乏类型检查而产生良好结果的情况极为罕见。正如我上面提到的,在 Mathematica 中,依赖这种行为是可能的,有时甚至是常见的。
输入“类型不可知”。我喜欢它不置可否的立场,听起来不像“无类型”那样激烈。我觉得它反映了 Mathematica 本质上无类型的本质,但为那些容易支持 LISP 中惯用类型检查的语言功能、动态风格(即“head”习惯用法和支持功能)留下了一些回旋余地。
所以,简而言之,我觉得 Mathematica 徘徊在完全无类型和动态类型之间。 “类型不可知论”为我捕捉到了这种情绪。 YMMV :)
我坦白承认,没有人可能仅仅通过检查“无类型”和“类型不可知”这两个短语来重构我在此回复中所写的任何内容。我再次强调,我认为“无类型”是对 Mathematica 的公平描述,但我也喜欢“类型不可知”这一事实,它回避了对这个 SO 问题的各种回答所解决的许多问题。
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). The1 + "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.
更多的是从实践而不是理论方面来看,我相信您可能会说 Mathematica 与类型无关而不是无类型。
此外,您可以使用以下内容轻松构造类型化子语言(非常基本的示例如下):
然后尝试:
和
Edit
此外,您可以将用户定义类型构造为命名模式,并使用它们在上面Set的重新定义中,而不是整数。
类型组合应该以同样的方式工作。
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):
and then try:
and
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 确实有一些类型,而且它是动态的。您的类型有
String
、Integer
、Real
、Complex
、List
和 <代码>符号。您可以通过执行诸如f[x_Integer]:=x+1
之类的操作来创建仅对整数进行操作的函数,从而创建仅对一种类型进行操作的函数。
Mathematica 在很大程度上基于模式和替换;在我看来,类型总是帮助你开发模式的另一种方式。在
1 + "foo"
的情况下,没有模式可以计算添加到字符串中的数字,因此结果只是表达式本身。在1 + 2
的情况下,存在一种将数字相加的模式并对其进行求值。 Mathematica 的模式和替换规则可能要复杂得多,如果您有兴趣最好读一本书。Mathematica does have some types, and it is dynamic. You have the types
String
,Integer
,Real
,Complex
,List
andSymbol
. You can create functions operating on only one type by doing something likef[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 of1 + 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.简短的回答:无类型或无类型。这就是 Wolfram Research 对产品本身的描述。 参见此处。
长答案:
乔恩,我认为你的问题实际上取决于你所说的非类型化的含义。为了吸引权威资源,即Wikipedia“相反,无类型语言,例如大多数汇编语言允许对任何数据执行任何操作,这些数据通常被认为是各种长度的位序列。”
阅读之前的答案,争论的核心似乎是类型检查器遇到错误时应该做什么。通常的答案是停止评估并报告某种错误。来自之前的几个问题(1)和(2) 在 Stackoverflow 上,我们可以看到没有一个优雅的Mathematica 内置了这种方法。 (我想补充一点,在版本 8 中更加强调编译为 C,可以编写类型检查代码,但我不确定这是否应该算作主要语言的一部分。)
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.)