-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Functional Programming #42
Comments
Are you talking something like the MooX::NonOO module, where you can use Beam::Wire methods without needing an object, getting a magic singleton? Or when trying to satisfy a dependency and right now it always requires that it be a Or is this more related to #11? The problem with doing subs as dependencies is that they shouldn't be serialized into the config file, so I was thinking if we could do like Bread::Board does and have a DSL for constructing a container, then the services could be any valid executable Perl code. Or are you using Config::Any's Perl-based config file support to do what #11 wants (does that work?) and then need to ensure that the container knows you've got a different kind of dependency? Do you have an example of how the result would look when being used? We haven't yet had to add a container-level config value to the configuration files, but that doesn't mean we'll always be that lucky. And if it works nice, we can figure out an implementation. |
Sorry for the confusion; None of the above describes what I'm talking about. Currently, Beam::Wire is all OO, however, there are many people moving towards the functional programming paradigm. Functional programming, although not OO, still has the need to dependency injection/management, composition, etc. The gist of what I'm saying is that Beam::Wire could also support this style of development (I've been moving toward functional myself). Essentially, Beam::Wire would generate functions and support high-order functions and return them. Also, we'd be able to say that Beam::Wire is now the only DI container supporting functional programming in Perl. Here's how is might work: rabbitmq:
class: RabbitMQ
args:
host: example.com
port: 61312
user: root
password: secret
enqueue:
class: MyApp::Functions
function: rabbitmq_enqueue
args:
- { $ref: "rabbitmq" } ... so what does this do exactly? Well, it defines an object and a function, the function takes the object as a parameter. The enqueue function returns a coderef which when executed calls the MyApp::Functions::rabbitmq_enqueue function with the RabbitMQ object as it's first argument. The implementation might look something like:
The usage might look something like:
Which is super cool in my opinion? Also, we'd be able to support high-order functions by allowing functions to depend on other functions essentially creating coderefs which take coderefs as arguments. I hope you're in agreement, I think this addition will make Beam::Wire extremely powerful and stand out above anything else. What do you think? |
Yes. I like it. By declaring a service (we know we're declaring a service because we're in the top level) with "function" (could it be "sub" instead?), we are going to return a subref. The args would let us curry the returned subref (so one could do And yes, you're right. Functional programming has the same need for dependency injection. Maybe even a bigger need: every Moo attribute is a dependency that can be injected, but how do you wire up subs? Well, how about Beam::Wire! Do we use But I can also see the idea that a service is the value returned from the sub call and not the sub itself. So maybe that's a distinction between "function" in the service description and "sub" or "method" (though I like making people conform to best practices by making better practices easier, and this new thing is a lot more awesome, so it should get priority for a shorter keyword). Or maybe "call the sub" is "call" instead. Whatever, not important right now. So yes, we should definitely try this. And don't let my above bikeshedding slow you down. |
So, combining this with #43, #46, and #47, I've come up with the following idea: There should be a small number of meta-keys:
Fuck. I've created a programming-by-config language. Next obvious step is making a real language using Marpa... Well, a bunch of this stuff isn't going to be used all the time. The core bit is "service creation" and I'm going to write the docs for this new stuff first, in a branch, and get some feedback on it before I release v2.0 with this new stuff. I think I can get mostly backwards-compatible, considering the new functionality is mostly new config that is currently invalid. |
This specification/proposal is awesome. I love the new approach and functionality. I think we should be mindful in the terms we use so we don't confuse people who might want to use this system. For example, the The term Additionally, we could use an "engine" abstraction (factory pattern) to support backwards compatibility, and as we evolve the configuration language, I see the need for backwards compatibility even more. I'll keep my eye out for the v2.0 branch so that I can help implement it. I use BW daily, I love it, and I'm looking forward to the v2. |
The larger idea is to stop trying to use combinations of meta keys as indications of what should be done, trying to DWIM breaks down when I could mean two different things. Meta keys with their own internal keys is far better. I was giving some thought to non-object methods (plain subs, functions) as services, somehow declaring a service from nothing without an object to instantiate, and it brings in a bunch of complications, not the least of which is crossed terminologies. But I think we should do it, so I imagine we'll do some experimenting in a branch. Oh, and I just thought of a few cases where it would be massively useful for me (File::ShareDir::dist_dir is one big one, since so many of my configuration files are in share dirs), so here's an off-the-cuff idea: Perhaps using My idea for if it turns out we need backcompat is a special, top-level One of the things I've been trying to design for is this: https://github.com/preaction/Beam-Runner. The idea is that a Beam::Wire container is basically a string (YAML, JSON, or otherwise) that describes how to create objects, and we can ship that string as a message to another machine, have it create the object, run whatever method we want, and give us the result back, possibly running multiple things, and possibly farming out all the things to a huge cluster. And, looking over that again, |
@preaction I wanted to give you a heads-up that I just released Rewire, a reimagining of this project with support for all of the construction strategies but with some important differences which makes the codebase and configuration simpler, also this:
See https://github.com/iamalnewkirk/rewire. Let me know what you think! |
The only thing required to support dependency injection with function programming is a feature-flag in the configuration file which tells the container not to treat the first argument as an invocant.
The text was updated successfully, but these errors were encountered: