Hacker News new | past | comments | ask | show | jobs | submit login
Building OS X Apps with JavaScript (tylergaw.com)
166 points by snyp on Sept 28, 2014 | hide | past | favorite | 60 comments

That pipe is a C bitwise OR operator. I’m not gonna pretend to know what that means.

I'm honestly not being sarcastic, but I think there's something interesting about reading an enjoyable programming article by someone who doesn't know what bitwise OR is. It sorta feels like a huge reminder we've moved on to a whole new generation/level of abstraction where competent developers no longer need to understand binary.

I gave a talk the other day about the future of code (think 2024 and on) and one of the biggest things out of my research was that we'll eventually not need to think about intermediate data structures in code anymore as AI profilers, VMs, compilers, etc. will be able to optimize and profile almost everything away with developers working more with specifications and constraints. I wonder if in 10 years' time a programmer not knowing what a linked list or a binary tree is will not be considered unusual either.

>where competent developers no longer need to understand binary

Experts master their dependancies. All software depends on binary representation. All expert programmers need to understand binary.

Of course, you said "competent" and yes, you can get things done without knowing binary. Although it pains me to think that it can't be understood or explained simply! Bitwise or is so foundational to many techniques, like efficient storing flags, security, and so much more.

BTW a 'bitwise or operator' loops through the digits of a binary representation of both operands, or's the binary digits, and outputs the result. That one little operator has elements of a transform, a for-each (or a map(), if you like), and a logical operator, all in one! It's powerful and cheap to compute, and programmers and others, would do well to learn what it does. One practical, everyday use: numeric arguments to chmod (e.g. chmod 712 myfile.txt)! The reason why the modes are assigned to powers of two then added is so that they can be recovered from a bitfield using...bitwise or.

haha, knew I was gonna get called out on that one! That is super interesting and spot on in my case. Would love to see your talk.

When I got to that part of the article I stared researching bitwise operators to try and give a short explanation. I couldn't sum it up well in the voice I wanted to. So I decided to just say, "I don't know, and that's OK." I try to write in a way that's accessible to people that are maybe newer at programming. Maybe without a CS background, like me. With this, I felt like there would likely be so many new concepts, that it would help to leave one out that wasn't essential to building the example.

For my next post I should research and write about bitwise operators.

I also do not know what a linked list or binary tree is, but I'll certainly take the time to learn about them in the future.

Thanks for reading it and commenting.

I've already written a response to you elsewhere on this, but wanted to add here that I don't think writing about bitwise operators here would have made much sense. What struck me though was how you didn't just hand wave through it, but actually admitted you weren't au fait with them. I think this actually makes the content more accessible and could encourage readers to go and learn for themselves, never a bad thing!

This is an interesting thing that has cropped up in interviews with my company. The company is mostly made of C++ guys (lots of game and sim dev), but we have recently started on some web projects and we seem to have no idea how to evaluate interviewees.

Personally, I am a recent grad (last May), but have focused on web dev in my free time. However, having gone through formal CS I do know a good bit about the low level data structures and bitwise operations. Some of the interviewees have been developing for over a decade and can't say what a linked list is, let alone contrast it with vector or an array.

It is all, anecdotal, but we've seen a fair amount of correlation between ability to solve simple problems (writing simple functions with no expectation of optimization) and knowledge of these entry level CS topics. So as much as I feel like we are testing for the wrong things when we ask about simple bitwise operations or linked lists when interviewing for front-end JS guys, it has still been a good test for us.

All of that being said, this post is definitely well written and interesting. It is odd to me that an author who seems interested in learning and trying something new would so actively choose not to know what the code he's writing (and telling the reader to write) is doing.

I wrote the post. I'll speak to that last part. I commented elsewhere in the thread about this too. I included the part about not knowing for two reasons.

1) I couldn't figure out a way to write an explanation of the bitwise OR operator that was terse enough to not derail the main topic of the article while still making sense. The post isn't a tutorial about bitwise operators, it's about building JS OSX apps. It's a long post, with a lot of concepts. I didn't want to add two or three more paragraphs to explain something that was non-essential to the task at hand.

