Re: DBI v2 - The Plan and How You Can Help
Darren Duncan wrote: 3. Redefine prepare() and execute() such that the first is expressly for activities that can be done apart from a database (and hence can also be done for a connection handle that is closed at the time) while all activities that require database interaction are deferred to the second. That would be nice, but there are some DBDs for which you need the database on hand for $dbh.prepare() to work. In particular, DBD::Oracle. I think that what you are asking for can still work, though; # this module creates lots of SQL::Statement derived objects, without # necessarily loading DBI. use MyApp::Queries <%queries>; # not connect, so doesn't connect my $db = DBI.new( :source("myapp") ); # prepare the objects as far as possible my %sths; for %queries.kv -> $query_id, $query_ast_or_template { %sths{$query_id} = $db.prepare($query_ast_or_template); } # connect $db.connect; # now proceed as normal my $sth = %sths; $sth.execute( :param("foo"), :this("that") ); So, effectively the prepare can happen at any time, and it's up to the DBD to decide whether to actually do anything with it immediately or not. ie, on Pg the STHs would be built before the DB is connected, and on Oracle they are built the first time they are used (and then cached). Now I realize that it may be critically important for an application to know at prepare() time about statically-determinable errors, such as mal-formed SQL syntax, where error detection is handled just by the database. For their benefit, the prepare()+execute() duality could be broken up into more methods, either all used in sequence or some alternately to each other, so users get their errors when they want them. But regardless of the solution, it should permit for all database-independent preparation to be separated out. OK, so we have these stages; 1. (optional) generate an AST from SQL 2. (optional) generate SQL string from an AST 3. generate a handle for the statement, sans connection 4. prepare handle for execution, with connection 5. execute statement I think these all fit into; 1. SQL::Statement.new(:sql("...")); 2. $statement.as_sql; 3. $dbh.prepare($statement) or $dbh.prepare($statement, :nodb); 4. $dbh.prepare($statement) or $sth.prepare while connected 5. $sth.execute In particular, I don't think that the DB driver should automatically get a chance to interfere with SQL::Statement; if they want to do that, then they should specialise SQL::Statement. IMHO. Perhaps you have some other examples that don't fit this? 5. All details used to construct a connection handle should be completely decomposed rather than shoved into an ungainly "data source". I interpret this as asking that the detailed parameters to the DBI connection are expanded into named options rather than simply bundled into a string. That, I agree with, and I guess it would be useful occasionally to be able to specify all that rather than just setting it up once and labelling those connection parameters with a "source" that comes from ~/.dbi. Particularly for writing gui dialogs for interactive database utilities. Either way, you don't want most applications dealing with this complexity at all, really. 6. DBI drivers should always be specified by users with their actual package name, such as 'DBD::SQLite', and not some alternate or abbreviated version that either leaves the 'DBD::' out or is spelled differently. Similarly, the DBI driver loader should simply try to load exactly the driver name it is given, without munging of any type. This approach is a lot more simple, flexible and lacks the cludges of the current DBI. DBI driver implementers can also name their module anything they want, and don't have to name it 'DBD::*'. A DBI driver should not have to conform to anything except a specific API by which it is called, which includes its behaviour upon initialization, invocation, and destruction. Is this useful? I can't see a reason that the DBI.new() / DBI.connect() call shouldn't be flexible in what it accepts; $dbh = DBI.new( :driver ); # means DBD::Rosetta $dbh = DBI.new( :driver ); # specify full package $dbh = DBI.new( :driver(Rosetta::Emulate::DBD) ); # pass type object $dbh = DBI.new( :driver(DBD::SQLite.new(:foo)) ); # pass driver object Sam.
Re: DBI v2 - The Plan and How You Can Help
Darren Duncan wrote: Okay, considering that using the same name prepare() like this may confuse some people, here is a refined solution that uses 3 methods instead; please disregard any contrary statements that I previously made: I think I'm beginning to like it. Allow me to suggest one or two further refinements... # Opt 1: A user that wants the most control can do this (new feature): my $sth1 = $dbh.compile( $sql_or_ast ); # always sans connection $sth1.prepare(); # always with connection, even if DBD doesn't use it $sth1.execute(); # always with connection To me, the "compiled" form of the STH is related to the driver, but re-usable between connections; you should be able to use something like; my $sth1 = DBD::SQLite.compile( $sql_or_ast ); $sth1 = DBI.compile( :statement($sql_or_ast), :driver ); This would give you a STH which is divorced from the actual DB connection instance. Because you constructed it like this, without reference to a (possibly unconnected) connection object, then $sth1.prepare is not available. You'd then need to use something like; $sth1.prepare($dbh); $dbh.prepare($sth1); Note I also think what you wrote should work, too. The new feature is if you decide to use compile(); you then give that method the arguments you would have given to prepare(), and you invoke prepare() on the result with no arguments; each DBD would decide for itself how the work is divided between compile() and prepare() with the limitation that compile() is not allowed to access the database; ideally the DBD would place as much work there as is possible, which would vary between Oracle/Pg/etc. Agreed. In particular, I don't think that the DB driver should automatically get a chance to interfere with SQL::Statement; if they want to do that, then they should specialise SQL::Statement. IMHO. I am operating under the assumption here that while the new DBI is designed to effectively support wrapper modules, the wrapper modules would also be altered from their current DBI-1-geared designs to accomodate DBI-2. But still, what do you mean by "interfere"? Well, when you parse the statement into an AST, the flavour of SQL will affect how it is parsed and what is allowed. Eg, Oracle has significant features in some comments (query hints). It also has quirky and somewhat useless keywords like CONNECT BY. So, when you ask a DBH connected to a driver to parse something, then it will use that driver's SQL dialect, if one exists, but I still want to be able to deal with SQL ASTs without implying a SQL flavour. Either way, you don't want most applications dealing with this complexity at all, really. I am operating under the assumption that this system should work if there are no external config files that the DBI/DBD would read, and the application would provide that information; if its in a file, the application would read it in, or would explicitly tell DBI where it is. Or at least it should be possible for this to happen, even if a DBD defaults to look in a default location when it doesn't get the equivalent from the application. Absolutely, that must work. But it would still be nice to be able to config this without digging through the application to see where the password is written. Unless there is a design flaw in DBI, we should not have to update that module just because a new driver came into existence whose name has not yet been hard-coded into DBI. See this block for example, from DBI.pm v1.48: my $dbd_prefix_registry = { ad_ => { class => 'DBD::AnyData',}, [...] yaswi_ => { class => 'DBD::Yaswi',}, }; I mean, what's up with that? I assume DBI 1 has this for legacy app backwards compatability, but DBI version 2 should never have to accomodate such abhorrent computer programming practices in its core. Such a great word, abhorrent. So fitting for this case. It sure does look like an (over&premature&misguided)-optimisation to avoid using the full module name in an internal hash or something like that. But then maybe (I&we&none(Gaia)) are missing some context there. Sam.
Re: Time::Local
Darren Duncan wrote: Actually, there was a big oversight in my last message. It does not handle approximate or relative dates, such as when you don't know the details. FWIW, this is handled by DateTime::Incomplete, and also will be natively supported by Date::Gregorian. You're describing with this and other messages very much how the `Date' distribution in pugs is being designed. I'd very much appreciate input on that interface. Sam.
Re: Time::Local
Craig DeForest wrote: Using the TAI epoch of 1958-01-01 00:00:00 has several advantages: - TAI is recognized by international standards-setting bodies (BIPM). - Perl6 will then shake out the 31-bit time rollover a full 12 years before I like this in principle, however I wonder of the merits of professing to return something of more accuracy than can actually ever be realistically assured from any of the platforms Perl runs. For a start, to convert from the available time source - the system clock - to TAI, you need to know; a) current adjustments, or when the lack of adjustments is considered valid up to (after that date, of course, if the list of adjustments is not updated, getting the time or converting from a time to a date on a calendar is an exception). b) whether or not the system clock is automatically correcting for leap seconds, ie when ntpd is running and sync'ed up. In any case, I'll add "to_TAI" as one of the marshalling methods for Date objects in Date.pm I guess it comes down to what guarantees we decide to make on the nature of time(). If a leap second passes while the script is running, can the value returned by time() regress? In fact, do we even need a fixed epoch? Why not just free-wheel it and make 0 the time the script started, get it to count seconds, and let interfaces for the system clock / orson database solve the hard problems. Sam.
Re: DBI v2 - The Plan and How You Can Help
Maxim Sloyko wrote: But this is not the point. The point was that usage of some file with passwords by *DEFAULT* is not the way to go, IMHO. It raises more problems than it solves. Can you give an example of such a problem that wasn't already there? Just to be clear, the file would only need to contain passwords if the DBD requires them. Sam.
Re: Dependency Injection
Piers Cawley wrote: Then the harness that actually sets up the application would simply do use Logger::DBI :dsn<...>, :user<...>, :password<> and Logger::DBI would install itself as the default Logger class. The question is, how does one write Injected to make this work? Or what features do we need to be able to write Injected? Thinking about this, it shouldn't be too hard to implement 'Injected' in Perl 5: FWIW this is exactly what I would like to achieve with the Date objects; allowing code that doesn't care about which Date representation they want the ability to just say "any Date representation". Sam.
Re: DBI v2 - The Plan and How You Can Help
Darren Duncan wrote: I should emphasize that I never expected to be able to send any type of ASTs over the pipe to the database. They would still be interpreted by the database driver for Perl and/or a wrapper thereon, into the database native format. Its just that, to an application, it would appear that the ASTs were going over the pipe, as to their effect, even though they weren't behind the scenes. Indeed. I think the principle "bug" to "fix" is getting away from this notion that all you need to do is do a little bit of template-based query building, use the DBI and magically expect all database portability problems to go away. And then, recommend an approach that *is* portable. Take your excellent Rosetta infrastructure, pull the API to pieces, simplify the documentation, then condone it as another simple and effective way to write new database driven applications. And hopefully simplify the DBDs that necessarily need to do SQL parsing along the way. So, everyone who is still happy to code to a particular database's SQL language can continue to do so, but we'll eventually move the Cargo Cult away from the situation we're in today where there is a vague promise of portability but so many caveats that it's practically impossible to write portable code. Sam.
Re: DBI v2 - The Plan and How You Can Help
Dean Arnold wrote: RE: LOBs and "SQL Parse Trees": having recently implemented LOB support for a JDBC driver (and soon for a DBD), I can assure you that SQL parse trees are unneeded to support them. For databases Great! Perhaps you can shed some light on how to do it for this, then. SQL command; INSERT INTO FOO (?, ?, ?, ?); Column 3 is a BYTEA column in Pg and needs special peppering to work. or this; SELECT * FROM FOO WHERE SOME_DATE_COLUMN > ? SOME_DATE_COLUMN is the database native date type. On Oracle you'll need to convert the ? to a 'TO_DATE(?)'. Sam.
Re: Raw bytes in perl6
Yuval Kogman wrote: By the way, a nice use case for using the rules engine could be "parsing" a stream of SAX events into a structure... XML::Simple in perl6 could be really as simple as it sounds =) Can anyone see this being retrofitted on top of current rules semantics? How does PGE relate to this? Yes, in fact SGML DTDs, once reduced to compact forms such as in; http://search.cpan.org/src/SAMV/Perldoc-0.13/t/09-scottish.t End up looking surprisingly similar to rules. Sam.
Re: DBI v2 - The Plan and How You Can Help
Dean Arnold wrote: Column 3 is a BYTEA column in Pg and needs special peppering to work. What sort of "peppering" ? DBI provides SQL_BLOB, and SQL_CLOB type descriptors (as well as SQL_BLOB_LOCATOR and SQL_CLOB_LOCATOR), so presumably DBD::Pg (or any other DBD supporting LOBs) provides the logic to map from $sth->bind_param(3, $somelob, SQL_CLOB); >>> SOME_DATE_COLUMN is the database native date type. On Oracle you'll >>> need to convert the ? to a 'TO_DATE(?)'. > Er, why ? I haven't used DBD::Oracle lately, but assuming you > $sth->bind_param(1, '2005-07-13', SQL_DATE), > I'd assume DBD::Oracle would be smart enough to communicate that That bind_param peppering is precisely what I'm talking about, thanks for demonstrating my point. This requirement to use "bind_param" to explicitly tell the DBI which placeholders correspond to which types is rarely mentioned on any introductions to DBI, and as a result, very few people carry this out in practice or are prepared to do the necessary re-work to code bases to perform it. So, DBD drivers need to hope that the database driver is smart enough to pull apart the query, match it against the schema and automatically setup the type correctly. Perhaps many C database access libraries provide enough information to do this, and pardon my ignorance for never having written or worked on a DBD to this level - but I'm guessing that such query introspection isn't always possible. And, in a sense, requiring that the DBD is able to introspect the query and DTRT is an "extra restriction" that DBD authors need to conform to, setting the bar for conformance so high that it is practically impossible to write portable database access code. Please note that I'm not suggesting that we do away with the existing interface, for people who don't care about writing portable database code. But I'd like to be able to write, for instance; use v6; use DBI-2; my $query = SQL { SELECT * FROM FOO LEFT JOIN BAR ON BAR.FOOID = FOO.ID }; if ($one) { $query &&= SQL::WhereClause { ONE = $one }; } my $dbh = DBI.connect(:source("myapp")); my $sth = $dbh.prepare($query); my $resultset = $sth.execute(); for =$resultset -> @row { ... } So what's happening here? Well, the SQL construct marks the beginning of a segment of code that happens to be in an alternate grammar, corresponding to some level of ANSI SQL. This builds an object which corresponds to that query. In fact, this can happen at compile time! The SQL { } is actually a closure that returns a SQL object when it is called. The later SQL::WhereClause is the same; the variable isn't merely interpolated, but is closed over, and included as if it were a placeholder. The &&= assignment operator uses the overloaded && operator on the SQL object, which sees it is being given a query fragment, and adds it into the appropriate point on the SQL AST. This should all be quite transparent - of course, an optional (but portable) method of writing database queries. And it's all deliciously Perlish, yielding less fussing around with buggy code stitching together queries, and more clean expression of queries using a standard language. Of course it will be entirely possible to layer support for this sort of thing atop any DBI interface; but this *is* a version 2, we do have prototypes for the mechanics of all this stuff - and Done Right™, it could actually fulfil the goal of DBI - being able to write Database-driven applications that are truly independant of the database product in use. DBI v1 cuts the porting time down to next to nothing; but we can get it even closer! Sorry to "bang on" about this for so long, I'm sure you're all getting sick of it by now- I had hoped that the original suggestion was just going to be acknowledged as a valid way to enhance portability and flexibility and considered without too much rehashing of what to some is an old topic. Sam.
Re: MML dispatch
Larry Wall wrote: In addition to what chromatic said, I'd like to point out that you've got the abstraction levels backwards by my lights: these days I tend to think of the class as a restricted form of role. A class is restricted to having to provide a working interface to real objects. Can I present an alternative way of viewing them, which I don't think contradicts with what I've understood of them so far from the Apocalypses and Synopses documents. First a couple of definitions; A "runtime class" is a package name, and a collection of functions that form a "dispatch table". There are actually two tables - one for private and one for public methods. The public table links to "superclasses" where further dispatch may occur. A "method" on a Role or a Class is a function that takes two implicit arguments; a dispatch table for private method lookups, and one for public methods lookups. The private dispatch table is bound when the function is added to a runtime class, but the public dispatch table is bound as late as possible (or until the class is closed in some situations). Here's the meat: A Class is then a Role that gets its runtime class created, and all its methods' private dispatch tables bound at declaration time. A Role, on the other hand, leaves methods that can't be called, until they are bound into a "runtime class". So they _look_ like they are flattened as the runtime classes are composed, unless you are introspecting to the sufficient level. The "runtime class" would be the ::Type objects, and the real Class and Role objects what you get from the .meta objects. This might be a half empty / half full thing, I just thought you might find that description interesting. Note that I don't deal with "state", I'm just treating attributes as if all they are is a set of accessor functions, which store in an unspecified&unimportant location. Sam.
Database Transactions and STM [was: Re: STM semantics, the Transactional role]
Yuval Kogman wrote: everyone gets to choose, and another thing I have in mind is the Transactional role... DBI::Handle does Transactional; To the STM rollbacker and type checker thingy this means that any IO performed by DBI::Handle invoked code is OK - it can be reversed using the Transactional interface it proposes. Is this needed, when you can just; atomic { unsafeIO { $dbh.begin_work }; unsafeIO { $dbh.do(...) }; unsafeIO { $dbh.commit }; } CATCH { $dbh.rollback; }; Of course, these unsafeIO calls can go inside a higher level wrapper for the DBI, assuming that it is possible to detect whether or not we are running in an atomic{ }, and "which" atomic block we are in. As for the efficiency of things, hate to say it but that's really up to the backend in use, and it's highly unlikely that anything other than Parrot or GHC will support atomic{ }. However a standard Role for this kind of behaviour might make sense. Maybe draw up a prototype? Sam.
Do I need "has $.foo;" for accessor-only virtual attributes?
Say I make an "accessor" method for an attribute that doesn't really 'exist'. For instance, a good example of this is the "month_0" vs "month" properties on a date object; I want to make both look equivalent as real properties, but without the users of the class knowing which one is the "real" one. Users of the class includes people subclassing the class, so to them they need to be able to use $.month_0 and $.month, even though there is no "has $.month_0" declared in the Class implementation, only "has $.month". So, is $.month just shorthand for $?SELF.month, which happens to be optimised away to a variable access in the common case where the "method month" isn't defined, or has a sufficiently simple "is accessor" trait in its declaration? And that, in turn, $:month is actually $?SELF.(":month"), where ":month" is an alias for the submethod called "month". After all, we want Roles used by Classes to have access to this virtual attribute coolness, too. These simple definitions should make all sorts of OO tricks possible, and reduces the definition of Classes to one that is purely functional (ie, state is just a set of functions too). Sam.
Re: Do I need "has $.foo;" for accessor-only virtual attributes?
Larry Wall wrote: > > Users of the class includes people subclassing the class, so to them > > they need to be able to use $.month_0 and $.month, even though there > > is no "has $.month_0" declared in the Class implementation, only > > "has $.month". We thought about defining the attribute variables that way, but decided that it would be clearer if they only ever refer to real attributes declared in the current class. Clearer in what way? This implies that you cannot; - refactor classes into class heirarchies without performing code review of all methods in the class and included roles. - "wrap" internal attribute access of a superclass in a subclass This in turn implies that the $.foo syntax is, in general, bad practice! Allow me to demonstrate with an example, taken from S12 with additions: role Pet { has $.collar = { Collar.new(Tag.new) }; method id () { return $.collar.tag } method lose_collar () { undef $.collar } has $.owner; } class Dog does Pet { has $.location; has $.home; does Run; method play { if $owner.location ~~ $.location { $?SELF.lose_collar(); } else { $?SELF.run(); } } } Now, as a user of the "Dog" class, I want to specialise it so that the collar cannot be removed unless the dog is at home; class Rotweiler is Dog { method collar { Proxy.new( STORE => sub($self, $val) { if ($val or $.location ~~ $.home) { $self.SUPER::collar = $val; } else { die "rotweilers must be kept on a leash" } }, FETCH => { $self.SUPER::collar }, ); } } OK, so that's all well and good - you've changed the public property "collar" so that your extra logic is there. But what happens? You lend your dog to someone else, they call $dog.play, which calls lose_collar(), which sets $.collar directly. Whoops, your Rotweiler is on the loose and slobbering over some unsuspecting 4 year old. This means that people designing classes and roles have to conciously make the decision to use $?SELF.foo or ./foo() instead of the more tempting looking and consistent $.foo Perhaps you could elucidate your point by giving some examples of when you *wouldn't* want $.foo to mean ./foo(), and when using a private attribute would not be the "correct" solution. : These simple definitions should make all sorts of OO tricks possible, : and reduces the definition of Classes to one that is purely : functional (ie, state is just a set of functions too). One can certainly rewrite $.foo and $:foo in terms of lower level functional primitives, but we must be careful not to confuse those with higher-level virtual method calls. Otherwise we are mixing OO interface with OO implementation, and we've already discovered in Perl 5 that that's a Bad Idea. Funnily enough, I found in Perl 5 that it's a good idea. Perhaps I should demonstrate; package MyObject; use base qw( Class::Tangram ); # define a string accessor for attribute "foo" our $fields = { string => ["foo"] }; sub get_foo { my $self = shift; return $self->SUPER::get_foo . "bar"; } sub set_foo { my $self = shift; my $new_foo = shift; return $self->SUPER::set_foo($new_foo . "baz"); } package main; my $object = MyObject->new(foo => "foo"); print $object->foo, "\n"; # prints "foobazbar" As you can see, instead of ever looking into the object's internal state, the "superclass" accessor is always used to find the object's internal state. This happens by munging @ISA at 'schema import' time, and building the accessors in an extra inserted class. Never do you have to use $object->{foo}; in a sense, so long as you don't circumvent the designed interface, the objects are already "opaque". Interfaces between organisms are cleaner when their innards stay in and their outtards stay out. Cleaner, perhaps - but how will they ever reproduce? Seriously, this isn't about innards (private attributes/properties) and outtards (public attributes/properties). This is about if you make a new version and replace one of the outtards, that the replaced outtards are not used anyway. Perhaps it would be better to stick to mechanical things. As you have already stated you do not want to include general Quantum Mechanical theory of extended entanglement into Perl 6 [1], it is unlikely that we will be designing organisms with it. Organisms do not fit the mould; they do not reduce easily into clean components, each piece of the whole is connected to the other via a quantum entanglement field. It is therefore not object oriented as the internal state of every part of the system affects the whole. So, I will use the analogy of an Automobile. If you replace the Engine of
Re: Do I need "has $.foo;" for accessor-only virtual attributes?
Piers Cawley wrote: > > Users of the class includes people subclassing the class, so to them > > they need to be able to use $.month_0 and $.month, even though there > > is no "has $.month_0" declared in the Class implementation, only > > "has $.month". We thought about defining the attribute variables that way, but decided that it would be clearer if they only ever refer to real attributes declared in the current class. Clearer in what way? This implies that you cannot; [ - refactor classes into class heirarchies without performing code review of all methods in the class and included roles. , >> - "wrap" internal attribute access of a superclass in a subclass ].map:{$_ ~ That's why it's generally a bad idea to use the C<$.whatever> forms outside your basic accessor methods. } This in turn implies that the $.foo syntax is, in general, bad practice! Yup. Not very huffmanised, is it? Making $.foo =:= $?SELF.foo, and getting to the "raw" attribute $.SUPER::foo seems like the better solution to me. But of course, it would, because that's how *I* program, and $?SELF != all(@coders). Then we could even sneak in making $.foo(bar) a not-so-offensive ./foo(bar), with ($.foo)(bar) meaning what $.foo(bar) currently means. But that really is a seperate issue, and speculation of it meaningless if we retain the current specified behaviour. Sam.
Re: Do I need "has $.foo;" for accessor-only virtual attributes?
Larry Wall wrote: : Do the following exist then: :has @x; # private, lexically scoped [...] :has %y; # private, lexically scoped [...] Yes, the sigil is fairly orthogonal to all this, hopefully. Yes, for isn't the sigil just a compact form of saying "does Hash" or "does Array" ? (as well as being part of the unique name, of course) Sam.
Re: Do I need "has $.foo;" for accessor-only virtual attributes?
Stevan Little wrote: Yes, we have. One thing to consider is that it is much easier to get the "Role order doesn't matter" thing when they are composed. Once you start keeping the roles around, you run into the possiblity for such things as "next METHOD" being executed in Role context. I wont even speculate on what that should/could/would do, because I think we just shouldn't go there. We talked briefly about considering this "flattening" as being a run-time state thing rather than necessarily taking place in the Meta-objects. Is this still tenable? Side effects like what happens if you do "higher level" stuff like run-time modification of Roles after they have been composed into classes can be addressed seperately. No, that's correct. We've just basically said that $.x is now a method call, and as long as you stick to that invocation syntax it just has to be declared as a method somewhere in the parentage/role-age of this object. But collisions in $.x declaration will be treated as collisions in method declaration. So we really are looking at closure based access to attributes. This also means that the idea behind P6Opaque as a storage format is very different. In theory, we could implement these style classes in a very "Inside-Out" manner. In a way, we could look at: has $.x is rw; as being sugar for this (pseudo) Perl 6: { my %x; $?CLASS.meta.add_method('x' => method ($self: ?$value) { %x{$self.id} = $value if $value.defined; %x{$self.id}; }); } Yes, precisely ... except the method returns a Proxy object. The proxy object responds differently depending on its context. This is why I wanted the "accessors" to be traits hanging off the code object itself, as described in http://xrl.us/guyx, as it makes this not suck - a null accessor can be quickly optimised away to direct variable access. There is a pugs test for these in t/oo/attributes/mutators.t Of course, this interface will need to be extended to support the full TIE-like interface that proxy objects support. Thankfully as we're a lot more object oriented these days, I think we might be able to get away with: my $hash = %object.hash_property; :FETCH => should return a Hash object (or Facade), ie .does(Hash) my $array = %object.array_property; :FETCH => should return a Array object (or Facade), ie .does(Array) As everything else is just a method call on the returned object. Exactly which methods are uppercased into "is accessor"-provided entry points is then a matter of style; though perhaps for a little sugar a few should be provided where the function names are awkward to type, in particular .(post_circumfix:<{}>) and .(post_circumfix:<[]>) To summarise with code for those who are lost; has $.foo; would be sugar for: has $foo; method foo is accessor( :FETCH { $foo }, :STORE -> $x { $foo = $x }, ); If you use \( $object.foo ) - that is, create a reference to the .foo property, you get a Proxy object; the above should be considered functionally equivalent to; has $foo; method foo is rw { return Proxy.new(:FETCH { $foo }, :STORE -> $x { $foo = $x }, ); } This is extended into the other sigil types; has %.foo; is sugar for this: has Hash $foo; # or has %foo, but really, the point is it's # an implementation detail, right? method foo is rw { return Proxy.new( :FETCH{ $foo }, # or a facade :STORE -> Hash $x { $foo = $x }, ) but { method post_circumfix:<{}>($key) is rw { return Proxy.new( :FETCH{ $foo{$key} }, :STORE -> $x { $foo{$key} = $x }, ); } }; } Doesn't that look nice and ugly! :-D Note that this means that taking a reference to a hash slot is actually returning you a proxy object that will access the hash when you call it. Sneaky, huh? This means that this doesn't have to auto-vivify the slot any more, closing the caveat found in t/builtins/arrays_and_hashes/exists.t by Darren Duncan: my $slot_ref = \( %foo ); This looks much tidier with Luke's nomenclature of "is accessor"; has Hash $foo; # or has %foo, but really, whatever method foo is accessor :FETCH { $foo }, :STORE -> Hash $x { $foo = $x }, :HASHENT -> $key is accessor :FETCH { $foo{$key} }, :STORE -> $x { $foo{$key} = $x }; Add brackets to suit. The HASHENT is an early idea for an optional shortcut; to avoid creating a facade when "all you wanna do" is define what happens when you treat the object property as a Hash/Array via $object.property{key}. But it's still sugar for the above "but { }" clause (or any other way of returning a Facade object that .does(Hash)). Well, if we ditch the
Re: Database Transactions and STM [was: Re: STM semantics, the Transactional role]
Yuval Kogman wrote: everyone gets to choose, and another thing I have in mind is the Transactional role... DBI::Handle does Transactional; To the STM rollbacker and type checker thingy this means that any IO performed by DBI::Handle invoked code is OK - it can be reversed using the Transactional interface it proposes. Is this needed, when you can just; atomic { unsafeIO { $dbh.begin_work }; unsafeIO { $dbh.do(...) }; unsafeIO { $dbh.commit }; } CATCH { $dbh.rollback; }; Why have STM like constructs if that's what you're going to do anyway? The point is to be able to compose unrelated atomic block into one atomic action. If we don't get some separation of concerns from STM we might as well be using locks. Sorry for the necro-equine flagellation, but I think STM would have to support general nesting to be useful. In fact I'd be highly surprised if the Haskell STM implementation doesn't already support it. We'll need this, because a "transparent" object persistence layer won't want data to mismatch the database in the event of a rollback, as Tangram takes some effort to ensure now in Perl 5. So it will be doing its own atomic { } stuff that will all "commit" to memory on the successful database commit, or undo changes in the event of a rollback. The end goal is to be able to give the DB layers enough hooks that we can say a well written one Just Works™ in the face of atomic { }. Does that seem relevant to the point you were making? Sam.
Re: Subroutine and Method Introspection
chromatic wrote: A12 and S12 describe introspection on objects and classes. The metaclass instance has the method getmethods() which returns "method descriptors". The design specifies several traits queryable through these descriptors. [...] Currently, there's no way to query these traits through introspection, nor is there a description of the descriptors beyond indicating that they're some sort of object. I have no strong feeling as to what type of object they should be, but they ought to support some sort of traits() method to return a list of [...] Well, arguably Stevan's perl5/Perl6-MetaModel is the best place to prototype such interfaces. Getting traits requires deeper introspection. You need to ask the Meta-Objects themselves what properties they support. In other words, by looking at .meta.meta you should be able to see this. Even though we're aiming to avoid the Smalltalk '72 problem[1] of meta-meta-meta-meta-model madness. There is some early rantings of it in modules/Perl-MetaModel/docs/perl6_meta_model.pod Quite how far the "turtles all the way down" principle works will be an interesting test of the design, I think. I wouldn't expect making changes to .meta objects 3-4 levels deep to work, and that they should be like a "reciprocal" (or a metaclass that can be its own metaclass). Sam. 1. Piers Cawley drew the prior art connection here. I forget the exact years, but there were two Smalltalk language versions, the first where each meta-model layer was independant, and the second where they had figured out how to make the system close back on itself simpler. Maybe someone can give a better description than this.
Re: Exposing the Garbage Collector
Piers Cawley wrote: Let's say I have a class, call it Foo which has a bunch of attributes, and I've created a few of them. Then, at runtime I do: eval 'class Foo { has $.a_new_attribute is :default<10> }'; Assuming I've got the syntax right for defaulting an attribute, and lets assume I have, the Perl runtime needs to chase down every instance of Foo or its subclasses and add an attribute slot (adding a method to a class is nowhere near as interesting, because every instance of the class shares a single class object). But adding an attribute is simply defining a new method in the Class' instance methods. And you don't need to chase down the objects for that. What you wrote could be implemented as; class Foo { has $a_new_attribute is :default(10); sub a_new_attribute is accessor :FETCH{ $a_new_attribute }, :STORE -> $val { $a_new_attribute = $val }, } } So this way the extra attribute can be lazily added. The other ways of finding out that the property should be there, such as the visitor pattern interface, will "trip" the part that adds the slot to the object. However I think this is somewhat besides your original point. Sam.
Re: Do I need "has $.foo;" for accessor-only virtual attributes?
Stevan Little wrote: This is extended into the other sigil types; has %.foo; is sugar for this: has Hash $foo; # or has %foo, but really, the point is it's # an implementation detail, right? method foo is rw { return Proxy.new( :FETCH{ $foo }, # or a facade :STORE -> Hash $x { $foo = $x }, ) but { method post_circumfix:<{}>($key) is rw { return Proxy.new( :FETCH{ $foo{$key} }, :STORE -> $x { $foo{$key} = $x }, ); } }; } I am not sure if it makes sense to handle whats inside the hash with the accessor. I think that is the responsibility of either the hash container type itself, or what you really need here is some kind of object to wrap your hash and get such fine grained control. But that is just my gut reaction. This is what the monkey-but syntax is about. The returned Proxy object must behave like a Hash for the property to behave like a hash, which (minimally) means implementing the post_circumfix:<{}>($key) method. Quite what that looks like in the metamodel is another question; the above makes it look like monkey-but can make anonymous sub-classes that derive new methods, which I inducted as being potentially legal syntax from the examples of monkey-but I've seen so far. Ideally this wouldn't have to happen every time the attribute is accessed ;). So, if you want a "visitor pattern", you grab a visitor iterator via the Meta-Objects, right? Which could also solve the STORABLE_freeze/STORABLE_thaw / Pixie::Complicity / etc problem by unifying the way that "foreign" objects can marshall themselves to Perl objects when required. You mean for persistence operations? Where you need to thoroughly inspect the object to save it to disk/DB/etc. Yes, that sort of thing. Sending objects between processes in some marshalled format, like YAML, XML, binary/Storable, etc. But there are plenty of other applications of the visitor pattern; I think a nice tidy split would be to either allow walking at the public attribute or the private attribute level. In the face of AUTOMETH, the public "attibutes" of a Class might not be trivial to find, or indeed be infinite. So the class needs to have a way to tell the visitor iterator which public attributes are considered to represent the entire state of the object. Of course, the same problem doesn't apply for visiting private attributes, which are either there or not. I can see arguments for walking at both levels for certain tasks. I think the ideal way to write something like that would be to write is as a metaobject. Meaning using the Persistent metaclass. As opposed to using something on the "user" side of things to interogate the "meta" side of things. But this may be because I am too deep into the meta side if things right now. Yes, I imagine that the iterator will be returned from a metaobject method, with gratuitous use of callbacks to make the simple uses really simple; including the logical equivalent of $File::Find::prune = 1. Sam. ps. Monkey-but Monkey-but Monkey-but
RE: $object.meta.isa(?) redux
On Wed, 2005-08-10 at 21:00 -0400, Joe Gottman wrote: >Will there be an operator for symmetric difference? I nominate (^). That makes sense, although bear in mind that the existing Set module for Perl 6, and the Set::Scalar and Set::Object modules for Perl 5 use % for this (largely due to overloading restrictions, of course). There is no unicode or mathematical operator for symmetric difference, it seems. Sam.
Re: Time::Local
On Mon, 2005-08-15 at 16:33 -0700, Larry Wall wrote: > : I would assume that you would choose time 0.0 = Jan 1, 2000 at 00:00:00.0 > : TAI (December 31, 1999 at 23:59:29.0 UTC), making the whole thing free of > : any UTC interferences. But there is an argument for making the zero point a > : recognizable boundary in civil time. > That's my leaning--if I thought it might encourage the abandonment of > civil leap seconds, I'd be glad to nail it to Jan 1, 2000, 00:00:00.0 UTC. If we're going with TAI, can't we just nail it to the epoch it defines, instead? Sam.
Re: Time::Local
On Mon, 2005-08-15 at 22:24 -0700, Larry Wall wrote: > : > That's my leaning--if I thought it might encourage the abandonment of > : > civil leap seconds, I'd be glad to nail it to Jan 1, 2000, 00:00:00.0 UTC. > : If we're going with TAI, can't we just nail it to the epoch it defines, > : instead? > Because I'm a megalomaniac, silly dilly. Plus I like round numbers. > Not to mention the fact that it makes it really easy to calculate days > since 2000, give or take a squishy leapsecond or three. > But the best part is that if we abandon UTC leap seconds for civil time, > we don't have to remember leap seconds going forward, only backward from > 2000. Why on earth would you want to encourage such a short sighted programming practise? The earth wobbles like a spinning top. In fact its speed increased after the two major Earthquakes in Antarctica and Indonesia last December. Subtle adjustments are necessary to track this; perhaps including the possibility that the Earth's rotational speed might change by more than one second per day. Just why were the Mayan, Babylonian and Aztec calendars 360 days long, anyway? Were days 20 minutes longer then? These are questions I've been wondering as an old machine I have loses about this amount ... it would certainly explain it if the machine was actually so old it used a Mayan timer chip. (Sometimes the impossible has a coherency to it that the merely improbable simply lacks...) How about killing the argument by saying the epoch is only guaranteed by the language to be relative to the same value within the lifetime of a script, relative to 0.0 TAI in 1958 or whenever it was. Then Perl 6 implementations are free to pick their own epoch, and possibly also annotate the time via traits/properties as not being confirmed to be NTP synced, etc. Date modules (which, really, people should be using) then have something sensible to work with and can easily provide the alternate times. Environments that really can't guarantee an absolute epoch can simply return unanchored times and let the modules throw exceptions when you try to convert them to real times or times with impossible levels of accuracy. Sam.
Re: Time::Local
On Wed, 2005-08-17 at 01:28 -0500, Dave Rolsky wrote: > > Why on earth would you want to encourage such a short sighted > > programming practise? The earth wobbles like a spinning top. In fact > It's hardly short sighted to want leap seconds to be abandoned (not in > Perl but world wide). The few people who _really_ care about syncing to > midnight can still have them, but the rest of the world would be just fine > with a leap hour every couple hundred years. Well, right now one of the great things about looking at the wall to read the clock and see the time, is that you know that based on the time of day and the time of year, and where you are, roughly how far through the actual solar day it is. It's crude, but useful. Just ask a Dairy Farmer. What else do you want the time of day to represent? You would prefer it something completely arbitrary, just to make it easier to program with? That we don't just use a straight solar clock is probably down to the fact that it was technically infeasible to have one without a sundial, which obviously doesn't work at night or in England. > > alternate times. Environments that really can't guarantee an absolute > > epoch can simply return unanchored times and let the modules throw > > exceptions when you try to convert them to real times or times with > > impossible levels of accuracy. > Great, so now code that works in one environment throws a "cannot find an > up-to-date leap seconds table" exception in another? Eek! Well, only if you try to do something silly like ask for the number of seconds between two points of time in different days a long time in the future, where those times were composed from Gregorian components. If you were to ask for the number of minutes, or not cross the boundary of when leap seconds are allowed, then it would still be OK. I would expect a similar exception if I tried to calculate the number of hours between two dates in an unknown timezone. Of course feel free to consider this all worthless heckling, given the lack of time I've been putting towards an implementation of all this ;). Sam.
Complex types
Hi all, Is it intentional that S09 lists unboxed complex types, but equivalent Boxed types are missing from the "Types" section in S06? Sam.
Re: new sigil
On Thu, 2005-10-20 at 08:45 -0700, Larry Wall wrote: > More info. ¢T is a scalar variable just like $T, but enforces a > class view, so you can use it as a class parameter, and pass any > object to it, but only access the classish aspects of the object. > The only other big difference is that you can use it in the class > syntactic slot, so it's legal to say ¢T $x where it would be illegal > to say $T $x. Is this necessary? Isn't putting a variable before another variable like that in the correct context (subroutine declaration, in this case), enough to imply that the variable "does Class" ? While I'm not arguing against another sigil type, I think this would distinguish it from the other sigils % and @, which are just an implicit (does Hash) / (does Array), as well as being a part of the unique name, as I understand it so far. This makes me wonder which language feature is used to describe sigils themselves. Can I define my own sigils with their own type implications? Sam. ps, X11 users, if you have any key bound to "AltGr", then "AltGr" + C might well give you a ¢ sign without any extra reconfiguration.
Re: Why submethods
On Sat, 2005-10-29 at 17:30 -0400, Stevan Little wrote: > However, it could also be that the creator of Foo did not intend for > subclasses to be able to "Just Work", and that the whole idea of Foo > is to do a "Template Method" style pattern in which subclasses must > implement the &help_process_data submethod in order for things to > work. This is an entirely valid usage for a submethod, and in fact, I > think it is an excellent way for implementing the "Template Method" > pattern. Hmm. I think I much prefer; method you_must_implement { ... } or a trait, perhaps method you_must_implement is required; I think that methods disappearing out of scope in subclasses is just Nasty And Wrong™, for the exact reason Luke outlined. Side-effects like that are just asking for trouble IMHO. > It is also possible that we could bring over the role idea of > "required methods" and have the same basic principle relate to > classes and submethods. If marked as such, a submethod is required to > be implemented by a subclass, or class composition fails. > I think that could be a useful feature which would allow very safe > re-use along those lines. Good point, which is why the "is required" as above would be better. It seems to me that there's an awful lot of specification going into these varied types of methods. Method Type Purpose DispatchVisibility ---|--|---| $.method()| external API| MMD | all $.submethod() | refactoring | package | single $:private() | internal API| package | single I must admit I also fail to see the difference between submethods and private methods. And what do I use for methods that I don't want to make visible to "the world"? Perhaps a more useful definition might be that submethods are only available on $?SELF (and are still subject to normal dispatch). Sam.
Re: $_ defaulting for mutating ops
On Wed, 2005-11-02 at 11:46 -0700, John Williams wrote: > It is not so much an operator, as it is a subroutine with really strange > syntax, and the side-effect of changing the $_ variable. You need to use > an operator to get it to affect a different variable. operators _are_ subroutines. There is no difference. multi sub *infix:<*> (Set $one, Set $two) returns Set { $one.intersection($two); } Sam.
Re: $_ defaulting for mutating ops
On Wed, 2005-11-02 at 09:03 -0500, Rob Kinyon wrote: > I think the difference comes from the Principle of Least Surprise. The > various operators being discussed in this thread are all operators > which are in languages that have common use - C, C++, Java, the .Net > stack, etc. Regexen and the various built-ins are generally considered > to be Perl-specific, so if they're weird, this is just a Perl-ism. The > PoLS doesn't apply. > > Yes, from a consistency point of view, ALL operators should default to > $_ or some other sensible item ($*STDIN for <>, etc). However, the > PoLS does need to guide our decisions. I think the PoLS should be applied firstmost and foremost to a person who is learning the language without any preconceptions of how previous languages work. The logical building blocks of how the language works should build on each other; the fewer exceptions relative to *those foundations* the better. Specifically, catering for the preconceptions of how the language behaves as a whole to those trained in lower order languages like you mention (though is .net a language?) should probably be avoided. That being said, there are probably other more pressing reasons that ops should not accept $_ as default; I would guess, for a start, it makes determining semantics very difficult. Does ++; mean &postfix:<++> or &prefix:<++> ? Sam.
Re: scalar/array contexts in perl5 vs. perl6
On Sun, 2005-12-04 at 13:10 -0500, Mike Li wrote: > what is a good translation of the following C into perl6? > [...] >int x = 0; int y[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; y[x++]++; /* line > that matters */ [...] > > > in perl5, i would've written something like: > > my $x = 0; my @y = 1..9; @y[$x++]++; print "$x\n"; print "@y\n" > Note that when you run this in perl 5: $ perl -we 'my $x = 0; my @y = 1..9; @y[$x++]++; print "$x\n"; print "@y\n"' Scalar value @y[$x++] better written as $y[$x++] at -e line 1. 1 2 2 3 4 5 6 7 8 9 You've already used a Perl6-ism! > but in perl6, the '@' sigil always means list context, so should i > write the following? > > > my $x = 0; my @y = 1..9; [EMAIL PROTECTED]; print "$x\n"; print "@y\n" > I'm not sure what you're trying to do with all those derefs, but the only change you need to make to your original code is to put the @y interpolation inside a block; { my $x = 0; my @y = 1..9; @y[$x++]++; print "$x\n"; print "{ @y }\n" } Try downloading and installing pugs; it's great for trying out this sort of thing! Sam.
Re: Some thoughts on threading
On Thu, 2005-12-08 at 17:16 +0100, Ron Blaschke wrote: > The Free Lunch Is Over: A Fundamental Turn Toward Concurrency in Software." > [1] He starts with "The biggest sea change in software development since > the OO revolution is knocking at the door, and its name is Concurrency." Perhaps have a read of: http://svn.openfoundry.org/pugs/docs/AES/S17draft.pod Two non-traditional methods of concurrency are discussed; * atomic blocks - an atomic { } guard around a block that, assuming the block performs no I/O, will guarantee atomic success or failure of the block. * co-routines - essentially co-operative multitasking between 'blocking' threads that actually switch tasks when they block (or yield). There is also some stuff there on other types of timesharing and multiprocessing - Threads, Processes and Multiplexing (like Ruby). Sam.
Re: handling undef - second draft
On Sat, 2005-12-17 at 17:27 -0800, Darren Duncan wrote: > 3. A flag that says we know that some operation failed, such as would > be exploited in the " err " > situations. > This concept is like an exception which isn't thrown but returned. "Dropping" an exception, perhaps? :) > 1. I accept the proposal that we just make another class that > implements the SQL concept of a null value, perhaps named Null or > SQL::Null, rather than having this behaviour in the core language, so > that should simplify the rest of the discussion. If someone wants > undefs to propagate through expressions like SQL's NULLs do, rather > than failing or defaulting, then this can be done with the new class. > A Null object would be defined but false. It would overload standard > operators so that most expressions involving it would propagate a > Null object, or compare unequally as desired. Therefore, this sort > of behaviour will be isolated and standard data types won't behave > this way by default. I think this is out of scope; if a module chooses to use "undef" as a well defined part of its interface, that's its call. > 2. Modify the 'Exceptions' section of S04 so that built-in functions > return a 'error' or 'failure' or 'exception' if they fail, instead of > an "interesting value of undef". The behaviour and handling of or > response to these is essentially unchanged, but the value is called > something more distinctive and it is not called 'undef'. Instead of > testing for .defined(), invoke a different method like .failed() or > .error() instead; invoking .defined() on an error should perhaps > return true instead of false. Perhaps update err() to activate on > the error rather than or in addition to undef. I'm not sure what this adds. You ask for a system call, you don't get a result. In other words, the result is undefined, and it has a supplemental error. It just seems a bit silly to make the "err" operator have to call *two* methods in sequence, it would be a hack just for system calls. Besides, aren't all these values just "undef but { .error = '...' }" etc? > 3. Have the functionality of 'use fatal' turned on by default in > large programs, though not one-liners, and it can be turned off > otherwise. It is safer to have them brought to your attention where > you make a conscious effort to respond to or dismiss them. > > 4. An expression or statement having an 'err' would impose a > try-block around the expression it is attached to, so the right thing > still happens when errors are thrown by default. And 'err' is a > conscious effort to deal. > > 5. Autovivification in larger programs should not happen by default, > unless you have something like 'use autovivify;'. But with > one-liners it would work by default. > > 6. Attempts to use undef where a defined value is expected, such as > wherever they currently generate warnings, should be upgraded to a > stricture and fail by default in larger programs. But like with > other strictures, this would be turned off by default in one-liners. > If the DWIM behaviour is wanted in larger programs, one can say 'no > strict undefs;' or such. I think we need to be very careful not to impose too many good practice measures on the developer. All of the situations you describe (except perhaps autovivification) can potentially be picked up by the compiler, and warnings generated. > There may be remaining holes in my suggestions, but hopefully I dealt > with the worst ones from the preceeding first draft. FWIW, I didn't read the first thread. Sam.
Re: Obsoleting "require 'Some/Module.pm'"
On Mon, 2005-12-19 at 14:58 +0200, Gaal Yahas wrote: > Can we make this work? > > my $mod = "Some::Module"; > require $mod; What about casting it to a package; require ::{$mod}; (not sure if the syntax is quite right) Sam.
Re: Another dotty idea
Damian Conway wrote: >I'm not enamoured of the .# I must confess. Nor of the #. either. I wonder >whether we need the dot at all. Or, indeed, the full power of arbitrary >delimiters after the octothorpe. > > Agreed. >What if we restricted the delimiters to the five types of balanced brackets? >And then simply said that, when any comment specifier (i.e. any octothorpe) is >followed immediately by an opening bracket, the comment extends to the >corresponding closing bracket? > >Then you could have: > > #[ This is a comment ] > #( This is a comment ) > #{ This is a comment } > #< This is a comment > > #« This is a comment » > > This does mean that if you comment out blocks with s/^/#/, you mess up on: #sub foo #{ # if foo { } #} >That would also mean that # is *always* the comment introducer >(and the *only* comment introducer). > > I agree with this goal. I propose this form: #* *# As a leading * on a line is unusual, and it also has visual similarity to multi-line comments in C. >As for gappy dotting, that would become: > > $x#[ ].foo() > or: > > $x.#< >foo() > > For comparison: $x#* *#.foo() or: $x.#* *#foo()
Re: Another dotty idea
Larry Wall wrote: >On Tue, Apr 11, 2006 at 12:26:13PM +1200, Sam Vilain wrote: >: This does mean that if you comment out blocks with s/^/#/, you mess up on: >: >: #sub foo >: #{ >: # if foo { } >: #} > >Well, actually, that still works. > > Oh, true :-) But this fragment dies: #sub foo #{ # bar { } unless baz #} Unless you consider the idea of balancing the {}'s inside the comment, which I think would be just plain nasty. The #* .. *# form actually has a natural follow-on I didn't think of before: #[ This is a comment ]# #( This is a comment )# #{ This is a comment }# #< This is a comment ># #« This is a comment »# While technically the same thing applies to code that uses these delimited, it means that the block I gave is now a parsefail. #-comments directly following closing braces are probably sufficiently uncommon for this not to be such a problem. >To be certain though, you could always >use s/^/##/ or s/^/# /. > > I guess that works, but it breaks convention of # somewhat. >Even better is: > >=begin UNUSED >sub foo >{ > if foo { } >} >=end UNUSED > >And I don't really care if that's not what people are used to. >The whole point of Perl 6 is to change How Things Work. > > Sure, but there is still the principle of least surprise to worry about. Sam.
Re: Another dotty idea
Larry Wall wrote: >: But this fragment dies: >: >: #sub foo >: #{ >: # bar { } unless baz >: #} >I don't see how that's different at all from the first example. > > “#sub foo” is parsed as a comment token “#{ # bar { }” is the next comment token then we get “unless baz” Unless you are balancing {}'s inside the # blocks, like q{ } does. Sam.
Re: using the newer collection types
Darren Duncan wrote: >Speaking a little more technically, a Relation has 2 main components, >its heading and its body. The heading is a set of 0..N keys (called >"attributes" in relation-land), and the body is a set of 0..N >Mappings (called "tuples" in relation-land), where they set of keys >of each Mapping is identical to the Relation's heading. Its very >likely that a language-embedded Relation implementation would >actually not repeat the keys for each member Mapping, but we can >conceptualize as if they were present for simplicity. > > I don't think this terminology or these restrictions are particularly useful. I do think that a Pair should be a sub-type of a more general "Tuple" type, with the 'where' clause being { .items == 2 } or something like that. I think that the most flexible arrangement is to define; - a Collection as a Bag of Tuples - a Relation as a Collection where the tuples have a shape and no duplicate tuples are allowed (but Relation does not need to be a core type) Then, Mappings, Sequences, etc, become sub-types of one of the above two types. For instance, a sequence is a Collection of (Int, Any) where the first Int is unique across the collection. Similarly a Mapping is a Collection of (Any, Any) where Unique(0). something like role Tuple { has @.items }; role Collection { has Tuple @.tuples }; subset Pair of Tuple where { .items.items == 2 }; subset Bag of Collection where { ! .tuples.grep:{.items > 1 } } subset Set of Bag where { all( .tuples.map:{ .items } ) == one( .tuples.map:{ .items } ) } subset Mapping of Collection where { ! .tuples.grep:{ .items != 2 } } subset Array of Mapping where { .tuples.grep:{ .items[0].isa(Int) } } subset Hash of Mapping where { .tuples.grep:{ .items[0].does(Str) } } The above should probably all be written in terms of parametric roles (see S12), but for now the above run-time checking versions should hopefully express the relationships between the core collection-like types as I see them. That sounds like it might bite, but you wouldn't normally access an Array as a Collection of (Int, Any), you'd access it as an Array, so you get the nice .post_circumfix:<[ ]> method that makes array access easy. You don't care that it has this higher order type as a parent class, and you certainly wouldn't care for the 'bare' Collection interface (as for one, you don't want to have to deal with the Integer keys). And it is probably all backed by native methods. I'm prototyping much of this using Moose in Perl 5, however Hubris is delaying its release :-) >Moreover, the Relation type has these >operators that the Set type doesn't have: rename(), project(), >restrict(), extend(), join(), divide(), summarize(), group(), >ungroup(), wrap(), unwrap(), matching(), etc. > Is there a reference for the meaning of these methods? >1. Are Sets or Junctions allowed to contain undefined elements? Can >undef be a key of a Mapping or Hash? > > undef.isa(Object), so you should be able to use it as you would any other object. I would definitely not think of it as the absence of a value in this context. >2. What actually is the practical distinction between a Set and a >Junction? Why would someone use one over the other? I recognize >that the use of Junctions is supposed to make parallelism easier, as >iterating through one is known to be order independent. But, >conceptually a Set and a Relation are exactly the same; you could >process their members in any order and/or in parallel as well. So is >the use of a Junction effectively like a compiler flag to make >certain kinds of Set ops faster at the expense of others? > > Well one side effect at the moment is that Junctions are immutable, whilst Sets are mutable. This is perhaps a deficiency in my original Set.pm design; all of the mutating functions should be in a seperate role, really (or just not be mutators). >6. Can I declare with named Set (or Junction) and Mapping typed >variables and/or parameters that their members are restricted to >particular types, such as Str, as I can with Arrays and Hashes, so >that Perl itself will catch violations? Eg, can I say as a parameter >"Set of Str :$heading?" or "Set of Mapping(Str) of Any :$body?" so >Perl will check that arguments are suchwise correct? > > These are variously called "Generics" (ada I think, Java 1.5+), "Parametric Types", "Higher Order Types" (Pierce et al), "Generic Algebraic Data Types" (Haskell) In Perl 6 they are parametric roles (as in S12 mentioned above) >7. Can we add some operators to Mapping that are like the Relation >ones, so that implementing a Relation over Mappings is easier (or, >see the end of #8)? Eg, these would be useful: rename(), project(), >extend(), join(). In particular, implementing join() into Mapping >would help save CPU cycles: > > Again, a reference to a prototype of the behaviour would be useful. Sam.
Re: using the newer collection types
Darren Duncan wrote: >>>Is there a reference for the meaning of these methods? >>> >>> >>There are many written references to these methods; just type >>"relational algebra" into Google. >> >> > >I will add that the first hit on such a search, the Wikipedia page on >relational algebra ( http://en.wikipedia.org/wiki/Relational_algebra >), is a perfectly good primer on what relational algebra is and what >its importance is. > > Thanks for the pointer. >While this may not actually change anything, I should point out that >every collection type can also be expressed in terms of a Relation >definition and/or they can all be implemented over a Relation (whose >members are actually always unique). For example: > >1. A Set of Any is a Relation with one Any attribute. >2. A Bag of N Any attributes is a Relation of N+1 attributes, where >the extra attribute is an Int (constrained >= 1) that counts >occurrances of the distinct other attributes. >3. A Mapping can be a Relation of 2 Any attributes. >4. A Hash is a Relation of 2 attributes, Str (key) and Any (value), >where the key has a unique constraint. >5. A Seq is a Relation of 2 attributes, typed Int (>= 0) and Any, >where the first shows their ordinal position and the second is the >actual value; the first has a unique constraint. >6. An Array is the same, assuming it is a sparse; if it is not >sparse, there is an additional constraint that the greatest Int value >is the same / one less than the count of Relation members. > > I don't know if anyone will care, but you can't emulate the raw "Collection" type with this fixed Relation type. That is, a collection of tuples, each of which may be of differing length and type. This is what leads me to think that Collection is the more generic role. I'm not saying Relations are not useful, perhaps they are more useful than Collections in the practical case, but they are a sub-type. Also, I don't agree with the notion of a "header" of each relation. It has a type for each tuple item, sure, but "header" just sounds like the sort of thing you want in a ResultSet, not a Relation. Sam.
Re: using the newer collection types
Darren Duncan wrote: >>Also, I don't agree with the notion of a "header" of each relation. It >>has a type for each tuple item, sure, but "header" just sounds like the >>sort of thing you want in a ResultSet, not a Relation. >>Sam. >> >> >A relation's heading is essentially the definition of the relation's >structure, and is not redundant if the relation has no tuples in it, >which is valid. > > The Relation has a type, which is a Relation of Tuples of something. The "Header" you refer to is the higher order part of the Tuple, the "something". Sam.
Re: ACID transactions for in-memory data structures
Rob Kinyon wrote: >On 5/15/06, Audrey Tang <[EMAIL PROTECTED]> wrote: > > >>Rob Kinyon wrote: >> >> >>>I'm pretty sure it wouldn't be very feasible to do this natively in >>>P5. But, would it be possible to do it natively in P6? As in, >>>supported within the interpreter vs. through some sort of overloading. >>> >>> >>Look at "is atomic" in S17draft, and Software Transaction Memory in general? >> >> > >Would there be a way for me to say "Yes, I understand that Perl may >not generically understand how to revert this outside resource, such >as a database, but I do." and do a catch-type block for the revert? > > There was discussion about this on one of the dbi2 lists at some point. I think a minimal API was even fleshed out - but it probably died there and would love someone to pick it up. Sam.
Re: packages vs. classes
Larry Wall wrote: >'Course, I left out everything about prototype objects there... > >The name Foo also (in context) represents an uninitialized object of >the class in question. Any object, initialized or not, can get at >its type handlers by saying > >Foo.meta >$foo.meta > >and, in fact, the Foo.^bar syntax is just short for Foo.meta.bar. > > Perhaps saying it is like: Foo.meta.get_attribute("bar") Would be safer. Don't want to stomp on the meta-objects. >[...] >of the actual magic being defined elsewhere. It would be possible >to access classes et al. only via the mechanisms supplied by the >metaobject protocols, but that would be kind of like the bad old >[...] > > Right, but we should really ship with at least a set of Meta Object Protocol Roles, that covers the core requirements that we will need for expressing the core types in terms of themselves; - classes and roles - attributes and methods - subsets (ie constraints/subtypes) - generics (including, by induction, nested generics) I *think*, at this point, that's all that are necessary. They are actually quite a useful set for the concerns I raised earlier about automatically inferring relational information from the metamodel (if only I knew these terms back then... ;)) http://groups.google.com/groups?threadm=200303042358.56560.sam%40vilain.net People can instantiate the roles that cover all that to an actual metaclass in whatever way they like (eg, Moose::Meta::Class->isa(Class::MOP::Class)), but not having to detect the type and then figure out how to talk to it for at least the core of the object system would be good. People can diverge completely with completely incompatible metaclasses that don't .do those roles, the only side effect of which being that people who write code for the standard Perl 6 metamodel will be incompatible, and maybe some ways of setting up the class won't work without another layer of trickery. I *think* that's what you're getting at. Of course, it shouldn't be prohibited just because it smells. On different note, there should be nice, per-class ways to make type constraints not simply code blocks - otherwise too much reverse engineering will be required to do the final stage of compiling typesafe code, where you close the classes and discard all the runtime type checks. An easy example of this is generics. With "where", this is what you write (ignore the syntax errors for now): class "Array of Str" is Array where { $_.isa(Str) for @$_ } But that sucks, because that information about the type of the container is buried deep within the code reference, is slow, and we can't build our methods with the right signatures. So, we write; role Array[::T] { ... } class "Array of Str" does Array[Str]; Great. Now that information is available to Array in a structured manner and the signatures can be built correspondingly. But to represent the core types like Mapping or Set, we also need, for instance, the "unique" constraint to be represented as an object, not a code block: For instance, role Mapping[::T1, ::T2] does Coll[::T1, ::T2] where Unique(0); The "where Unique(0)" is the important bit. What is "Unique", and who uses it? In my prototypes, I've been considering it being the job of the composing class or role to handle that, as a meta-object method call. So, the above might call Coll.meta.Unique(0) (look, I'm stomping all over the meta-object now) during the composition of the "Mapping" role, and it uses this to affect the methods that it builds until you get something that behaves not entirely quite unlike a Mapping. However feel free to continue to handwave for now. Personally I'd like to see this synoptic before the Perl 6.0 release, to avoid the mistakes of other (*cough* C# *cough* Java 1.5 *cough*) languages that slipped on getting the generics in their libraries, to their ultimate detriment. Sam.
Re: hyp-op examples of a Bag type in S03
Darren Duncan wrote: > $bag1 >>-<< 1; # Bag(2,7,[1,Seq(8,2)],7) > $bag2 >>-<< (1,1,1,1); # probably the same > $bag3 >>-<< (1,1,2,1); # ? > > Bag's won't .does(Array) or .does(Coll[Seq,...]), so that hyperoperator won't work - if anything it would try to add the (1,1,1,1) list to all of the elements of the bag. You'd need to put the bag in something that does imply ordering first. This applies to any unordered collection, bags or sets. Sam.
Re: [svn:perl6-synopsis] r9307 - doc/trunk/design/syn
[EMAIL PROTECTED] wrote: >+In either case this sets the C property of the container to C. >+Subroutines have a variant of the C property, C, that >+sets the C property instead. The C property specifies >+a constraint to be checked upon calling C that, unlike the C >+property, is not advertized as the type of the routine: > It doesn't have to be run-time; it could also merely alter the signature of the (implied or explicit) return() function within that sub. Sam.
Re: Concurrency: hypothetical variables and atomic blocks
Jonathan Lang wrote: >How does an atomic block differ from one in which all variables are >implicitly hypotheticalized? I'm thinking that a "retry" exit >statement may be redundant; instead, why not just go with the existing >mechanisms for successful vs. failed block termination, with the minor >modification that when an atomic block fails, the state rolls back? > > State rolling back automatically is the key feature of STM. However, it can only cover pure perl state; any time that you enter a function that performs I/O of any kind, then you are forcing bad things to happen. With Haskell this is sorted out by making the default "pure", and everything else must be in a Monad. However we're not into bondage here so "is pure" is not default. Instead we just die and rollback just before I/O is attempted. In principle, the compiler could automatically attach "pure" traits to all functions and methods that it can prove will never perform I/O and warn about this at compile time. It might be possible for clever classes to circumvent this and carefully call special unsafeIO() methods, and be passed messages about the STM and hope that they do the right thing. I don't know that anyone's explored this area in depth in Perl 6 space. >Also, what can "retry_with" do that testing the atomic block for >failure can't? > I think the answer lies in the "checkpointing" references in that document. I don't know whether that's akin to a SQL savepoint (ie, a point mid-transaction that can be rolled back to, without committing the entire transaction) or more like a continuation that when resumed can see the atomic changes, and when exiting finally applies them (or rolls back). Perhaps someone else will have more of a clue. Sam.
Re: Concurrency: hypothetical variables and atomic blocks
Daniel Hulme wrote: >>How does an atomic block differ from one in which all variables are >>implicitly hypotheticalized? >> >> >I assume that the atomicness being controlled by some kind of lock on >entry, it also applies to I/O and other side-effecty things that you >can't undo. > The lock on entry approach will only be for non-threaded interpreters that don't know how to do real STM. Sam.
Re: Perl5 -> Perl 6 Translations Design Document
Sage La Torra wrote: >Hello all, > >I'm the student picking up on the translation work lwall started. Since the >perl 5 parser is more or less complete, I've headed straight to the >translation work. I'm going to be taking on the translations a few at a >time, starting with the easiest translations and moving to the more complex. >I've got a design document detailing the first few translations I'll be >handling, and I'd greatly appreciate feedback and advice. Larry already took >a good crack at it, catching a few things I had stupidly thought were >simpler then they are, and now it's ready for general review. > >The current version can be found at >http://infohost.nmt.edu/~slatorra/conversionstageone.txt > >Any advice/comments/criticism on the document and even ideas on >implementation would be greatly appreciated. > > Looks like a reasonable starting point. I assume that the "AST" will include comment nodes etc? Sam.
Re: easier duck typing in .can
Yuval Kogman wrote: Since CANDO is a multimethod, IMHO this can be safely extended to allow: $object.can(Class); $object.can(Role); to better support duck typing. Why would you not use .does or .isa there? Are you wanting this to go through all of the Class/Role's methods and check that the $object.can() them? I think that perhaps .can($Method) (where $Method.isa(Meta::Method)) would be acceptable, then .can(Role) can either be defined to be .can(all(Role.get_methods)), or we just leave the user to use that snippet - after all, such extreme duck typing is expensive and shouldn't be huffmanised overly IMHO. We want people to use the Role objects unless they have a really good reason, and besides you can always just wrap things up in a Facade if you have to. Sam.
Re: lvalue functions and lvalue parameters
Jonathan Scott Duff wrote: >> sub cond(Bool $c, $a, $b) is rw { >> if $c return $a else return $b; >> } >> >> Will this fail because $a and $b are not rw? If so, will it fail at run- >> or compile-time? What about this: >> > That looks like it should be a compile-time failure to me. > Depends on the interpreter of course, but ideally, yes, compile time. >> sub cond(Bool $c, $a is copy, $b is copy) is rw { >> if $c return $a else return $b; >> } >> >> Is it allowed, and if so is the behaviour to return a writeable copy of >> $a or $b? I imagine that in any case >> > I'd expect a compile-time failure here too, or at the very least a > warning. Besides, returning a local copy each time hardly seems > useful, except perhaps as a way to leak memory. > It doesn't have to be a real copy, that's up to the implementation to apply whatever COW mechanism it likes. The type of $a and $b in this case is compatible with the return type of the function, so it should be fine. This example is a bit useless - cond($x, $a, $b) = $foo won't store the result anywhere. So this could be a warning along the lines of "useless use of variable in void context" (but more tailored to this condition) >> sub cond(Bool $c, $a is rw, $b is rw) is rw { >> if $c return $a else return $b; >> } >> >> will do what I want. >> > That is what I would expect too. > Right. >> my Int $a is constant = 0; >> my Int $b is constant = 0; >> (cond(True, $a,$b))++; >> > > We have a "constant" declarator now, so that would be > > constant Int $a = 0; > constant Int $b = 0; > (cond(True, $a,$b))++; > > and that should fail at compile time because the compiler knows that > $a and $b are constant and can't be rw. > Indeed it should, with the same disclaimer as above re: compile/runtime Sam.
Re: features of and declaring Mapping|Set|Hash values|variables
Darren Duncan wrote: > 1. Looking at the language in Synopsis 6 for data types, I see: > > Set Unordered Seqs that allow no duplicates > JunctionSets with additional behaviours > PairSeq of two elements that serves as an one-element Mapping > Mapping Pairs with no duplicate keys > > I would like to know if Mapping.does(Set) and whether I could use the > full range of Set operators on them, as I would like to do? > > My impression is that it be reasonable to define a generic Mapping as > being a Set whose elements are all constrained to be Pairs, and > further that all keys of those pairs are distinct; eg: > >subset Mapping of Set where { > all(.members).does(Pair) and +all(.members.map:{.key}) == +all(.members) >}; > Hmm. I still think a more generic Collection makes this more correct. subset Set of Collection where { all(.members) =:= one(.members); } subset Mapping of Collection where { all(.members).does(Pair) and all(.members).key =:= one(.members).key; } ie, being a Set is introducing a constraint, which is then duplicated in the Mapping type. Now, you could argue that the Set constraint is "shadowed" by the Mapping constraint and the constraints analysis system could prove it does not need to be applied, but that's quite a high level thing to expect the compiler to do at this point, I think. However the above definitions, in my opinion, miss the potential of parametric roles. > If this is true, then I suggest rewording the above line in Synopsis > 6 to better clarify the situation, like this: > > Mapping Set of Pairs that allow no duplicate Pair keys > > It would be very useful to employ Set operations like subset() or > union() or difference() etc on Mappings, that return Mappings. > > 2. Similarly, I would like to know if Hash.does(Mapping) and so that > we can therefore use all the Set and Mapping operators on Hashes, but > that their output is Hashes. Likewise very useful. > How about; Mapping Collection of Pairs that allow no duplicate Pair keys. If "Collection" is parametric it must be a role, which means that we can't directly subset it; we use role composition instead (I'm assuming that we can use where{} during role composition). role Set of Collection[Item] where { all(.members) =:= one(.members) }; # one of these role Mapping of Collection[Pair] where { all(.members).key =:= one(.members).key }; # what is a pair, anyway? role Pair of Seq[Item,Item] { method key of Item { &.item(0) } method value of Item { &.item(1) } }; role HEK of Seq[Str, Item] does Pair; role Hash of Collection[HEK] does Mapping; role ArrayItem of Seq[Int, Item] { method index of Int { &.item(0) } method value of Item { &.item(1) } }; role Array of Collection[ArrayItem] where { all(.members).index == one(.members).index; } { method post_circumfix:<[ ]>(Int $index) of Item { my $seq = first { .index == $index } &.members; $seq ?? $seq.value :: undef; } } There are some problems with the above, notably "Pair" could be parametric, and the Array post_circumfix method should be an lvalue return. I'm terribly sorry I haven't dedicated more time to developing this into a working prototype module for Perl 5. RSN I hope. > 3. I missed the syntax for declaring anonymous Set or Mapping in the > Synopsis. Has it been defined yet? > > Something that is distinct from: > >[1,2] # Array >(1,2) # Seq >{1=>2,3=>4} # Hash >(1=>2) # Pair in positional context >1=>2 # Pair in named context >all(1,2,3) # Junction > > Eg, do we need to use keywords: > >set(1,2,3) >mapping(1=>2,3=>4) > > Or can this be accomplished without such keywords? > > I am assuming we don't have to invoke some new() because these are > built-in basic types. > I don't see a problem with .new() for these types, which some might consider arcane. set() doesn't work for the Perl 5 prototypes, too many modules want to use $object->set(). Users who want a shorthand can use a module that lets them write ⟦ ⟧ etc (say). > 4. Since they are already known to be unique, is it possible to get > an actual Set returned when invoking something akin to .keys or > .pairs or a Mapping or Hash? Or do we need to always construct such > ourself by wrapping the call with a set() or all(), in order to use > set operations on them? Would the latter case be inefficient or > verbose? > Interesting idea. I guess that there are many places where a list or array type is specified where it should be a set. > 5. I'm wondering about syntax for using Sets like Junctions. Eg, if > I want to see if one set is a proper subset of another, can I say > this: > >all($s1) === any($s2) > > Or do I have to rewrap their members into explicit Junctions first like this: > >all($s1.members) === any($s2.members) > > I am ignoring for the moment that Set probably declares named > operators that let me do this: > >$s2.subset($s1) > > I don't want to have
Re: binding operators and related introspection
Darren Duncan wrote: > But I would also like to have an easy way to change all bindings to > the same variable at once to point to the same new variable. > [...] >my $x = 'foo'; >my $y = 'bar'; >my $z := $x;# $x and $z point to same 'foo', $y to a 'bar' >$z.rebind_all_aliases_to( $y ); # $x and $y and $z all point to 'bar' > Maybe we need ruby's Object.all or whatever it is. Then you can write something like Object.all.grep:{ $_ =:= $z }.map{ $_ := $y }; Sam.
Re: META vs meta
Larry Wall wrote: > : There is currently a mismatch between S12 and Pugs. The former specifies > $obj.META, the latter has implemented $obj.meta. > > .META is more correct at the moment. > Does making it all upper caps really help? It's still a pollution of the method space, any way that you look at it... What about this form: # $o.?meta # $o.?type # $o.?var # $o.?id > Only that I'm thinking of renaming all the meta-ish methods to use > interrogative pronouns: > > .META -> .HOW > .SKID -> .WHO > .PKG -> .WHAT > .VAR -> .WHERE > Oo-er. Well, you're the linguist ;) Sam.
Re: Capture sigil
Larry Wall wrote: > Okay, I think this is worth bringing up to the top level. > > Fact: Captures seem to be turning into a first-class data structure > that can represent: > > argument lists > match results > XML nodes > anything that requires all of $, @, and % bits. > Also; role type parameters Sam.
Nitpick my Perl6 - parametric roles
Anyone care to pick holes in this little expression of some Perl 6 core types as collections? I mean, other than missing methods ;) role Collection[\$types] { has Seq[$types] @.members; } role Set[::T = Item] does Collection[T] where { all(.members) =:= one(.members); }; role Pair[::K = Item, ::V = Item] does Seq[K,V] { method key of K { .[0] } method value of V { .[1] } }; role Mapping[::K = Item, ::V = Item] does Collection[Pair[K,V]] { all(.members).does(Pair) and all(.members).key =:= one(.members).key; } role Hash[Str ::K, ::V = Item] does Mapping[K, V] where { all(.members).key == one(.members).key } { method post_circumfix:<{ }> (K $key) of V|Undefined { my $seq = first { .key == $key } &.members; $seq ?? $seq.value :: undef; } } role ArrayItem[::V = Item] does Seq[Int, V] { method index of Int { .[0] } method value of Item { .[1] } }; role Array of Collection[ArrayItem] where { all(.members).index == one(.members).index } { method post_circumfix:<[ ]> (Int $index) of Item { my $seq = first { .index == $index } &.members; $seq ?? $seq.value :: undef; } } I'll take the feedback I get, and try to make a set of Perl 6 classes in the pugs project that look and feel just like regular Perl 6 hash/arrays but are expressed in more elementary particles. Cheers, Sam.
Re: Nitpick my Perl6 - parametric roles
TSa wrote: >> role Collection[\$types] { >>has Seq[$types] @.members; >> } > This is a little wrapper that ensures that collections have got > a @.members sequence of arbitrary type. This immediately raises > the question how Seq is defined. > [...and later...] > Are you sure that the underlying Seq type handles the one and > two parameter forms you've used so far? Ah, yes, a notable omission. I understood a Seq as a list with individual types for each element, which are applied positionally. The superclass for things like Pair. Here's a quick mock-up of what I mean: role Seq[ \$types ] { submethod COMPOSE { # a la BUILD for classes loop( my $i = 0; $i < $types.elems; $i++ ) { # assumption: "self" here is the class # we're composing to, and "has" is a class # method that works a little like Moose self.has( $i++ => (isa => $types.[$i]) ); } } my subset MySeqIndex of Int where { 0 <= $_ < $types.elems }; method post_circimfix:<[ ]>( $element: MySeqIndex ) { $?SELF.$element; } } Seq is certainly interesting for various reasons. One is that it is a parametric role that takes an arbitrary set of parameters. In fact, it's possible that the type arguments are something more complicated than a list (making for some very "interesting" Seq types); the above represents a capture, but the above code treats it was a simple list. >> role Set[::T = Item] does Collection[T] where { >> all(.members) =:= one(.members); >> }; > > Nice usage of junctions! But how is the assertion of > uniqueness transported into methods that handle adding > of new values? I haven't defined any mutable state yet; it's still "pure". I'd expect mutability to be a different role, and a set of primitives that work on this level by returning a new set with the changes made. In fact the mutable Set could re-use those primitives, by just having a Set as a member (that 'handles' the Set role methods), and automatically changing that member each time a change is made, to point to the new Set with the new contents. Which all sounds very inefficient and scary until you realise what happens inside generative GC VMs that support STM. >> role Mapping[::K = Item, ::V = Item] does Collection[Pair[K,V]] { >> all(.members).does(Pair) and >> all(.members).key =:= one(.members).key; >> } > > I guess this is a typo and you wanted a where clause. The first > assertion of the members doing the Pair role should be guaranteed > by using Pair as the type argument when instantiating the Collection > role. Well spotted; yes, that is superfluous. >> role Hash[Str ::K, ::V = Item] does Mapping[K, V] > > Will the Str assertion not be too specific for non-string hashes? Another assumption I make here is that there is a basic type "Hash", which as its name suggests, is all about hashing strings, and that the more general form is called "Mapping" where any object can be the source, not just Str subtypes. Thanks for your other nitpicks and comments - much appreciated! Sam. >> where { all(.members).key == one(.members).key } >> { >> method post_circumfix:<{ }> (K $key) of V|Undefined { > > Nice union type as return type. But isn't the type name Undef? > >> my $seq = first { .key == $key } &.members; > > Wasn't that @.members? > >> $seq ?? $seq.value :: undef; > > Ternary is spelled ?? !! now. > > >> } >> } >> >> role ArrayItem[::V = Item] does Seq[Int, V] { >> method index of Int { .[0] } >> method value of Item { .[1] } >> }; > > Here we see the two parameter version of Seq at work. > > >> role Array of Collection[ArrayItem] >> where { all(.members).index == one(.members).index } >> { >> method post_circumfix:<[ ]> (Int $index) of Item { >> my $seq = first { .index == $index } &.members; > > Is this first there a grep-like function? Shouldn't it then > read 'first { .index == $index }, @.members'? > > >> $seq ?? $seq.value :: undef; >> } >> } >> >> I'll take the feedback I get, and try to make a set of Perl 6 classes in >> the pugs project that look and feel just like regular Perl 6 hash/arrays >> but are expressed in more elementary particles. > > This might be very useful in future debates about these types. But > I think everything hinges on the basic Seq type. > > > Regards, TSa.
Re: Mutability vs Laziness
Aaron Sherman wrote: > Carried over form IRC to placeholder the conversation as I saw it: > > We define the following in S06 as immutable types: > > ListLazy Perl list (composed of Seq and Range parts) > Seq Completely evaluated (hence immutable) sequence > Range Incrementally generated (hence lazy) sequence > Set Unordered Seqs that allow no duplicates > JunctionSets with additional behaviours > PairSeq of two elements that serves as a one-element Mapping > Mapping Pairs with no duplicate keys > > It seems to me that there are three core attributes, each of which has > two states: > > Laziness: true, false > Mutability: true, false > Ordered: true, false I don't think "Ordered" is an attribute of a collection other than in the abstract, user-centric sense - it is a type parameter difference (though also there are method differences etc). Things that are not ordered map from items to presence (or themselves, if you prefer). Things that are ordered map from array indices to items. > There are, thus, eight types of containers, but two (unordered, mutable, > lazy/eager) don't really work very well, so let's say 6: Mutable sets don't work? I don't see why not. > Ordered, Immutable, Eager: Seq > Ordered, Immutable, Lazy: Range and/or Seq of Range? > Ordered, Mutable, Eager: ? > Ordered, Mutable, Lazy: Array > Unordered, Immutable, Eager: Set > Unordered, Immutable, Lazy: x and/or Set of x? > > In that last example, x is "an unordered range", Sounds a bit like an iterator. Sam.
Re: Nitpick my Perl6 - parametric roles
Miroslav Silovic wrote: > TSa wrote: > >>> role Set[::T = Item] does Collection[T] where { >>> all(.members) =:= one(.members); >>> }; >>> >> Nice usage of junctions! >> >> > > But buggy - one means *exactly* one. So for an array of more than 1 > element, all(@array) never equals one(@array) - if they're all the same, > it's more than 1, otherwise it's 0. > > perl -MPerl6::Junction=one,all -le '@foo=qw(1 2 3 4); print "yes" if (all(@foo) eq one(@foo))' yes Didn't test on pugs yet. Sam. > all(.members) =:= any(.members) would also not work, as it will try to > match each member with some other or same member of the array. It will > always return true, in other words, as each element of the array is > equal to itself. > > This leaves all(.members) =:= .members[0], possibly extra with > non-emptiness test. > > Miro > > >
Re: Nitpick my Perl6 - parametric roles
Darren Duncan wrote: > Unless I'm mistaken, you may be going about this the wrong way. > > Within a system that already has an underlying > set-like type, the Junction in this case, a test > for uniqueness is (pardon any spelling): > >all(@items).elements.size === @items.size > > The all() will strip any duplicates, so if the > number of elements in all(@items) is the same as > @items, then @items has no duplicates. > Perhaps, but then Junctions might not assume elements have equality or identity operations defined. To do that you need to require this (and which identity operator would you like to use today?), and that would also have the side effect of making creating a junction an O(N^2) operation. I think that the S06 definition needs re-wording. It's more like a Bag than a Set AIUI. Sam.
Re: Nitpick my Perl6 - parametric roles
TSa wrote: > HaloO, > > Sam Vilain wrote: > >> perl -MPerl6::Junction=one,all -le '@foo=qw(1 2 3 4); print "yes" if >> (all(@foo) eq one(@foo))' >> yes >> > > But does it fail for duplicates? I guess not because junctions > eliminate duplicates and you end up testing unique values as > above. E.g. all(1,1,2) == one(1,1,2) might actually give the > same result as all(1,2) == one(1,2). > Neither Pugs nor Perl6::Junction behaves like this. pugs> for ([1,2,3], [1,1,2,3]) -> $x { my @x = @$x; my $all_unique = ( all(@x) == one(@x) ); print "{ $x.join(",") } became ", $all_unique; say " (which is { $all_unique ?? "TRUE" !! "FALSE" })" } 1,2,3 became all(VJunc one(VBool True)) (which is TRUE) 1,1,2,3 became all(VJunc one(VBool False,VBool True),VJunc one()) (which is FALSE) Sam.
Re: Nitpick my Perl6 - parametric roles
Darren Duncan wrote: >> Perhaps, but then Junctions might not assume elements have equality or >> identity operations defined. >> > As I recall, every type in Perl 6 has an equality and identity > operation defined because the Object superclass provides one. If > nothing else, the type's equality and identity are the same as =:= > and .WHERE. > Ok, seems reasonable. >> and that would >> also have the side effect of making creating a junction an O(N^2) operation. >> > Not if the type uses a hash-like index internally; then creating a > junction (or set) is more like O(N). > Oh, yes, good point. >> I think that the S06 definition needs re-wording. It's more like a Bag >> than a Set AIUI. >> > I don't know what part you are reading, but the list of types that I > see says that a Junction is "Sets with additional behaviours". > We're on the same page. It's just not the way that any of the prototypes have behaved to date. Sam.
Re: class interface of roles
TSa wrote: > HaloO, > > is this subject not of interest? I just wanted to start a > discussion about the class composition process and how a > role designer can require the class to provide an equal > method and then augment it to achieve the correct behavior. > Contrast that with the need to do the same in every class > that gets the equal method composed into if the role doesn't > have a superclass interface as described in the article. > This will be the same as requiring that a class implements a method, except the method's name is infix:<==>(::T $self: T $other) or some such. Sam.
Re: Junctions - feedback and desires
Rod Adams wrote: I do not believe that is possible. This is the "filtering" or "unification" behavior that people keep wanting junctions to have, which they do not. Aww! But what about all the great problems that could be expressed with them? I know of two languages that consider this to be a core feature now (Prolog, Oz[1]). A given junction always has all of the values it was made with. No more, no less. If you want something else, you have to make a new junction. Consider that it's been decided that : $j = 11|0; 10 < $j < 1 Is true. $j retains the 0 even after the 0 failed a test. I can't see how this can be possible with the possibility of autothreading as described in [2]. Maybe the example you suggest is true, if both comparisons happen "simultaneously", but what about this one? if ($j < 10) { if ($j < 1) { say "$j took on two values at once"; } } Let's say that the implementation chose to implement the first if() by auto-threading. The first thread where $j == 11 succeeds. The second, where $j == 1 fails. In the second thread, $j == 11 fails. It is by this assumption that the example in [3] was built. But wait, isn't (10 < $j < 1) likely to produce the same opcode tree as if($j<10){if($j<1){}} ? > As for the "current" value, there is only a current value during > threading. Isn't the threading conceptual, and actual threading invoked only when the optimiser has finished using available logic / set theory operations to prevent absurd numbers of threads being made that exit immediately? Sam. References: 1. http://xrl.us/fehh (Link to www.mozart-oz.org) A representation of send+more=money in Oz 2. http://dev.perl.org/perl6/synopsis/S09.html Some contexts, such as boolean contexts, have special rules for dealing with junctions. In any scalar context not expecting a junction of values, a junction produces automatic parallelization of the algorithm. In particular, if a junction is used as an argument to any routine (operator, closure, method, etc.), and the scalar parameter you are attempting to bind the argument to is inconsistent with the Junction type, that routine is "autothreaded", meaning the routine will be called automatically as many times as necessary to process the individual scalar elements of the junction in parallel. 3. An implementation of send+more=money using Perl 6 Junctions http://svn.openfoundry.org/pugs/examples/sendmoremoney.p6 http://xrl.us/feis (revision at time of writing this message)
SEND + MORE = MONEY (works now in pugs with junctions!)
Rod Adams wrote: And as one who recently proposed a way of getting Prolog like features in Perl (through Rules, not Junctions), I understand the appeal completely. Junctions are not the way to that goal. They are something different. > Taking multiple values at once is what junctions are all about. > People seem to forget the role the predicate plays in junction > evaluation. You thread over the different values, gain a result, and > then use the predicate to recombine the results into a single scalar. > That assumption is in err, and the example does not generate the > solutions desired I've changed examples/sendmoremoney.p6 in the pugs distribution to use junctions correctly to demonstrate that they *can* be used to solve these sorts of problems, and that it is just a matter of semantics and writing code correctly. However, poor semantics can make the task of writing optimisers unnecessarily difficult or impractical, as Bourne demonstrated. in short, it seems people want this: my $a = any(1..9); my $b = any(1..9); my $c = any(0..9); if ( $a != $b && $b != $c && $a != $c && ($a + $b == $a * 10 + $c) ) { print "$a + $b = $a$c"; } To mean this (forgive the duplication of collapse() here): sub collapse($x, $sub) { $sub.($x) } sub collapse($x, $y, $sub) { $sub.($x,$y) } my $a = any(1..9); my $b = any(1..9); my $c = any(0..9); collapse($a, $b, -> $a, $b { ($a != $b) && collapse($c, -> $c { if ( ( $b != $c ) && ( $a != $c ) && ($a + $b == $a * 10 + $c) ) { say "$a + $b = $a$c"; } }); }); (and YES THAT WORKS ). However, the former keeps the optimisation out of the algorithm, so that when someone comes along later with a nice grunty optimiser there is more chance that it gets a go at the entire solution space rather than having to fall back to exhaustive searching. (which might have to find ways to prove associativity of &&, etc, to make `real' optimisations). I'm trying to see a way that these two ways of using junctions are compatible. As I see it, people want to stretch out the time that the junction is "true", to something non-zero, without having to explicitly create all those closures. Getting the old behaviour would be easy, just set a variable in the `if' clause: my $j1 = any(1..5); my $j2 = any(5..9); my $they_equal; if ($j1 == $j2) { # intersection of sets - $j1 and $j2 are any(5), any(5) $they_equal = 1; } else { # symmetric difference of sets - $j1 and $j2 are now # any(1..5), any(5..9) (where $j1 != $j2 :)) } if ($they_equal) { } Now, the `where $j1 != $j2' bit there, which looks like it's on crack, is a way of representing that instead of actually calling that second branch 24 times, it could be calling it with two junctions which are `entangled' (or, if you prefer, `outer joined'). $j1 and $j2 appear almost untouched - except any test that uses $j1 and $j2 together will not see the combination of ($j1 == 5) and ($j2 == 5). I mean, wouldn't it really be nice if you could write stuff like this: my @users is persistent("users.isam"); my @accounts is persistent("accounts.isam"); my $r_user = any(@user); my $r_account = any(@account); if ( $r_account.user == $r_user ) { say("That junction is:", $r_user); } $r_user at that point represents only the users which have at least one object in @accounts for which there exists an $r_account with a `user' property that is that $r_user member[*]. The closure would then either be run once, with $r_user still a junction (if the interpreter/`persistent' class was capable of doing so), or once for every matching tuple of ($r_account, $r_user). We're still talking in terms of Set Theory, right? One last thing - that comment about any(@foo) == one(@foo) not checking for uniqueness in a list is right - the correct version is: all(@foo) == one(@foo) Sam. Footnotes: * - any relational database `experts' who want to remind me of which normalisation form rules this breaks, please remember that RDBMSes and normalised forms approximate Set Theory, which this is trying to do as well, so I believe such discussion is irrelevant.
Re: [Fwd: Re: [RFC] A more extensible/flexible POD (ROUGH-DRAFT)]
Aaron Sherman wrote: Sam "mugwump" Vilain refers to each of these syntaxes as /Pod dialects/. He is working on more formally defining the common model or "AST" that these dialects map to. Why? Seriously, why on earth do you want to encourage the proliferation of variant markup languages?! There aren't enough? My effort here was to try to PREVENT the proliferation (e.g. by Kwid and POD butting heads and ending up in a stalemate). The only problem is that, presented with a compromise, the Kwid folks seem to be content to ADD it to the list of variants rather than, in fact, compromise and collapse the list. I'll continue only as far as is needed to propose this in full as an example parser / converter, and then I'm going to stop. My goal is not to proliferate the number of markups further, and I'd MUCH rather see Perl 6 rely on POD than fragment the SINGLE MOST IMPORTANT TASK in creating code to share with the world: documentation. Well, I don't think anyone wants to see as many POD dialects as there are wiki text formats (BBCode, anyone?). Maybe there will be something very close to the original POD, but with a verbose way of making tables, and an enhanced linking syntax. But otherwise identical to the original Perl 5 POD. Note that POD dialects, and differing POD conventions already exist in Perl 5 and are in common use. They were designed in the original POD with the =for tag. At the moment, tools like `pod2html' have to be heavily aware of the POD dialect, which I think is sub-optimal when it comes to some of the really interesting things people have achieved with POD. Look at MarkOv's OODoc, or Test::Inline, for instance. All I'm trying to do is giving these beasts a name, and defining a mechanism by which they can be used by tools that only know how to deal with "standard" documents - thus giving users the freedom to define a local convention if one of them doesn't quite fit their needs. Using a local Subversion repository, and Request Tracker, and want to be able to put hyperlinks in POD to refer to these entities? No problem, just extend the dialect and add a link style. Then select from a dozen output tools or variants to see which one works for you. Sam.
Re: [Fwd: Re: [RFC] A more extensible/flexible POD (ROUGH-DRAFT)]
Damian Conway wrote: [No, I'm not back; I'm just passing by. But I feel that I need to comment on this whole issue] Thanks! This message has lots of useful information that I would have otherwise probably missed. It seems that the basic premise of the POD document object model gels well with that early design document, so I look forward to being able to flesh out the details. Using ^=\s to delimit a line starting with a = will interfere with the Kwid method of: = Heading foo Which I was imagining would be converted to a DOM tree that when represented in the "Normative XML" would look like: Heading foo That's sort of DocBook style, and in fact I was thinking that for the internal representation, DocBook node names could be used where there is no other better alternative. Of course, non-documentation things like Test fragments or inclusions of external entities, like UML diagrams won't have a representation in DocBook :-). The uses of a leading = in a paragraph are fairly uncommon. For instance, when quoting POD you would simply indent it a bit to make it verbatim and there is no issue. I see a middle ground; that is, `=` quoting is only is allowed if it directly follows the initial POD marker; =head1 Foo = = =head1 = = = = =head1 That's just getting ridiculous Which I see as represented by; Foo =head1 = = =head1 That's just getting ridiculous Which of course would lose the ='s. But that's OK, because if you wanted verbatim you could have just indented the block. If you wanted to lead a normal paragraph with it, you'd just use the normally implicit =para (equivalent to =pod): =para = = = This is what a Kwid =head1 looks like As for going with =kwid to denote the starting of kwid, I have so far been pessimistically assuming that something like `=dialect kwid`, or `=use kwid` (as described in the design doc you attached) would be required. However, we could allow `=unknown`, where `unknown` is an unknown keyword, to try to load Pod::Dialect::unknown, and hope like hell it provides the Role of Pod::Dialect. While the `^=` escaping is “active”, the presence or absence of whitespace following the initial `=` will delimit breaks in paragraphs. This has to be so, otherwise the previous example would have been: Foo =head1 = = =head1 That's just getting ridiculous Which is just plain silly. This follows what people are used to with POD - blank lines must be empty, not just no non-whitespace characters (an increasingly vague concept these days). So, the POD processing happens in 3 levels (note: the first isn't really mentioned in perlpodspec.kwid, which is a bug); =list - chunkification from the original source, into POD paragraphs, which may or may not include an initial `^=foo` marker. At *this* level, the only escaping that happens is the `^=` escaping. That's all that needs to happen while the code is being read, and for most code that is how the POD will remain, in memory, somewhere intermingled with the Parse Tree for the code, so that the code can still be spat back out by the P6 equivalent of `B::Deparse` - parsing of these raw chunks into a real POD DOM. Please, tired XML veterans, please don't get upset by the use of the term "DOM", I think the last thing anyone wants is to have studlyCaps functions like `getElementById` and `createTextNode`. It is the tree concept itself which is important, and this pre-dates XML anyway. Strictly speaking, this step actually converts POD paragraph chunk events into POD DOM events. These can be used to build a real DOM, for instance if you need to do an XPath style query for a link (I was amazed that someone's actually gone and built Pod::XPath!), or they might simply be passed onto the next stage by an output processor with no intermediate tree being built. So, at this point, dialects get hooks to perform custom mutation of POD paragraph events into DOM events, and the arbitrator of this process ensures that the output events are well "balanced" by spitting out closing tags where it has to. They can store state in their parser object, but none of this state will be preserved past the parsing state. However, the nodes that they "spit out" after this point may still not be "core" POD, such as for includes or out-of-band objects. These hooks will be sufficient to allow them to hijack subsequent chunks that would otherwise be served to other dialects, ie, they can choose to "arbitrate" subsequent chunks. I'm aiming to make it so that it is possible for dialects to be "round trip safe", by being able to go back from this DOM state to the original POD paragraph chunks. This would require dialects to "play nice" of course, but is a potential option to help make things like smart text editors be able to automatically syntax highlight POD dialects :). Linking will be in terms of this intermediate tree, so you won't be able to link to included portions of m
Re: identity tests and comparing two references
Darren Duncan wrote: Now I seem to remember reading somewhere that '===' will do what I want, but I'm now having trouble finding any mention of it. So, what is the operator for reference comparison? As someone who wrote a tool that uses refaddr() and 0+ in Perl 5 to achieve the same thing, I agree with the need for such an operator. I think that =:= compares *lexical* identity is fairly clearly spelled out in S03. However, we need a way to compare *value* /identity/ (not equality or equivalence), without being subject to overloading etc. Of course, actually comparing two `ref' or `Ref' objects for pointing to the same place is achieved via `==' (or, if === is used, ${$ref1} === ${$ref2} or the P6 equivalent :) ) Sam.
Re: Documentary annotations: $what doc
Luke Palmer wrote: Supposing I had a "doc" trait, could I say: sub f2c (Num $temp doc) doc {...} Or would I be forced to spell it doc('stuff') ? Well, first you need an `is` somewhere in there. And after that I think you'll need to do it in doc('stuff') form. If we did allow doc<>, then this: A word of warning... Perldoc[*] will eventually support this sort of thing, for sure. But it will lead to the unfortunate side effect that your code needs to at least compile without syntax errors, and without too many obscene mistakes - so that these traits are accessible by the dialect that interprets them into a Perldoc tree. That's if you care about seeing the information presented nicely when you use `perldoc Foo', of course. Sam. * - the project aiming to provide dialect-agnostic inline documentation for Perl 5 and Perl 6. The Perl 5 prototype is on CPAN... still in early stages.
Re: :=: (OT)
Juerd wrote: For some reason, I keep typing :=: instead of =:=. Do other people experience similar typo-habits with new operators? One of my other Perl 6 typo-habits is <<^H^Hargh!^H^H^H^H^H«, but that's because I like how « and » look, but can't yet easily type them. Juerd «»«»«»«»«»«»«»«»«»«»«»«»«»! :-þ an excerpt from my xkb config... key { symbols[Group1]= [ z, Z ], symbols[Group2]= [ guillemotleft,less ] }; key { symbols[Group1]= [ x, X ], symbols[Group2]= [ guillemotright, greater ] }; xkb (keyboards that fail, leading to making it easier for me to enter «» and þ than )-- Sam.
Re: Whither "use English"?
Juerd wrote: According to Wikipedia there are around 400 million native English speakers and 600 million people who have English as a second language. Should the remaining ~5.5 billion humans be exluded from writing perl code just so that we English speakers can understand all the code that is written? Yes. So, you gladly invite the curse of semantic fixation. æäé As we will know exactly what are symbols and what is code, it should even be possible to automatically perform L10N on source code, without breaking it. So stop being empirical! TIA, Sam.
Macros [was: Whither "use English"?]
Larry Wall wrote: (B> Well, only if you stick to a standard dialect. As soon as you start (B> defining your own macros, it gets a little trickier. (B (BInteresting, I hadn't considered that. (B (BHaving a quick browse through some of the discussions about macros, many (Bof the macros I saw[*] looked something like they could be conceptualised (Bas referring to the part of the AST where they were defined. (B (Bie, making the AST more of an Abstract Syntax Graph. And macros like (B'free' (ie, stack frame and scope-less) subs, with only the complication (Bof variable binding. The ability to have recursive macros would then (Brelate to this graph-ness. (B (BWhat are the shortcomings of this view of macros, as 'smart' (symbol (Bbinding) AST shortcuts? (B (BThe ability to know exactly what source corresponds to a given point on (Bthe AST, as well as knowing straight after parse time (save for string (Beval, of course) what each token in the source stream relates to is one (Bthing that I'm aiming to have work with Perldoc. I'm hoping this will (Bassist I18N efforts and other uses like smart editors. (B (BBy smart editors, I'm talking about something that uses Perl/PPI as its (Bgrammar parsing engine, and it highlights the code based on where each (Btoken in the source stream ended up on the AST. This would work (Bcompletely with source that munges grammars (assuming the grammars are (Bworking ;). Then, use cases like performing L10N for display to non- (BEnglish speakers would be 'easy'. I can think of other side-benefits (Bto such "regularity" of the language, such as allowing Programatica- (Bstyle systems for visually identifying 'proof-carrying code' and (B'testing certificates' (see http://xrl.us/programatica). (B (Bmacros that run at compile time, and insert strings back into the (Bdocument source seem hackish and scary to these sorts of prospects. (BBut then, one man's hackish and scary is another man's elegant (Bsimplicity, I guess. (B (B* - in particular, messages like this: (B- http://xrl.us/fr78 (B (Bbut this one gives me a hint that there is more to the story... I (Bdon't grok the intent of 'is parsed' (B- http://xrl.us/fr8a
Re: Sun Fortress and Perl 6
Luke Palmer wrote: `is pure` would be great to have! For possible auto-memoization of likely-to-be-slow subs it can be useful, but it also makes great documentation. It's going in there whether Larry likes it or not[1]. There are so incredibly many optimizations that you can do on pure functions, it's not even funny. Haha. Er... How about the one that goes further and also implies that the function is strictly typed throughout; is ML He'd love that, for sure! :) Sam.
Re: Threading in Parrot vs Perl
Rod Adams wrote: I would be dismayed if autothreading used threads to accomplish it's goals. Simple iteration in a single interpreter should be more than sufficient. For sure. No point in doing 10_000 cycles to set up a scratch area for a single boolean test that might take 10 cycles. A software transaction (atomic { } block) behaves in many ways like setting up a new interpreter thread and exiting at the end. I expect these will be more lightweight than a real thread... in some cases able to be reduced to no-ops. So, implementing autothreading using STM as the 'localizing' engine is another possibility within a single process/thread. Sam.
Re: S29: punt [pwned!]
Rod Adams wrote: It looks like I'm going to have to punt on finishing S29. On behalf of pugs committers, we will gladly adopt this task, which is in the pugs repository already at docs/S29draft.pod, as well as having a set of foundation classes that correspond to all these object methods in docs/src/ (of course, most of the actual code is in src/Pugs/Prim.hs etc) I'm finding myself in a perpetual state of either no time to work on it, or when there is time, having insufficient brain power left to properly assimilate everything that needs to be considered to do any of the functions justice. Looking ahead, I do not see this state changing for the better in the foreseeable future. Drop the feeling of guilt for not having written enough and it will already be better. Thanks for what you have done, it is an outstanding achievement! It's my hope that someone none(@Larry) can and will pick this effort up. I will give whatever assistance I can to anyone choosing to do so. Drop me a line. If you could make sure your last revision corresponds to what is in the pugs repository, that will be more than enough... Sam.
Re: Quick question: '1.28' * '2.56'
Rob Kinyon wrote: If that's the case, then if I change a variable that isa Str (that isa Num), does it change what it inherits from? Please don't use "inherits" when talking about these core types. Classical inheritance just doesn't work with the varied sets of numbers. All those stories you were told about Classical Inheritance being able to describe any problem were naïve lies. Roles-based inheritance (or Traits-based if you like Smalltalk, or Haskell's Classes) is a superset of classical inheritance. In fact it seems reasonable to me at this point in time that a Perl 6 Class is a subtype of a Role. The distinctions seem minor enough not to matter. See also http://svn.openfoundry.org/pugs/docs/src/number-types.png Sam.
Re: Quick question: '1.28' * '2.56'
Larry Wall wrote: : pugs> '1.28' * '2.56' : 3.2768 : What is (or should be) going on here here? : [1] role NumRole { : method infix:<*> returns Num (NumRole $x, NumRole $y: ) { ... } : } : Str.does(NumRole); : [3] multi sub prefix:<+> (Str $x) returns Num { ... } : multi sub infix:<*> (Num $x, Num $y) returns Num { ... } : multi sub infix:<*> (Any $x, Any $y) returns Num { +$x * +$y } I tend to think of it most like [3], but it's possible that it's the same as [1] if the role is supplying the coercion assumed in [3]. I like #3, because it doesn't have any nasty implications to the type calculus. I don't really have the theoretical or practical knowledge to really be able to back this up, but I have a strong hunch that value-based type shifting is the type system equivalent of $&. Sam.
Re: Default precedence level of user defined infix ops
Luke Palmer wrote: And how do I explicitly define the precedence? Using the `tighter`, `looser`, and `equiv` traits. You specify precedence in terms of the precedence of other existing ops. sub infix:<.>(&f, &g) is looser(&infix:<+>) {...} This is interesting. So, infix:< > is similar to Haskell's () circumfix operator, like ((+) 1 2) â (1 + 2). Which method does &infix:<+> refer to, if you have; multi sub infix:<+>(Num $i, Num $j) { $i.add($j) } multi sub infix:<+>(Set $i, Set $j) { $i.union($j) } ? Are these automatically locked to the same level, in fact, does it make sense for any 'operator' (ie, the sub's short name) to exist in multiple precedence levels at once? Or is it simply a major ParseF*** to have to determine precedence /after/ determining types of operands? Sam.
Re: reduce metaoperator on an empty list
Edward Cherlin wrote: Here is the last answer from Ken Iverson, who invented reduce in the 1950s, and died recently. file:///usr/share/j504/system/extras/help/dictionary/intro28.htm [snip] Thanks for bringing in a little history to the discussion. Those links are all local to your system; do you have internet reachable versions of them? Cheers, Sam.
Re: reduce metaoperator on an empty list
Stuart Cook wrote: In Haskell, there is a distinction between foldl and foldl1 (similar remarks apply to foldr/foldr1[1]): The former (foldl) requires you to give an explicit 'left unit'[2], which is implicitly added to the left of the list being reduced. This means that folding an empty list will just give you the unit. i.e. foldl (+) 0 [a,b,c] = ((0+a)+b)+c foldl (+) 0 [] = 0 The latter (foldl1) doesn't use a unit value, but this means that you can't fold empty lists. i.e. foldl1 (+) [a,b,c] = (a+b)+c foldl1 (+) [] = ***error*** sure. Maybe the identity values could be supplied by making the reduce operator for them a curried version of reduce, where reduce requires a list with at least one element (or DIES :)) eg, something similar to; (sorry for the psuedo-perl6, corrections welcome :)) sub prefix:<[+]> ([EMAIL PROTECTED]) ::= &reduce.assuming(func => &infix:<+>, first => 0); sub prefix:<[*]> ([EMAIL PROTECTED]) ::= &reduce.assuming(func => &infix:<*>, first => 1); This would mean that unless the operator specifically defines a curried reduce version of itself, then the [] version of it on an empty list will be a hard run-time error. Then again, maybe an identity trait is more elegant and covers the varied ways that multiple operators combine inside reduce.. > You /could/ try to do something 'sensible' and return 0 or undef, but > this seems likely to result in more confusion. Personally I think returning an undef for this kind of situation would be as wrong as returning undef for 0/0. Sam.
Re: Complex Arithmetic
Edward Cherlin wrote: There was a discussion of the principal value of square root on this list some time back, making the point that for positive [...] It turns out that the domain and range and the location of the cut lines have to be worked out separately for different functions. Mathematical practice is not entirely consistent in making these decisions, but in programming, there seems to be widespread agreement that the shared definitions used in the APL, Common LISP, and Ada standards are the best available. Do we want to get into all of this in Perl6? pugs currently has "Complex" as a built-in type, though it isn't explicitly listed in S06. I can't see any tests for them yet, though. So, testing the Complex number functionality as well as detailed exploration of the corner cases, and alignment with best practice will surely be appreciated by people looking at doing Complex math in Perl 6. I think this applies regardless of whether it ends up a "core" type (whatever that means) or not. Personally I don't think that Complex numbers are so bizarre an entity that you wouldn't want sqrt(-1) to return one out of the box. It's likely that very little implementation changes will need to be done, as no doubt the mathematically minded folk that write GHC will have been through that before. But it will be invaluable in testing compliance of the different run-time engines. I suggest you come to the IRC channel at #perl6 on irc.freenode.net, and ask for a committer account. Sam.
Re: [S29] uniq
Mark Overmeer wrote: 'uniq' differs from 'sort' because there is no order relationship between the elements. A quick algorithm for finding the unique elements in perl5 is sub uniq(@) { my %h = map { ($_ => 1) } @elements; keys %h; } ...and an even quicker one is: use Set::Object; sub uniq(@) { set(@_)->members; } or use v6; use Set; sub uniq([EMAIL PROTECTED]) { set(@items).members; } Sam.
Junctive and Higher order Types
Hi all, While trying to convert Haskell statements like this to Perl 6: data Cxt = CxtVoid -- ^ Context that isn't expecting any values | CxtItem !Type -- ^ Context expecting a value of the specified type | CxtSlurpy !Type -- ^ Context expecting multiple values of the -- specified type deriving (Eq, Show, Ord) I'd like to be able to write it something like this: type Cxt is CxtVoid | CxtItem of Type | CxtSlurpy of Type does (Eq, Show, Ord); To be a shorthand for: type CxtVoid; type CxtItem of Type; type CxtSlurpy of Type; type Perl::Cxt is CxtVoid | CxtItem | CxtSlurpy does Eq does Show does Ord; Is this overloading the 'of' operator too far? For many there will be a lot of new concepts there. For a start, I'm assuming that "of" is being used as a higher order type definition, much like "Array of Wotsits" would declare. Also, there is a type there - CxtVoid - which is nothing but a Type! No representation. Of course, if you have a variable of type Cxt, and it is a CxtVoid, then that will need to be represented in some way. But you generally wouldn't care how. An alternative might be to try to shoe-horn the concepts into Roles etc. Who knows, perhaps they'll even fit! :-) Sam.
Re: Sets
Patrick R. Michaud wrote: > The continuing exchanges regarding junctions, and the ongoing tendency > by newcomers to think of them and try to use them as sets, makes > me feel that it might be worthwhile to define and publish a standard > C class and operations sooner rather than later in Perl 6 I agree. See pugs/ext/Set. It presents a set-like interface to Junctions. eg, use Set; my $low = set( 0..4 ); my $odd = set( (0..4).map:{ $_ * 2 + 1 } ); say ($low ∩ $odd).members.join(","); # 1,3 say ($low ∪ $odd).members.join(","); # 0,1,2,3,4,5,7,9 # difference - not this is not a backslash, it's U+2216 say ($low ∖ $odd).members.join(","); # 0,2,4 say ($odd ∖ $low).members.join(","); # 5,7,9 # symmetric difference - union of the above say ($low % $odd).members.join(","); # 0,2,4,5,7,9 # test for membership say $low ∋ 4; # true say $low ∌ 5; # true say $odd ∋ 4; # false say $odd ∌ 5; # false # set relations say ( $low ∪ $odd ) ⊇ $low; # true Well, actually the above doesn't work yet. But there are ASCII versions and english methods for those that like coding something that actually works today ;). Here's a directed graph traversal that handle cycles correctly; this is largely why I'd like to see a common Role to all containers... so that .values can be expected to DTRT. OTOH, maybe Maps with object keys would "miss out" in this algorithm so another method name is more appropriate. use Set; my @stack = ($root); my $seen = set(@stack); while (my $item = shift @stack) { # do something with $item if $item.can("values") { push @stack, $item.values.grep:{ $seen.insert($_) }; } } Caveats for the above probably abound, but you get the picture. Note that the Set::Object module for Perl 5 is useful for the same thing (assumes that $root is a ref): use Set::Object qw(set); use Scalar::Util qw(reftype blessed); use Perl6::Junction qw(any); my @stack = ($root); my $seen = set(@stack); while (my $item = shift @stack) { # do something with $item if (blessed $item and $item->can("members")) { push @stack, grep { ref $_ && $seen->insert($_) } $item->members; } if (reftype $item eq "HASH") { push @stack, grep { ref $_ && $seen->insert($_) } values %$item; } elsif (reftype $item eq "ARRAY") { push @stack, grep { ref $_ && $seen->insert($_) } @$item; } elsif (reftype $item eq any(qw(REF SCALAR)) ) { push @stack, $$item if $seen->insert($$item); } } As you can see, this sort of thing ends up an anti-design pattern. Sam.
Re: function signatures?
Ingo Blechschmidt wrote: Are signatures going to be an exposed first class object in Perl 6? I hope so, too. ~&foo.signature; # Signature objects should stringify to a canonized form, e.g.: # ~sub (Str $bar, CoolClass $z where {...}) {...}.signature ==> # 'Str $bar, ANONCLASS(0xDEADBEEF)' # (BTW, I don't think it's possible to display anonymous subtypes more # friendly, as the where-clause may contain arbitrary code, and Code # objects are not (yet?) fully introspectable -- i.e. # &foo.statements[3].line doesn't work.) +&foo.signature.required_args; # Number of required args &foo.signature.required_args; # Hash name -> class &foo.signature.positional_args; &foo.signature.named_args; # etc. Thoughts? Translations of the corresponding Pugs types into Perl 6 code is at: ext/Perl-MetaModel/lib/Pugs/VCode.pm However they are mostly still sketches. If you have specific ideas about the Code::Signature signature in Pure Perl terms, place it in; ext/Perl-MetaModel/lib/Code/Signature.pm These objects will eventually be what you get from &foo.meta, etc. Or at least I assume that the way to get to the object's signature will be .meta. Maybe the "Code" class will define a ".signature" method as an alternative to .meta.signature. Sam.
Re: Strongly typed containers?
Yuval Kogman wrote: > We already have the Set class, how do we say what it contains? > class Set { >has $.type; >method members returns $.type () { ... } > } > my Set of Int $s = Set.new; # is this how you call it? You are describing "Higher Order" types, also called Generic Algebraic Data Types (GADTs) in Haskell. Please refer to the earlier discussions Parts 1 and 2 of http://xrl.us/f9re I also started a similar post on a related note that was "warnocked", though the post was more to demonstrate an apparent syntax isomorphism between Haskell and Perl 6 than posing a particular question (probably why it was unanswered). http://xrl.us/f9rg I think there has probably been other discussions, including one where Autrijus specifically asked this question for the Set module, but I can't find that one. Sam.
Re: Unicode Operators cheatsheet, please!
Rob Kinyon wrote: I would love to see a document (one per editor) that describes the Unicode characters in use and how to make them. The Set implementation in Pugs uses (at last count) 20 different Unicode characters as operators. I have updated the unicode quickref, and started a Perlmonks discussion node for this to be explored - see http://www.perlmonks.org/index.pl?node_id=462246 Sam.
Re: date and time formatting
Rob Kinyon wrote: What I'm trying to get at isn't that DateTime's API should be preserved. I'm saying that the concept of DateTime should be ported. Core or not core - it doesn't matter. When use'd (or installed), it should override now() (and anyone else we can think of) to return an object that DWIMs, plus provides the interface you've outlined below. I've made a start on this. See ext/Date in pugs. I don't think that your views are necessarily contrary. The biggest reason I didn't use DateTime was that I found it awkward for the common case; most of the time I just want to stuff in an ISO8601 date. I also don't like implicit normalisation to seconds underneath the hood when I'm doing basic date calculations, and the way that the "DateTime" base class is inherantly based on the Gregorian calendar. The "Date" and "Duration" roles are extremely minimal; see http://svn.openfoundry.org/pugs/ext/Date/lib/Date.pm http://svn.openfoundry.org/pugs/ext/Date/lib/Duration.pm The major API is described at: http://svn.openfoundry.org/pugs/ext/Date/lib/Date/Gregorian.pod This module is supposed to be somewhere between DateTime and Class::Date, with built-in ISO-8601 support (as it's the standard ;)). With a bit of luck, all Date implementation can share this `Date' Role, and Gregorian calendar modules share the `Date::Gregorian' Role, so that the multitude of implementations that crop up will be mutually exchangable, and the simple case fast, efficient and useful. Sam.
Re: "returns" and context
Rod Adams wrote: How do I specify the signature of a context-sensitive function? sub foo() returns (what?) { return want ~~ Scalar ?? cheap_integer_result :: List_of_Sheep; } I suspect a typed junction would look like : "Junction of Int|Str". Not quite. AIUI that means a Junction of which the members are Int or Str. This is how I've been writing it: sub foo() returns Scalar|List { return want ~~ Scalar ?? cheap_integer_result :: List_of_Sheep; } I think the default return type of unlabeled subs would be: returns Void|Scalar|List but of course $?SELF =:= none(@Larry) ;) Sam.
Re: What the heck is... wrong with Parrot development?
Fagyal Csongor wrote: With all respect, I think this is a very important thing which needs attention, and I hope that you will help us to clarify the situation. I am pretty sure Dan did not leave because he had a bad day - we know he Dan's position was very stressful, he had people from all sides trying to tear him down, even though many were also propping him up and he has a great level of skill. However, to altercate on the hows and whys of his action is premature; I suggest a moratorium on such debate for at least as long as he was the project leader, for correct perspective. Please honour his decision to bow out gracefully without turning it into a childish battle of egos. In the meantime let us celebrate 5 years of Dan Sugalski's contribution to the Parrot and Perl 6 project. Three cheers for Dan! Sam.
Re: reduce metaoperator on an empty list
Roger Hale wrote: This is why I would rather the o -> [o] circumfixion left [o] an infix, not prefix operator. I would rather be explicit about my identity: $product = 1 [*] @array; Hmm. Not all operators *have* an identity. You'd have to write, in that case; @array[0] [ƒ] @[EMAIL PROTECTED] Which isn't great IMHO. Sam.
Re: reduce metaoperator on an empty list
Damian Conway wrote: What you want is: $product = ([*] @values err 0); Or: $factorial = ([*] 1..$n err 1); The "err" operator bind only to the point on the instruction it is attached to, ie it's not a shortcut for eval(), right? I'm just seeing some edge cases here for custom defined operators; you don't want exceptions getting silently converted to default values... Sam.
Re: reduce metaoperator on an empty list
Luke Palmer wrote: < and > still don't make sense as reduce operators. Observe the table: # of args | Return (type) 0 | -Inf 1 | Num (the argument) 2 | bool ... | bool Let's look at the type of one of the many `reduce' variants in Haskell; foldr1 :: (a -> a -> a) -> [a] -> a This is the Perl6ish; sub reduce( ::Code{( ::(someType), ::(someType) ) returns ::(someType)} $func, Array of ::(someType) ) returns ::(someType); ie, the function $func supplied must take and return arguments of a single type. So you have come to the same conclusion as the FP folk :-). Here I'm using ::(foo) as a coined syntax for a parametric type to the definition. `someType' need not be defined anywhere else, but must be the same within the application of a definition. IMHO we still need to make some movements towards a specification for how this sort of thing is specified... > I just think we have to give > nonhomogeneous operators like < some special treatment. So, from our > somewhat lexical definition of reduce, I don't think an identity input > is what we're looking for. We really want an identity output. When I last looked, in pugs, functions that return "bool" types are currently setup to return one or the other argument when used with reduce; like there is a similar; multi sub reduce( ::{Code( ::(someType) $a, ::(someType) $b ) returns bool} $func, Array of ::(someType) ) returns ::(someType); This gives meaning to operators like [>], which would return the maximum value from a list. Sam.
Re: reduce metaoperator on an empty list
TSa (Thomas Sandlaß) wrote: I'm not sure but Perl6 could do better or at least trickier ;) Let's assume that < > <= >= when chained return an accumulated boolean and the least or greatest value where the condition was true. E.g. 0 < 2 < 3 returns 0 but true 1 < 2 < 1 returns 1 but false 4 < 5 < 2 returns 2 but false An interesting idea, but seems a bit heavy.. Is it correct that [min] won't parse unless min is declared as an infix op, which looks a bit strange? if 3 min 4 { ... } Sure. Again there is a Haskell example to heed closely here; for instance, the function: divMod :: (Integral a) => a -> a -> (a, a) Can be written as either; divMod 42 9 or: 42 `divMod` 9 The reverse direction is (); (+) :: (Num a) => a -> a -> a (+) 7 5 7 + 5 Sam.
AUTLOAD and $_
From S10; In any case, there is no longer any magical $AUTOLOAD variable. The name being declared or defined can be found in $_ instead. The name does not include the package name. You can always get your own package name with $?PACKAGENAME. So, what is the prototype of AUTOLOAD? It is clearly called from the relevant (package dispatcher & type & perl5_compat(stash) ) object, but how? sub AUTOLOAD($_ = $CALLER::$_, [EMAIL PROTECTED]) { ... } In a way, $_ forms part of the prototype definition, but is "out of band" to the regular arguments on @_; it can't interfere with positional characteristics, or you have to "shift" it off before you goto the right sub. OK, we could play tricks with localization of variables, but in the face of continuations and coroutines, localization falls apart. This is fine for people writing `ordinary´ code (perhaps), but for a core language feature it should be resolved IMHO. Out-of-band arguments seem to have been a hot topic in the past; http://xrl.us/ggt7 - Long (50+ posts) thread http://xrl.us/ggua - suggestion from Damian; $foo = sub { print $_ } is given($_); I actually quite like that syntax, or at least the idea of using a trait of some kind to specify non-positional arguments. It keeps them well out of the way of `safe´ programming conventions :). In fact, it has to do wierder things than just accept it out of band to parameters - ideally it would not also interfere with another sub that uses $CALLER::_. Perhaps to avoid that mess, the AUTOLOAD function is simply expected to call &func.goto if it wants all the effects of the presence of the AUTOLOAD sub to go away. Assuming that the prototype is re-checked on a goto, to ensure that type guarantees specified in the function signature are honoured, then the necessary side effects should just happen. Sam.
Re: AUTLOAD and $_
Juerd wrote: I think there exists an even simpler way to avoid any mess involved. Instead of letting AUTOLOAD receive and pass on arguments, and instead of letting AUTOLOAD call the loaded sub, why not have AUTOLOAD do its thing, and then have *perl* call the sub? sub AUTOLOAD ($w) { return our &::($w) := get_subref_for $w } I like that. Makes it more consistent with the AUTOSCALAR, etc methods - returning a reference to the result (variable ref/code ref/sub name) rather than the actual result (variable value/calling the sub). After all, presumably the compiler might sometimes call the AUTOLOAD at compile time; to get its signature. So, for instance, you could AUTOLOAD all the methods you optionally export, which are all pulled in at once when a module imports a function and tries to use it in some code (as the signature will need to be checked then). I was going to bring that up next, but I think this has already answered it. Sam.
Re: AUTLOAD and $_
chromatic wrote: Who says AUTOLOAD will always either call a loaded sub or fail? Maybe it should be passed a continuation too, then? Then it could choose exactly what to do with it. Sam.
AUTOLOAD, this time distinct from AUTOSUB etc (and spelt correctly)
OK, that last discussion was productive, but I think we all (including myself) overlooked the fact that the AUTOLOAD and AUTOSUB methods are implied to have different calling conventions; There is still an AUTOLOAD hook that behaves as in Perl 5. The (AUTO*) routines are expected to return a reference to an object of the proper sort (i.e. a variable, subroutine, or method reference), or undef if that name is not to be considered declared. So, here are the prototypes of the (new) AUTO* methods: subtype Symbol of Str; sub AUTOSCALAR( Symbol $sym ) returns Ref of Scalar; sub AUTOARRAY ( Symbol $sym ) returns Ref of Array; sub AUTOHASH ( Symbol $sym ) returns Ref of Hash; sub AUTOSUB ( Symbol $sym ) returns Code; sub AUTOMETH ( ::$type: Symbol $sym ) returns Code(::$type: *); uh-oh, another sticky one; the implication is that AUTOMETH has an invocant, which is either a Type or the object, and is expected to return a sub whose signatute has the right type, but we don't care to type check anything more than the invocant type. And that's even before we look at MMD, so for now we'll think of it as; sub AUTOMETH ( Symbol $sym ) returns Ref of Code; So, those are all well and good. They can still do anything, including return little micro-subs that perform arbitrary munging of the argument stack before passing them on, or define the sub/variable that was referred to, to avoid the AUTOFOO call the next time around. And they're being invoked at compile time so that we can get their signatures, but that isn't a problem with people doing selective loading because they're clever enough to know what to do. Great, we can all start using those. But what about AUTOLOAD? It has to "behave as in Perl 5", which had different calling conventions and expected you to make the loaded function call yourself. This has some side-implications; the signature used for a Class' AUTOLOAD will be used as the signature for all unknown function calls; so, defining; sub AUTOLOAD { ... } Will forfeit your right to apply signatures to the arguments of an auto-loaded method, which is probably an acceptable penalty for someone who is just expecting P6 to work like P5 did. Method calls, too. It seems these requirements are still in conflict; - Preserving AUTOLOAD thou-shalt-make-the-call semantics - Keeping the new $AUTOLOAD off the argument stack for AUTOLOAD() - Use of $_ as an out-of-band way of passing arguments to a function cannot be localised due to the non-stack-like characteristic of the call stack, in the face of continuations and coroutines - disallowing "explicit" out-of-band arguments Time to re-think the out-of-band arguments idea? Sam.
Re: AUTOLOAD, this time distinct from AUTOSUB etc (and spelt correctly)
Rod Adams wrote: I never liked the idea of out-of-band arguments. Either something is passed, is available due to being in a broader scope, or can be gleamed from introspection. ok. First of all, I agree with the basic sentiment. However, to play devil's advocate and re-interpret what you just said, it does imply that there are some implicit lexicals being passed around - ? twigil variables. These are effectively out-of-band arguments to a function, but not user- modifyable. So what we're saying is that out-of-band arguments must be passed via language/grammar special variables, so to do that from Perl code you'll have to extend the interpreter, quite a challenging task at present. That'll stop them being used Where We Don't Want Them To Be Used™. :-> In this case, I think introspection is the answer. Hang the info off &?SUB or caller. Something like "&?SUB.Invocation" or "caller.call" could be made to return something useful, I think. Also makes the info available for more than just AUTO.* methods, which opens the door up for all kinds of useful perversions, especially in the age of bindings and such. Sure. Structurally, and architecturally, I like this too. But syntactically, $?LASTQUOTEDPARA.idea is a little overweight. But no big problem. Perhaps the problem here is that sometimes you want to explicitly specify which available lexical variable the topic refers to on an arbitrary block. Personally I'm of the leaning that there is no global $_ at all. There is no such thing as a global topic of a program, after all. I don't think I'm contradicting the Synopses there, either. ie, in the main program $_ should not be in scope. In this manner, $_, instead of actually being a real variable, is simply an alias which always has lexical scope and happens to be normally bound to $?SELF in method calls, and to @_[0] in bare blocks, and an anonymous temporary variable in for loops. And in AUTOLOAD blocks, it's bound to the $?SUB.called_as (or whatever) lexical, out-of-band variable. But how does that happen? What makes the AUTOLOAD sub special to get this action? Clearly, we don't want people to have to explicitly say so in their AUTOLOAD signature: sub AUTOLOAD($_ = $?SUB.called_as) { } Plus, the above still wouldn't do what we want because it's still specifying a positional argument. I'm seeing something like this; however it's still a bit awful for various reasons. package Package; sub dispatcher { ... %symtable::.assuming($_ = $method)(@args); ... } Perhaps it is simply a mistake to assume that the package dispatcher will itself be simple, accessible Perl like that. Anyone got any bright ideas? :) Sam.
Magic mutators and my $var is Proxy( ... );
To me it is a trivial case that you want to provide a fake attribute which for all intents and purposes behaves exactly like there was a real attribute there, backing against another attribute. A Date object is a classic example of this; you want to provide 0-based and 1-based attributes, which you want to present as equivalent to each other. So, we've got this "my $var is Proxy( ... )" construct in A06. Say you've got this class: class MagicVal { has Int $.varies is rw; method varies returns Int is rw { return my $var is Proxy ( :for($.varies), :FETCH{ $.varies += 2 }, :STORE{ $.varies = $_ + 1 }, ); } } Firstly, would this be correct syntax? In particular, what should I call $.varies inside the :FETCH and :STORE subs? Would they close over $?SELF, too? If they did, doesn't this mean that $var will be a new Proxy attribute every time that the attribute is read, and will have side effects? Such as; my $foo = MagicVal.new(); $foo.varies = 5;# sets to 6; say $foo.varies;# says 8 say $foo.varies;# says 10 my $var = $foo.varies; # $var is proxy for attribute say $foo.varies;# says 12 say $var; # says 14 It seems to me that the only time I'd want to actually return a Proxy object is when taking a reference to the fake attribute. In all other situations, you'd simply want to dispatch to either an accessor or a mutator, depending on the context. ie, I'd like the design of this feature to be sufficient that most of the time, the Proxy object need never be constructed, and instead the relevant closure could be bound to that method instead. In particular, I think this would mean making Proxy objects automatically call FETCH when returned, unless in reference context. In fact, I think I'd rather see the proxy as a closure trait; class MagicVal { has Int $.varies is rw; method varies returns Int is Proxy( :FETCH(&get_varies), :STORE(&set_varies) ); method get_varies { $.varies += 2 }; method set_varies { $.varies = $^v + 1 }; } Of course this wouldn't preclude the possibility of using the syntax in A06 where it is more suited to the problem at hand. Also, in the case where you do take a reference of a $foo.varies, then a Proxy object could be constructed to DTRT based on the information there. This would make the "is Proxy()" construct effectively a compile-time want() switch. Any opinions on this? Sam.
Re: Magic mutators and my $var is Proxy( ... );
Sam Vilain wrote: To me it is a trivial case that you want to provide a fake attribute which for all intents and purposes behaves exactly like there was a real attribute there, backing against another attribute. A Date object is a classic example of this; you want to provide 0-based and 1-based attributes, which you want to present as equivalent to each other. FWIW, I think this question also applies to fetching members from a hash collection. For example, if you have a function; sub foo($foo) { $foo || "bar" } And you call it, passing it a hash slot; foo(%hash); Then it will be auto-vivified, as in Perl 5; because a reference to the slot had to be taken. Actually there is no reference taken; it's a read-only binding of the hash slot. But either way, it is a read-only point in the signature that is affecting the input argument, which is arguably (right^wrong). By returning a Proxy object 'tied' to the slot, then this autovivification could be circumvented and the straightforward implementation - passing bound variables as transparent references, continues to be acceptable. Albeit requiring that the Hash::postcircumfix:<{ }> method is a Proxy method, too. Sam.
Re: AUTLOAD and $_
Piers Cawley wrote: For myself, I'd like to see AUTOLOAD with a signature along the lines of: sub AUTOLOAD (Symbol $sym, ArgumentCollection $args, Continuation $cc) returns (Code | Pair) { ... } This presupposes a deal of support infrastructure, but also provides flexibility. For the 'NullObject' case, you'd simply do C<$cc()> to return directly to the caller, skipping over whatever Perl is up to. That's an excellent suggestion. After your very enlightening discussion about continuations in IRC, this popped to mind as an interesting application for them, along with exception handlers. This would be great for at least AUTOSUB and AUTOMETH. However, for AUTOLOAD we're looking for simple Perl 5 alikeness. And in Perl 5, the sub name was passed out of band. So, we need a compromise somewhere, please @cabal.pick: - just go for old AUTOLOAD + $AUTOLOAD interface and spit warnings profusely -OR- { - allow topic to refer to variables in lexical scope, but not in @_ (and pick a good name for $?SUB.called_as) -OR- - allow generic out-of-band parameters to be passed in } implies { - there needs to be a special subroutine calling method, similar to .assuming that lets you do this -OR- - the method prototype, and specify some way that methods defined without a signature can inherit it from somewhere else. } -OR- - declare the topic to be the only out-of-band parameter that does this. To avoid it being an accidental global, it would need to be declared with "my $_" when used in this manner (of course, other methods like for, given, etc that set it have the declaration implicit). -OR- - scrap complete AUTOLOAD interface compatibility -OR- - insert solution here ;) Sam.