Re: block-based programming...
by dragonchild (Archbishop) on Apr 22, 2004 at 11:48 UTC
|
I'm of two (or more) minds about this. Firstly, this is not some radical new style. This is a form of imperative programming without subroutines, similar to some older languages (like Apple Basic and the like). You are, essentially, programming with goto.
Now, you did say that this is a small program. In a way, so long as your stuff is well-named and well laid out, it almost doesn't matter what way you program this. Heck, your program seems to be simple enough that, if the hooks were there, you could program this in Parrot! (I don't reccomend it, but it could be interesting ...)
Now, you talk about a state machine. If you think about this being a state machine and you don't use CPAN code, you're (probably) reinventing the wheel. The standard distribution for handling state machines in Perl is POE*. It's a bit of a learning curve, but I would definitely suggest looking there if you consider this a state machine.
As for my feelings on block-driven programming in general ... I guess I would say that it's a neat idea, so long as your codebase remains very very small. This doesn't scale in any meaningful way. *shrugs*
*CGI::Application can be considered as another state machine distribution, but it is both domain-specific to web applications and doesn't really have built-in support.
------
We are the carpenters and bricklayers of the Information Age.
Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose
| [reply] |
|
|
$state = 'foo';
$running = 1;
while($running) {
if ($state eq 'foo') {
# do stuff
$nextstate = 'bar';
}
elsif ($state eq 'bar') {
# do stuff
$nextstate = 'baz';
}
elsif ($state eq 'baz') {
# do stuff
$running = 0;
}
$state = $nextstate;
}
| [reply] [d/l] |
|
|
__close1:
if (close (soc) < 0) {
if (errno == EINTR) {
goto __close1;
}
perror ("close");
exit (1);
}
I don't think this is less maintainable than writing a loop.
Abigail
| [reply] [d/l] |
|
|
|
|
|
|
|
|
|
|
|
|
| [reply] |
|
|
Re: block-based programming...
by Abigail-II (Bishop) on Apr 22, 2004 at 10:52 UTC
|
Which pro's and con's do you see for each approach?
Why don't you tell us what you think the pros are? I can't form any judgement based on a single, not worked out example. If you want to harvest useful opinions, you have to give us something to work on. Give a description of what "block programming" is supposed to be/do. Are you by any chance trying to re-implement make?
Abigail
| [reply] |
Re: block-based programming...
by fruiture (Curate) on Apr 22, 2004 at 12:27 UTC
|
You'll see the downsides of that approach as soon as you reach blocks F, G and H, which do the "same as .. with ..", which clearly looks like you want to have block C as a function, taking cartein arguments, being called from certain points of your main program with different parameters. I mean, you could write your block-based program and then refactor out all the redundant stuff that you find. Personally, i'd try to find the obvious things before and not write block-stuff at all. Perhaps writing a subroutine for each block may help. While you write each sub, try to make it as flexible as possible. Finally you only need a main script, keeping the main program's state variables and calling the subs accordng to the overall logic. You might want to think of an OO model for your data, not only refactoring to subs, but to classes and methods. The main program does then not just keep state "variables", but objects, which you might want to reuse somehwere else... I'm sure you won't need named blocks in the end, only "if", "while" and subroutines. No redo, but tail recursion.
| [reply] |
|
|
I agree with your post up until the point about tail recursion. Tail recursion is *easily* eliminated by reducing the recursion to a simple loop. This is much friendlier on your stack, and much more efficient! Other forms of recursion are harder to eliminate, but the refactoring of tail recursion is well known.
That being said, tail recursion often serves as as decent way to design an algorithm originally, but it should be eliminated when you get the chance.
In his case, assume the program is a "C" program implemented as a state machine that will run for years. Tail recursion would chew up a tremendous amount of stack and lead to program termination. Refactored as a simple while loop, the program would run forever.
This is one (not so rare) example where the reality of how a computer works oversteps the theory of basic "computer science". What appears to be logically equivalent is not once you put it on real hardware.
edit: darn, it looks like I'm turning into a CS professor now... run away! run away!
| [reply] |
|
|
This is one (not so rare) example where the reality of how a computer works oversteps the theory of basic "computer science". What appears to be logically equivalent is not once you put it on real hardware.
What has "real hardware" to do with it? All you need is a compiler that's able to detect tail recursion, and eliminate it, instead of putting the burden on the programmer. Yes, such compilers exist. Ironically, they are more common in environments that are more concerned with the 'theory of basic "computer science"' than in environments that use 'real hardware'.
Abigail
| [reply] |
|
|
|
|
|
Re: block-based programming...
by tilly (Archbishop) on Apr 22, 2004 at 21:35 UTC
|
I have used a similar block-style before, so I'm going to say that it is sometimes justified. (Look for redo in the Carp::Heavy shipped in Perl 5.8.) I'd only think that it is justified if you have many conditions that you need to satisfy to leave the loop (my situation there) or else factor the code so that the odd flow of control is compactly presented in an understandable way.
In your case that would mean that you should make A, B, C, etc into functions (hopefully well-named ones) and then write the flow of control in a small block. like this:
EDIT_MAP: {
attempt_edit($map);
redo EDIT_MAP unless can_parse($map);
redo EDIT_MAP unless user_confirms($map);
attempt_edit($reverse_map);
redo EDIT_MAP unless can_parse($reverse_map);
redo EDIT_MAP unless user_confirms($reverse_map);
}
commit_edit($map, $reverse_map);
Now the key flow issues are put somewhere where the redo logic is very easy to understand and is not intertwined with the grungy details of the steps. It would be easier, for instance, for someone who didn't know the code or technique to look at this and figure out how to add a "give up" option on those redos, or to have F-H by default fail back to F rather than C.
(Yes, my experience suggests that if someone wants a change in this script, then they are quite likely to want to make them to the flow of control.) | [reply] [d/l] |