November 20, 2013
I also think this is very powerful and under-explored approach but it really better belongs to certain domain framework than to stdlib. One example I keep thinking about is to re-declare vibe.d string functions in terms of EscapedString!(SQL), EscapedString!(HTML) and so on for better application safety and correctness. No idea how that may work in practice though.
November 20, 2013
20-Nov-2013 14:45, Lars T. Kyllingstad пишет:
> On Wednesday, 20 November 2013 at 00:01:00 UTC, Andrei Alexandrescu wrote:
>> (c) A variety of text functions currently suffer because we don't make
>> the difference between validated UTF strings and potentially invalid
>> ones.
>
> I think it is fair to always assume that a char[] is a valid UTF-8
> string, and instead perform the validation when creating/filling the
> string from a non-validated source.
>
> Take std.file.read() as an example; it returns void[], but has a
> validating counterpart in std.file.readText().

Sadly it's horrifically slow to do so. Above all practicality must take precedence. Would you like to validate the whole file just to later re-scan it anew to say tokenize source file?

>
> I think we should use ubyte[] to a greater extent for data which is
> potentially *not* valid UTF.  Examples include interfacing with C
> functions, where I think there is a tendency towards always translating
> C char to D char, when they are in fact not equivalent.  Another example
> is, again, std.file.read(), which currently returns void[].  I guess it
> is a matter of taste, but I think ubyte[] would be more appropriate
> here, since you can actually use it for something without casting it first.

Otherwise I think it's a good idea to encode high-level invariants in types. The only problem is inadvertent template bloat then.

[snip]

-- 
Dmitry Olshansky
November 20, 2013
20-Nov-2013 22:01, Simen Kjærås пишет:
> On 20.11.2013 18:45, Simen Kjærås wrote:
[snip]
>> May I suggest:
>>
>> struct Validated(alias fn, T) {
>>      private T value;
>>      @property inout
>>      T get() {
>>          return value;
>>      }
>
> Uh-hm. Add this:
>         alias get this;
>

And it decays to the naked type in a blink of an eye. And some function down the road will do the validation again...

>> }
>>
>> Validated!(fn, T) validate(alias fn, T)(T value) {
>>      Validated!(fn, T) result;
>>      fn(value);
>>      result.value = value;
>>      return result;
>> }
>>
>> void functionThatTakesSanitizedFileNames(Validated!(sanitizeFileName,
>> string) path) {
>>     // Do stuff
>> }
>>
>
>


-- 
Dmitry Olshansky
November 20, 2013
On Wednesday, 20 November 2013 at 18:30:58 UTC, Dmitry Olshansky wrote:
> 20-Nov-2013 22:01, Simen Kjærås пишет:
>> On 20.11.2013 18:45, Simen Kjærås wrote:
> [snip]
>>> May I suggest:
>>>
>>> struct Validated(alias fn, T) {
>>>     private T value;
>>>     @property inout
>>>     T get() {
>>>         return value;
>>>     }
>>
>> Uh-hm. Add this:
>>        alias get this;
>>
>
> And it decays to the naked type in a blink of an eye. And some function down the road will do the validation again...
>
>>> }
>>>
>>> Validated!(fn, T) validate(alias fn, T)(T value) {
>>>     Validated!(fn, T) result;
>>>     fn(value);
>>>     result.value = value;
>>>     return result;
>>> }
>>>
>>> void functionThatTakesSanitizedFileNames(Validated!(sanitizeFileName,
>>> string) path) {
>>>    // Do stuff
>>> }

Yes. It is very important not to allow direct access to the underlying value. This is important for ensuring that it is not put in an invalid state. This is a mistake that was made with std.typecons.Nullable, making it useless for anything other than giving a non-nullable type a null state (which, in fairness, is probably all that it was originally intended for).
November 20, 2013
On Wednesday, November 20, 2013 19:53:43 Meta wrote:
> Yes. It is very important not to allow direct access to the underlying value. This is important for ensuring that it is not put in an invalid state. This is a mistake that was made with std.typecons.Nullable, making it useless for anything other than giving a non-nullable type a null state (which, in fairness, is probably all that it was originally intended for).

It's arguably pretty pointless to put a nullable type in std.typecons.Nullable. If you want a nullable type to be null, just set it to null.

