Fatal/autodie exception hierarchies for Perl 5
G'day p6l and p5p, I'm currently working on the 'autodie' pragma for Perl 5, which is essentially 'Fatal' but with lexical scope. It's similar to the 'fatal' pragma described in S04/Exceptions. autodie is implementing an exception hierarchy for in-built functions. Essentially we have a tree that looks like: :all :USER :CORE :math atan2 :io :file open close :filesys opendir :socket accept bind connect ... Currently, when testing exceptions from autodie, we can use: given ($@) { when (undef) { say "No errors here" } when ('open') { say "Open died" } when (':file') { say "Some sort of file error" } when (':io') { say "Some other error" } when (':CORE') { say "Some other CORE error" } when (':USER') { say "A non-CORE error" } when (':all') { say "Any autodie exception at all." } default{ say "Not an autodie exception." } } There's a 5 minute presentation on what autodie is and how it currently works at: http://pjf.id.au/blog/?position=540 This also looks very similar to what I remember is the desired plan for P6 exception handling, although my memory may be playing tricks on me as I can't seem to find the document where I read this. So, why does p6l care? Well, if there's already a p6 exception hierarchy designed for built-ins, I'd like to use it. It saves me work, and saves surprises for the developers. If there isn't a p6 exception hierarchy yet, then I'd like for p6 to have the option of stealing mine, for essentially the same reasons. Questions I'm seeking answers to are: * Is there a document that describes the current p6l exception hierarchy? My searching skills seem to be impaired today. * Does anyone have any input they'd like to make before I start fleshing out the hierarchy for p5 autodie? * Is this an appropriate question for p6l? While it relates to a p5 pragma, I hope to make the behaviour as compatible with p6 as possible. Many thanks, Paul -- Paul Fenwick <[EMAIL PROTECTED]> | http://perltraining.com.au/ Director of Training | Ph: +61 3 9354 6001 Perl Training Australia| Fax: +61 3 9354 2681
Re: assignable mutators (S06/Lvalue subroutines)
Jon Lang wrote: > This approach could be functionally equivalent to the "proxy object" > approach, but with a potentially more user-friendly interface. That > is, > > sub foo (*$value) { yadda } > > might be shorthand for something like: > > sub foo () is rw { >return new Proxy: > FETCH => method { return .doit() }, > STORE => method ($val) { .doit($val) }, > doit => method ($value?) { yadda } > } Correction: sub foo (*$value) { yadda } might be shorthand for something like: sub foo () is rw { return new Proxy: FETCH => method { return .() }, STORE => method ($val) { .($val) }, postcircumfix:<( )> => method ($value?) { yadda } } i.e., it can be called like a regular function as well as via assignment semantics. -- Jonathan "Dataweaver" Lang
Re: assignable mutators (S06/Lvalue subroutines)
David Green wrote: > It seems overly complex to me, but perhaps I'm missing good reasons for such > an approach. I see lvalue subs mainly as syntactic sugar: > >foo(42); # arg using normal syntax >foo <== 42; # arg using feed syntax >foo = 42; # arg using assignment syntax > > Feeds are a way of passing values to a function, but work like assignment > when used on a variable; assignment is a way of giving a value to a > variable, so it should work like passing args when used on a function. Then > you can easily do whatever you want with it. > > In fact, it could work just like a feed, and pass values to the slurpy > params, but I think assignment is special enough to be worth treating > separately. Maybe something like: > >sub foo ($arg1, $arg2, [EMAIL PROTECTED], =$x) {...} > >foo(6,9) = 42; # the 42 gets passed to $x > > That example uses a leading "=" for the "assigned" param (parallel to the > leading "*" for the slurpy param), but I'm not crazy about it for various > reasons (and =$x refers to iteration in other contexts). OK; my take on it: An "lvalue sub" is a sub that can be assigned to - the operative word being "can". There's a reason why Perl 6 talks about "is rw" and "is ro" so much, but has yet to (and may never) officially approach the idea of "is wo". You don't _have_ to assign to an lvalue sub in order to use it. As such, an lvalue sub needs to be written in such a way that it can be called to assign a value or to return a value. The current "proxy object" approach makes this explicit by mandating separate FETCH and STORE methods to handle the two uses. This has the benefit of a fully consistent mechanism for handling "assignable routines": return an assignable object; if a value was going to be assigned to the subroutine, it is instead assigned to the returned object. Simple, and straightforward. And sometimes messy. Let's consider the following alternative, inspired by David's suggestion: (I'm thinking aloud here, exploring possibilities and looking for problems as I go. Please bear this in mind.) If a routine is rw, you may optionally define a single "slurpy scalar" (e.g., '*$value') in its signature. This scalar counts as the last positional parameter, much like slurpy arrays and hashes must be declared after all of the positional parameters have been declared. You do not need to pass an argument to it; but if you do, you may do so in one of two ways: through the usual arguments syntax, or via assignment syntax. If an assignable routine does not have a slurpy scalar in its signature, it operates exactly as currently described in S06: it returns something that is assignable, which in turn is used as the lvalue of the assignment operator. If the slurpy scalar is present in the signature, then an attempt to assign a value to the sub passes the value in through the slurpy scalar, while an attempt to read the value that the sub represents doesn't pass anything to the slurpy scalar. The routine then replaces the normal assignment operation and returns a value in much the same way that the assignment operator would. This approach could be functionally equivalent to the "proxy object" approach, but with a potentially more user-friendly interface. That is, sub foo (*$value) { yadda } might be shorthand for something like: sub foo () is rw { return new Proxy: FETCH => method { return .doit() }, STORE => method ($val) { .doit($val) }, doit => method ($value?) { yadda } } -- Jonathan "Dataweaver" Lang
Re: ordinal access to autosorted hashes
David Green wrote: > Jon Lang wrote: >> Would it be reasonable to allow hashes to use .[] syntax as something >> of a shortcut for ".iterator in list context", thus allowing >> autosorted hashes to partake of the same sort of dual cardinal/ordinal >> lookup capabilities that lists with user-defined array indices have? > > I thought it already did, but apparently it's something that we discussed > that didn't actually make it into S09. I agree that .[] should apply to > hashes just as .{} can apply to arrays. The hashes don't even need to be > sorted -- %h[$n] would basically be a shorter way of saying > @(%h.values)[$n], in whatever order .values would give you. I believe that the order that .values (or is that :v?) would give you is determined by .iterator - which, if I'm understanding things correctly, means that any use of :v, or :k, :p, or :kv, for that matter, would autosort the hash (specifically, its keys). Or am I reading too much into autosorting? Bear in mind that keys are not necessarily sortable, let alone autosorted. For instance, consider a hash that stores values keyed by complex numbers: since there's no way to determine .before or .after when comparing two complex numbers, there's no way to sort them - which necessarily means that the order of :v is arbitrary, making %h[0] arbitrary as well. This is why I was suggesting that it be limited to autosorted hashes: it's analogous to how @a{'x'} is only accessible if you've actually defined "keys" (technically, user-defined indices) for @a. -- Jonathan "Dataweaver" Lang
Re: ordinal access to autosorted hashes
On 2008-May-27, at 8:32 pm, Jon Lang wrote: [...] Would it be reasonable to allow hashes to use .[] syntax as something of a shortcut for ".iterator in list context", thus allowing autosorted hashes to partake of the same sort of dual cardinal/ordinal lookup capabilities that lists with user-defined array indices have? I thought it already did, but apparently it's something that we discussed that didn't actually make it into S09. I agree that .[] should apply to hashes just as .{} can apply to arrays. The hashes don't even need to be sorted -- %h[$n] would basically be a shorter way of saying @(%h.values)[$n], in whatever order .values would give you. Side issue: S09 doesn't specify whether or not you need to explicitly declare a hash as autosorted. I'm assuming that the parser is supposed to figure that out based on whether or not .iterator is ever used; but it isn't immediately obvious from reading the "Autosorted hashes" section. As well, there might be times when explicitly declaring a hash as autosorted (or not) might be useful for optimization purposes. Does the parser need to know? All hashes have an .iterator method, but you can override it to force elements to be returned using some particular ordering. Providing a flag for optimisation sounds useful... although since Perl doesn't do any sorting for you, if you want something more optimised than making .iterator re-sort the hash every time it's called, you'd have to replace the innards of the Hash type yourself anyway. But if you did make a Hash::Sorted class, defining an "is sorted" trait might be a nice way to use it. -David
Huffman encoding (was Re: treatment of "isa" and inheritance)
On 2008-Apr-30, at 1:29 pm, Brandon S. Allbery KF8NH wrote: On Apr 30, 2008, at 15:14 , Jon Lang wrote: On a side note, I'd like to make a request of the Perl 6 community with regard to coding style: could we please have adverbal names that are, well, adverbs? "is :strict Dog" brings to my mind the English -ly suffixes everywhere conflicts with Huffman coding, which per @Larry is a primary design concern. Consider the leading colon to be the Perl6 equivalent. Logically, yes, a ":" on the front of a word is as good an indicator of an adverb as an "ly" on the end. Psychologically, however, it isn't; for one thing, my mind doesn't pronounce punctuation the same way as letters. Whatever the reason, I've been reading English for decades longer than I have P6 (and by the time I've spent that many decades getting familiar with P6, I'll be even more familiar with English... which is of course one of the reasons why Perl tries to look kinda sorta like English in the first place; it may as well try to look like half-decent English!). But the more general point I wish to make is that extra characters don't necessarily conflict with the goal of Huffman encoding. I assume the idea was that extra 'ly's everywhere take up space that isn't needed -- of course Huffman himself was concerned with minimising bits, but in terms of Perl what we're interested in is efficient understanding, not efficient storage. Now "short code" is not a bad first approximation to "understandable code", since longer reading-time will contribute to longer understanding-time. But that's only a very rough rule of thumb: if something is too short, it will take even more work to figure out what it's saying, and thus any time saved by shortness will be swamped by the much greater effort to figure out what the heck it means. (In this particular example, it seems quite reasonable that the cognitive dissonance from seeing an adjective where one's English- trained brain is expecting an adverb will outweigh the negligible time it takes to scan a couple of extra letters.) That's why Perl6 has abandoned all the punctuation-variables from P5 in favour of their "use English" equivalents. Real words are longer to read (and write) but easier to understand overall. (Of course, more characters are less efficient to type, but except for throw-away one-liners, code gets written once and read multiple times, so Huffman meta-encoding dictates that we should optimise for reading. And anyway, making code more efficient to write is the job of one's text-editor, not the language. Maybe we should work on auto- completion files for popular editors that will expand things like ":str" into ":strictly", etc.) -David
Re: assignable mutators (S06/Lvalue subroutines)
On 2008-May-27, at 9:40 am, Dave Whipp wrote: TSa wrote: method inch { yield $inch = $.mm * 25.4; self.mm = $inch / 25.4; } Would you regard that as elegant? That looks functionally incorrect to my eyes: if the caller resumes at the time of the "yield" statement, and immediately assigns a new value to the "mm" attribute, then there is a race between the two updates to "mm". It seems overly complex to me, but perhaps I'm missing good reasons for such an approach. I see lvalue subs mainly as syntactic sugar: foo(42); # arg using normal syntax foo <== 42; # arg using feed syntax foo = 42; # arg using assignment syntax Feeds are a way of passing values to a function, but work like assignment when used on a variable; assignment is a way of giving a value to a variable, so it should work like passing args when used on a function. Then you can easily do whatever you want with it. In fact, it could work just like a feed, and pass values to the slurpy params, but I think assignment is special enough to be worth treating separately. Maybe something like: sub foo ($arg1, $arg2, [EMAIL PROTECTED], =$x) {...} foo(6,9) = 42; # the 42 gets passed to $x That example uses a leading "=" for the "assigned" param (parallel to the leading "*" for the slurpy param), but I'm not crazy about it for various reasons (and =$x refers to iteration in other contexts). Perhaps it could be identified as "$x is assigned" -- but that doesn't look quite right to me either. However it's written, it would be simpler than having to use proxies. -David