Blocks in Objective C

written by Martin Häcker on

I've long had a fascination with SmallTalk style blocks in Objective-C. So much so, that I learned a lot about how C and GCC work when I implemented them on the primitive of GCCs nested functions myself.

[browser:open-source/closures-in-objc/trunk Heres the Source]

Of course, just as I had it working, Apple deprecated GCCs nested functions, as they where implemented using a trampoline on the stack. And of course, a trampoline being executable code they where out when the non executable stack came in.

Ah well.

BUT, Apple just released with Snow-Leopard a new compiler feature [Blocks]!

Yay, closures in C!

So here's how it looks if you implement the Smalltalk collection iteration protocoll in ObjC. (Note: this of course are not propper ObjC-Names, but each Smalltalker will none the less get a tear in their eye when they see this)

#import <Foundation/Foundation.h>

@implementation NSArray (BlocksTest)

- (void) do:(void (^)(id))aBlock;
{
    // Take care, -enumerateObjectsUsingBlock: wraps an auto-release pool around the iteration
    [self enumerateObjectsUsingBlock:
        ^(id obj, NSUInteger idx, BOOL *stop) {
            aBlock(obj);
        }];
}

- (NSArray *) collect:(id (^)(id))aBlock;
{
    id collectedItems = [NSMutableArray arrayWithCapacity:[self count]];
    [self do:^(id each) {
        [collectedItems addObject:aBlock(each)];
    }];
    return [collectedItems copy]; // REFACT: consider to drop copy
}

- (id) detect:(BOOL (^)(id))aBlock;
{
    // Take care, -enumerateObjectsUsingBlock: wraps an auto-release pool around the iteration
    __block id resultObject = nil;
    [self enumerateObjectsUsingBlock:
        ^(id obj, NSUInteger idx, BOOL *stop) {
            if (aBlock(obj)) {
                resultObject = obj;
                *stop = YES;
            }
        }];
    return resultObject;
}

- (id) detect:(BOOL (^)(id))aBlock ifNone:(id (^)())errorBlock;
{
    id foundElement  = [self detect:aBlock];
    if (foundElement)
        return foundElement;
    else
        return errorBlock();
}

- (id) inject:(id)aValue into:(id (^)(id, id))aBlock;
{
    // Need to take care with retain here, because apple wraps an auto-release pool around the block iterator. :/
    __block id collected = [aValue retain];
    [self do:^(id each){
        collected = [aBlock([collected autorelease], each) retain];
    }];
    return [collected autorelease];
}

- (NSArray *) reject:(BOOL (^)(id))aBlock;
{
    id selectedObjects = [NSMutableArray arrayWithCapacity:[self count]];
    [self do:^(id each){
        if (aBlock(each))
            return;
        [selectedObjects addObject:each];
    }];
    return [selectedObjects copy]; // REFACT: consider to drop copy
}

- (NSArray *) select:(BOOL (^)(id))aBlock;
{
    return [self reject:^(id each){ return (BOOL) ! aBlock(each); }];
}
@end


#define log(objcObject) fprintf(stdout, "%s\n", [[objcObject description] UTF8String])

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

    id array = [NSArray arrayWithObjects:@"first", @"second", @"third", nil];

    log(@"\ndo:");
    [array do:^(id each){
        log(each);
    }];

    log(@"\ncollect:");
    log([array collect:^id(id each){
        return [each uppercaseString];
    }]);

    log(@"\ndetect:");
    log([array detect:^(id each){
        return [each isEqual:@"second"];
    }]);

    log(@"\ndetect:ifNone:");
    log([array detect:^(id each){ return NO; } 
                        ifNone:(id)^{ return @"Yeehaw!"; }]);

    log(@"\ninject:into:");
    log([array inject:@"" into: ^ id (id concatenation, id element){
        return [concatenation stringByAppendingString:element];
    }]);

    log(@"\nreject:");
    log([array reject:^(id each){
        return [each hasSuffix:@"nd"];
    }]);

    log(@"\nselect:");
    log([array select:^(id each){
        return [each hasSuffix:@"d"];
    }]);

    [pool drain];
    return 0;
}

Ain't that pretty?

