Posts for the month of October 2008

Syntax matters

Gerade habe ich doch ein Stück Code hochgeladen? mit dem man jeden beliebigen Methodenaufruf in eine Invocation umwandeln kann.

Nun, das hat mir nicht gereicht. Jetzt hab ich mich noch mal hingesetzt und mich an einer anderen Syntax versucht:

// anstatt
id invocation = NMCatchInvocation(@"fnord", stringByAppendingString:@"42");

// jetzt
id invocation = [NMRecordingInvocation invocation];
[invocation recordWithTarget:@"fnord"] stringByAppendingString:@"42"];

// oder
id invocation = [NMRecordingInvocation invocationWithTarget:@"fnord"];
[invocation record] stringByAppendingString:@"42"];

Und ich finde das ist von der Syntax her deutlich eleganter als das Makro.

Allerdings:

  • Es ist etwa der doppelte Aufwand dass zu implementieren
  • Das Makro erzeugt viel schnelleren Code (viel weniger allokationen)

Was soll ich davon jetzt halten? Small is beautifull? Keep it simple stupid? Oder ist doch wichtiger dass der zweite Versuch eher dem Objc-Spirit entspricht?

Mir ist das auch nach einem Tag darüber nachdenken erheblich unklar.

Grundeinkommen

Spannend wars heute auf  dem Kongress.

Vormittags der Workshop über Simulationsmodelle über die Auswirkungen der Einführung von Grundeinkommen auf ein Modell der österreichischen Volkswirtschaft (in dem sich zeigte dass Gewinnsteuerfinanziertes Grundeinkommen das verwendete Modell stärker destabilisierte als ein durch negative Einkommenssteur finanziertes.

Well, dafür das der verantwortliche für das Modell nur einen Tag lang simuliert hat...

Danach ging es noch ein bisschen mit zellulären automaten weiter um damit zu simulieren wie sich das Wissen um Grundeinkommen in der Bevölkerung ausbreiten konnte.

Beides nicht großartig, aber doch ein interessanter Einblick darin dass auch in der Simulation eben nur mit Wasser gekocht wird. Will sagen: Das hätte ich auch gekonnt.

Danach gabs dann einen Argumentationsworkshop gegen Stammtischparolen und Killerargumente - das war mal was praktisches und für mich (trotz einer was Argumente angeht eher mageren Ausbeute) damit das Highlight des Tages.

Schlussendich noch eine (gefühlt endlose) Podiumsdiskussion. Bei der ich wie auf Kohlen saß - mir ist nach wie vor noch nicht klar wieso ich das so extrem nervig fand. Naja.

Immerhin kam mir dabei noch eine interessante Idee: Viel beschworen ist ja die Angst vor der Arbeitsunwütigkeit der Bevölkerung wenn es ein Grundeinkommen gibt. Dass die dann nicht mehr Arbeiten würden und es sich nur noch gut gehen lassen werden.

Tja, das kann man doch einfach Testen. Alle Gemeinden < $GRENZWERT dürfen sich für eine Lotterie anmelden. Die Leute die in der Gemeinde leben die Gewinnt (und nur die die zu dem Zeitpunkt dort leben) kriegen dann von da ab bis an ihr Lebensende ein garantiertes und bedingungsloses Grundeinkommen.

Voila - schon weiß man bald viel mehr darüber wie sich Menschen mit Grundeinkommen verhalten. Und dann kann man bald die Angst dass die dann ja alle nicht mehr Arbeiten würden fundiert wiederlegen. (Ok, kann man IMO jetzt auch schon, aber es wäre halt doch etwas anderes)

Bonus wäre natürlich wenn man gleich mehrere solcher Versuche macht um verschiedene Rahmenbedingungen zu testen.

Billiger als ein Bankencrash wäre es allemal - und viel Produktiver.

NSInvocations zusammenbauen...

...ist deutlich schmerzhaft.

Man muss eine Menge Aufwand treiben um aus einem objc-call etwas zu machen dass man schön hin und her passen kann.

Zum Beispiel:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    id aString = @"fnord";
    
    id signature = [aString methodSignatureForSelector:@selector(stringByAppendingString:)];
    id invocation = [NSInvocation invocationWithMethodSignature:signature];
    
    [invocation setTarget:aString];
    [invocation setSelector:@selector(stringByAppendingString:)];
    id appender = @"23";
    [invocation setArgument:&appender atIndex:2];
    
    [invocation invoke];
    
    id returnValue = nil;
    [invocation getReturnValue:&returnValue];
    
    NSLog(@"Got: %@", returnValue);
    
    [pool drain];
    return 0;
}

