Live data from Hacker News

In defence of Objective-C

splinter.com.au

61–70 of 122 posts

Re: In defence of Objective-C

#61
post #43

Earlier quoted context omitted.

> Languages with macros and (often) monads allow developers to redefine the syntax and types to accomplish these goals. You can't redefine haskell's syntax unless you're using Template Haskell (which is a language extension, not part of Haskell itself). It also has nothing to do with monads. Likewise with most MLs, or with Erlang. All of them have a literal list syntax. And if containers have no reason to be special,…

The way the do notation syntax (used by most people for describing monads) in Haskell translates to function application allows you to do some fairly interesting things with syntax abuse. As for strings, it is very seldom that you find interesting alternative implementations: the only one I can think of is a rope. Interestingly, C++11 now allows you to override string literals, so you can actually do this.

> The way the do notation syntax (used by most people for describing monads) in Haskell translates to function application allows you to do some fairly interesting things with syntax abuse.

Sure but it's not syntax redefinition.

> Interestingly, C++11 now allows you to override string literals, so you can actually do this.

You still have a literal string notation. Literal notations don't have to impede multiple implemetations, and the truth is there is generally a primary representation used for the vast majority of cases (even if that representation is a cluster class and flexible under the interface).

In Cocoa, the primary sequence and maps are NSArray and NSDictionary, what would be the issue with making those literal? And one of your objections is

> When this suddenly matters, you are in the situation where what you want to be able to do is to make a very small modification to areas of your code where you need to select a different algorithm, in order to get the different result; you don't want to be forced to rewrite half your code to use a different syntax just because it was slow