[browser:open-source/smalltalk-like-iterators/trunk Here's the current version!]

Zur Polizeigewalt auf der Freiheit statt Angst-Demo

written by Martin Häcker on

Spannend - vor allem die diversen Analysen im Netz dazu.

Peter Piksa hat die beste Zusammenfassung der Ereignisse die ich kenne.

Besonders Spannend finde ich da die Nachlese von Markus Hansen der sehr schön die Fakten zu Körperlicher Gewalt auf den Tisch legt.

Sehr Lesenswert.

Der Kampf gegen den Überwachungsstaat…

written by Martin Häcker on

ist auch meine Sache.

Und die von Gerhart Baum. Der immerhin ein Innenminister war der tatsächlich Gesetze für Bürgerrechte gemacht hat.

Ahoi!

IE 8 oh IE 8, wärst Du doch kein IE 7...

written by Martin Häcker on

Heute bin ich auf einen sehr interessanten Bug gestoĂźen - im IE natĂĽrlich. Genauer genommen im IE 8.

Folgendes ist passiert: Wir hatten ein Problem mit dem Rendering einer Webapplikation - dort fehlte mal wieder ein Teil das eigentlich hätte da sein sollen. Stellt sich heraus, dass auf manchen der Rechner der IE 8 die Seite im IE 7 Kompatibilitätsmodus gerendert hat - ok wir hatten also eigentlich einen Bug mit dem IE 7 der das CSS nicht vertragen hat. Soweit so gut.

Mysteriös war das ganze, denn es ließ sich auf verschiednen Rechnern nicht reproduzieren. Dabei verwendeten wir sogar die gleichen images (VirtualBox ich liebe dich).

Ok, wir sind also irgendwie auf manchen Rechnern in den IE 7 Kompatibilitätsmodus gerutscht. Wirklich Lustig wurde dass als wir auf dieser Seite auf die Erklärung gestoßen sind:

IE 8 kann nämlich den IE 7 emulieren. Aus 'Kompatibilitätsgründen'. Und weil das natürlich total kompatibel sein muss hat Microsoft das so eingestellt dass alle Intranetseiten automatisch im IE 7 Modus gerendert werden - natürlich ohne einen Knopf mit dem man das abstellen kann. (Andersrum gibt es schon einen…)

Das geile daran: IE erkennt Intranetseiten nicht an der IP, sondern an der Domain! Weil das nicht anders geht! [sic] Und da auf dem anderen Rechner die Webseite per IP aufgerufen wurde wurde das Problem da nicht sichtbar…

Überhaupt ist die Implementierung dieses Kompatibilitätsmodus eine einzige Katastrophe.

  1. Der Modus aktiviert sich automatisch fĂĽr Intranet-Webseiten
  2. Er lässt sich für diese nicht deaktivieren
  3. IE merkt sich welche Webseiten der User irgendwann schon einmal (vielleicht aus versehen) in den Kompatibilitätsmodus geschaltet hat - aber löscht dieses Wissen wenn man die History löscht.
  4. Jede Webseite kann diese User-Einstellung ĂĽberschreiben, indem sie einen meta-tag setzt
    1. und dann wird die User-Einstellung auch gleich komplett gelöscht! (rotflol)
    2. Man kann über den Meta-Tag nur einstellen dass man gerne eine IE 8 Emulation hätte - wenn der IE 9 dann herauskommt darf man also wieder ran und noch mehr Meta-Tags definieren… (kotz)

Also wirklich verkackt auf der ganzen Linie - eine LektĂĽre des Original-Artikels ist wirklich empfohlen. :)

Ich bleibe dabei: DaĂź wir oft an Wahlkampfaussagen gemessen werden, ist nicht gerecht.

written by Martin Häcker on

Franz MĂĽntefering, SPD

Noch Fragen?

Neues vom Grundeinkommen

written by Martin Häcker on

Dazu gibt es ja viel zu wenige empirische Experimente - nur mehr oder weniger begrĂĽndete Vermutungen von allen Seiten.

Gerade deswegen finde ich es so ungemein wichtig dass diese Experimente jetzt beginnen, damit wir wissen was aus dieser Idee werden kann und wie man sie umsetzen kann dass es funktioniert.

