From: "trans (Thomas Sawyer)" Date: 2012-07-01T05:27:04+09:00 Subject: [ruby-core:46015] [ruby-trunk - Feature #6594] Integrated Functor Issue #6594 has been updated by trans (Thomas Sawyer). =begin @prijutme4ty I think you last paragraph actually makes it quite clear why I make this proposal. You say that "only libraries should use methods like #send and other metaprogramming techniques". But you see meta-programming is the *only* way to implement this presently. What I am proposing is to address precisely that --a means of getting rid of having to use #send and "meta-programming". Then you say, "methods like #every can be defined in a gem". But that hits the very problem of defining any HOM, such as #every: it can't be done *efficiently* in pure Ruby. There is simply no way to do it b/c one has to create this (usually) extraneous Functor object to act as the intermediary. So #every is actually a very good example precisely b/c it is so simple. I think your callable symbol idea is a good one, but it is more limited than Functor, which is full HOM. For instance how would you handle Enumerable#accumulate (http://rdoc.info/github/rubyworks/facets/master/Enumerable#accumulate-instance_method)? This is not a method, that I created, btw. It was contributed by other developers who were using it in there own code and thought it general enough to be reusable by others. I think "user-code" is misleading b/c I'm not so sure it's the kind to thing one would generally use in say one's Rails model, for example (though I could well be wrong!). It's a tool geared more toward libraries. For instance one could use it very effectively for creating a DSL for database querying. The blog link I gave before is in the spirit of that kind of application. Nonetheless, I think I have an example that might fit your bill, albeit it's still abstract b/c I am not pulling it from existing code. Consider a case of delegation in which you want to expose an object to another class, but you only want to expose a few methods, not the entire object. class Example def thing => op, *a, &b @thing ||= Thing.new case op when :foo, :bar @thing.public_send(op, *a, &b) else raise MethodError end end end ex = Example.new ex.thing.foo You might think of other ways to handle this, but this approach is particularly concise and flexible (and low overhead!). Consider further if we also wanted to support another method, but with a fixed argument. class Example def initialize(special) @special = special end def thing => op, *a, &b @thing ||= Thing.new case op when :foo, :bar @thing.public_send(op, *a, &b) when :baz @thing.public_send(op, @special, *a, &b) else raise MethodError end end end ex = Example.new("light-bulb") ex.thing.baz =end ---------------------------------------- Feature #6594: Integrated Functor https://bugs.ruby-lang.org/issues/6594#change-27619 Author: trans (Thomas Sawyer) Status: Open Priority: Normal Assignee: Category: core Target version: 2.0.0 =begin I know the developers meeting is coming up so I'd like to get a few ideas I've had sitting in the wings out in the air before then. One the more useful is the idea of integrating Functors directly into the language. "Functor" is the term I use for "higher-order function". I blogged about this idea and you can read it here: http://trans.github.com/2011-09-07-ruby-heart-higher-order-functions/ The super short version is this: def f => op, arg arg.send(__op__, arg) end f + 3 #=> 6 f * 3 #=> 9 Another example: class String def file => op, *args File.send(__op__, self, *args) end end "README.rdoc".file.mtime #=> 2012-06-14 12:34:45 -0400 I'm using `=>` as means of indicating a higher-order function. Of course another syntax could be used if this won't fly. The important thing is the idea of higher-order functions being integrated directly into the language. Doing this without that integration requires the creation of an intermediate object for each call which is very inefficient. =end -- http://bugs.ruby-lang.org/