2) I wanted to show vulnerability in myself. I could have left out the two sentences in question, they were also non-essential to the main topic. But, I knew this post was going to garner attention. I wanted to show–by example–that it’s OK to not know things and to say, "I don't know."

I didn't foresee this much discussion about it, but I think it's good. Look at all the great information about bitwise operators in this thread. There's also a good explanation in the comments on the post. Those comments would not have been made if I chose to leave those two sentences out.

Thanks for reading the post and commenting.

> I didn't foresee this much discussion about it, but I think it's good.

Your comment about not knowing bitwise OR was fine.

I looked at your blog and could easily see that your background is designer (HTML+CSS) and then programmer (Javascript, Ruby, etc). If anyone reasonable keeps this in mind, they would actually be surprised if you did know what bitwise OR was because a developer who built knowledge in that sequence wouldn't need to come across it.

There are large swaths of programming communities that don't come across the bitwise OR topic. This includes ERP (Enterprise Resource Planning) programmers such as SAP, PeopleSoft. Linux/Windows admins writing bash or Powershell scripts. The office power user writing Visual Basic macros for Excel spreadsheets. And of course, many web developers. All these folks are productive doing "programming" and yet they get by without bitwise OR.

When a programmer is surprised at why developers of <insert_whatever_technology> doesn't know <insert_whatever_knowledge_he_happens_to_know>, it's often because he forgets that others interface with programming tasks quite differently from him.

A typical type of programmer that would know bitwise OR is a C/C++/assembly programmer. But even within this group, there would be knowledge that one C programmer would be "surprised" that another C programmer doesn't know. For example, a C programmer might not know the intricacies of the Link process. Well if that C programmer was a university student that only used the C language to write 500 line programs to calculate matrices for his science experiments, he may not know the subtleties of the Compile & Link. To him, it's all just a black box to spit out an executable file. When he needs to know what "can't resolve symbol" error means, he'll learn what the LINK in COMPILE+LINK actually does.

I saw your other comment, and I'm glad to see your comments line up with my general feeling of your voice and attitude in your post. The only reason I make any comments on it is because the general attitude of learning and experimenting was great and that one part just seemed like a sudden break from it.

I agree that a real explanation would have been out of scope and probably even more odd. My only suggestion (not that it is really better or you want it :) ) is to to pay it lip service with something like, "The syntax is odd, but it is just specifying options with a bitwise OR" With the "bitwise OR" as a link to documentation for the cocoa options or some article explaining bitwise operations.

Most importantly, it was a good article and I'm going to do a little bit of research for myself on writing these simple OSX apps with JS. First thing is to figure out just what is required for these applications and try to decouple it away from that script editor.

I wanted to show–by example–that it’s OK to not know things and to say, "I don't know."

And I really appreciated that. I think far too many people (including myself, at times) give the impression they know more than they do and I see how intimidating it can be for beginners to think everyone fully groks X, Y and Z and is way ahead of them when the real picture might be quite different.

There was a lot more of this sort of honesty back in the earlier days of programming blogs, but then all the "you've blogged something totally obvious!!" assholes turned up. I hope we can get back to people just writing and sharing what they want without people assuming admitting ignorance or not being a 100% expert in a field makes one unsuitable to write about that field.

> Some of the interviewees have been developing for over a decade and can't say what a linked list is, let alone contrast it with vector or an array.

Jaw dropping. Some degree of this is acceptable - e.g. I wouldn't really expect a front-end dev to know browser-native DOM manipulation, because everyone uses some sort of shim (particularly jQuery), and modern-modern frameworks abstract away DOM manipulation entirely (think React). But that's a high-level API trade-off, rather than a foundational issue. OTOH it's far more serious when a dev doesn't know about Array.forEach and insists on using $.each for iteration, showing an inability to distinguish between native JS and jQuery.

Part of the problem with JS and data structures in particular is that, AFAIK, there is not even a de facto collections standard. Google's Closure structs[1] might come the closest, but generally brings a lot of baggage. js_cols[2] is pretty good. And then you have what I would consider "fringe" solutions like mori[3]. The bottom line is that even an autodidactic developer starting off in JavaScript land is going to have a much harder time learning about basic data structures than if they started off in Java land, which, while it has it's warts, does have a wonderful standard library for collections[4].

