3 ms·
Imagine if functions were polymorphic over the ability to pass in a function as an argument. So both f(1) and f(() => 1) would be valid for a function that take
by charcircuit 3y ago
Imagine if functions were polymorphic over the ability to pass in a function as an argument. So both f(1) and f(() => 1) would be valid for a function that takes a number. It would also apply to variables and such too. So "const a = () => 1; const b = a + a;" would be possible to do.
- rezonant 3y agoThis is a good explanation. So effectively it's making the lazy/eager distinction controlled by the caller and not the callee.
- Izkata 3y agoAhh k. So like Rebol and Red have worked for decades: >> F: func [A][print type? :A print join "Arg: " A] >> F "Foo" string Arg: Foo >> F func [][return "Bar"] function Arg: Bar I really got spoiled learning Rebol as my first language, I'd already internalized a ton of concepts long before they were introduced during school and college. Higher-order functions were the first time I really realized it, I guess here's another to add to the pile. Even knowing this though, that post really is really obtuse. Definitely could have been better written. Basically in these languages, functions don't have a special syntax to be called, like F(), they just get called when used. So usage of a no-argument function is identical to a variable, and what happens depends on its datatype (function, string, whatever). The special :A syntax is to get the value without evaluating it if it is a function.
- vidarh 3y agoThat's already the case for any dynamic languages, and it's just down to whether you write your code to be flexible about inputs. E.g def int(i) = i.respond_to(:call) ? i.call : i.to_i def f(i) = int(i) * 2 f in this case can take both ints and lambdas or anything call-able. In practice we'd usually do this via any of the normal conversion methods like expecting the caller to support to_i etc., and bear the complexity for us as needed unless there's a really compelling reason to think the caller will often want to defer the evaluation past the call site and into the method itself. That's usually very obvious when you come across it, like e.g. if the argument is expected to come from a remote source, but as long as the API for how the method uses the value is clear, substituting the value for a deferred calculation is easy.