Das nervt sobald man es öfters als einmal machen muss.

Darum hab ich mir nach langem nachdenken mal etwas zusammengebaut das das erleichtert. Es ist nicht perfekt und ich hab auch eine Menge Ideen wie man es noch schöner machen kann, aber es funktioniert. :)

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    id invocation = NMCatchInvocation(@"fnord", stringByAppendingString:@"23");

    [invocation invoke];

    id returnValue = nil;
    [invocation getReturnValue:&returnValue];
    
    NSLog(@"Got: %@", returnValue);
    
    [pool drain];
    return 0;
}

Und das sieht schon bedeutend besser aus.

  • Posted: 2008-10-25 07:42 (Updated: 2008-10-26 20:28)
  • Author: dwt
  • Categories: code
  • Comments (0)

Captcha again

Kongress zum bedingungslosen Grundeinkommen

C-Code für C und C++ verwendbar machen

Ich hab mich schon immer gefragt woher man eigentlich diese Defines nimmt um C-Code deklarationen so zu schützen, dass sie auch in C++ Code gut reingeholt werden können.

Ja klar, man kann das selber machen, etwas präprozessor bla und los gehts. Aber, das gibts ja vielleicht schon.

Enter #import <sys/cdefs.h>.

Und das ist in in Apple-Code praktischerweise immer schon includiert und enthält praktische Kleinigkeiten wie:

  • __BEGIN_DECLS - jetzt kommen C-Deklarationen
  • __END_DECLS - fettich
  • __dead2 - diese Funktion kehrt nicht zurück (über das 2 könnte ich mich total amüsieren)
  • __pure2 - diese Funktion hat keine Seiteneffekte
  • __unused
  • __printflike(formatArg, firstVarArg)
  • __scanflike(formatArg, firstVarArg)
  • __COPYRIGHT(string) - erzeugt eine globale variable
  • __PROJECT_VERSION(string) - erzeugt eine globale variable
  • __deprecated

Dann gibts natürlich noch <AvailabilityMacros.h> das auch noch ein paar Kleinigkeiten enthält - neben dem ganzen Zeug um APIs zu versionieren sind da auch noch mal Attribute definiert:

  • WEAK_IMPORT_ATTRIBUTE -- funktion ist vielleicht da
  • DEPRECATED_ATTRIBUTE -- funktion soll nicht mehr verwendet werden
  • UNAVAILABLE_ATTRIBUTE -- funktion ist nicht vorhanden (z.B. weil sie API ist die erst in einer späteren Version des Frameworks unterstützt wird)

Vor allem __BEGIN_DECLS, __END_DECLS und __deprecated werde ich mit Sicherheit sofort benutzen. Ob ich die anderen auch verwende, weiß ich noch nicht. Mal schaun. :)

Ich find User-Ideen großartig

Einfach mal kreativ mit der Techik umgehen. Mal probieren und testen und dann die Erfahrung austauschen.

http://failblog.files.wordpress.com/2008/09/fail-owned-yahoo-science-mirror-fail1.jpg ( via)

Unglaublich über sowas einfach herzuziehen.  Einfach die eingebaute Kamera als Spiegel verwenden. Zum Beispiel  damit.

If you want to count on it - pirate it

  • Posted: 2008-10-13 09:17 (Updated: 2008-10-13 09:18)
  • Author: dwt
  • Categories: fnord
  • Comments (0)

Das Gedicht zum Bankendomino

(via  Fefe, von  Brokerz)

Wenn die Börsenkurse fallen,
regt sich Kummer fast bei allen,
aber manche blühen auf:
Ihr Rezept heißt Leerverkauf.
Keck verhökern diese Knaben
Dinge, die sie gar nicht haben,
treten selbst den Absturz los,
den sie brauchen - echt famos!

Leichter noch bei solchen Taten
tun sie sich mit Derivaten:
Wenn Papier den Wert frisiert,
wird die Wirkung potenziert.

Wenn in Folge Banken krachen,
haben Sparer nichts zu lachen,
und die Hypothek aufs Haus
heißt, Bewohner müssen raus.

Trifft's hingegen große Banken,
kommt die ganze Welt ins Wanken -
auch die Spekulantenbrut
zittert jetzt um Hab und Gut!