[1] http://docs.closure-library.googlecode.com/git/namespace_goo...

[2] https://code.google.com/p/jscols/

[3] https://github.com/swannodette/mori

[4] http://docs.oracle.com/javase/tutorial/collections/index.htm...

A couple links for those who, like me, want to learn more about bitwise operators:

http://www.cprogramming.com/tutorial/bitwise_operators.html (A decent intro to the concept of bitwise operators and what you might use them for.)

https://developer.mozilla.org/en/docs/Web/JavaScript/Referen... (Their use in JS.)

And Peter: I'd love to watch that talk! Was it recorded? A quick search for "peter cooper future of code" brought up some references, but no videos (at least not yet).

I've been a programmer for 15 years (web dev, self-taught) and I don't know what those are. I think a linked list is like a JSON object, right?

Yes, I am a real developer but the technologies I use don't have those paradigms. I doubt it this is good or bad, just different.

Linked lists are another way of getting a lot of the functionality of arrays. While arrays are like a box of ordered things, linked lists are like a chain.

Here's a model of a linked list. We start with an empty list represented by an empty array.

In normal arrays we'd add a number by putting it into the array, like [1], but we'll do something a little weirder:

    [1, []]
we build a new array which contains one value and the empty array. We add new elements in the same way

    [1, []]
    [2, [1, []]]
    [3, [2, [1, []]]]
The final one there is a bit like the array [3,2,1], but seems to have a lot more ceremony. In any case, the values above model linked lists.

Why would you use such a thing?

Well, when you want to push a new value on to an array you may find (internally) that the array you have so far is too small. To fix this, you build a new, larger array and move all of the old elements to the new array plus the one new thing you've added. This can be expensive.

With linked lists, adding a new element is always the exact same process. It is in this way faster and simpler.

Of course, the downside of linked lists is that there is more overhead to, say, read the 10th element. In an array you can just do a[10], but in an linked list you must do a[0][0][0][0][0][0][0][0][0][1]. Obviously this involves much greater overhead.

Linked lists are closely related to infinite streams, however. Sometimes they better model what you actually want to talk about—the idea of having a value "now" and some more values "in the future". They also are much more naturally implemented immutably and have a much more natural sense of a fold or reduction.

So, as with all data structures, there's a tradeoff.

> the technologies I use don't have those paradigms.

Your language most certainly has a syntax for bitwise operators. If you want to optimize (speed up) your code, knowledge like that would help you.

Node/Javascript: https://developer.mozilla.org/en/docs/Web/JavaScript/Referen...

PHP: http://php.net/manual/en/language.operators.bitwise.php

Python: https://wiki.python.org/moin/BitwiseOperators

Ruby: http://calleerlandsson.com/2014/02/06/rubys-bitwise-operator...

Visual Basic: http://msdn.microsoft.com/en-us/library/wz3k228a.aspx

