On 20/08/02 09:18 -0400, Steve Howell wrote:
> From: "Brian Ingerson" <ingy@...>
> >
> > Right. YAML can't (and shouldn't) be able to do Perl arrays and hashes. It
> > can only deal with (Perl)refs to those. This is due to the screwed up and
> > convuluted semantics of Perl data structures. (See, I'm not defending Perl at
> > all here.) Perl sucks in this sense because it listifies its data structures
> > when they get put on the call stack.
> >
> > BUT...
> >
> > I one were to (and I've always done this) call hashrefs "hashes" and
> > arrayrefs "arrays", then everything works out semantically correct for YAML,
> > like it would in a sane language like Python or Ruby or hopefully Perl6. A
> > Perl hash can be thought of as a Perl hashref that is stuck into the Perl
> > symbol table. So it can use a '%' in front of it, and work in the builtins
> > that manipulate hashes and have its crazy listify behaviour.
>
> Ok, makes sense.
>
> > Perl lists never exist as a data structure in memory. They are merely a
> > concept relating to the call stack. This concept can be exploited nicely in
> > YAML, since I don't need to serialize the listness. It seems incorrect usage
> > to me to use tuples (which (I think) are a data structure), since people will
> > want to preserve the tupleness.
> >
> > ---
> >
> > I just bounced this off of Jon Prettyman, the hacker whose house I'm staying
> > with. He knows Perl a bit, but mostly does Python.
> >
> > I think this all boils down to the fact that in Perl you have arbitrarily
> > variable length argument lists, but not in Python. I simply point this out to
> > show that we'll have different APIs for some things.
> >
>
> Sorry to be pedantic, but Python does have arbitrarily variable length argument
> lists:
>
> def greet(greeting, *people):
> for person in people:
> print greeting + ' ' + str(person)
>
> greet('hello', 'ingy', 'steve')
> greet('aloha', 'jeff', 'guido', 'alex')
>
> The only substantive difference between Perl and Python in terms of calling
> sequence, that I see in terms of YAML anyway, is that Perl has wantarray, and
> Python doesn't. This is the only place where we'll be forced into different
> APIs. This variable argument list discussion is just a big red herring.
>
> If you were to forgo the use of wantarray in Perl, then I think we could have
> virtually identical APIs for yaml. On the other hand, I have also said that I
> like how our Perl library is Perlish, and our Python library is Pythonic, etc.,
> so you could make a good argument for wantarray and I'd accept that.
> Consistency and hobglobbins...
That's good. I didn't know about that. Thanks for explaining.
>
> > > How do you intend to add additional arguments to the dump method?
> > > Where would the list of thingies to dump end, and where would the
> > > formatting arguments start? It would be pretty ambiguous, and I think
> > > once you add more arguments to dump(), you're back to my original
> > > conundrum.
> >
> > OK. My interface for extra parameters is to specify them separately. In the
> > simplest case, I use global variables. In the more complicated case I use
> > an OO interface.
> >
> > $YAML::Indent = 1;
> > YAML::Dump($foo);
> >
> > vs
> >
> > YAML->new->Indent(1)->dump($foo);
> >
> > This is the interface that Data::Dumper uses. It's familiar to Perl
> > programmers. In a sense, the global variables are like attributes of the
> > global object. Just like Ruby. Well, perhaps that's a bit of a stretch.
> >
>
> Yep, but global objects do defeat reentrancy, correct? I can guess you say
> YAGNI, but what if under some future version of Perl folks want to use YAML in
> two different threads? Won't the formatting variables conflict? Or suppose
> you're doing a YAML dump of a large structure, and then one of your objects has
> a to_yaml method(), and then, to help you debug the to_yaml() method, you make
> another call to YAML in there? Won't the inner call mess up the args for the
> outer call?
The global interface is for simple things. The oo interface is is for more
complicated things. As I said Data::Dumper does this. It's common in Perl to
provide a no frills functional interface.
Now the global interface simply copies the global settings into an internal
object at the start of a dump or load. I stack the object before calling back
to a to_yaml, etc. So there's really no problem.
>
> If I want to avoid global variables in Python's dump protocol, I think the code
> below is my best option, which is inspired by your comments above:
>
> def _dump(options, *documents):
> # ...
>
> class Options:
> def setIndent(self, indent):
> self.indent = indent
> return self
>
> def dump(self, *documents):
> _dump(self, *documents)
>
> def dump(*documents):
> _dump(DefaultOptions(), *documents)
>
> Then you'd say:
>
> print Options().setIndent(4).dump({'foo': 'bar'})
> print Options().setIndent(3).dump('Steve', [3, 4, 5], {'foo': 'bar'}) # three
> different documents
> print dump(['apple', 'banana', 'carrot']) # normal formatting
>
> So, I guess the way out of my conundrum was the same way you get out of it in
> Perl. So, despite all the flames (which were intended to be lighthearted, but
> they never read that way, I guess), we got something useful out of this
> discussion. :)
Cool.
>
> On a related issue, Dave Kulhman has submitted a patch for PyYaml that adds a
> dumpToFile() method to the emitter. Minor issue here, but I think Dave and I
> both prefer dumpToFile() to dumpFile(), because that extra preposition makes it
> clear that the file's the target, not the source.
Sounds good.
Cheers, Brian
|