4 ms·
Re: function parameters, here's a concrete example. Clojure's `reduce` takes a function `f` as an argument: https://clojuredocs.org/clojure.core/reduce https:/
by sillysaurus3 9y ago
Re: 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.
- deleted 9y ago[deleted]
- Veedrac 9y agoThe type of the reduction function would just be something like (X, Y) -> (X Y) args pair The type of a reduce that has an initial seed is something like X -> ((E, X) -> X) -> [E] -> X seed reducer list result The result is going to need to be some recursively defined type, which I'll call List, type List E = E | (E (List E)) Apply these together trivially (List E) -> ((E, (List E)) -> (List E)) -> [E] -> (List E)