November 20, 2013
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?

-- 
/Jacob Carlborg
November 20, 2013
On 2013-11-20 13:22, Marco Leise wrote:

> None of that is feasible. We can only hope that we simply
> catch every case of user input (or untrusted data) and check
> it before passing it to Phobos APIs. That's why there are
> functions to validate and also to sanitize UTF strings on a
> best effort basis in Phobos.
>
> So in my opinion Phobos should continue forward with assert
> instead of enforce. I/O functions, of course, have to use
> exceptions.
>
> That said, I never thought of validating args[] before passing
> it to getopt or using them as a filename. Lesson learned, I
> guess?

I don't know how getopt behaves but using them as a filename will most likely end up calling a system function, which will hopefully take care of the checking.

-- 
/Jacob Carlborg
November 20, 2013
On 2013-11-20 14:01, Timon Gehr wrote:

> void process(Data data)in{ assert(isValid(data)); }body{
>      // process
> }

Right, forgot about contracts.

-- 
/Jacob Carlborg
November 20, 2013
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.
November 20, 2013
On 11/20/13 6:14 AM, Timon Gehr wrote:
> Yes, hence SortedRange being sorted is just a convention in any case.

That's right. In particular we can't have assumeSorted check for isSorted even at the point of creation, and even with debug-only asserts. This is because checking would change the complexity of binary search and related algorithms, which is often prohibitive.

Andrei

November 20, 2013
On 20.11.2013 12:49, Jacob Carlborg wrote:
> On 2013-11-20 12:16, Jonathan M Davis wrote:
>
>> You'd do it the other way around by having something like
>>
>> ValidatedString!char s = validateString("hello world");
>
> Right.
>
>> ValidatedString would then avoid any extra validation when iterating
>> over the
>> characters, though I don't know how much of an efficiency gain that would
>> actually be given that much of the validation occurs naturally when
>> decoding
>> or using stride. It would have the downside that any function which
>> specializes on strings would likely have to then specialize on
>> ValidatedString
>> as well. So, while I agree with the idea in concept, I'd propose that we
>> benchmark the difference in decoding and striding without the checks
>> and see if
>> there actually is much difference. Because if there isn't, then I
>> don't think
>> that it's worth going to the trouble of adding something like
>> ValidatedString.
>
> If not just if the string is valid UTF-8. There can be many other types
> of valid strings. Or rather other functions that have additional
> requirements. Like sanitized filenames, HTML/SQL escaped strings and so on.

May I suggest:

struct Validated(alias fn, T) {
    private T value;
    @property inout
    T get() {
        return value;
    }
}

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
}

-- 
  Simen
November 20, 2013
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?
November 20, 2013
On Wednesday, 20 November 2013 at 17:56:22 UTC, 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 is, a mutating function that takes a sorted range strips the SortedRange wrapper and returns the underlying type.
November 20, 2013
On 20.11.2013 18:45, Simen Kjærås wrote:
> On 20.11.2013 12:49, Jacob Carlborg wrote:
>> On 2013-11-20 12:16, Jonathan M Davis wrote:
>>
>>> You'd do it the other way around by having something like
>>>
>>> ValidatedString!char s = validateString("hello world");
>>
>> Right.
>>
>>> ValidatedString would then avoid any extra validation when iterating
>>> over the
>>> characters, though I don't know how much of an efficiency gain that
>>> would
>>> actually be given that much of the validation occurs naturally when
>>> decoding
>>> or using stride. It would have the downside that any function which
>>> specializes on strings would likely have to then specialize on
>>> ValidatedString
>>> as well. So, while I agree with the idea in concept, I'd propose that we
>>> benchmark the difference in decoding and striding without the checks
>>> and see if
>>> there actually is much difference. Because if there isn't, then I
>>> don't think
>>> that it's worth going to the trouble of adding something like
>>> ValidatedString.
>>
>> If not just if the string is valid UTF-8. There can be many other types
>> of valid strings. Or rather other functions that have additional
>> requirements. Like sanitized filenames, HTML/SQL escaped strings and
>> so on.
>
> May I suggest:
>
> struct Validated(alias fn, T) {
>      private T value;
>      @property inout
>      T get() {
>          return value;
>      }

Uh-hm. Add this:
       alias get this;

> }
>
> 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
> }
>


-- 
  Simen
November 20, 2013
On Wednesday, 20 November 2013 at 17:45:43 UTC, Simen Kjærås wrote:
> On 20.11.2013 12:49, Jacob Carlborg wrote:
>> On 2013-11-20 12:16, Jonathan M Davis wrote:
>>
>>> You'd do it the other way around by having something like
>>>
>>> ValidatedString!char s = validateString("hello world");
>>
>> Right.
>>
>>> ValidatedString would then avoid any extra validation when iterating
>>> over the
>>> characters, though I don't know how much of an efficiency gain that would
>>> actually be given that much of the validation occurs naturally when
>>> decoding
>>> or using stride. It would have the downside that any function which
>>> specializes on strings would likely have to then specialize on
>>> ValidatedString
>>> as well. So, while I agree with the idea in concept, I'd propose that we
>>> benchmark the difference in decoding and striding without the checks
>>> and see if
>>> there actually is much difference. Because if there isn't, then I
>>> don't think
>>> that it's worth going to the trouble of adding something like
>>> ValidatedString.
>>
>> If not just if the string is valid UTF-8. There can be many other types
>> of valid strings. Or rather other functions that have additional
>> requirements. Like sanitized filenames, HTML/SQL escaped strings and so on.
>
> May I suggest:
>
> struct Validated(alias fn, T) {
>     private T value;
>     @property inout
>     T get() {
>         return value;
>     }
> }
>
> 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
> }

I was having the exact same thought. I think this could be very powerful if done correctly.