5 ms·
This 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
by john_butts 11y ago
This 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.
- qwertyuiop924 11y agoI've never met a problem where tailcalls were more awkward than loops. But then, scheme kind of pushes you toward tail-calls, so hey.
- qwertyuiop924 11y agohellofunk: Reasoning is easier in functional languages, so fair enough.
- fleitz 11y agoI think swift really found the sweet spot in this regard by not thinking about mutability but value/reference semantics. I've found that in swift the things that should be values are and the things that should be references are, rather than taking an all or nothing approach.
- 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() } }