Schließlich wollen wir nicht dass wir alle wie die Maori-Indianer in ihren Reservaten enden, die zwar ein Grundeinkommen garantiert haben (da fühlt sich die US-Regierung offenbar doch sehr schuldig) aber die ohne eine kulturelle Identität nur vor sich hin vegitieren können.

Was wir brauchen ist eine Lotterie an der sich alle Dörfer unter 10.000 Einwohner beteiligen können. Aus diesen Dörfern werden dann 3 Gewinner gezogen und denen 10 Jahre Lang ein Grundeinkommen bezahlt - in verschiedenen Höhen, in unterschiedlichen Ausprägungen. Natürlich mit wissenschaftlicher und psychologischer Betreuung.

Dann wissen wir mehr.

Und das coole ist, in Namibia hat der Basic Income Grant (BIG) 2008 so ein Projekt gestartet - mit halbjährigen Evaluierungszyklen.

Und da kommen jetzt die ersten Ergebnisse herein.

via

FreeNode dass ich nicht lache...

written by Martin Häcker on

Heute bin ich mal wieder im CCC - und überraschenderweise fällt mir da diese Fehlermeldung auf:

20:05:26 wolfe.freenode.net: (notice) 
*** Banned:  You've been temporarily blocked 
due to filtering problems. Sorry for the 
inconvenience! Mail kline@freenode.net with questions.

Well, da melde ich mich doch mal:

Your IP address is: 195.160.172.2
Your hostname is: fuckup.club.berlin.ccc.de
I am writing this because I got a message about a 
filtering problem that accidentally banned me.

So here I am.

To witch I got this answer:

Please connect from a host which has an IP that doesn't resolve to a
name that contains "fuck".

Thanks,
stew

Meine Hinweis dass:

You do realize that this is in reference to the "First Universal 
Cybernetic-Kinetic Ultra-Micro Programmer" from 
Hagbard Celine in the Illuminati Trilogy?

So I'd urge you to please take that out of the filter list.

wurde dann allerdings nur noch abgebĂĽgelt.

No, and I don't think you should expect people to know this reference.

> So I'd urge you to please take that out of the filter list.

I don't believe there are any plans to change this filter.

thanks,
stew

Tja. So viel zu selbsternannten Moralaposteln die mit Wortfilterlisten spielen. Mein Vorschlag: Erwachsen werden und Illuminatus! lesen!

Update: Florian hatte die gute Idee doch mal nach dem Servernamen von Freenode auf dem ich connected war zu googeln. Sieh an, was für eindeutige Angebote... Ich finde im Lichte dieser neuen Erkenntnis sollten die dort dringend ihren Servernamen ändern.

Programmierer-Fun

written by Martin Häcker on

Stackoverflow ist immer wieder ein Quell der Freude:

Dazu auch eine absolute Weisheit:

Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Rick Osborne

Git Handarbeit II: Submodules

written by Martin Häcker on

Noch so eine Stelle an der GIT einem extra viel Handarbeit aufdrĂĽckt. Submodules.

Erst mal die Idee (die eigentlich ganz gut ist): Oft will man Teile der Software (Frameworks, Plugins, ...) eigentlich als eigenes Projekt in einem eigenen Repository entwickeln. Und das ist GUT (TM).

Daher bieten eigentlich alle etwas fortgeschritteneren Versionskontrollsysteme irgend eine Möglichkeit solche externen Repositories einzubinden, damit man es einfach hat an aktuelle Versionen dieses Codes heranzukommen.

Dazu gibt es jetzt in der Regel zwei Ansätze: Entweder man verlinkt einfach auf den HEAD des anderen Repos oder auf eine bestimmte Revision. Letzteres ist im allgemeinen Fall zwingend, denn sonst hat man nie die Chance einen alten Build auch tatsächlich exakt wieder herzustellen - im Speziellen Fall ist ersteres aber sehr Praktisch, wenn man z.B. aus einem globalen Repository einfach Teile an verschiedenen Stellen einblenden möchte, damit sie im Repo nur einmal, im Checkout aber mehrfach oder einfach an einer anderen Stelle erscheinen.

