[comp.lang.perl] dynamic formats

jgreely@giza.cis.ohio-state.edu (J Greely) (01/16/90)

In article <JV.90Jan15163050@mhres.mh.nl> jv@mh.nl (Johan Vromans) writes:
>A format specification is apparently of a static nature. Is it
>possible to dynamically create formats,

Yes, but only the clumsy way.

>Currently the only way I can think of, is creating a temporary file
>with the format spec in it, and 'do'ing it.

That's what I use.  I have a subroutine 'feval' that I keep handy in a
library.

	sub feval {
		local($form,$file) = @_;
		$file = "/tmp/feval.$$.pl";
		open(file,">$file") || die "$file: $!\n";
		print file $form;
		close(file);
		do $file;
		unlink $file;
	}

It's a quick and dirty workaround, and I brought the problem to
Larry's attention a while back.  I'm sure he'll respond with the
current status.

  Easy to use, though:

	$field = "foo";
	&feval(<<'EOF');
	format STDOUT =
	@<<<<<
	$field
	.
	EOF
	write;
--
J Greely (jgreely@cis.ohio-state.edu; osu-cis!jgreely)

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (01/16/90)

In article <JV.90Jan15163050@mhres.mh.nl> Johan Vromans <jv@mh.nl> writes:
: A format specification is apparently of a static nature. Is it
: possible to dynamically create formats, e.g.
: 
:     eval('format=\n@...\n$...\n.');
: 
: Or to switch formats:
: 
:     if (...) { 
:     format =
:     ...
:     .
:     } else {
:     format = 
:     ...
:     .
:     }

A format is a non-executable compile-time declaration, just like a
subroutine declaration, so the latter doesn't work.  The eval trick
ought to work, but doesn't.

: Currently the only way I can think of, is creating a temporary file
: with the format spec in it, and 'do'ing it.

That is the only way to do it currently.  The format parser only knows
how to parse things that come in one line at a time.  Strings which
are eval'ed are already all there, so the format parser gets confused
after the first line.  This restriction should go away someday.  It's
not technically hard--it'll just take some elbow grease.  The load_format()
routine is one of the oldest in perl, and antedates eval by many moons.

Another thing you should be aware of is that redefining a format doesn't
currently free the storage for the old one.

Larry

jv@mh.nl (Johan Vromans) (01/16/90)

A format specification is apparently of a static nature. Is it
possible to dynamically create formats, e.g.

    eval('format=\n@...\n$...\n.');

Or to switch formats:

    if (...) { 
    format =
    ...
    .
    } else {
    format = 
    ...
    .
    }

Currently the only way I can think of, is creating a temporary file
with the format spec in it, and 'do'ing it.

Johan
--
Johan Vromans				       jv@mh.nl via internet backbones
Multihouse Automatisering bv		       uucp: ..!{uunet,hp4nl}!mh.nl!jv
Doesburgweg 7, 2803 PL Gouda, The Netherlands  phone/fax: +31 1820 62944/62500
------------------------ "Arms are made for hugging" -------------------------

tchrist@convex.com (Tom Christiansen) (02/07/90)

I've been using formatted writes and I find that it's a real
pain to be forced to associate one sole format() with a 
given output channel.  I've tried Johan Vromans's indirect-thru-
a-subroutine work-around:

   format =
   @<<< @<<< @<<< @<<<
   $_[0], $_[1], $_[2], $_[3]
   .

   sub fmt_write {
           write;
   }

   &fmt_write("A", 1, 2, 3);

which works ok, but not quite what I'd like.

I think what I'd most like is something just *mildly* more similar
to FORTRAN's write statements.  I'd like to be able to dynamically
specify *which* format to use.  The documentation on format has

    format NAME
	picture
    .

When you first look at that, you figure you should be able to use:

    format FOOFORM
	blah
    .

    write FOOFORM;  # use FOOFORM to write to current output channel

except that NAME really means a FILEHANDLE in this case.  Formats
don't really have their own namespace, and I wish they did.

I'm trying to figure out a way to extend the syntax without breaking
anything.  If write's syntax were

	write(FILEHANDLE);
    or	
	write(FILEHANDLE, FORMAT);

where FORMAT were the name of a tagged format field, it could work.
(Assume either FILEHANDLE or FORMAT could be scalar expressions 
for indirection.)  

But how to tag the format?  We (probably) can't use

	format TAG

because you couldn't (easily) disambiguate the TAG from a FILEHANDLE.

Comments, criticisms, or inspirations anyone?

--tom
--

    Tom Christiansen                       {uunet,uiucdcs,sun}!convex!tchrist 
    Convex Computer Corporation                            tchrist@convex.COM
		 "EMACS belongs in <sys/errno.h>: Editor too big!"

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/08/90)

In article <5195@convex.convex.com> tchrist@convex.com (Tom Christiansen) writes:
: I'm trying to figure out a way to extend the syntax without breaking
: anything.  If write's syntax were
: 
: 	write(FILEHANDLE);
:     or	
: 	write(FILEHANDLE, FORMAT);
: 
: where FORMAT were the name of a tagged format field, it could work.

# Usage: &write(*FILEHANDLE, 'format-name', 'top-of-form-name');
#     or &write(*FILEHANDLE, 'format-name');

sub write {
    local(*HANDLE,$format,$top) = @_;

    $oldsel = select(HANDLE);
    $^ = $top if $top;
    $~ = $format;
    select($oldsel);

    write(HANDLE);
}

Formats do have their own namespace, as you can see here.  It just looks
like they don't from the examples because the default format for a filehandle
is of the same name.

Larry