7
$\begingroup$

Is there any way to add my own annotations to values or functions in Mathematica? Imagine, for example, that I wanted to annotate a List specifically as a List of Strings.

I don't think Mathematica will really do anything to enforce such a thing, but what I'd like to use this for is for connecting Mathematica to .NET generic functions. If I know that a List is expected to only contain a single type, I could more easily decide what type to call into a generic function with.

An example syntax might be something like:

mylist = {"Alice", "Bob", "Carol"}
SetAttribute[myList, NETType[String]]

(* The NETType[] attribute is used to call "GenericListMethod<String>(myList);" *)
NETGenericCall[GenericListMethod,Sequence[myList]]

Update: It's also significant that myList should retain (nearly?) native behavior in Mathematica. For example, I should be able to iterate over the list with Map[] without having to explicitly unwrap the list first. I figure it's asking almost entirely too much for normal Mathematica functions to preserve type information.

$\endgroup$

3 Answers 3

4
$\begingroup$

You could use UpValues:

mylist = {"Alice", "Bob", "Carol"};
numlist = {1, 2, 5, 3};

SetAttributes[NETType, HoldAll]

NETType[mylist] ^:= String
NETType[numlist] ^:= Integer

{NETType[mylist], NETType[numlist]}

(* Returns:
{String, Integer}
*)

Of course, this does not perform any checks that the elements in the list actually are of the type claimed.

$\endgroup$
2
$\begingroup$

I do not know if there is a trick to do that using Attributes and such. But just wanted to suggest a simple method, may be it work for you, may be not.

Mathematica lists are very flexible, they can be ragged in shape.

Hence you could always have the first entry in your lists be the 'type' of the list content, by having the head of the types of the item in the list be the first entry in the list. Like this:

lst = {String, {"Alice", "Bob", "Carol"}}
lst = {Real, {0.4, .9}}

Then you can just do

First[lst]

to get the 'type', and do

Rest[lst]

to obtain the actual list.

In the above, I used Heads I know about. You can replace that with your NETType[String] if you want, since I do not know what that is now.

$\endgroup$
1
  • $\begingroup$ That's a cool suggestion, but one ideal property of what I'm looking for is that the resulting structures still behave "natively" to Mathematica. You're certainly right that I can unwrap the annotated list and do work with it, but that makes it feel non-native. Maybe there's some trick I can do with pattern matching rules that will give me "unwrapping" for free in the context of most functions, and not in the case where it's in some NETGeneric function call? $\endgroup$
    – sblom
    Jan 26, 2012 at 4:57
2
$\begingroup$

Many functions in Mathematica don't care about the head actually being List so you can do something like this:

In[516]:= s = StringList["1", "foo", "bar"]

Out[516]= StringList["1", "foo", "bar"]

In[518]:= Length[s]

Out[518]= 3

In[519]:= Prepend[s, "z"]

Out[519]= StringList["z", "1", "foo", "bar"]

In[523]:= Map[StringLength, s]

Out[523]= StringList[1, 3, 3]

That Map worked fine but violated the sematics of StringList. When you know this will happen it is easy to fix.

In[524]:= Map[StringLength, List @@ s]

Out[524]= {1, 3, 3}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.