Re: Type Conversion Matrix, Pragmas (TAKE 4)
On Friday, June 13, 2003, at 10:26 PM, David Storrs wrote: On the subject of untyped scalars...what does it mean to say that the conversion is 'lossless'? For example: I've been using the word to mean that a conversion is lossless if, for a particular A--B conversion, you can recreate the typed value A *completely* from B, including value, definedness, and properties. So if you can say A--B--A, and always get _exactly_ the same thing in A that you started with, for _any_ valid starting value of A, it's lossless. Which is darn rare, looking at the matrix, because of range issues, etc. my $a = 'foo'; my Int $b = $a; # legal; $b is now 0; is there a warning? my $c = $b; # is $c 0, or 'foo'? 0, I think. Or specifically, CInt 0. (I've been operating under the assumption that an untyped scalar doesn't _remove_ the type of something, it just can store values of _any_ type, and is by default much more generous about autoconverting them for you, so that you could use $c as an Int, int, Num, num, Str, str, etc., without warning or error... but internally, it's actually still storing the value as an CInt 0, because that's what you assigned to it.) my Str $d = $a; # no loss my $a = $d; # no effective change in $a my $e = $b; # what is $d? $d? Still a Str, I would think. And $e would be Int 0, same as $c In the above, I would expect that $c is 0 and my $a = 7 but false; my Str $b = $e; # ??? What value does $f end up with? (My vote would be '7'.) My understanding is that properties go with the values, (just like traits go with the variables), so I would expect $f to be C7 but false. So if a value is Cbut false, it stays Cbut false until you say otherwise. Are any warnings emitted? Yeah, I dunno. I think we need somebody smart to tell us at this point. I have no idea how close or how far we are on our musings about pragmas and defaults... I sure hope somebody does. :-) MikeL
Re: Type Conversion Matrix, Pragmas (TAKE 4)
On Mon, Jun 16, 2003 at 10:15:57AM -0700, Michael Lazzaro wrote: On Friday, June 13, 2003, at 10:26 PM, David Storrs wrote: my $a = 'foo'; my Int $b = $a; # legal; $b is now 0; is there a warning? my $c = $b; # is $c 0, or 'foo'? 0, I think. Or specifically, CInt 0. So then conversion from Scalar to Int is not lossless, and (by extension) conversions from Scalar to any other LargeCapPrimitive are presumably not lossless either. (I've been operating under the assumption that an untyped scalar doesn't _remove_ the type of something, it just can store values of _any_ type, and is by default much more generous about autoconverting them for you, so that you could use $c as an Int, int, Num, num, Str, str, etc., without warning or error... but internally, it's actually still storing the value as an CInt 0, because that's what you assigned to it.) Seems reasonable. pedantic Although I would assume that it would store and pull the value from an Int slot, then create a new value of the converted to type, and use that. /pedantic my Str $d = $a; # no loss my $a = $d; # no effective change in $a my $e = $b; # what is $d? $d? Still a Str, I would think. And $e would be Int 0, same as $c I obviously had either a typo or a braino on the last line there. I have no idea what I was trying to ask. What value does $f end up with? (My vote would be '7'.) My understanding is that properties go with the values, (just like traits go with the variables), so I would expect $f to be C7 but false. So if a value is Cbut false, it stays Cbut false until you say otherwise. A better example of what I was driving at would be this: my $a = 'foo' but purple; my Int $b = $a; In other words: I've just created an untyped Scalar. This Scalar is (presumably in it's Str slot) storing a string value which happens to have a property set on it (i.e., Cfoo but purple). Now I assign this Str to an Int. String values get converted when assigned to Ints. Are we converting and assigning THE IDENTICAL VALUE or are we creating a new value (whose value, in a numeric context, is considered equivalent) and assigning that? In the first case, I would expect that the property would be preserved. In the latter case, I would expect it NOT to be preserved. --Dks OT afterthought: In the past, whenever we've gotten embroiled in one of these thorny, knotty issues, @Larry has pulled a stunningly beautiful, elegant rabbit out of their hats. And when I thought that, I had this vision of a single quantum rabbit simultaneously coming out of multiple hats with widely divergent spatial coordinates
Re: Type Conversion Matrix, Pragmas (TAKE 4)
--- David Storrs [EMAIL PROTECTED] wrote: On Mon, Jun 16, 2003 at 10:15:57AM -0700, Michael Lazzaro wrote: On Friday, June 13, 2003, at 10:26 PM, David Storrs wrote: my $a = 'foo'; my Int $b = $a;# legal; $b is now 0; is there a warning? my $c = $b;# is $c 0, or 'foo'? 0, I think. Or specifically, CInt 0. So then conversion from Scalar to Int is not lossless, and (by extension) conversions from Scalar to any other LargeCapPrimitive are presumably not lossless either. Not *guaranteed* lossless. Indeed, how could they be? I suppose you could construct your scalar as: my $a = foo; my Int $b = $a; $b == 0 but Scalar(foo); such that you may reconstruct the Scalarness. But that seems like trouble waiting to happen -- propagating the value means that eventually someone calls Cprint $b3 and gets foo instead of 0. Unless operator semantics strip extended-value-attributes, so that $b == 0 but Scalar(foo) while C$c = $b + 1 == 1 but Scalar(1); Frankly, I prefer to regard Scalar-Int as a narrowing conversion and accept the lossage. (I've been operating under the assumption that an untyped scalar doesn't _remove_ the type of something, it just can store values of _any_ type, and is by default much more generous about autoconverting them for you, so that you could use $c as an Int, int, Num, num, Str, str, etc., without warning or error... but internally, it's actually still storing the value as an CInt 0, because that's what you assigned to it.) Seems reasonable. pedantic Although I would assume that it would store and pull the value from an Int slot, then create a new value of the converted to type, and use that. /pedantic This goes back to Damian's point some months ago that function call arguments are pass-by-reference and the limitations that imposes on automatic conversion/coercion. In essence, because we say: sub foo(Int $arg) {...} foo($a); The parameter to foo has to be type compatible with Int, or the compiler will have to automatically instantiate a temp and convert in one or more directions. Currently, I believe the pendulum has swung towards must be type compatible or you get an error. A better example of what I was driving at would be this: my $a = 'foo' but purple; my Int $b = $a; In other words: I've just created an untyped Scalar. This Scalar is (presumably in it's Str slot) storing a string value which happens to have a property set on it (i.e., Cfoo but purple). Now I assign this Str to an Int. String values get converted when assigned to Ints. Are we converting and assigning THE IDENTICAL VALUE or are we creating a new value (whose value, in a numeric context, is considered equivalent) and assigning that? In the first case, I would expect that the property would be preserved. In the latter case, I would expect it NOT to be preserved. My preference is: $temp = foo; $temp.setProperty(purple); $a = $temp; $temp = Str_to_Int($a); # 0, no property. $b = $temp; Although it occurs to me that there might be such a thing as Int properties and Str properties, and maybe the conversion propagates the appropriate ones. That is: my $a = foo but $purple ; $a but= false; $a but= prime; $a but= charset(UTF8); $a but= encoding(text/utf8); my Int $b = $a; At this point, $b would be C0 but all(false, prime). =Austin
Re: Type Conversion Matrix, Pragmas (TAKE 4)
On Monday, June 16, 2003, at 11:04 AM, David Storrs wrote: On Mon, Jun 16, 2003 at 10:15:57AM -0700, Michael Lazzaro wrote: (I've been operating under the assumption that an untyped scalar doesn't _remove_ the type of something, it just can store values of _any_ type, and is by default much more generous about autoconverting them for you, so that you could use $c as an Int, int, Num, num, Str, str, etc., without warning or error... but internally, it's actually still storing the value as an CInt 0, because that's what you assigned to it.) Seems reasonable. pedantic Although I would assume that it would store and pull the value from an Int slot, then create a new value of the converted to type, and use that. /pedantic Yeah, I would think so. A better example of what I was driving at would be this: my $a = 'foo' but purple; my Int $b = $a; In other words: I've just created an untyped Scalar. This Scalar is (presumably in it's Str slot) storing a string value which happens to have a property set on it (i.e., Cfoo but purple). Now I assign this Str to an Int. String values get converted when assigned to Ints. Are we converting and assigning THE IDENTICAL VALUE or are we creating a new value (whose value, in a numeric context, is considered equivalent) and assigning that? In the first case, I would expect that the property would be preserved. In the latter case, I would expect it NOT to be preserved. I am almost positive that the assignment would perform a copy/clone of the original value, but would preserve the properties while doing so. So if we try to assign C'foo' but purple to the Int $b, it: - clones a new Scalar C'foo' but purple, but... - identifies the copied C'foo' but purple as being a Scalar, not an Int, so... - converts the copied CScalar 'foo' but purple to an Int, resulting in CInt 0 but purple - assigns CInt 0 but purple to $b. ... or something like that. But I would expect that the property _would_ be preserved... my gut feeling is that otherwise, they'd be _way_ to easy to accidentally lose, yes? OT afterthought: In the past, whenever we've gotten embroiled in one of these thorny, knotty issues, @Larry has pulled a stunningly beautiful, elegant rabbit out of their hats. And when I thought that, I had this vision of a single quantum rabbit simultaneously coming out of multiple hats with widely divergent spatial coordinates Yeah. What I wouldn't give for a quantum bunny, right about now. It's not even that type conversion is a particularly difficult issue, it's just so *very* all-encompassing that it's got to be done precisely, because it chains through everything else about the language... what happens when calling subroutines, what happens in the multimethod dispatcher, what simple lines of code do or don't give big honkin' errors, etc... MikeL
Re: Type Conversion Matrix, Pragmas (TAKE 4)
On Mon, Jun 16, 2003 at 11:47:35AM -0700, Austin Hastings wrote: Although it occurs to me that there might be such a thing as Int properties and Str properties, and maybe the conversion propagates the appropriate ones. That is: my $a = foo but $purple ; $a but= false; $a but= prime; $a but= charset(UTF8); $a but= encoding(text/utf8); my Int $b = $a; At this point, $b would be C0 but all(false, prime). =Austin Yeek. That gives me the screaming willies. Let's either have it preserve all the properties or none, but please don't make me remember a big list of which properties exist for which types...and oh, btw, did I happen to overload/modify that? Did any of the modules I'm using? Where do user defined properties (if those still exist) fit in? --Dks
Re: Type Conversion Matrix, Pragmas (TAKE 4)
On Tue, Jun 10, 2003 at 12:04:14PM -0700, Michael Lazzaro wrote: J: (scalar junctive to typed scalar) A scalar junctive, e.g. an untyped scalar, can always be silently used as and/or converted to a more specific primitive type. This will quite frequently result in the loss of information; for example, saying: my $a = 'foo'; my int $b = $a;# $b is now C0 works, but silently sets $b to 0, because the numeric value of C'foo' is C0 but true. On the subject of untyped scalars...what does it mean to say that the conversion is 'lossless'? For example: my $a = 'foo'; my Int $b = $a; # legal; $b is now 0; is there a warning? my $c = $b; # is $c 0, or 'foo'? my Str $d = $a; # no loss my $a = $d; # no effective change in $a my $e = $b; # what is $d? In the above, I would expect that $c is 0 and my $a = 7 but false; my Str $b = $e; # ??? What value does $f end up with? (My vote would be '7'.) Does it have any properties? Are any warnings emitted? (iv) Pragma-Controlled Conversions Given the above, and given the fact that our general answer to everything is to Use A Pragma ;-), we have the following tentative list of needed pragmas. For each possibility, we need to be able to declare that a given implicit type conversion will be silently allowed, will result in a warning, or will result in an exception. A (very) rough proposed pragma form, for the sake of argument, is: use strict conversions; # all on (exceptions) no strict conversions; # all off use strict conversions allow = cv1 cv2 ... ; # selected conversions are allowed use strict conversions warn = cv1 cv2 ... ; # selected conversions give warnings use strict conversions fail = cv1 cv2 ... ; # selected conversions give exceptions Seems generally, but I'd like to see this be organized into hierarchies, like Perl 5 (recent versions) warnings: the Numeric group would control every form of numeric conversion, the Truncation subgroup would control everything in the Numeric group that could end up truncating data (e.g. int - short), etc. S: (string to numeric) My vote for default: Callow F: (float to int) My vote for default: Cwarn N: (numeric range) My vote for default: Callow I also suggest adding an extra pragma: use rangechecking warn = Int_to_int ; use rangechecking warn = Num_to_num ; use rangechecking fail = Int_to_int ; use rangechecking fail = Num_to_num ; This lets you trade speed for safety on a lexically-scoped basis. (vi) Conversions of User Defined Types/Classes It may be useful to allow the same level of pragma-based control for user-defined types and classes. For example, a given class Foo may wish to be silently convertable to an Cint. One proposed syntax to declare the method of coercion/conversion might be: class Foo { ... to int {...} # or Cas int {...}? } However, users of such a class could adjust the warning level of the given conversion using the alternate syntax given above (v): use strict conversions warn { Foo = int }; Adding to the 'hierarchical pragmas' idea that I mentioned above...how about a 'to_int' group, which controlled any type (user defined or system) that was attempted to convert itself to an int? The extensions are obvious. --Dks
Re: Type Conversion Matrix, Pragmas (TAKE 4)
On Tue, Jun 10, 2003 at 12:04:14PM -0700, Michael Lazzaro wrote: *: (undefness and properties lost) Using/converting an uppercase type as/to a lowercase (primitive) type is silently allowed. If you're sending an Int to something that requires an Cint, you know that the 'something' can't deal with the undef case anyway -- it doesn't differentiate between undef and zero. Thus, you meant to do that: it's an intentionally destructive narrowing, and the Cundef becomes a C0. my Int $a = undef; my int $b = $a; # $b is now C0, NOT Cundef I'm not sure what silently allowed means here (compile time perhaps?) but I'd certainly want that to generate the traditional Use of undefined value warning (controlable via the perl6 equiv of the warnings pragma, but defaulting to enabled). F: (float to int) Historically, accidentally using a float as an int can be a significant source of errors. Proposed pragma variants: use strict conversions allow = num_to_int ; # which is the default? use strict conversions warn = num_to_int ; use strict conversions fail = num_to_int ; I don't see a problem with compile time warnings by default *if* there's an easy way for the developers to express the fact that they know what they're doing (easier, that is, than wrapping the assignment in a { use strict conversions allow ... } block). Something like a cast function would fit: $int = int($num); N: (numeric range) This one is a giant pain. Converting, say, an Int to an int will, in fact, fail to do the right thing if you're in BigInt territory, such that the number would have to be truncated to fit in a standard int. But 99% of the time, you won't be working with numbers like that, so it would seem a horrible thing to disallow Int -- int and Num -- num conversions under the remote chance you *might* be hitting the range boundary. Then again, it would seem a horrible thing to hit the range boundary and not be informed of that fact. Thus, deciding the default state here will be a challenge: use strict conversions allow = Int_to_int ; # which is the default? use strict conversions warn = Int_to_int ; use strict conversions fail = Int_to_int ; use strict conversions allow = Num_to_num ; # which is the default? use strict conversions warn = Num_to_num ; use strict conversions fail = Num_to_num ; Same as above. I could live with a compile time warning if it's trivial to silence it for a particular assignment. But I'd also like separate control over the detection and behaviour of underflow / overflow / loss of precision etc at runtime. So if I assign an int a value that's too big (from a Int, or Num, or untyped scalar), I would like to know about it. Similarly for num. (v) Alternative Pragma Form An alternative pragma form could possibly allow finer control over every individual possible conversion. The disadvantage of this form is that it would be very difficult to correctly set each of the 100 cells of the matrix, or even the 14 critical cells that most often change: Perhaps it would be better to think in terms of styles of coding or policies, and aim to meet those needs with simple pragmas (implemented on top of a more general mechanism). Basically, do both. The simple forms could just be an interface to the more general. (vi) Conversions of User Defined Types/Classes It may be useful to allow the same level of pragma-based control for user-defined types and classes. For example, a given class Foo may wish to be silently convertable to an Cint. One proposed syntax to declare the method of coercion/conversion might be: class Foo { ... to int {...} # or Cas int {...}? } However, users of such a class could adjust the warning level of the given conversion using the alternate syntax given above (v): use strict conversions warn { Foo = int }; For my int $int = $foo; isn't the int() method (vtable entry) called on $foo? (effectively) So the $foo object is asked to provide an int for assigment to $int. So the Foo class gets to decide how to do that. In which case what you're proposing requires either - the compiler to write the code to pass extra flags to the int method - the compiler to write call a different int method (eg, int_warn()) - for the int method to look at the calling context to get flags Please correct me if I'm wrong (which I could easily be as I've not been following any of thise closely). I think this is an important topic because it may reflect back on how the specific Int/Num/Str classes should also be handled. Tim [quite possibly talking nonsense]
Re: Type Conversion Matrix, Pragmas (TAKE 4)
On Wednesday, June 11, 2003, at 05:48 AM, Tim Bunce wrote: (vi) Conversions of User Defined Types/Classes It may be useful to allow the same level of pragma-based control for user-defined types and classes. For example, a given class Foo may wish to be silently convertable to an Cint. One proposed syntax to declare the method of coercion/conversion might be: class Foo { ... to int {...} # or Cas int {...}? } However, users of such a class could adjust the warning level of the given conversion using the alternate syntax given above (v): use strict conversions warn { Foo = int }; For my int $int = $foo; isn't the int() method (vtable entry) called on $foo? (effectively) So the $foo object is asked to provide an int for assigment to $int. So the Foo class gets to decide how to do that. Yep. The general question that has come up before is to what extent the user of a given class or module should be able to influence the strictness of the interface of that class/module -- without altering the module, obviously. The general feeling was that people wanted to be able to do it, because they didn't want to be bound to a particular CP6AN author's decisions on interface strictness. The specific issue discussed previously, IIR, was something like this: class Foo { method bar(str $s); } If you said: my int $i = 5; $foo-bar($i); what should happen? Should bar() convert $i to a str, or give a compiletime warning or error because it's not a str? And is that determined by the strictness level of the Foo class, or the strictness level of the calling code, or --shudder-- possibly both? Please correct me if I'm wrong (which I could easily be as I've not been following any of thise closely). I think this is an important topic because it may reflect back on how the specific Int/Num/Str classes should also be handled. Tim [quite possibly talking nonsense] Talking perfect sense. It's a nasty issue. MikeL