SVN macht das mit svn:external attributen die sowohl auf HEAD als auch auf spezifische Revisionen verlinken können. HG macht das mit forests (noch eine extension), bzr weiß ich nicht und git macht das mit submodules.

Bei SVN hat man noch den Nachteil das es, weil es branches und tags nur als Verzeichnisse kennt natĂĽrlich auch Handarbeit erfordert, das hieĂźt, dass man beim Taggen von HEAD z.B. nicht automatisch von dem link auf einen anderen HEAD auf einen Link auf eine spezifische Revision umschalten kann. Das gibt dann das Ergebnis, dass man oft im Tag auf den HEAD eines anderen Teils des Repos verweist. Gratulation! Und wiedererzeugbare Builds ade.

Besonders geärgert haben mich aber die GIT-Submodules. Zuerst: Die sind auch ein Plugin - und in bester GIT manier gibt es natürlich überhaupt keine integration in die anderen Kommandos.

Das bedeutet schon mal das man nicht ein Repository pullen kann um danach einen Build zu machen - NEIN, man muss erst merken dass man noch die Submodules benötigt und dann git submodule init && git submodule update eingeben.

Yeah. Give me useless extra steps!

Es wird aber noch besser, weil es keine Intgegration gibt, sieht man natürlich mit git status nicht das es in einem submodule Änderungen gab. Ok, das stimmt nicht ganz. Man sieht nicht dass es in einem submodule uncommittete Änderungen gab. Commitet man dann nämlich dort, dann sieht man im parent repository dass sich etwas verändert hat - und dass muss man dann nochmal committen.

Yeah. Give me useless extra steps!

Auch schön, wenn man z.B. von GitHub ein Projekt mit Submodules auscheckt, dann zeigt der Origin des Projekts auf GitHub - sinnvoll, weil dahin wird man seine eigenen changes ja schieben wollen, damit Upstream sie mergen kann. Nicht so bei submodules - dort zeigt der origin natürlich auf das ursprüngliche Projekt - auf das man natürlich regelmäßig nicht pushen kann/will. Man muss also einen eigenen branch des submodules auf GitHub anlegen und dann das bei sich von hand als Branch registrieren und dann immer daran denken das im submodule natürlich nicht origin sonder ein anderer name für den parent branch gilt.

Yeah. Give me useless extra steps!

Hach, und natürlich sind GIT submodules IMMER auf eine bestimmte Revision gebunden - tollerweise auch gleich ohne mitzubekommen auf welchem Branch diese jetzt liegt. Das heißt dass man sowieso dort drin per default nix committen kann. Man muss also in jedem fall einen eigenen Remote clone des origins anlegen, den als neuen Remote eintragen, dann einen lokalen tracking branch erstellen, auf den wechseln, dort dann commiten und jeweils nicht vergessen diese Commits im Parent Repo dann zu bestätigen (einzeln natürlich, sonst sieht man dort die history nicht). Das geile daran: macht man dann im Parent Repo einmal git submodule update ist man natürlich wieder auf einer disconnected revision.

Yeeehaw. Give me useless extra steps!

Umbenennen ist noch so eine Sache, DVCS sind ja so toll beim Mergen, nicht? Aber wehe man benennt ein Submodule um. Dann nämlich kriegt man das nach git pull && git submodule update NICHT. Nein, viel besser man muss lediglich .git/config von hand bearbeiten um den alten submodule Eintrag zu entfernen und dann ein git submodule init && git submodule update machen.

Yeah. Give me useless extra steps!

Mein Fazit: GIT, das Tool fĂĽr Leute die gerne mehr Zeit in ihr DVCS als in ihre Software stecken wollen.

Mal auf den Punkt gebracht

written by Martin Häcker on

Volker Pispers hat eine wunderschöne Sendung auf dem Deutschlandfunk gehabt. Und die ist jetzt bei YouTube

Hier etwas zum Anfixen:

"Unter Hitler hatten wir auch den Fingerabdruck im Personalausweiß. Haben die Mütter und Väter des Grundgesetztes abgeschafft. Die haben wörtlich gesagt: Der deutsche ist kein Verbrecher. Das wissen Schilly und Schäuble natürlich besser.

Man kann Menschen nicht daran hindern von sich auf Andere zu schlieĂźen."

Hier auf Youtube