4 ms·
Agreed that immutability seems overrated right now. The pendulum will swing back in full force, eventually. But of course, the art is in putting mutability and
by norswap 9y ago
Agreed that immutability seems overrated right now. The pendulum will swing back in full force, eventually.
But of course, the art is in putting mutability and immutability in the right places. There are no fast rules, but in general mutability of local variables is harmless, and you probably need some mutability at the top level as well (as per: "functional core, imperative shell"). Mutability in other places can still be useful though.
I don't agree or really follow your comment on function parameters. It seems an argument against typing in general.
- panic 9y agoI think type systems derived from linear/affine/uniqueness typing will help a lot here. Mutability is fine -- it's sharing that's the problem.
- sillysaurus3 9y agoRe: function parameters, here's a concrete example. Clojure's `reduce` takes a function `f` as an argument: https://clojuredocs.org/clojure.core/reduce https://clojuredocs.org/clojure.core/reduce When you pass an empty list, `f` is called with no arguments. That way, `(reduce + [])` can return 0, whereas `(reduce * [])` can return 1. It's very easy to write such a function in Clojure, thanks to a lack of types. What would that look like in Kotlin? A function that can either take zero arguments or takes two arguments of types specified by the input list?
- Nullabillity 9y agoThe usual implementation of fold/reduce takes a separate seed argument (as does clojure, optionally!), which IMO is far more sensible than having the same function do two completely separate things depending on the number of arguments.
- deleted 9y ago[deleted]
- sillysaurus3 9y agoSure, let's roll with that. How would you write a function parameter that takes two arguments, whose type is determined by the seed argument? Also, with reduce, the return value of the function can determine what the type of the input arguments should be. For example if you pass in a `(fn (x y) (list x y))`, you end up with: > (reduce (fn (x y) (list x y)) (list "a" "b" "c" "d")) ("a" ("b" ("c" "d"))) Let's throw in a print statement to print out the `y` parameter: > (reduce (fn (x y) (print (str y)) (list x y)) (list "a" "b" "c" "d")) "d" ("c" "d") ("b" ("c" "d")) ("a" ("b" ("c" "d"))) So `y` starts out as a string, then a list of strings, then a list whose first element is a string and the second element is a list of strings, and so on. I'm not sure what the type of that function would even look like. And if there's no way to express something as simple as `reduce` without resorting to `f: (x: Any, y: Any) -> Any`, are we certain it's good design?
- wolfgang42 9y ago> How would you write a function parameter that takes two arguments, whose type is determined by the seed argument? I feel like I'm missing something here. I would think it would just be reduce<I, O>(fn:(O, I|O)=>O, seed:I): O
- sillysaurus3 9y agoHow would you call it? I'm interested in how you'd specify `I` and `O`. `I` is obviously a string, but it seems like `O` needs to be at least three different types: > (reduce (fn (x y) (list x y)) (list "a")) "a" > (reduce (fn (x y) (list x y)) (list "a" "b")) ("a" "b") > (reduce (fn (x y) (list x y)) (list "a" "b" "c")) ("a" ("b" "c"))
- lilactown 9y ago`O` would be whatever the type of the reducer is, so for `list` in the lisp you're using (is it Clojure? The function params look wrong) has a type signature `(A, B?, ...Z?) -> A | List(A, B, ...Z)`. So the transducer in this case would have the type `List(A, B?, ...Z?) -> A | List(A, B | List(B, ...etc))` It's not three different types, but it is necessarily recursive, which seems tricky.