A linked list is a kind of (abstract) data structure (http://en.wikipedia.org/wiki/Linked_list). If you come in touch with a static typed language (C, C++, C#, Java) such knowledge is essential. In languages like JavaScript and PHP you usually just use an object or an array. You can think of an linked list as an array of objects.

Most of the optimizing I do has to do with DOM manipulation and replacing slow generic library functions with native and/or custom-written ones. I've got a lot of low-hanging fruit to pick before I get to things like bitwise operators. Most optimizations I've seen are very language-specific and it can be hard to guess what is faster. Which is why profiling and a tool like http://jsperf.com/ are critical.

By the way, from what I've read bitwise operators aren't very efficient in JavaScript because of the overhead of conversion from generic duck-typing to binary.

You probably already know this, but your last sentence also has one minor advantage, in that you can use an otherwise pointless bitwise operation to strip off decimals, e.g. 100.919 | 0 .. => 100

I actually fond the most efficient solution to a problem recently (generating massive numbers of DNA sequence combinations, and checking for the number of mismatches between them) came from using MySQL and bitwsie operators. I tried Python, it was at least an order of magnitude slower. I tried Java, but that ran out of memory surprisingly quickly. I might try it in C at some stage but that will involve a fair bit more time.

A linked list is an actual data structure, whereas JSON is just a format for storing data. The computer actually has to lay the json out in memory somehow.

JSONs have keys that are strings so a hashmap or hashtable is probably more likely.



A linked list is a tool for making sure that your data is never in the cache when you want it to be that a lot of developers fetishize because lisp and because they're so easy to implement that every CS curriculum will make you implement one at some point. Just use (dynamically growable) arrays, like, almost always, or heaps or binary trees in special circumstances.

Okay, now that I've got that out of my system, I'll try to contribute something positive. Linked lists are useful to understand because they're very similar to, but less complex than, a common representation of trees and graphs. In a tree or graph, each node can have several children instead of just one.

There are also some special algorithms that make use of the ability to grow or shrink a linked list in the middle without copying the whole tail [1]. The thing that makes this more rarely useful than you might think is that random access to the middle is O(n), so you have to be moving around in order adding/deleting things.

[1] Dancing Links: http://en.m.wikipedia.org/wiki/Dancing_Links

Note, this is actually a circular, doubly linked list.

Imagine an object:

    { data: stuff,
      next: more_stuff }
`next` is a reference to the next object like this one in the list, and `data` is a reference to the actual object at this point in the list.

You've now got a close-enough idea about what a linked-list is.

You can also have dual-linked lists, where each object also has a `previous` pointer to the previous object in the list.

If you want, you could store the data directly in this object, rather than having a pointer out to the actual data (of course).

This kind of thing can be very useful for certain kinds of data manipulation, where the built-in lists aren't efficient enough - for whatever reason. Say the language you're using creates an entirely new list whenever you try to remove an element from the middle of a list - or when you need to be moving / removing elements all over the place.

The big downside of such a linked list is that you can't easily jump to a specific item number in the list. So jumping to item 200 means walking through the first 199 elements in the list to find it.

I've only had to implement a linked list once in a JS project, I don't remember the reason why. I think the algorithm just worked a lot more efficiently that way.

One reason a linked list could be useful in a javascript (or PHP, or whatever) language would be, for instance, if you had a game where when a player hit a block with a hammer, that block would bounce up and down, as would the two blocks on either side. If you store all the blocks in a regular list, then you need to know the index of the block in order to find the blocks on either side. In a linked list, you don't.

One of the original big advantages of linked lists is that you can have objects of variable size, and the list can grow and shrink without adjusting any of the previous elements. Opposed to this is an `array` (sometimes called a vector) which is a fixed size chunk of memory which is split up into identical sized parts. You can then jump to element 200 by looking at the starting position + 200 * the size of a single element.

This works pretty well, but if you want to add another 20 elements into the middle of the array, you need to allocate a new chunk of memory and move the whole lot into it, and deallocate the previous entire array. This is one of the reasons why strings are usually immutable in many languages. Strings are stored as arrays, not linked lists of letters.

I think it's worth learning about all this "Computer Science" stuff, even if you don't need it very often, as it means when you come across a new problem you have a much bigger mental toolkit from which to figure it out.

A better reason why linked lists are better than arrays is that they have obvious, fast immutable APIs. Immutable data is not always a win, but sometimes it is.

Could you recommend any good books about that for a web developer?

Probably not, you can have a career never using linked lists . The problem is that it's such a fundamental CS concept it's going to be hard to pass interviews without that knowledge if you were starting from a junior position.

To me it's not a paradigm. It's how data is stored and represented in memory. Where such issues become problems in larger projects is when you have a lead that doesn't know what B-trees are and they need to optimize database access. Or that person is loud and influential and derails every technical conversation because it's way over their head.

You know, I understand the urge, once one has really gotten deep and mastered their first language, to try to apply it everywhere. But I really must strongly encourage the kids on the come-up to continue mastering new tools. It's not that javascript is a bad language (although that helps), so much as the industry doesn't allow any of us to rest on our laurels. This year's rock star is tomorrow's dinosaur.

You are looking at a wrong problem. This isn't one language beginners as much as it is a desire not to write code twice for two platforms. Even cheap software developers are expensive, so it make sense to not make them do the same work twice.

Great. Now master Java, C#, and Objective-C to build the same app on multiple platforms. JavaScript is the only language that let's you target every platform.

> JavaScript is the only language that let's you target every platform

Ironically, the three languages you listed - Java, C#, and Objective-C are all available on all major platforms. I could write code in any of those languages and have it run on

  - Windows
  - MacOS
  - Linux
  - Android
  - iOS
Furthermore, the apps would all be native. That closest Javascript can come is to use the uncanny-valley of HTML5 without native widgets or performance.

Frankly, Given that the burden of learning a new language is tiny, I see no reason why we should try and cram Javascript into every nook and cranny. It's a fairly mediocre language at best.

tl;dr The three languages you listed are all capable of better cross platform support than Javascript.

Really? Seems like HTML/JS is the best choice for cross platform application development. These days with Chrome, Firefox and even Safari you can create really full featured applications. The new HTML5 API's are incredibly full featured. Just the other day I created an App for my daughter to helper her login to her school computers - so I decided to create a login screen and then I realized with HTML5 audio API, I can also read aloud each key press as well as an intro text so even though she can't read yet she can use the App. It's 100% JS and HTML/CSS for UI.

At my job we spend thousands of hours building our native App for Android and IOS for work and it's painful - when I can open the browser and nearly all the capabilities are in browser and the browser already cleanly abstracts the process of editing UI via HTML/CSS. I've yet to find another UI framework as powerful or quick to develop in as HTML/CSS - and the performance is looking really good in the browser. Native app performance is a myth unless maybe you're writing a video game?

> I've yet to find another UI framework as powerful or quick to develop in as HTML/CSS - and the performance is looking really good in the browser.

Really? Until a couple of months ago with the advent of flexbox, you couldn't reliably do columns that fit dynamically to the browser window (frameworks like Bootstrap simply define three different window sizes and switch between them, rather than allowing for fluid resizing) as well as you can in every other UI framework I've used, never mind vertical layout. (See all the hacks for "sticky footers" over the past decade.)

"Quick" - sure. HTML5 lets you spin up UIs fairly quickly.

"Powerful" - I'm not so sure. Generally I find native toolkits, while requiring a bit more effort up front, generally yield much nicer user experiences.

It may not be powerful, but it is quick to develop in.

If all you know is web related stuff.

For simple apps, HTML5 works fairly well. But you quickly run into problems.

My company has been working on a cross mobile application in HTML5 using Cordova. It was quick to prototype, but as we scaled up we started hitting the limitations of the platform very quickly.

The main issue is that every single mobile device has a slightly different rendering engine. Even two different Android phones from the same manufacturer will behave slightly differently. If you're making a simple CRUD app, this probably won't affect you - but once you reach a moderate level of complexity you spend more time playing whackamole fixing bugs and testing on every possible combination of devices.

We're currently rewriting as pure native across all platforms, since it works out to be less effort in the long run.

This is on top of the obvious limitations of HTML5 - Performance is never quite there for anything other than trivial tech demos, and the lack of native widgets mean your users will have that "uncanny valley" experience where it doesn't quite feel right.

tl;dr HTML5 is ok for prototyping and simple apps, but doesn't scale well. Ditto for Javascript.

Actually, JavaScript can create native controls and calls on all of those platforms through an API layer, using a framework such as Titanium. JavaScript has not been limited to webviews for at least 5 years now.

Many Gnome (Linux) apps original language is JavaScript (GJS). iOS 7 came with a JS API. It is such a powerful language for async and UI design that it adapts well to all these platforms.

Can you write Java applications for Windows Phone 8? (without buying a third party software which allows you to do so)

Yes. Java can be compiled to native machine code via GCJ, and can expose a normal C++ Api.

Whether you'd want to do this or not is another story. C# and Xamarin would be a far better choice for a one-size-fits-all cross platform codebase.

No, but you can in C and C++.

Not only that, certain APIs are only available if you use them.

The overhead of learning a new language is pretty small. The overhead of learning a new framework is much bigger.

Well, C and C++ come to mind.

The really cool thing about this is that you can also use alternative languages which compile to Javascript. I develop Cursive, an IDE for Clojure and Clojurescript, and one of my users has a native app written in Clojurescript published on the App Store. He had to jump through a few hoops to get the REPL working but once he got it going he could edit code on his device live. It's really cool to see. I'm hoping to add debugging support using the Webkit Remote Debugging Protocol, which will make it even nicer.

Yes, this is what I'm excited about.

You can write Go code and compile it to JavaScript. You could create bindings for Cocoa APIs in Go.

"…one of my users" Do you have users? What part of your body do they use?

Do you need a certain number of points to downvote pedantic dickheads like this?


Will Apple allow apps written with this to be distribued on the Mac App Store?

I don't see why they wouldn't, but I couldn't find a confirmation either way.

I haven't seen anything official, but I think you can. Mavericks introduced Code Signing for applets http://macosxautomation.com/mavericks/codesign/02.html so you can at the very least distribute JS Apps. The first time someone tries to push one up to the app store for review will be interesting.

What's great about this isn't just that you can do it with JavaScript, which is much easier than ObjC, and probably also easier than Swift.

It's that it's also essentially natively supported. Having futzed with PyQt and PyObjC to build a medium-sized desktop application, I never want to go back to dealing with bridges to low-level libraries again. But this looks much more manageable.

Reading this code makes me think I just might write an OSX app again some day. And if CoffeeScript can compile down to it - no idea why it couldn't - even better.

Why is this easier than ObjC or Swift? I'm a huge JS fan, and I'd still choose those two over this. The API is still very much Cocoa, and now in JS form it's even more tedious. Not sure how you'd truly debug an app written this way, and not to mention almost all docs, examples, blog posts, etc that you ever find will be based on ObjC and Swift.

"Easy" and "hard" are always relative terms. If someone doesn't already know ObjC or Swift, they may be considered harder for that person. Not necessarily harder in absolute terms. But I'll take that as a serious recommendation!

ObjC is a very small, simple language. The hard part is Cocoa. The JavaScript bindings don't address the hard part at all.

> ObjC is a very small, simple language

Objective-C is a small language only if you already know C. Otherwise you will have to learn C first.

But C combines the power of assembly language with the ease of use of assembly language!

Or to quote Bill Joy, "C is really just peek and poke with some syntactic sugar".

I'd learn Swift and use it for something non-trivial before saying something like that. I haven't yet, but what I've seen makes it look pretty good, with a whole lot less bullshit and bad design decisions to constantly keep in mind (I'm looking at you, "this")!