- Jonathan M Davis
November 20, 2013
On Wednesday, 20 November 2013 at 19:23:32 UTC, Jonathan M Davis wrote:
> On Wednesday, November 20, 2013 19:53:43 Meta wrote:
>> Yes. It is very important not to allow direct access to the
>> underlying value. This is important for ensuring that it is not
>> put in an invalid state. This is a mistake that was made with
>> std.typecons.Nullable, making it useless for anything other than
>> giving a non-nullable type a null state (which, in fairness, is
>> probably all that it was originally intended for).
>
> It's arguably pretty pointless to put a nullable type in
> std.typecons.Nullable. If you want a nullable type to be null, just set it to
> null.
>
> - Jonathan M Davis

See the discussion from the other thread for why it can be useful to wrap a nullable reference in a option type (nullable is a pseudo-option type).
November 20, 2013
On 11/20/13 9:56 AM, Meta wrote:
> On Wednesday, 20 November 2013 at 14:14:28 UTC, Timon Gehr wrote:
>> On 11/20/2013 02:52 PM, Jacob Carlborg wrote:
>>> On 2013-11-20 13:56, Timon Gehr wrote:
>>>
>>>> We do in any case:
>>>>
>>>> import std.algorithm, std.range;
>>>>
>>>> void main(){
>>>>     auto a = [1,2,3,4,5];
>>>>     auto s = sort(a);
>>>>     swap(a[0],a[$-1]);
>>>>     assert(is(typeof(s)==SortedRange!(int[])) && !s.isSorted());
>>>> }
>>>>
>>>
>>> I don't understand what this is supposed to show. That the type is
>>> "SortedRange" but it's actually not sorted?
>>>
>>
>> Yes, hence SortedRange being sorted is just a convention in any case.
>
> Couldn't we have an overload of each of the mutating functions in
> std.algorithm that takes a SortedRange and does static assert(0, "Cannot
> modify a sorted range")? I suppose there are cases where we *want* to
> mutate a sorted range... Unwrap the inner type, maybe?

That wouldn't help much - people have access to the underlying range anyway.

Andrei
November 20, 2013
On Wednesday, November 20, 2013 20:40:40 Meta wrote:
> On Wednesday, 20 November 2013 at 19:23:32 UTC, Jonathan M Davis
> 
> wrote:
> > On Wednesday, November 20, 2013 19:53:43 Meta wrote:
> >> Yes. It is very important not to allow direct access to the
> >> underlying value. This is important for ensuring that it is not
> >> put in an invalid state. This is a mistake that was made with
> >> std.typecons.Nullable, making it useless for anything other
> >> than
> >> giving a non-nullable type a null state (which, in fairness, is
> >> probably all that it was originally intended for).
> > 
> > It's arguably pretty pointless to put a nullable type in
> > std.typecons.Nullable. If you want a nullable type to be null,
> > just set it to
> > null.
> > 
> > - Jonathan M Davis
> 
> See the discussion from the other thread for why it can be useful to wrap a nullable reference in a option type (nullable is a pseudo-option type).

I know. And I still think that it's pointless - and it incurs extra overhead to boot, making it _worse_ than pointless. But clearly there's disagreement on the matter.

- Jonathan M Davis
November 20, 2013
20-Nov-2013 22:28, Dicebot пишет:
> I also think this is very powerful and under-explored approach but it
> really better belongs to certain domain framework than to stdlib. One
> example I keep thinking about is to re-declare vibe.d string functions
> in terms of EscapedString!(SQL), EscapedString!(HTML) and so on for
> better application safety and correctness. No idea how that may work in
> practice though.

I think the obstacles are mostly:

1. There is a non-zero intersection between validated subsets. Some kind of NiceStringWithNoPunctuation fits practically every EscapedString!(XYZ). There must be a way to cascade and mix/match these classes.

2. Template bloatZ! It would be real hard to fight the IFTI duping functions bodies behind your back. Or if you dumb down these escaped types to not fit the most of templates, it may become a usability problem.

3. This kind of thing is viral. With escape hatch though, it may be done step by step.

-- 
Dmitry Olshansky
November 20, 2013
On Wednesday, 20 November 2013 at 20:19:28 UTC, Dmitry Olshansky wrote:
> 2. Template bloatZ! It would be real hard to fight the IFTI duping functions bodies behind your back. Or if you dumb down these escaped types to not fit the most of templates, it may become a usability problem.
>
> 3. This kind of thing is viral. With escape hatch though, it may be done step by step.

This is the very reason why I am saying it makes much more sense as part of certain application framework as those tends to have more clear separation between internal and external infrastructure and strict usage API expectations. So it is not a usability problem, it is a usability feature :)