[Date Index]
[Thread Index]
[Author Index]
Re: Re: Re: Types in Mathematica
*To*: mathgroup at smc.vnet.net
*Subject*: [mg62910] Re: [mg62872] Re: Re: Types in Mathematica
*From*: Sseziwa Mukasa <mukasa at jeol.com>
*Date*: Thu, 8 Dec 2005 00:05:23 -0500 (EST)
*References*: <dn22fb$kum$1@smc.vnet.net> <200512070411.XAA23826@smc.vnet.net> <F505B3D5-9BCD-49F6-A894-D997D33F5C6D@jeol.com> <200512071343.34678.hattons@globalsymmetry.com>
*Sender*: owner-wri-mathgroup at wolfram.com
On Dec 7, 2005, at 1:43 PM, Steven T. Hatton wrote:
> On Wednesday 07 December 2005 10:54, Sseziwa Mukasa wrote:
>> On Dec 6, 2005, at 11:11 PM, Steven T. Hatton wrote:
>>>> Fair enough but Head[{1,2,3}] is not Symbol.
>>>
>>> I would say that we have to be clear about what we mean by "Head
>>> [{1,2,3}]".
>>
>> I meant the value of evaluating the expression.
>
> In[1]:= Head[Head[{1,2,3}]]
>
> Out[1]= Symbol
I'm not sure what that's supposed to prove we know that of Head
[{1,2,3}][[0]] is Symbol but Symbol[List] is not a list.
> Hmmm.... That's a very interesting statement. In reality, at that
> level of
> detail the description of a Mathematica expression is distinct from
> the Lisp
> model. Mathematica expressions are described as being arrays of
> pointers to
> other Expressions.
I believe the point about being arrays of pointers is related to
implementation efficiency concerns, such as being able to take parts
of lists in linear time eg:
Block[{a=Table[Random[],{1000}]},
ListPlot[Plus @@@
Table[Table[Timing[a[[i]]][[1]], {
i, j}] /. Second -> 1, {j, 100}], PlotJoined -> True];]
Admittedly that is not the purest example but I think it demonstrates
the point. For reasoning about the behavior of Mathematica with
respect to transformation rules though the Head[Arguments...] model
should be correct even though it will not be correct for predicting
algorithmic performance.
>> The fact that we display
>> and write 1 instead of Integer[1] is syntactic sugar as far as I'm
>> concerned because at that point we are typically more interested in
>> the interpreting Integer[1] as a value which is the result of some
>> computation which is really what one is interested in.
>
>
> In[2]:= Integer[1]===1
>
> Out[2]= False
OK calling it syntactic sugar is a bit extreme, it doesn't change the
validity of the statement. You cannot create the argument that
Integer[_] uses to represent an integer, but we know that Integer[_]
represents an atomic expression so there's no point in wondering
about what _ is without a head because we cannot create it. Integer
[1] is evaluated as Integer[Integer[(something)]] so of course Integer
[1]/=1.
> In[3]:= Attributes[1]
>
> Attributes::ssle:
> Symbol, string, or HoldPattern[symbol] expected at position 1 in
> Attributes[1].
>
> Out[3]= Attributes[1]
Attributes expects a symbol as its argument, Integer[1] or 1 is not a
symbol so this behavior is not surprising. On the other hand:
In[18]:=
Attributes[Integer]
Out[18]=
{Protected}
as we'd expect.
>> Especially if you consider the heads of atoms as defining their type,
>> which is why I think that is a useful paradigm for reasoning about
>> types in Mathematica.
>
> I would say that the distinction has more to do with their fundamental
> characteristics than with the name or symbol attached to them. In
> particular, the kinds of data they store.
>
> Head[Symbol]
> SymbolName[Symbol]
>
> Head["string"]
> Characters["string"]
>
> Head[12345]
> IntegerDigits[12345]
>
> Head[10/3//N]
> RealDigits[10/3//N]
>
> Head[25/17]
> Numerator[25/17]
> Denominator[25/17]
>
> Head[E^I GoldenRatio//N]
> Re[E^I GoldenRatio//N]
> Im[E^I GoldenRatio//N]
I'm not sure what you are expecting in these cases so I'm not really
sure what the point of this exercise is, at any rate
In[34]:=
Head[Symbol]===SymbolName[Symbol]
Head["string"]===Characters["string"]
Head[12345]===IntegerDigits[12345]
Head[10/3//N]===RealDigits[10/3//N]
Head[25/17]===Numerator[25/17]
Head[25/17]===Denominator[25/17]
Head[E^I GoldenRatio//N]===Re[E^I GoldenRatio//N]
Head[E^I GoldenRatio//N]===Im[E^I GoldenRatio//N]
Head[List]===Symbol
Out[34]=
False
Out[35]=
False
Out[36]=
False
Out[37]=
False
Out[38]=
False
Out[39]=
False
Out[40]=
False
Out[41]=
False
Out[42]=
True
Again as we'd expect.
>> The fact that Head[Sqrt[2]] isn't Sqrt as Jon
>> Harrop pointed out seems to me more an artifact of the evaluator than
>> a problem with Mathematica.
>
> There are countless examples of this kind.
>
> In[8]:= Head[Subtract[a,b]]
>
> Out[8]= Plus
>
> In[9]:= Subtract[a,b]//FullForm
>
> Out[9]//FullForm= Plus[a, Times[-1, b]]
>
> Regardless of whether you consider the head of the expression as
> representing
> a "type", that is a very tricky aspect of Mathematica.
I agree dealing with the evaluator is subtle, but we have tools for
dealing with it
In[43]:=
Head[Unevaluated[Subtract[a,b]]]
Out[43]=
Subtract
> See the examples above regarding Integer[1].
To restore clarity, when reasoning about why Head[1] returns Integer
as a value we have to understand that 1 is an atomic object that can
be considered to be the expression Integer[1] where the argument is
actually something I can't create from the Notebook. Using the
following as an example:
In[48]:=
Head[1]
1[[0]]
1[[1]]
Out[48]=
Integer
Out[49]=
Integer
From In[48]:=
"Part specification 1[[ 1 ]] is longer than depth of object.
Out[50]=
1[[1]]
we begin to understand what makes an expression atomic, it is an
object of Depth 0. But objects of Depth 0 still have a head, even
though the arguments are inaccessible.
> I don't believe I suggested that A.9.2 documents exactly what
> everything is.
> I've been rather clear that I do not find the documentation complete.
You have, but I haven't seen an example of behavior that cannot be
explained by A.9.2. I will admit that the time complexity of
algorithms is not what you'd expect from A.9.2 but the behavior with
respect to types is.
>> Some
>> expressions are atomic, and if you want to assign a "type" to the
>> atoms other than expression the best candidate I can see is the head.
>
> That's what Wolfram says in the appendix. "These [atomic] objects
> have heads
> which are symbols that can be thought of as 'tagging' their types. The
> objects contain 'raw data', which can usually be accessed only by
> functions
> specific to the particular type of object. You can extract the head
> of the
> object using Head, but you cannot directly extract any of its other
> parts."
So what's the difficulty?
> C++, however does not have
> a statement type. It has statements, but "statement" is not a type.
I suppose it depends on your perspective, in order to compile or
execute C++ code one has to be able to reason about the code and in
order to reason about the code structures like for(;;){...} and void
op() have to be represented by something and I'd call that something
which represents them their type. Except for the compiler/
interpreter though there is nothing within C++ which deals with such
structures directly, but C++ also has typedef _ structures (and int,
float, etc.) which can be used for explicit manipulation of types of
objects during execution (or evaluation) of a program. The
difference between C++, Java etc. and Mathematica (and to a certain
extent ML, Haskell etc.) is that at evaluation type the structures
that correspond to for(;;){...}, void op() etc. can be manipulated by
the program itself.
I'm aware that clever hackers can write self modifying code in C++
with injudicious use of pointers, but those programs typically rely
on a well defined external environment of linkers, machine
architecture etc. to work.
> "You can't inspect the structure of the function in C++ because it's a
> function definition and there is no facility for programmatically
> inspecting the contents of a definition in C++. In Mathematica the
> contents are stored as an expression in the DownValues which can be
> modified as any other expression in Mathematica sans restrictions."
>
> How does that compare to rtti or having a virtual function table
> and using
> virtual funcitons to implement polymorphism?
There is no need for rtti in Mathematica, again because the type of
everything is known because there is only one type of thing in
Mathematica. A C++ program typically (if we're going to be pedantic
I'll allow for clever hacks) cannot rewrite its virtual function
table at run time, during Mathematica evaluation I can rewrite the
body of a function though.
> You most certainly can get some
> internal information from an object that way.
I didn't say you couldn't get any information, I said you can't get
at the implementation.
>> (actually is that a requirement? http://root.cern.ch/root/
>> Cint.html)
>
> That would not pass muster among 99% of C++ programmers.
I actually posed that question to myself as I was writing then found
Cint through Google. I didn't even bother to evaluate it, I was just
interested in the question of whether being compiled was a necessary
part of the C or C++ specification.
>> there are no facilities for
>> programmatically altering statements.
>
> There certainly are at compile-time. As a matter of fact that is
> the entire
> purpose and function of templates. The are meaningless unless they
> are
> transformed into compilable specializations.
C++ templates don't modify statements, they are used to generate new
statements at compile time. I cannot take a pointer to an if{a}else
{b} block and change the value of b.
I'm not arguing that is a good idea in general, merely that it isn't
possible.
>> On the other hand, I've noticed a trend in OO graphics programs for
>> defining 3 and 4D vectors and matrices as classes and then
>> overloading +,-,* etc. which leads to inefficient code like
>>
>> t=a*b;
>> d=c*t
>>
>> instead of
>>
>> d=a*b*c
>
> There is no reason you cannot use the latter expression if you have
> overloaded
> * with something reasonable.
And what is something reasonable? The naive vector3D operator*(a
vector3D, b vecto3D) {return Vector3D(a.x*b.x,a.y*b.y,a.z*v2.z)}
requires the creation of an intermediate object in compiling a*b*c to
hold the result of either a*b or b*c. Mathematica gets around the
problem using the Listable attribute, C++ gets around it with
template metaprogramming (and given your interest in ML perhaps you'd
appreciate this http://people.cs.uchicago.edu/~jacobm/pubs/
templates.html) but as far as I'm aware Java can do neither and ends
up being inefficient.
> You can also use composite function objects
> which will blow the doors off of any Mathematica code you can dream
> up.
We're starting to wander of topic, and I suppose I led us here. This
was really just meant as an aside about standard OO programming.
Regards,
Ssezi
Prev by Date:
**Re: Re: Types in Mathematica thread**
Next by Date:
**Re: Re: Re: Types in Mathematica**
Previous by thread:
**Re: Re: Re: Types in Mathematica**
Next by thread:
**Re: Re: Re: Types in Mathematica**
| |