But that makes no sense: as long as all equivalent containers implement the same interface (which they do, or you can't swap them anyway) that creating an object be done with a literal or with a constructor and a bunch of messages has no influence on the rest of the code, the only thing you need to change is the initialization code in both cases.

Hell, a smart enough editor can even swap between the literal and the "constructor" versions of a given collection (IntelliJ can do that for Python dicts, for instance). Not to mention in many cases the non-literal can just take the literal as a parameter, if the collection with a literal syntax has been well chosen, that way you get your cake eat it.

Re: In defence of Objective-C

#62
post #20

There is one thing in Objective-C that still gets my goat, even after 8 years of working with it: it's the lack of syntax for container-types: [NSMutableDictionary dictionaryWithConstructorIDontWantToType:...] is just a huge pain in the ass. Other problems with the syntax have been solved by introducing sugar at the right place. Why not id hash=@{ @"key" : @"value }; and id array=@[ @"value1", @"value2", @"value3"];

Can't get rid of the issue completely, but at least we can have: #define MD(val, key, vals...) [NSMutableDictionary dictionaryWithObjectsAndKeys:val, key, ## vals , nil] then do: NSMutableDictionary* dict = MD(@"value1", @"key1", @"value2", @"key2") And so on. Courtesy of http://news.ycombinator.com/item?id=1789839 .

Very nice, thanks for that.

Re: In defence of Objective-C

#63
post #19

As someone who likes Objective-C a lot, I have to say this is a pretty bad defense of it. No offense, clearly we are both fans of the language, I just don't think this will convince anyone on the other side. In fact, I find very little defense of it at all in this post. It seems his fundamental argument is "its a matter of taste", which while true, in no way conveys the many "whys" of the choices made in this languag…

On #4: personally, I believe it is a mistake to attempt to abstract memory management from developers unless you can abstract all resource management (as there is no fundamental difference between memory mappings, file handles, database connections, or minimum-wage bicycle messengers), and in the attempt to fully abstract memory management (as in, with garbage collection) it usually becomes impossible to abstract arb…

Unlike other resources, dangling references to memory are catastrophic. They generally go undetected (no layer of indirection to invalidate them) and can arbitrarily corrupt any future object, violate any type safety rules of the platform, and make even bug-free code execute incorrectly. "Is this object really dead?" is the kind of mind-numbing but critically important question that computers demonstrably answer much more reliably than people. That's why even objc uses a simple but expensive form of garbage collection (reference counting) rather than making you declare "not only am I not using this, I hereby bet my reputation that nobody else is either" by calling free().

Re: In defence of Objective-C

#64
post #8

Does Objective-C really need defending? After doing a couple of projects with it I've found it to be a really beautiful language from a code formatting point of view. The whole 'overly verbose' thing is probably just because you are encouraged to give your methods and arguments good descriptive names, and often when you do need short variable names for some maths calculations or something it will be while inside a me…

99% of the people who use it have no choice, so not really.

But it's nice to see a semi-tutorial wrapped in an argument. Arguments are more fun to read than tutorials, so I picked up a few factoids (named args) without having to read Apple's documentation (which is a little dry).

Re: In defence of Objective-C

#65
post #20

There is one thing in Objective-C that still gets my goat, even after 8 years of working with it: it's the lack of syntax for container-types: [NSMutableDictionary dictionaryWithConstructorIDontWantToType:...] is just a huge pain in the ass. Other problems with the syntax have been solved by introducing sugar at the right place. Why not id hash=@{ @"key" : @"value }; and id array=@[ @"value1", @"value2", @"value3"];

Can't get rid of the issue completely, but at least we can have: #define MD(val, key, vals...) [NSMutableDictionary dictionaryWithObjectsAndKeys:val, key, ## vals , nil] then do: NSMutableDictionary* dict = MD(@"value1", @"key1", @"value2", @"key2") And so on. Courtesy of http://news.ycombinator.com/item?id=1789839 .

That ## vals syntax is new to me. What's the difference with the following?

  #define MD(...) [NSMutableDictionary dictionaryWithObjectsAndKeys:__VA_ARGS__, nil]

Re: In defence of Objective-C

#66
post #19

Earlier quoted context omitted.

On #4: personally, I believe it is a mistake to attempt to abstract memory management from developers unless you can abstract all resource management (as there is no fundamental difference between memory mappings, file handles, database connections, or minimum-wage bicycle messengers), and in the attempt to fully abstract memory management (as in, with garbage collection) it usually becomes impossible to abstract arb…

Unlike other resources, dangling references to memory are catastrophic. They generally go undetected (no layer of indirection to invalidate them) and can arbitrarily corrupt any future object, violate any type safety rules of the platform, and make even bug-free code execute incorrectly. "Is this object really dead?" is the kind of mind-numbing but critically important question that computers demonstrably answer much…

The idea of type-safety has nothing to do with this: a type-safe language implemented entirely with reference counting, having no ability to write to arbitrary memory locations on purpose or on accident, has this same tradeoff.

Additionally, as I think this is also relevant to your comment, if you take a step back for a second from the notion that an object /is/ memory, and think of memory as being one of the resources that an object is using, things become more clear.

Simply put, we have two common ways of reclaiming objects automatically: garbage collection and reference counting. The tradeoff is that with garbage collection, you get free cycle detection at the cost of not having deterministic finalization.

Each of these options has downsides: neither is fundamentally better than the other, and not having either one causes you to have to scratch your head occasionally, or add extra code to deal with the lack of automation.

(edit:)

Thinking about this overly simple description, I realize that I'm over-simplifying a little too much... a lot of the fundamental problem has to do with an inability to determine the order of finalization of objects in a cycle, which is what causes a lot of mistakes in Java finalizer implementations.

In comparison, the practical problems are that the common implementations involved take extreme positions: if you have a garbage collected language, it normally is not "reference counting with a cycle detector bolted on", which yields a weird property of possibly arbitrary delays on finalization of valuable resources when you aren't under memory pressure.

Re: In defence of Objective-C

#67
post #18

Earlier quoted context omitted.

There's ConciseKit for precisely this problem: https://github.com/petejkim/ConciseKit We use it in a lot of our code here. Its quite nice. You'll end up with something like: myDict = $mdict(val, key, val2, key2);

And the values and keys are still backwards.

  #define KV(KEY,VALUE)   VALUE, KEY

  myDict = MD(KV(key,val), KV(key2,val2));
Ugly but a case can be made that this end justifies the means.

Another option is implementing your own dictionaryWithObjectsAndKeys where you flip the varargs and feed them back into the subclass dictionaryWithObjectsAndKeys.

Re: In defence of Objective-C

#68
post #65
post #20

Earlier quoted context omitted.

Can't get rid of the issue completely, but at least we can have: #define MD(val, key, vals...) [NSMutableDictionary dictionaryWithObjectsAndKeys:val, key, ## vals , nil] then do: NSMutableDictionary* dict = MD(@"value1", @"key1", @"value2", @"key2") And so on. Courtesy of http://news.ycombinator.com/item?id=1789839 .

That ## vals syntax is new to me. What's the difference with the following? #define MD(...) [NSMutableDictionary dictionaryWithObjectsAndKeys:__VA_ARGS__, nil]

Both of them wouldn't work for MD() due to the trailing nil.

But for MD(val, key, vals...), it'd give you a slightly better error, complaining about the number of arguments when you do MD().

Otherwise they are the same in this case.

## removes one non-whitespace character – often the comma – before the ## if vals or __VA_ARGS__ is empty.

e.g

  #define MO_LogDebug(fmt, ...) NSLog((@"DEBUG " fmt), ##__VA_ARGS__)

  MO_LogDebug(@"This works as expected %d", resultCode);

  // Removes the comma automatically in here:
  // NSLog((@"DEBUG " @"This works too without args"), );
  MO_LogDebug(@"This works too without args");

Re: In defence of Objective-C

#69
I don't think these are the real problems with Objective-C.

To quickly address this issues, before discussing the real problems: "Ugly" - get over it, "Verbose" - get over it, "Memory Management" - Obj-C memory management is in fact super simple as long as you follow some really simple rules, especially with ARC.

Now the real problems I have:

1. Lots of unnecessary code. With the old runtime, you had to modify your code at four (!) places to introduce a new property in a class. With the new runtime, that has decreased to three, with ARC, to only 2, but that's still one more than what should really be necessary (@synthetize should go).

2. The whole header file thing. I know that Obj-C is a descendant and strict superset of C but I still find separating header files from .m files somewhat tedious and unnecessary. This leads to

3. Having to declare methods and properties before you use them. I mean, this is 2011, this shouldn't be necessary.

4. The syntax for having "private" methods and properties is awkward even by Obj-C standards. Basically you have to create an anonymous category in the implementation file.

5. Properties (with ARC) should default to strong for objects, assign for everything else.

6. The [[X alloc] init] way to construct objects; I understand that from a theoretical point of view it's cool to separate allocation from initialisation but I've never ever needed to allocate an object with anything other than the alloc message.

7. The debugger. GDB and Xcode are atrocious. Have a look at the C# debugger in Visual Studio; that's how a debugger should look like.

Overall, while a lot has been improved recently in Obj-C, my main gripes with the language all come from the facts that it's a C superset (which is also a massive advantage) and that it's an almost 30 years old language; the programming world was very different 30 years ago.

Re: In defence of Objective-C

#70
Looking at the example given of how lovely obj-c is:

   filteredArray = [allRecords filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"someField == %d", someFieldFilterValue]];
Makes me wonder if the author has ever seen languages that do this like so:

   let filteredArray = Seq.filter (fun f -> f = "foo") allRecords
Post reply on HN