damerell: (computers)
Add MemoryShare This Entry
posted by [personal profile] damerell at 08:51pm on 01/04/2009
Dear Lazyweb,



I'm writing a Perl program which I intend to have a curses interface. I've already written such a program, so that's not a problem.

However, this time it would be nice not to tie myself to _just_ curses, but to have the option of supporting other interfaces (SDL graphics tiles? libtcod?)

So what I want to do is to find out early on which interface the program is going to use (command-line option, config file, whatever) and then do something like loading an interface-specific module which contains a bunch of subroutines the main program can use, which have the same names regardless of the interface.

I suspect there is an existing idiom for this but I can't even think how to Google it. The approach that springs to mind is to "if (this) {require and import one module} elsif (that) {require and import another module}" and so forth but I really have no idea if that's sensible.

Any advice?
There are 9 comments on this entry. (Reply.)
 
posted by [identity profile] gaius-octavian.livejournal.com at 08:22pm on 01/04/2009
I don't know much Perl but the thing you want is called "late binding" so something like this I guess.
 
posted by [identity profile] damerell.livejournal.com at 01:24pm on 02/04/2009
Thank you, that helps with Google.
fanf: (Default)
posted by [personal profile] fanf at 08:33pm on 01/04/2009
Yes, you can use require with a module name calculated at run time.
 
posted by [identity profile] solipsistnation.livejournal.com at 09:48pm on 01/04/2009
Yeah, you can require libraries whenever you want as long as you don't use pieces of them before they've bene loaded. Here's an example from the middle of a program I was looking at yesterday:

 eval { require Mail::Box::Manager; };
 die "You need to install the Mail::Box module, exiting" if $!;


You could even, if you were a meanie (or awesome), replace the "die" with something like "CPAN::Shell->install("Your::Module::Here");". I can't see that causing any problems whatsoever. 8)

I think what I'd do, were I doing something like this, would be to create a config file (or a flag) that specifies an interface and then switch off of that somewhere early-on. In the block for each interface, require() the appropriate module (and die if it's not there, and maybe even fail gracefully to the bare minimum interface) and then include another file with the function definitions for that type of interface. That's not very OO of me, I guess, but OO is for jerks and stuff.

There are probably cleaner ways to do it...
 
posted by [identity profile] damerell.livejournal.com at 01:26pm on 02/04/2009
Mmm. What I am wondering is not so much if it can be done as whether there is a cleaner way, what the accepted idiom is. But Googling suggests this is as good as any.
 
posted by [identity profile] paxed.livejournal.com at 05:52am on 04/04/2009
libtcod suggests a roguelike, true?
 
posted by [identity profile] damerell.livejournal.com at 04:11pm on 04/04/2009
I'm reluctant to say anything until there's something to say, not wanting to pull a Krice...
cjwatson: (Default)
posted by [personal profile] cjwatson at 03:40pm on 04/04/2009
If you want an example of a Perl program that does this and actually works properly (with fallback from one frontend to another if it can't load one due to e.g. X not being available), you could try debconf.
 
posted by [identity profile] damerell.livejournal.com at 04:09pm on 04/04/2009
Glee! That is exactly what I was looking for. Thanks.

April

SunMonTueWedThuFriSat
    1
 
2
 
3
 
4
 
5
 
6
 
7
 
8
 
9
 
10 11
 
12
 
13
 
14 15
 
16
 
17
 
18
 
19
 
20
 
21
 
22
 
23
 
24
 
25
 
26
 
27
 
28
 
29
 
30