Mittwoch, 3. März 2010

F# und der Umgang mit out Parametern

Jede Funktion bzw. Methode kann zunächstmal nur immer eine Informationen zurückgegeben. Dies wird durch den Rückgabewert oder Rückgabeparameter ausgedrückt. Was macht man aber, wenn man in einer Methode mehrere Informationen zurückgeben möchte, die evtl. sogar optional sein sollen? Eine Möglichkeit ist natürlich einen komplexen Datentyp zu definieren und diesen als Rückgabetyp der Methode zu benennen. Aus Bequemlichkeit macht man das aber eher nicht.

Ein pragmatischster Ansatz ist es, für die zusätzlichen Rückgabewerte jeweils out Parameter zu definieren. Die out Parameter sind in der Regel primitive Datentypen wie string oder int.

Im .NET Framework gibt es einige Methoden die einen out Parameter haben. Eine oft verwendete Klasse ist z.B. das Dictionary.

Hier ein Beispiel:

var dict = new
Dictionary<string, int>();

dict.Add("A", 1);

dict.Add("B", 2);


 

Jetzt versuchen wir Werte aus dem Dictionary zu ziehen. Da nicht garantiert werden kann, dass der gesuchte Wert auch in dem Dictionary ist, verwenden wir die Methode TryGetValue. Da diese nun einen out Parameter definiert, müssen wir bevor wir diese Methode aufrufen können eine Variable mit dem entsprechenden out Parameter Typ definieren und die Methode mit der Variablen aufrufen.Der Rückgabewert von TryGetValue ist ein bool, so dass man erkennen kann, ob der Wert im Dictionary vorhanden ist. Nur wenn der Wert vorhanden ist, hat auch die Variable einen Wert. Aber Vorsicht! Da int ein Werttyp, ist hat er immer einen Defaultwert, nämlich 0. Zur Sicherheit sollte man daher der out Variablen einen anderen Wert als den Defaultwert zuweisen, bei int z.B: -1 statt o.


 

int value = -1;

var success = dict.TryGetValue("A", value);

if (success)

{


Console.WriteLine(value);

}

Soweit dürfte das jedem klar sein und sicherlich schon oft gemacht worden. Für mich ist die o.g. Methode, genauso wie TryParse, ein legitimer Grund out Paramter zu verwenden. Alle anderen Gründe sind eher zweitrangig da hier Bequemlichkeit im Vordergrund steht. Man will halt keinen komplexen Datentypen nur für einen Rückgabeparameter erstellen.

Aber es geht auch anders: mit F#!

F# to the rescue

Da F# eine ganz normale .NET Sprache ist, kann man natürlich auch die Klassen des Frameworks aufrufen. Z.B. auch die Methoden die out Parameter definieren, wie z.B. das Dictionary. Wie geht F# damit um?

In F# können wir ganz normal ein Dictionary erzeugen.

open System.Collections.Generic

let dict = new Dictionary<string,int>()

Nun fügen wir Werte zum Dictionary hinzu

dict.Add("A",1)

dict.Add("B",2)

Schließlich wollen wir die Werte auch wieder auslesen.

let result = dict.TryGetValue("A")

Nun von welchem Typ ist jetzt result? Und warum muss man keinen out Parameter übergeben?

F# Interactive gibt die Anwort.

val result : bool * int = (true, 1)

Result ist vom Typ bool * int
, was in F# bedeutet dass dies ein Tupel ist. In .NET 4.0 kann man dies als Tuple<bool,int>
beschreiben.

Nun können wir diesen Tupel mit den Funktionen fst und snd zerlegen.

let success = fst result

val success : bool = true


 

let value = snd result

val value : int = 1

F# wäre nicht F# wenn man es nicht noch einfacher ausdrücken könnte. Man kann nämlich den Tuple direkt in seine Bestandteile zerlegen.

let (success,value) = dict.TryGetValue("A")

val value : int = 1

val success : bool = true

let (success,value) = dict.TryGetValue("C")

val value : int = 0

