5 ms·
The problem is that closures don't usually refer to mutable entities, and most functional programmers are used to an immutable language. The idea that a closure
by hellofunk 11y ago
The problem is that closures don't usually refer to mutable entities, and most functional programmers are used to an immutable language. The idea that a closure itself is mutated (its return value can change) just because something outside and separate of it mutated goes against the very heart of functional programming, and is not how functional languages behave at all.
- john_butts 11y agoThis gets back to the point that Swift is not a functional language. By default, the closure is capturing an immutable reference - the fact that the value might change is implicit to the way you must think about programming in a non-functional language. The mechanism to capture a constant value is to declare it in in a capture list: var f = {[i] in print("hello I'm a callback and i =", i)}
- rdtsc 11y ago> By default, the closure is capturing an immutable reference I think some imperative languages still refer to those things as closures, which is unfortunate. Capturing a closure then having everything in there mutable kind of defeats the purpose in my opinion. But maybe I've been damaged/spoiled by functional programming and/or have spent to much time debugging issues related to concurrency and shared mutable state.
- qwertyuiop924 11y agoWait, What? Immutable closures are way less useful than mutable closures. Immutable closures can pretty much only be used to create thunks. Mutable closures are basically objects. On the other hand, if your closure depends on global mutable state, than you have a piece of GLOBAL state that is VARIABLE. Sometimes known as the root of all evil. But maybe I've been damaged/spoiled by scheme and/or not done enough concurrency programming to get your point.
- hellofunk 11y agoAnytime I see someone claim that immutability is "less useful" than mutability, I know that the individual has not spent a long time working in an immutable language. Because things are tremendously easier when mutation rarely enters the picture. But, it can take some experience to grasp this.
- DrJokepu 11y agoMeh, depends on the situation. Some problems are easily solved in a functional way, some problems aren't, and then there are problems that are best solved using a mixed approach. Sometimes a good old-fashioned for loop (or the equivalent) and stateful I/O is "tremendously easier" to work with than layers of tail recursion and I/O monads. Professional developers are expected to know which tool to use when, rather than religiously sticking to one approach in all circumstances.
- hellofunk 11y agoI have yet to encounter any problem that would be better served with an imperative for loop or nested for loop than an immutable list comprehension in Clojure, for instance.
- coldtea 11y agoDo you have actual science (comparative studies --plural, not some single paper--, etc) behind the assertion of "better" for the functional approach or is it just blind faith? An empirical observation says that the most important software in the world, including most of the internet infrastructure, OSes, databases, filesystems, office suites, embedded systems and such, powering 99% of the modern era is written in an imperative or OO language. That's a fact. Whereas "there would be less issues if we had made them in a functional language" is mere conjecture, unless proven otherwise. Note that common errors such as null pointer exceptions are not only avoided in functional languages for example, but in any imperative language with optionals, bounds checking etc too. So if one is gonna bring those up as something in favor of functional programming they're not giving the full picture.
- DrJokepu 11y agoCocoa and Cocoa Touch were designed with imperative programming in mind though, so this is what the creators of Swift had to work with. I think the main use case for mutable captured values is mutable self, in particular the following, extremely common pattern: dispatch_async(my_background_queue) { do_some_io() let result = do_expensive_computation() dispatch_async(dispatch_get_main_queue()) { self.value = result update_ui() } }