144 karma · joined February 11, 2015
I also prefer using a native editor and am more productive with spell checking and auto correction, surprisingly.
edit: I'm also not a user that uses the keyboard all the time. After using Komet, I am surprised how often I actually used the mouse to hit commit instead.
lldb ~/Desktop/ruby
:-)
The main concern I have is the inconsistency that this command does not request a password while the keychain access app, as far as I know, does request one.
Apple has been aware about their security behavior here at any rate.
(I really don't know if that many apps do this btw, I think most apps I download today are packaged in zip..)
Other users are just baffled and run apps from disk images or Downloads just because.
The authors point is that at least before 10.12 zip was a decent approach.
Too bad they aren't offering signed zip or something similar that takes same advantages that a signed dmg does..
The author's concern is that they (and many other developers) ship apps in zips, have many users download them, and run them from ~/Downloads/ or wherever their browser downloaded the app to. Only in 10.12, this practice will prevent most 3rd party apps from being able to update themselves.
The author wants an info.plist key (plus perhaps app signing) to opt-out of translocation and say that they are competent enough. Before thinking that this "defeats" the point, people may miss that Apple is fine with opting out provided you code sign and package a dmg.
The author and many others also don't like dmgs, however, and find that they confuse many users. What the author is concerned about does indeed affect a lot of apps.
Recently, I've been using a tool to show the dependency graph of my program and I've found it to be quite helpful. Perhaps a bigger point is to find and use tools for your environment that really help!
I like others also favor minimizing changing global state, unit testing (increases odds your code's interface is more well designed), code reviews..
Some developers that distribute their app in dmg's try to nudge the user to move the application for them into /Applications, but that's kind of hostile, and developers shouldn't have to go out of their way to do that.
Before 10.12 at least, developers were generally okay with the updater not running on read-only media - this is more intended behavior rather than being 'broken'.
Anyway, just pointing out the real concern from the article.
Apple wants developers to use dmgs (and signed ones particularly) but updaters don't have an easy time with apps being launched from those either, and people don't think dmgs provide a good user experience as well.
Perhaps Edge will a nice competitive impact on the Windows side :P.
At work I deal with Java code, but we have a framework we wanted to use that's written in Scala, and since Scala can interop with Java, we were all productively able to transition over for the better.
For a hobby project we use Objective-C, but we are starting to write some bits in Swift. Apple is especially effective at trying to convince the developers to change over to this shiny language.
I think "advanced" languages can be used in real world applications, and the transition experience from other well known languages can certainly matter.
My own reality is I used a "ergonomic" labeled keyboard that I felt caused me more discomfort.
Of course there are convenience trade offs somewhere and laptops to me fall under convenience.
Some notes based on my own experience:
* If you can touch type very well in Qwerty already, you may have a much easier time picking up a layout than the average typist. And you may have an easier time retaining more than one layout.
* What you're typing (context) is important with regards to adjusting to a layout. For example, if you learn Colemak and decide to try using the Terminal some time after you've become proficient, you might find it awkward - at first. I personally haven't found the type of physical keyboard you use to matter much with regards to this..
* When I was at the state where I could type in both layouts very poorly (due to muscle memory being confused), I realized I took many things for granted that eliminate needing to type quickly altogether like auto-suggestion/completion - and a lot about software development is about automating tasks.
* When I started to become proficient at Colemak and started to lose my proficiency at Qwerty, I developed a justification and bias that Colemak is way more comfortable for my daily usage.
* The most effort I ever put into typing was ironically typing tests, not programming =P. And those can be really tiring if you do them frequently regardless of layout.
Maybe I find these days that colemak is marginally more comfortable. Maybe I just don't type that much though, although I use the computer a lot. Software developers certainly don't type nearly as much as a "typist job" (if those still exist) in any case. If I lose my ability to type in Colemak, I don't think it will effect me that much. All in all, I can't say my transition was worth my time.
Besides, people also use laptops and may not want to swap their keyboard.
* Static typing is good.
* As I expected, the standard library and other packages available had the http & routing stuff I needed, which is all good.
* I like that errors are specified in function signatures, unlike exceptions in languages like ruby/python.
* I don't like errors being easily ignored, and return values being assigned default or arbitrary values. I once may have also accidentally used the wrong equality operator against nil.
* Defer is nice, but would be better if it was based on current {} scope.
* Append on arrays? has very bizarre semantics sometimes mutating or returning a different reference.
* Initially I ran into trouble reasoning how to use some sql package and ran into "invalid memory" deference issues or some such when passing a reference. Thus, I'm skeptical about "memory safety."
This was only a simple program though and turned out to be worthwhile for me in the end.
Garbage collection is a controversial topic too, and if I understand correctly, a part of the reason Lua has a stack based API (with how its GC works). I somewhat liked the level of control I had with reference counting from working with CPython. Some applications may even go out of their way to disable the GC and use weak references to guarantee determinism similar to Apple's ARC. Squirrel, born as a competitor to Lua, looks to use a GC approach similar to Python at a glance..
Threading and reference counting may be some ugly aspects of embedding CPython sure, although I don't think manipulating the stack in Lua is that praiseworthy either.
It's not really specific to Python, so "poorly documented" isn't a surprise.
Python bundles a bunch of modules one may not need for embedding in either case, and they can be turned into byte code before distribution.
I had compiled python myself and used static linking instead of dealing with install_name_tool, although I do wonder if I should have built a dynamic library instead. Anyway, compiling from source (or adjusting the homebrew formula?) gives you control and being mindful of eg: LC_VERSION_MIN_MACOSX as already mentioned here.
For my specific use case, I also wanted to use Apple's GCD and have Python do all of its work on a secondary thread. I had to make sure the interpreter would only stay on a single thread (whereas GCD normally doesn't make such a guarantee).
Which is kind of why I wish for tooling outside the compiler to make the effort in specifying types (when it increases readability, maybe based on heuristics) very minimal. Wishful thinking.
I often wish I was using a text editor or IDE that understood my code and could insert type annotations for me, maybe automatically, and maybe not choose to do so if the line of code would "look" more redundant (i.e: parsing variable name or constructor/initializer).
Rust is one language that, while has the capability of doing full type inference, deliberately chose not to (https://doc.rust-lang.org/book/functions.html):
> This is a deliberate design decision. While full-program inference is possible, languages which have it, like Haskell, often suggest that documenting your types explicitly is a best-practice. We agree that forcing functions to declare types while allowing for inference inside of function bodies is a wonderful sweet spot between full inference and no inference
I think deciding what to allow and prohibit by default is an important design decision.
But I'm glad it's just for initializers.
After playing with Scala, I've found out I don't love type inference as much as I thought I did. In Scala, the compiler can infer return types of named procedures for example, but I've always found omitting these makes my code harder to read, having to read the body (an implementation detail) to see what it may be returning. It would be even worse if types were optional for parameters (ala Haskell). Other modern languages (ala Rust) have come to realization that this is a bad idea.
The same even applies to having the compiler infer types from local variables to a lesser extent. A lot of my code goes through transformations and chains, and sometimes it's not obvious what the resulting type is (and what the code is doing) if the type is not specified.
Even looking at the simple example mentioned from the article in isolation:
var stream = list.stream();
I don't know what type stream is. Sure, I can make an educated guess that it's some kind of Stream, but then knowing it's a parameterized, and then knowing what kind of type it takes is even more challenging. I would have to look at the right hand side (again, an implementation detail), or may have to traverse up even further (eg: looking up how `list` is derived in this case) to figure out for sure. Or worse yet, look up documentation. Imagine if the right hand side was composed by calling a series of procedures, then you have to traverse all the way to the right to validate the type. In the end, you have a mental burden.The same issue applies with calling functions and assiging their result to a local variable you're initializing.
I'm happy to see type inference is just added for initializers. Whilst I haven't found writing 'Foo foo = new Foo()' that common in functional code, I see that being prevalent in Java at least. On the flip side though, if your language or use case (C++?) makes code harder to understand rather than easier by specifying types, then you may be wishing you had type inference :)