What I wonder is: can this style of development be used with Interface Builder?

Yes, you can! Which is totally cool. There is a sample app written in JS that uses Xcode. They have it set up with a main.js file, they use the same ObjC.registerSubclass to create an AppDelegate. Then they have .xib for the interface. You can make the same connections from IB to the JS as you're used to.

If you have an Apple Developer account, you can download the sample project here https://developer.apple.com/wwdc/resources/sample-code It's listed under "JavaScript for Automation Cocoa Application"

It's been possible to develop AppleScript-ObjC applications using Xcode and Interface Builder for several years. I think you define properties in the AS code that Interface Builder recognises as IBOutlets to allow you to connect it all up, so I'd expect there to be a similar thing set up for the new JS stuff.

Why would you want that? You can programmatically defibe your interface with Swift/objective-C. JavaScript feels like a step backwards to me.

Because defining constraints in code is more of a faff than just doing it visually? Its also more immediate since (as far as I know) Xcode doesn't support anyform for edit and continue outside of Playgrounds.

Learning Objective-C was never the limiting factor for me writing native OS X code. The hard part about it was always figuring out the APIs. It's one of those things where if you have someone to teach you it's great, but learning on your own is time consuming and tedious and frustrating.

As much as I like using JS for scripting purposes in the OS, I feel like with this, I have the same problem: namely that the cocoa APIs are massive and I have trouble understanding what's going on, even after trying to learn them three or four times in the past decade.


Applications are open for YC Winter 2022

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact