December 2007 - Posts
A couple of weeks ago a friend was chatting to me in IM and asked me about a problem he was having with generics constraints. I told him he was trying to solve the lack of an INumeric interface issue. Then last week I watched Brian Beckman go through the same thing with generics, again unable to use a numeric constraint, instead having to create his own wrapper types. This issue is not new, it is well known. But what is still lacking is clear and open discussion from Microsoft on how to address this, Anyway, here's my point of view :
The numeric types can be grouped into two separate categories, Integer types, and Real types. The Integer group currently has 8 types in it, the signed types, SByte, Int16, Int32, Int64, and the unsigned types, Byte, UInt16, UInt32, UInt64. The Real group has 3 types, Decimal, Single and Double. Although all of these implement IConvertible, there is no other common base other than ValueType or Object. In particular, none of these types has defined operators or methods such as Add, instead the operators are provided by languages.
One option would be to include an INumeric interface. The problem with this is that it would need to have methods for all the standard operators, and overloads for combining with each of the other of the 11 numeric types. You couldn't have just one overload and cast to a wider type, as you would have no way to know if there was a wider type. It may also be advantageous to be able to work with Integer types as distinct from Reals for both performance reasons as well as allowing bitwise operators.
So, I believe the best solution is not an interface, but rather a language provided grouping, or set of groupings. I'm going to use 3 sets, Numeric:Integer, Numeric:Real, and Numeric:All. With these you would define a constraint such as
Function MoveRight(Of T As Numeric:Integer)(x As T) As T
return x >> 1
End Function
Or
Function AnnualIncrease(Of T As Numeric:Real)(salary As T) As T
return CType(salary * 1.1, T)
End Function
This still has difficulties in that constants are hard to express in the given type, although that could be handled with some compiler relaxation. For example in the above sample of AnnualIncrease, if you declared a variable of type T then assigned it the 1.1, the constant would be inferred based on T.
Function AnnualIncrease(Of T As Numeric:Real)(salary As T) As T
Dim increase As T = 1.1
return salary * increase
End Function
Because the Numerics are all value types, when using generics I believe they cause a new type to be laid out, one per value type, thus allowing the CLR to verify the type and the operations on those types. The operators for numeric types are in fact provided by the CLR at an intrinsic level. The problem being is they are often type specific for loading of constants, and some of the operators are different for signed versus unsigned operations. The basic operations such as add, divide, multiply, and, or, etc are the same for all the numeric types. So it seems that perhaps a little help form the CLR combined with a little flexibility from the languages, providing such a constraint wouldn't be that difficult at all.
It certainly would be nice to see it addressed.
Visual Studio magazine's January On VB column, by your's truly, has a quick reference guide to what's new in VB 2008. The guide includes links to earlier articles that provide more in depth information on specific features.
Errata for my January column:
The web site fails to display & properly instead showing &. The relevant part of he article should read:
XML literals are, as the name implies, the literal representation of the XML as it would appear in a file (or close to it). For example, if you wanted to name a book "War & Peace" instead of "War and Peace," you'd need to encode the & to & inside the XML literal:
' won't compile
Dim el = _
<book>War & Peace</book>
' will compile
Dim el = _
<book>War & Peace</book>
On Monday night I was walking along the streets in Melbourne heading out to give a presentation on VB 2008. while waiting for some pedestrian lights I noticed this guy standing outside St George's bank with signs all over him. He had newspaper clippings, and what looked like stories scribbled over backboards plastered to himself. In the 90 seconds or so that anyone would be waiting it was too much information to get his message across. Instead of getting a message across to people, he frankly looked more like a loon ;) I'm not sure what his actual message was, but I imagine it would be about loans or similar. So he should have focused on that. Perhaps one big slogan, "St George heartless to customers" or "St George at the heart of sub-prime".
Anyway, it resonated with me when I saw this guy failing to get his message across as I headed out to give a presentation myself ;) The good news is from the accounts I heard, my brief presentation went well. I loved hearing folks say that it convinced them to use VB in 2008 :) And all within a 20 minute presentation !!
But here, I've probably rambled too much, because the message I wanted to get across to people isn't about any of the above, other than the "less is more" concept. What I wanted to talk about was Code Snippets and that you should go through what is there, modify them, remove them; get a list that you are comfortable with. I was just watching Brian Beckman And Beth, and saw that together they couldn't find the snippet for adding an operator overload. They were close at one point; they just had to scroll. Unfortunately VB comes with so many it's hard to know them all, and time consuming to wade through them looking for one.
Some things you can do are:
- try guessing the shortcut. For example, for operators if you guess "op" for starters and type in op? and press tab, you'd find the operator overloading snippets. Likewise for property, if you type prop? and press tab you'll find the shortcuts for most property snippets.
- Create your own folder for snippets, and organize your favourite snippets in there. This is pretty easy to do with the snippet editor, and you can just drag and drop the snippets around
Long term, I'd like to see snippets propagated into the normal intellisense, and concepts like most frequently and most recently used worked into the snippet shortcut menus as well as the snippet hierarchical views.
If you have some spare time over the holiday season do spend some of it looking at snippets, templates and customising the IDE. Streamline your experience for you. Just as a woodsman sharpens his axe before he fells a tree, you should take that time to sharpen your IDE experience. Don't be left fumbling around trying to find a snippet :)
Kathleen left it for others to discuss what dynamic programming means, so I thought I'd utter my thoughts on it here.
Some of the things I consider to be dynamic and of importance are:
- runtime expressions. In days of old for VB/VBScript this was often considered the role of Eval, allowing the user to enter in simple code and have it run. Today, I'd see greater relevance in having queries allowing dynamic expressions, thus allowing the user to filter or build reports over data. So perhaps an expression tree from a string would be more useful than an Eval. Once we have the expression tree we could always compile that if desired.
- dynamic storage types. Part of being able to have dynamic expressions is having dynamic data types for the results. Anonymous types don't really do that because they are compiled as real types. Rather what we'd need is a type that can be expanded, like an expando type. I talked aobut one idea on this a while ago using dynamic interfaces where the properties were as dictionaries,. I'm now thinking perhaps that storage could in fact be XElement and XNodes as they provide the expansion capabilities, the string lookup capabilities as well as a host of other functionality such as event bubbling on change.
- late binding and dynamic invocation. VB already has late binding, although that generally requires you know the method name even though you don't know the object's type. There's also CallByName which is like a reflection based invocation which allows you to specify the method name as a string at runtime. Perhaps a simplified means of invocation would help here. Dynamic interfaces which would allow a confined form of late binding would address the current all or not at all kind of problems with VB's late binding as it stands today.
Still, it's quite surprising to look at VB and see how much of these areas it already has covered or is on the way to :)
Sara Ford writes about inserting snippets in VB and C#. Unfortunately, Sara hasn't got it quite right. In VB 2008 the statement completion window does NOT show snippet shortcuts. It only shows namespaces, types, members and keywords. It just happens that many of VB's keywords are also snippet shortcuts.
In VB 2005 you could type the shortcut and press tab. In VB 2008 however the code completion window gets first preference, so if you type the shortcut and press tab, and that shortcut happens to be the first part of any name in the code completion window (namespace, type, member or keyword), then you will not get your snippet instead you'll get the match from the code completion window. You've got a couple of choices to actually get your snippet inserted. You can press Esc then the tab. That will close the code completion window, then your snippet is the only match. The other way is to type the shortcut or part there-of followed by a ? This will bring up the snippet shortcut list.
e.g type app?

