

Show HN: Underscore.js for Objective-C - robert-boehnke
http://underscorem.org

======
mullr
This brings to mind google's warning re: the use of functional idioms in Java:
[http://code.google.com/p/guava-
libraries/wiki/FunctionalExpl...](http://code.google.com/p/guava-
libraries/wiki/FunctionalExplained) Objective-C blocks make things smoother
than Java, but it still feels to me like the language _wants_ you to have a
bunch of small objects sending message to each other. (rather than doing
function composition)

That said, I use underscore.js in nearly all of my browser and node.js code,
so I'll certainly consider this when the iPhone train comes back around.

------
cpr
If you embrace the Smalltalk roots of Objective-C, you'll be a lot happier,
and "all those braces" are completely comprehensible.

~~~
travisjeffery
No, you need to embrace how Objective-C is written today because blocks (and
all those braces) are a fundamental part.

~~~
cpr
I think that's what I was trying to say, but apparently didn't make it clear.

------
draegtun
There are also ports of _Underscore.js_ to Perl & Lua:

* <http://vti.github.com/underscore-perl/>

* <http://mirven.github.com/underscore.lua/>

~~~
iron_ball
And AS3, if you're into that sort of thing (self-plug):
<https://github.com/amacdougall/underscore.as>

------
xsmasher
Interesting if you're already used to underscore.js.

The more Objective-C way to do this, without the dot syntax and the need for
wrapping, is to add categories (sets of extra methods) to the NSArray and
NSDictionary classes.

The square brackets don't impair chaining in any way - you can still [[[myDict
allKeys] filter:filterMethod] invoke: invokeMethod]

~~~
robert-boehnke
I've tried that, but once you pass in blocks as arguments, the whole thing
becomes a lot harder to read. I have no clue how to indent

    
    
        [[array filter:^BOOL (id obj) {
                return [obj passesTest];
            }]
            map:^id (id obj) {
                return [obj transformedObject]
            }];
    

Edit: Also, it's good practice to prefix your categories methods so they don't
clash with other category's, so you'd have something like us_map:, us_filter:,
reducing readability even further.

~~~
jawngee
It should be a category on NSObject so it supports anything that supports fast
enumeration which could be anything. And the indentation in the above is
correct. The way you've implemented it is "anti-conventional" and bad form,
imho.

~~~
natesm
Objective-C is a superset of C, functions can be just that - a function.
Especially for higher-order functions like map and filter. Not everything
needs to be glued to an object.

~~~
jawngee
No shit sherlock.

That's not what he's doing, he's exposing blocks as properties because he
couldn't wrap his head around indentation which is the wrong motivation. Maybe
read the source before condescending next time.

~~~
natesm
Uh, I did read it. Yes, it's a bad idea. So is adding random things to
NSObject for protocols that it does not conform to. That's actually worse, I'd
argue, since you suddenly have -[UIColor map:]. What does that do? Pass RGBA
NSNumbers to the block and return a new color? Throw an exception? Silently
disregard the message and return nil? At least this approach has type
checking.

Just declare a normal function, which can correctly throw a compiler warning
if you try to pass anything that does not conform to NSFastEnumeration to it.

------
natesm
What's the advantage of implementing map/filter as property accessors of a
wrapper object instead of just doing:

    
    
        NSArray* map(id<NSFastEnumeration> enumerable, id(^)(id object) block);
    

?

Obviously, you'd still want to have a prefix of some sort for namespacing.

~~~
robert-boehnke
In the case of NSDictionary, Underscore.m's map iterates over objects and
keys. Fast Enumeration only iterates over the dictionary's keys, when you
probably want the value or both.

But I agree, supporting any class that implements NSFastEnumeration would be
nice to have.

~~~
joubert
You may already know this, but you can also enumerate over NSDictionary
entries using enumerateKeysAndObjectsUsingBlock: [1] and
enumerateKeysAndObjectsWithOptions:usingBlock: [2].

The latter giving you the ability to enumerate in reverse order or spread the
enumeration across multiple cores using Grand Central Dispatch.

[1]
[https://developer.apple.com/library/mac/documentation/Cocoa/...](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/nsdictionary_Class/Reference/Reference.html#//apple_ref/occ/instm/NSDictionary/enumerateKeysAndObjectsUsingBlock):
[2]
[https://developer.apple.com/library/mac/documentation/Cocoa/...](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/nsdictionary_Class/Reference/Reference.html#//apple_ref/occ/instm/NSDictionary/enumerateKeysAndObjectsWithOptions:usingBlock):

~~~
robert-boehnke
It's exactly what's used internally :)

------
tubbo
It's cool that we have an Underscore for Obj-C now, but I'm really excited
about this because of the project's opinion that bracket syntax sucks.

It's always been a curiosity that a company like Apple, who prides themselves
on making great user interfaces can't even get it together to make a
programming language that's nice to look at. They seem to care about everyone
BUT their own kind these days...

~~~
speg
I just spent the last month learning about iOS (and Obj-C). I didn't find the
square brackets that terrible. Explicit is better than implicit after all. It
seems like dot notation is best used for properties, but I will reserve
judgement until I have more than just a month of casual experience.

~~~
jparishy
Indeed. Plus I think well-designed Objective-C is some of the prettiest code
out there. Though I've been using it for a few years now almost exclusively
(for the most part) so maybe I am a bit biased.