Soll man das System gefährden?
Da muss eingeschritten werden:
Der Gewinn, der bleibt privat,
die Verluste kauft der Staat.

Dazu braucht der Staat Kredite,
und das bringt erneut Profite,
hat man doch in jenem Land
die Regierung in der Hand.

Für die Zechen dieser Frechen
hat der Kleine Mann zu blechen
und - das ist das Feine ja -
nicht nur in Amerika!

Und wenn Kurse wieder steigen,
fängt von vorne an der Reigen -
ist halt Umverteilung pur,
stets in eine Richtung nur.

Aber sollten sich die Massen
das mal nimmer bieten lassen,
ist der Ausweg längst bedacht:
Dann wird bisschen Krieg gemacht.

Regexe updated

Hab ich mir doch gedacht, nur matching von regexen auf ganzen Strings ist doch langweilig - also hab ich noch containsRegex: hinzugefügt um etwas mehr komfort zu haben.

Da dachte ich ja zuerst dass ein Regex wie dieser hier eigentlich nicht funktionieren dürfte: .*^a angewandt auf "aaa" - aber interessanterweise funktioniert das ohne Probleme. Muss ich wohl noch etwas an meinen Regex-Verständnis feilen.

Ah well.

Code hier

Wie kriegt man eigentlich mit was sich im Linux Kernel so tut?

Schließlich gibt es dort nicht so ausgezeichnete release notes wie man sie von  Eclipse,  Gnome oder  Ubuntu kennt.

Die Antwort ist überraschenderweise:  Heise lesen. Und sogar  optional auch auf englisch.

Cocoa hat ja Regex Support

Überraschend.

Das der so vollständig ist, hätte ich nicht erwartet. Aber in der Tat,  ICU-Regexe in ihrer ganzen Pracht. Völlig ohne eine neue externe Dependency.

Laut der Dokumentation sollte das sogar in 10.4 schon funktionieren - mit dem einen Caveat, dass multiline Support dort wohl von Hand eingeschaltet werden muss (via (?m))

Sowas wird da möglich:

if ([@"aaa" matchesRegex:@"a{3}"])
    NSLog(@"gotcha");

// other examples
[@"argh fnord argh" matchesRegex:@".*\\bfnord\\b.*"];
[@"aaa" matchesRegex:@"\\w{3}"];

Und das mit extrem wenig Aufwand:

@interface NSString (SimpleRegexMatching)
- (BOOL) matchesRegex:(NSString *)aRegex;
@end

@implementation NSString (SimpleRegexMatching)
- (BOOL) matchesRegex:(NSString *)aRegex;
{
    id predicate = [NSPredicate predicateWithFormat:@"self matches %@", aRegex];
    return [predicate evaluateWithObject:self];
}
@end

Ich bin beeindruckt.

Code hier

  • Posted: 2008-10-09 20:43 (Updated: 2008-10-12 14:16)
  • Author: dwt
  • Categories: code
  • Comments (0)

Die gegenwärtige Finanzkrise ist...

Darfs noch etwas mehr Atommüll sein?

Gerne auch Freihaus...

 Extra 3 hat es mal wieder genagelt.

:-)

Aus einem Variablen-Namen einen String machen

Braucht man manchmal für Bindings. Gleichzeitig will ich aber nicht überall die namen meiner Variablen als Strings hinterlegen - schon alleine damit ich beim Refactorn auch alle Namen erwische.

Also den Macro-Prozessor zur Rettung:

#define NSStringize(aVariableName) @#aVariableName
#
macht aus einer beliebigen expression einen String
@
und das @ davor macht aus einem constanten c-string einen ObjC-NSString.

Und das problem ist gelöst. :)

_HiStOrY_V2_

Mit ein bisschen Hilfe von meinen Freunden...

Heute hab ich mal wieder die aktuelle Version von  Bazaar (1.7.1) ausprobiert. Soweit ganz schnuckelig. Sogar der SVN Checkout von  Adium hat hervorragend geklappt.

Ich muss sagen, beeindruckend.

Nur mit dem Plugin  bzrtools hatte ich Schwierigkeiten, denn die darin enthaltene shell (ein geiles feature) zu benutzen brachte bzr reproduzierbar zum Absturz. :-(

Stellt sich mit hilfe von #bazaar und nach einigen Detours über den Python Debugger (nice!) und  dtruss (nice!) heraus dass es an der libreadline liegt.

Die hat sich nämlich geändert und erwartet inzwischen am Anfang eines History-Files als allererste Zeile diesen eintrag: _HiStOrY_V2_.

Na toll. Und ansonsten stürzt das Programm einfach ab. Also wer sich das ausgedacht hat, der gehört aber auch echt erschossen. Wenigstens die Fehlermeldung hätte vernünftig sein können. Grumpf.

Ausnahmen vs. Regeln in der Usability

Heute hatten wir wieder ein schönes Beispiel für Usability unter Windows. Zuerst das Setting. Eine Bekannte hatte auf einem USB-Stick Fotos mitgebracht und diese sollten auf einem Windows-Vista Notebook dann angeschaut werden.

Das ganze wäre dann fast daran gescheitert, dass auf dem USB-Stick ein Trojaner drauf war und sich Windows nach Entdeckung und Beseitigung des Virus (durch irgend ein Third-Party-Programm) standhaft geweigert hat den Stick im Explorer anzuzeigen. Je nachdem in welchem der USB-Stecker man den Stick einsteckte erkannte Windows nicht mal das überhaupt ein USB-Stick eingesteckt war. Aber ich lenke ab, denn das Problem konnte ich mit etwas Windows-Shell dann doch lösen.

Zum Thema: Nachdem der Ordner mit den Bildern im Explorer aufgemacht wurde, ging es nach einem Doppelklick auf das erste Bild los - der Bildbetrachter ging auf und die Slideshow ging los.

Und das ist das Thema: Unter Windows öffnet der Bildbetrachter Bilder anders als sonst Programme Dateien öffnen - implizit wird dort nämlich der ganze Ordner geöffnet, damit man leicht eine Slideshow mit den Bildern starten kann.

Und das hat doch immerhin so gut funktioniert, dass die Slideshows doch zusammen kamen.

Das bringt aber die Abstrakte Frage mit, was passiert wenn solche "Ausnahmen" immer mehr werden. Verstehen die Anwender dann trotzdem noch das allgemeine Prinzip was dahinter liegt? Sind sie in der Lage zu abstrahieren und das Verhalten an anderen Stellen vorherzusagen?

Ich sehe ein Problem darin, dass Computer für die meisten Menschen "magisch" sind - man lernt nur die magische Formel, die zu einem konkreten Ziel führt. Dass hinter den 30 Formeln die man mit der Zeit lernt ein Prinzip steht geht dann nur allzu oft verloren.

Zurück zum Beispiel: Am Mac ist es so, dass man, wenn man eine Datei öffnet, dann auch nur diese Datei aufgeht. Und das ist auch so wenn man ein Bild öffnet. Unter Windows ist das anders, denn man öffnet im Bildbetrachter (wehe wenn die Zuordnung verloren geht, weil man ein Bildbearbeitungsprogramm installiert hat) der von sich aus schon die nächsten Bilder kennt und es einem leicht macht eine Slideshow zu starten.

Was ist Besser? Im Beispiel waren relative Laien in der Lage eine Slideshow zu starten - das ist ein Plus. Hätten sie das auch auf einem Mac geschafft?

Wann ist es Besser so eine Ausnahme vom regulären Benutzungs-Konzept zu machen und wann nicht? Für mich ist die Grenze völlig unklar - nur dass es irgendwann den Punkt gibt, wo zu viele Ausnahmen selbst zum Problem werden.

Creating NSNumbers from arbitrary values...

... without needing to care which constructor to use this time to get it right.

Well, I was offended by this just long enough, so I sat down and wrote a macro that allows this:

//  Use like this:
    id dict = [NSDictionary dictionary];
    NSNumber *ten = NMMakeNumber(10.0f);
    [dict setObject:ten forKey:@"numberOfFingers"];
    [dict setObject:NMMakeNumber(23) forKey:@"fnord"];
    [dict setObject:NMMakeNumber(YES) forKey:@"wantFries"];

I'ts almost the way  Autoboxing works in  Java or C#.

This quite eases the pain of creating NSNumbers correctly for me, because it means I don't have to repeat the type of what I am working with quite as often.

Pretty  DRY. :)

Here's the code to a NSNumber category and a makro that makes this happen.

  • Posted: 2008-10-04 12:20 (Updated: 2008-10-07 10:07)
  • Author: dwt
  • Categories: code
  • Comments (0)