ChwanRen has asked for the wisdom of the Perl Monks concerning the following question:
if some condition is met, the string "hi test test" will be unshifted onto STDIN. I'm using this to program 'functions' into my forth interpreter (written in perl of course).# old STDIN: 1 2 3 while (<STDIN>) { if (some condition) unshift "hi test test" to STDIN # new STDIN hi test test 1 2 3 }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Manipulating STDIN
by davido (Cardinal) on Apr 11, 2004 at 06:14 UTC | |
One thought I had while considering this question was that you could open a tied filehandle, tied to a class that hides the intricacies of allowing you to "unshift" data. The tied FH would read from STDIN, but would provide an OO interface on the side that allows you to do some funky things like $obj->push_fh($);. Here is a very simple implementation of this strategy. I wouldn't consider it complete, as it doesn't implement all of the required tied filehandle methods. But it does implement those necessary for the purpose of this example, and the result is executable code that seems to work fine in simple situations. Filling in the blanks to complete the rest of the required tied filehandle methods remains to be completed if you want to fully implement the solution. In particular, you'll need an EOF, PRINT, and GETC method, if I'm not mistaken. :)
You'll find that the output is:
This is the first line. So, as you can see, you now have a filehandle that reads from (in this case) DATA, but that allows you to push data back onto it for later use. Enjoy!
Dave | [reply] [d/l] [select] |
|
Re: Manipulating STDIN
by tilly (Archbishop) on Apr 11, 2004 at 06:16 UTC | |
Save that in Tie/Input/Insertable.pm and then you can do the following: Note that I made the tied handle not be the one that I was tying it to. If you do that, then you are playing on the edges of infinite recursion. Just make the handles different and you avoid lots of possible confusion. | [reply] [d/l] [select] |
by gmpassos (Priest) on Apr 11, 2004 at 07:56 UTC | |
And by the way, nice work in the TIEHANDLE. ;-P
Graciliano M. P. | [reply] [d/l] |
|
Re: Manipulating STDIN
by Zaxo (Archbishop) on Apr 11, 2004 at 05:04 UTC | |
Better to bring in the extra text from a new source, Any chance you'll post your forth interpreter here? I'd like to see it. Update: One way to slip in an extra STDIN is to localize the handle: That takes care of throwing away $_, too. BTW, your forth interpreter is 404 for me. After Compline, | [reply] [d/l] [select] |
by ChwanRen (Acolyte) on Apr 11, 2004 at 06:08 UTC | |
| [reply] |
by ChwanRen (Acolyte) on Apr 12, 2004 at 06:58 UTC | |
Anyway to the other replies, the reason I want to unshift to STDIN is because when my forth interpreter reads the "call" function, I want to unshift the commands stored in the variable onto STDIN. I'll elaborate. When curly braces are encountered, everything in it until the closing brace is added to a string. This string is then stored into a variable declared earlier. Like: pop3 { pop pop pop } store the string "pop pop pop" is stored into pop3 (via hash tables) then, when i do pop3 call, I want to unshift "pop pop pop" onto STDIN to be read. I've already implemented this differently by reading it everything from STDIN until EOF into a list, then handling each element of the list as though it is read from STDIN. Thus, I can unshift "pop pop pop" onto the list. Is there any other way to do this more elegantly? | [reply] |
|
Re: Manipulating STDIN
by Anonymous Monk on Apr 11, 2004 at 17:03 UTC | |
| [reply] |
|
Re: Manipulating STDIN
by graff (Chancellor) on Apr 11, 2004 at 21:36 UTC | |
First: to produce the result that you say you want, you would need to unshift "hi test test $_", wouldn't you? Second: why go to the trouble of doing deep magic with the file handle? That is, why wouldn't the following approach, which yields the same basic result, do just as well (with a lot less code and complexity)? If the problem is that some other branch in the while loop is looking for "hi test test " to trigger some action, it would seem easy enough to arrange the logic so that this other branch will execute on the same iteration after the prefix has been added. If it's more complicated then that, maybe you should be looking at a two-stage process, where the first stage is a simple text filter, adding prefixes to lines where needed, etc; the filter's output is piped to the second stage, whose logic is now much simpler, because the stream is appropriate to its task -- two simple scripts are often better than one complicated script. If you want to keep it really simple for the command-line user, you could set up the second script to handle its input like this:
| [reply] [d/l] [select] |
|
Re: Manipulating STDIN
by Revelation (Deacon) on Apr 11, 2004 at 23:11 UTC | |
If you won't be shifting '0' or '', then even $_ = shift @f || <STDIN> works. Both solutions are simpler than tie()-ing STDIN; just replace reads from STDIN to shift @f || <STDIN> inside the loop for seamless transition. Becase I'm a fan of using a block, instead of while syntax, with longer conditons and assignments, I'll also give you an alternative control structure: If you're only reading from STDIN at the beggining, or don't mind copying and pasting a bit, then both solutions are strong. They mean one less module to debug, and one less layer of complexity in your code. It also gives a speed bonus over tie()-ing. If you _must_ tie to *STDIN, gmpassos provides an elegant solution. I feel like that's an unnecessary convolution, though. Gyan Kapur Untested | [reply] [d/l] [select] |
| |