val success : bool = false

Fazit

Für meine Begriffe ist dies ein gutes Bespiel wie ausdrucksstark F# ist. In der Vergangeneheit sind viele Fehler im Programmiersprachendesign gemacht worden. Allem voran C++, aber leider auch bei C#. Tuples sind ein hervoragendes Mittel, um out Parameter zu vermeiden. Da Tuple in .NET 4.0 ein "first Class" Datentyp ist, gibt es keinen Grund mehr diesen nicht auch in C# als Alternative zu out Parametern zu verweden. Letztendlich macht es aber mit F# mehr Spaß!

Over und out!

Mittwoch, 24. Februar 2010

Cassidy Marie shipped


Beta


Release Candidate


Cassidy Marie shipped

Die glücklichen und schlaflosen Eltern
Marika und Benjamin Gopp

Freitag, 12. Februar 2010

F#: Units of Measure

Mit dem diese Woche erschienenen Release Candidate von VS2010, hat sich auch was bei F# getan. Wie Don Syme in seinem Blog schreibt, ist der F# Compiler auf Version 2.0 heraufgesetzt worden. Das bedeutet F# ist ausgereift um es produktiv einzusetzen (Obwohl viele es bereits mit früheren Version eingesetzt haben). Zeit sich also endlich ernsthaft mit F# und seinen genialen Features zu beschäftigen!

Ein Feature über das ich heute schreiben möchte sind Units of Measure oder zu Deutsch Maßeinheiten. Bei diesem Feature geht es um das Problem bei der Verwendung von unterschiedlichen Maßeinheiten im Code. Wie der Unfall des NASA Mars Climate Orbiter 1999 zeigt, kommt es auch heute noch zu Fehlern auf Grund der Verwendung von unterschiedlichen Maßeinheiten. Mittlerweile wird auch in der USA in Wissenschaft und Technik das Metrische System verwendet. Ein Zulieferer hatte jedoch in Pfund und Fuß gerechnet, was letztlich dazu führte, dass die Mars Sonde verglühte.

Dieses Feature hat also einen relativ ernsten Hintergrund. Damit solche Fehler sich nicht in Produktivcode einschleichen verwendet F# eine erweiterte statische Codeanalyse. Maßeinheiten werden dabei mit Attributen annotiert und bei Ihrer Verwendung vom Compiler auf Korrektheit geprüft. Dabei wird jedoch nicht nur geprüft ob der entsprechende Typ korrekt ist, sondern auch ob die Funktion in dem man diesen Typ verwendet, mathematisch korrekt ist. Durch die intelligente Typinferenz in F# können sogar abgeleitete Maßeinheiten ermittelt werden.

Nun wie funktioniert das? In C# könnte man eine gewisse Art der Typsicherheit hinbekommen, indem man für Maßeinheit einen eigenen Typen erstellt. Somit würde der Compiler beim Verwenden des Types dessen Typsicherheit garantieren. Was jedoch nicht möglich ist, dass auch auf die Einhaltung der mathematischen Regeln geprüft wird. Dies könnte man vielleicht zur Laufzeit realisieren in dem man für Maßeinheiten entsprechende Rules definiert. Letzlich würde aber eine Prüfung zur Laufzeit nicht den Absturz einer 100.000 km entfernten Sonde verhindern können. Die Prüfung muss also viel früher, also zur Compilezeit erfolgen.

Noch ein Hinweis: Units of Measure können nur mit Gleitkommazahlen verwendet werden! Dies liegt daran, dass man nicht nur dumme Maßeinheiten verwenden kann, sondern auch physikalische Größen wie Beschleunigung etc. Dies würde nicht mit Integers oder anderen Typen funktionieren. (Tatsächlich kann man aber Units of Measure mit Komplexen Zahlen oder Vektoren verwenden)

Ein Beispiel:

