From: Brian I. <in...@tt...> - 2002-08-20 20:54:20
|
On 20/08/02 09:18 -0400, Steve Howell wrote: > From: "Brian Ingerson" <in...@tt...> > > > > 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 |