Well I'm not sure about duck hunting season, but I am sure there's a family of ducks that's been hanging around for a while now as they raised the chicks (or is that ducklings?). They're really shy. I see them from out the windows often but can never manage to get a shot at them when I go outside. Today I finally got a good/reasonable shot of them on the orchard dam.

:)
A couple of weeks ago I wrote about XML Namespace issues in VB: one in particular was to do with namespace declarations being repeated in the output XML. In those cases we only looked at common namespaces for the entire document.
However the example of creating a word document I posted earlier today raises a similar issue, but this time it's with namespaces that are used in child elements not in the root element. Previously, one suggested workaround was to Import namespaces, and use expression placeholders, but as the word document shows, this does not produce what is often the desirable outcome.
The following simplified example demonstrates this:
- the goal of this exercise is to output the following XML:
<?xml version="1.0"?>
<a:root xmlns:a="url:a" xmlns:b="url:b">
<b:x></b:x>
<b:y></b:y>
</a:root>
The constraint is we want to create the x and y elements separately and insert them into the root element. .eg:
Imports <xmlns:a="url:a">
Imports <xmlns:b="url:b">
.....
Dim el1 = <b:x></b:x>
Dim el2 = <b:y></b:y>
Dim doc = <?xml version="1.0"?>
<a:root>
<%= el1 %>
<%= el2 %>
</a:root>
However that doesn't work. The output for that repeats the namespace of the b.
<a:root xmlns:a="url:a">
<b:x xmlns:b="url:b"></b:x>
<b:y xmlns:b="url:b"></b:y>
</a:root>
So I thought I would try declaring the b namespace in the root element:
Dim doc = <?xml version="1.0"?>
<a:root xmlns:b="url:b">
<%= el1 %>
<%= el2 %>
</a:root>
Now that works. That gives the correct output of :
<a:root xmlns:a="url:a" xmlns:b="url:b">
<b:x></b:x>
<b:y></b:y>
</a:root>
But what is going on here you may ask ? Why does this work ? Well VB removes xmlns attributes from the added elements for any declarations that are used in the containing node. So the minimal fix to get my word document have the namespace declarations at the start requires the correct injection of namespaces to the parent they are added to. For example :
Dim thirdParagraph = <w:p
xmlns:dm="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
xmlns:dp="http://schemas.openxmlformats.org/drawingml/2006/picture"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<w:r><%= drawing %></w:r>
</w:p>
I also had to re-declare 2 xml namespaces in the drawing variables; for the document I had to add 5. And that is in just a simple example. What's really annoying is those namespaces were Imported at the module level in the first place. It would have been nice to write that XML literal using the imported namespaces, e.g:
Dim thirdParagraph = <w:p <%= dm %><%= wp %><%= dp %><%= r %>>
<w:r><%= drawing %></w:r>
</w:p>
Alas that doesn't work. Nor does and combination of GetXMLNamespace that I could think of.
In the need I decided it was a lot easier to just add the namespaces once to the root document and remove all of them from added elements, using a modified extension method.
<Runtime.CompilerServices.Extension()> _
Function RemoveAllNS(ByVal el As XElement, Optional ByVal includeChildNodes As Boolean = False) As XElement
Dim current = el.LastAttribute
Do While current IsNot Nothing
Dim temp = current.PreviousAttribute
If current.IsNamespaceDeclaration Then
current.Remove()
End If
current = temp
Loop
If includeChildNodes Then
For Each child In el.Descendants
RemoveAllNS(child)
Next
End If
Return el
End Function
It's a shame this doesn't work easier than this :(
I was catching up on reading some msdn blogs and stumbled across an entry from Yves Dolce. Yves was showing how to create a word document part including a graphic. Thing was, he was using C#, not VB. Here's an example :
var graphic = new XElement(dm.GetName("graphic"),
new XAttribute(XNamespace.Xmlns + "dm", dm.NamespaceName),
new XElement(dm.GetName("graphicData"),
new XAttribute("uri", dp.NamespaceName),
new XElement(dp.GetName("pic"),
new XAttribute(XNamespace.Xmlns + "dp", dp.NamespaceName),
new XElement(dp.GetName("nvPicPr"),
new XElement(dp.GetName("cNvPr"),
new XAttribute("id", 0),
new XAttribute("name", "openxmldeveloper.gif")),
new XElement(dp.GetName("cNvPicPr"))),
new XElement(dp.GetName("blipFill"),
new XElement(dm.GetName("blip"),
new XAttribute(r.GetName("embed"), "rId1")),
new XElement(dm.GetName("stretch"),
new XElement(dm.GetName("fillRect")))),
new XElement(dp.GetName("spPr"),
new XElement(dm.GetName("xfrm"),
new XElement(dm.GetName("off"),
new XAttribute("x", 0),
new XAttribute("y", 0)),
new XElement(dm.GetName("ext"),
new XAttribute("cx", 4448175),
new XAttribute("cy", 1181100))),
new XElement(dm.GetName("prstGeom"),
new XAttribute("prst", "rect"),
new XElement(dm.GetName("avLst")))))));
Okay here's the same bit in VB:
Dim graphic = <dm:graphic>
<dm:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
<dp:pic>
<dp:nvPicPr>
<dp:cNvPr id="0" name="openxmldeveloper.gif"/>
<dp:cNvPicPr/>
</dp:nvPicPr>
<dp:blipFill>
<dm:blip r:embed="rId1"/>
<dm:stretch>
<dm:fillRect/>
</dm:stretch>
</dp:blipFill>
<dp:spPr>
<dm:xfrm>
<dm:off x="0" y="0"/>
<dm:ext cx="4448175" cy="1181100"/>
</dm:xfrm>
<dm:prstGeom prst="rect">
<dm:avLst/>
</dm:prstGeom>
</dp:spPr>
</dp:pic>
</dm:graphicData>
</dm:graphic>
And this is the complete example :
Imports <xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
Imports <xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">
Imports <xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
Imports <xmlns:dm="http://schemas.openxmlformats.org/drawingml/2006/main">
Imports <xmlns:dp="http://schemas.openxmlformats.org/drawingml/2006/picture">
Module Module1
Sub AddToDocToPackage(ByVal package As Package)
Dim documentUri = New Uri("/word/document.xml", UriKind.Relative)
Dim documentPart = package.CreatePart(documentUri, "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")
Dim firstParagraph = <w:p>
<w:r>
<w:t>A paragraph</w:t>
</w:r>
</w:p>
Dim secondPararaph = <w:p>
<w:r>
<w:t xml:space="preserve">A</w:t>
</w:r>
<w:hyperlink r:id="rId2">
<w:r>
<w:rPr>
<w:color w:val="0000FF" w:themeColor="hyperlink"/>
<w:u w:val="single"/>
</w:rPr>
<w:t>hyperlink</w:t>
</w:r>
</w:hyperlink>
</w:p>
Dim graphic = <dm:graphic>
<dm:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
<dp:pic>
<dp:nvPicPr>
<dp:cNvPr id="0" name="openxmldeveloper.gif"/>
<dp:cNvPicPr/>
</dp:nvPicPr>
<dp:blipFill>
<dm:blip r:embed="rId1"/>
<dm:stretch>
<dm:fillRect/>
</dm:stretch>
</dp:blipFill>
<dp:spPr>
<dm:xfrm>
<dm:off x="0" y="0"/>
<dm:ext cx="4448175" cy="1181100"/>
</dm:xfrm>
<dm:prstGeom prst="rect">
<dm:avLst/>
</dm:prstGeom>
</dp:spPr>
</dp:pic>
</dm:graphicData>
</dm:graphic>
Dim drawing = <w:drawing>
<wp:inline>
<wp:extent cx="4448175" cy="1181100"/>
<wp:docPr id="1" name="Picture 0" descr="openxmldeveloper.gif"/>
<wp:cNvGraphicFramePr>
<dm:graphicFrameLocks noChangeAspect="1"/>
</wp:cNvGraphicFramePr>
<%= graphic %>
</wp:inline>
</w:drawing>
Dim thirdParagraph = <w:p><w:r><%= drawing %></w:r></w:p>
Dim doc = <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document>
<w:body>
<%= firstParagraph %>
<%= secondPararaph %>
<%= thirdParagraph %>
</body>
</w:document>
Using writer = Xml.XmlWriter.Create(documentPart.GetStream)
doc.WriteTo(writer)
End Using
End Sub
Which is the right tool for the job ?
Some where, some time, the dark side managed to take hold of the MSDN documentation. In 1.0 and 1.1 the documentation was pretty much language agnostic. Constructors, where listed as Foo Constructor. Now it seems the dark side has taken hold and they are listed in C# syntax, e.g: Foo .
For those who don't realize, that's a C# language peculiarity. In IL they constructors are named ctor and cctor. In VB, they are named Sub New.
So why choose the C# syntax over VB or IL ? Well it's just another case of Microsoft giving VB folks the finger, sadly this time from the documentation team.
The dark side continues to expand like an untreated cancer :(
RJ posted an interesting entry about LINQ to XSD. The early LINQ to XSD bits that surfaced back in Orcas Beta 1 or thereabouts were basically an object layer of the underlying xml data. It was better than *just* an object model in that much of the XElement capabilities remained, but it was still just an object wrapper. I think VB can possibly do better ....
If you look at VB9 you'll see there's already basic intellisense support for schemas when working with XML axis properties. So the questions we should and could ask are can we make that better ? For example, let's say the compiler was to validate that. We could then enforce XSD constraints and give warnings or errors when they are broken.
One problem would be how would you specify what schema is being used. What if the XElement or XDocument has multiple schemas or you want to apply a different schema to a document ? One solution might be to have Schemas as a form of Interface, or more to the point as a Dynamic Interface.
Now if the constrain is only via dynamic Interfaces, you get all the flexibility of XML elsewhere, but if you cast the element to that dynamic interface you are constrained to that schema.
So if we had that, then why not let Dynamic Interfaces be schema fragments ? Then you could strongly type an element as a branch of a schema.
I don't think an object model is the best way of spanning that XML to general purpose programming divide. VB on the other hand has embraced XML and made the initial steps. Dynamic Interfaces seem like a logical extension to what VB9 already provides. And, speaking of extensions, if the schema or schema fragments are dynamic interfaces, then you could also provide extension methods typed to the dynamic interface.
There'd still be bits that would be more difficult such as interception of value setting, and eventing.. perhaps that would be the perfect opportunity for mixins ;)
With VB9 (aka 2008), there's tool-tips and intellisense everywhere... and I mean everywhere. And that's possibly a good thing for some folks. But do I really need to see a 3 line tool-tip every time I use the Dim statement ? It's a little patronising annoying. Sure for first timers or those with severe memory problems it's probably helpful. For me, it continually gets in the way.
Why didn't the tool-tips have a feature such as "don't show me this one anymore" ? Or an option to disable them for common keywords, or don't show me the same tool-tip more than 1000 times !!!!!!!!!
No doubt there's probably some arcane rule written in the tinniest print that says you will be tortured with the return of Clippy if you do the following, but you could always open up the msvb7ui.dll and modify the string table. Perhaps add some motivational messages in there.... Hmmm, maybe I should write a utility that inserts random messages into it :) Of course you can do this yourself at home.. Just open msvb7ui.dll in Visual Studio, open the string table and start with resource 50140.
If you were to do that, you'd find that empty strings weren't allowed. Mine is a smiley at present :) All you need do is save the dll somewhere, close Visual Studio and then copy over the original (of course you'd make a copy of the original too just in case ;) ).
So what would you replace that tooltip with ? Something inspiring ? Something *Mort*ifying ?? Perhaps "No you're not dim, you're very bright", or "the world was dim before Edison" or "it's always dim'est before the dawn", or "you're about to enter another dimension ....." (hmm, could we add twilight zone music to that ??). Or maybe something more motivating, like "yo, go d00d, you declare that variable !" or "u own3d that var bro"
Aggh, see what reading the same tool-tip over an over can do to a person ......
One thing I associate with Christmas time is cherries... not that I buy cherries or anything in particular, but it's one of the fruits of the season that for some reason remind me it's that time of the year ;) This year for the first time ever I actually got a heap of cherries of a couple off my cheery trees. Most years I only get a handful, but this year looks like a bumper crop and seems earlier than usual because even the parrots haven't homed in on them yet. I'm amazed at how many I picked and actually brought back inside considering I was eating more than what when into the bag. Kind of scary to think about that.... seeing as there were kilos of them in the bag ! This is some of what is left:
Don't ya just love summer :)