Man definiert zunächst die Maßeinheiten die man verwenden will als Typen. Diese Typen attributiert man mit[<Measure>]. (So sehen Attribute in F# aus. Eine Misschung aus C# und VB Attribute)

[<Measure>] type kg

[<Measure>] type s

[<Measure>] type m


 

Nun können wir Formeln schreiben. Wir wollen wissen, mit welcher Geschwindigkeit wir auf der Erde aufkommen, wenn wir aus einer bestimmten Höhe springen. Zunächst definieren wir die Höhe als Gleitkommazahl und auf welche Maßeinheit sich diese bezieht.

let höhe = 2.0<m>


 

Nun definieren wir die Gravitation. Diese ist eine Beschleunigungskraft: also Gravitationskonstate mal Meter pro Sekunde im Quadrat

let gravitation = 9.81<m/s^2>


 

Wir können nun ausrechnen wie groß die Geschwindigkeit ist, mit der man auf der Erde auftrifft.

let geschwindigkeit = sqrt (2.0 * gravitation * höhe)


 

F# Interactive sagt uns, dass die Geschwindigkeit in Metern pro Sekunde berechnet wird.

val geschwindigkeit : float<m/s> = 14.00714104


 

Demnach schlgt man mit 14 Metern pro Sekunde bei einem Sprung aus 2 Metern Höhe auf der Erde auf. Gut zu wissen!

Im F# Power Pack sind weitere Standardmaßeinheinten definiert, so dass man nicht jedes mal alle Naturgesetze herunterbeten muss. Auf der anderen Seite stellt sich die Frage, wann man dieses Feature wirklich brauch. Hier zeigt sich wieder das F# eine super Ergänzung zu bestehenden C# Code ist, jedoch keinesfalls den Anspruch erhebt C# in seiner Gesamtheit abzulösen. Bisher sind noch keine Überlegungen gemacht worden, Units of Measure auch nach C# zu portieren oder sogar in die CLR. Man wird mit der Zeit sehen müssen, ob dieses und andere Feature auch nach C# portiert werden, oder ob es dann keinen Grund mehr geben würde F# zu verwenden. Das wäre außerst schade!

Viel Spaß beim Ausprobieren mit F#

Benjamin


 

Dienstag, 26. Januar 2010

Top Ten Free Extensions for Visual Studio 2010

Kate Gregory hat auf Codeproject eine Top 10 der Erweiterungen für Visual Studio 2010 zusammengestellt.

Darunter auch meine Erweiterung die "ZoomEditorMargin". Meine Beschreibung findet ihr hier: http://hiq-software.blogspot.com/2009/10/vs2010-extension-zoomeditormargin.html

Ein Video von meiner Extension kann man sich bei Youtube ansehen http://www.youtube.com/watch?v=sM_20hptWDc

Weitere Tools und die entsprechenden Videos hierzu findet ihr unter http://www.codeproject.com/KB/macros/TopTenFreeExtensions2010.aspx


 

Benjamin

Dienstag, 17. November 2009

VSTO 4.0 Runtime

Die VSTO 4.0 Runtime wird nicht installiert, wenn man Office 2010 bereits installiert hat. Stattdessen wird die VSTO 3.5 Runtime installiert!

Warum? Keine Ahnung!

Mehr Informationen findet man unter: http://msdn.microsoft.com/en-us/library/bb608603(VS.100).aspx

Wer die Installation nachholen will kann die Runtime über den entsprechenden Bootstrapper installieren. Der wird nämlich installiert.

Der Bootstrapper Pfad lautet: C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages\VSTOR40

Dienstag, 20. Oktober 2009

VS2010 Extension: ZoomEditorMargin

VS2010 Beta2 ist endlich draußen. Kaum heruntergeladen und installiert, habe ich auch schon die erste Erweiterung für den neuen WPF Codeeditor geschrieben!



Besonders gespannt war ich auf die Zoom Funktion des Codeeditors. Als ich VS2010 zum ersten Mal öffnete, war ich jedoch etwas enttäuscht. Auf der linken Seite des Code Editors befand sich lediglich eine Combobox, über die man den Zoom einstellen kann. Aus meiner Erfahrung mit Office 2007, hätte ich jedoch gerne einen Slider gehabt, mit dem ich stufenlos zoomen könnte.



Zum Glück lässt sich der neue WPF Codeeditor in VS2010 an allen Ecken und Enden anpassen. Gesagt getan, habe ich eine eigene "Margin" für den Editor geschrieben. Eine Margin ist ein Bereich im Codeeditor, in dem man ein WPF Control platzieren kann. Dies ist nur eine von vielen Möglichkeiten den Codeeditor anzupassen und zu erweitern.



Wer das ZoomEditorMargin herunterladen und direkt ausprobieren möchte, kann dies in der , oder über den ExtensionManager in VisualStudio tun.



Der Code Editor ohne Zoom Extension




Der Code Editor mit Zoom Extension





In den nächsten Posts werde ich erklären, wie ich diese Extension erstellt habe. Es gibt viele Aspekte, auf die ich näher eingehen möchte. Deswegen verrate ich nicht alles schon in diesem Blog Post.



Viel Spaß und stay tuned



Benny

Donnerstag, 15. Oktober 2009

Stirnrunzeln über: "Stirnrunzeln über das Neuste von Microsoft seit geschnitten Brot"

Ralf Westphal schrieb in seinem Blog "Stirnrunzeln über das Neuste von Microsoft seit geschnitten Brot", über das neue Reaktive Framework (Rx) von Microsoft. Zunächst wollte ich einen Kommentar in sein Blog schreiben. Der Kommentar ist dann etwas länger ausgefallen, so dass ich mich entschieden habe, einen eigenen Blog Eintrag mit meiner Meinung zu diesem Thema zu schreiben. Ralf fordert sogar zu Reaktionen auf: "Oder übersehe ich hier die eigentliche Erfindung? Geht der brillante Innovationshub an mir vorbei? Ich bitte um Erhellung"

Also versuch ich doch etwas Licht ins Dunkeln zu bringen.

Wo ist das Problem?!

Für Ralf besteht das Problem an dieser neuen Technologie, dass er ein "neues Vokabular für etwas Altes" benutzen muss. Nach dem Motto: Raider ist jetzt Twix. Klar, wenn etwas Neues mit einem alten Begriff besetzt ist und das Neue immer mit dem Alten assoziiert wird, sinkt natürlich die Akzeptanz für das Neue. Heißt das aber, dass da Neue schlecht ist? Das kann ich (noch) nicht beurteilen. Trotzdem bin ich Neuem erst mal aufgeschlossen eingestellt.

Was ist also das Alte? Für Ralf ist das Alte: Complex Event Processing (CEP).

"Das ist nicht neu, das ist kein Hexenwerk".

Aber das ist doch mit den meisten Erfindungen so! Irgendwo hat's Irgendwer bereits erfunden. Das Neue sieht nur hübscher aus: "es ist eben keine tolle neue Erfindung seit geschnitten Brot, sondern etwas lange Bekanntes in aufgehübschtes Gewand gekleidet". Ja, das ist vermutlich so.

"Tut mir leid, da ist nichts Neues für mich dabei. Wenn ich im etablierten Paradigma data flow denke, dann ist das etwas uraltes und kann mit heutigen Mitteln bewältigt werden."

Ralf, das mag für dich alles "kalter Kaffee" sein. Aber hallo? Data flow, etabliert? Wo denn bitte? In welcher Firma die Software Entwicklung ist denn dieses Paradigma etabliert? Frag doch aber bitte mal deine Kunden, die Teilnehmer der CCD Seminare, die Besucher einer Konferenz, die Zuhörer deiner Vorträge. Wer von denen:

  • hat von CEP, Esper oder CCR gehört?
  • hat einen Artikel über CEP, Esper oder CCR gelesen (von dir oder jemand anders)?
  • verwendet CEP, Esper oder CCR produktiv in seinen Buisiness Anwendungen?

Antwort: fast
Niemand.

Das ist das Problem: Für Dich und einige Wenige ist das alles Schnee von gestern (siehe 1. Kommentar von Holger Hofstätte). Für die breite Masse, absolutes Neuland.

"Wer das wirklich einmal ausprobieren will, was man mit einer Abfragesprache auf Event-Strömen tun kann, dann kann mit NEsper spielen"

Nein Ralf, ich will nichts ausprobieren, ich will auch nicht nur damit spielen. Ich möchte diese Funktionalität im .NET Framework haben und produktiv sein.

Reaktive Programmierung wird im Core .NET Framework vorhanden sein. Das ist das Neue! Das ist Etablierung!


Was ist mit LINQ

Zur Erinnerung: für Ralf besteht das Problem am Reactive Framework, dass es das alles schon einmal gab. Was war aber gleich nochmal LINQ?

Das Konzept hinter LINQ kommt aus der funktionalen Programmierung (Map, Filter, Reduce). Anscheinend hatte hier Ralf keine oder nicht genügend Berührungspunkte mit der funktionalen Programmierung, dass er automatsch LINQ mit einer längst erfundenen Technologie assoziiert hätte. Zumindest wird Erik Meijer für sein "Brainchild" LINQ gelobt, jedoch nicht für seine anderen Projekte (z.B: Volta und Rx).

Funktionale Programmierung war doch auch nur ein akademisches Thema. Vielleicht ist man im Studium mit LISP, ML oder Miranda in Berührung gekommen. Angekommen im Berufsleben hat man aber seine Daten über geschachtelte for-Schleifen gefiltert. Von wegen Map, Filter, Reduce. Obwohl die Technologie doch bereits in .NET vorhanden war (Delegates, Iteratoren). Trotzdem hat es keiner genutzt. Aber dann kam LINQ daher und mit ein bischen "syntactic sugar" für C#, etabliert sich ein Konzept aus der funktionalen Programmierung auch in einer objektorientierten Programmiersprache wie .NET. Und da das Konzept im Framework verankert ist, ist LINQ sogar für alle.NET basierten Programmiersprachen verfügbar.

Erst mit LINQ hat sich das funktionale Paradigma in der breiten Masse etabliert. Immer mehr Leute benutzen LINQ Queries um ihre Listen zu projizieren, filtern und aggregieren. Immer mehr Leute verwenden Lambda Ausdrücke für die alltäglichsten Dinge.

BetaMax vs. VHS, HD vs. BlueRay

LINQ hat da eine Tür aufgestoßen, das Reaktive Framework wird das gleiche machen und den Weg in den Mainstream finden

"Flows habe ich aber natürlich nicht erfunden. Die sind alt"... "Mainstream ist es aber nicht geworden, wie wir sehen. Schade. Denn die Schritte in einem Flow steigern die Evolvierbarkeit von Software, finde ich"

Ralf, das ist doch genau dein Wunsch, dass das Konzept den Weg in den Mainstream findet. Welche Technologie letztendlich das Rennen macht spielt doch keine Rolle. Ob BetaMax oder VHS, HD oder BlueRay, CEP oder Rx.


Fazit

Es gab schon immer Erfindungen, die nur einem kleinen elitären Bereich in Industrie und Forschung, zugänglich oder erschlossen waren. Nur weil es eine Technologie in einem kleinem Bereich Anklang gefunden hat, kann man nicht sagen die Technologie sei etabliert. Erst wenn sie es in den Mainstream geschafft hat, kann man von Etablierung sprechen. LINQ ist ein super Beispiel dafür, dass ein akademisches Thema dem Mainstream zugänglich wird.

CEP, Esper und CCR haben sich nicht etabliert und werden sich nicht etablieren.Das Reactive Framework wird sich aber etablieren. Warum? Ganz einfach, es wird Kernbestandteil von .NET sein und damit zugänglich und allgegenwärtig für .NET Entwickler. Kein separates Tool, kein irgendwo runterladen, kein rumspielen. Es wird einfach da sein. Bleibt nur noch es auch zu nutzen...