July 10, 2012
On 10-Jul-12 17:59, H. S. Teoh wrote:
> On Tue, Jul 10, 2012 at 09:28:51AM -0400, Andrei Alexandrescu wrote:
>> On 7/10/12 2:50 AM, Jacob Carlborg wrote:
>>> On 2012-07-09 22:16, Andrei Alexandrescu wrote:
>>>
>>>> So foo is a range of strings, because each element of it is a
>>>> string.  Then you want to chain a range of strings with a string,
>>>> which is a range of dchar. That doesn't work, and I agree the error
>>>> message should be more informative.
>>>
>>> Is that by design or something that can be fixed?
>>
>> We can arrange things in the library that a custom message is issued,
>> or in the compiler to do it once for all.
>
> Please don't do it in the compiler. Custom messages should be in the
> library. Tying the compiler to phobos is a bad idea; druntime should be
> the only dependency.
>
>

Time and again I think of

T func(Blah)(Blah param)
	if(isMagic!Blah, Blah.stringof~" is not magic") //second param is an error hint
{
	
}

The idea is that when all functions from overload set fail to meet constraints the error on "doesn't match template parameters" should contain this extra HINTs on what's wrong.

HINT in general must be short, and clear. No need to do elobarate a statements.

-- 
Dmitry Olshansky


July 10, 2012
On 7/10/12 10:26 AM, Andrei Alexandrescu wrote:
> On 7/10/12 8:50 AM, Nick Treleaven wrote:
>> On 10/07/2012 12:37, Jacob Carlborg wrote:
>>> The corresponding D version would be:
>>>
>>> auto a = [5, 3, 5, 6, 8].uniq.map!(x => x.to!(string)).array.sort.array;
>>> writeln(a);
>>>
>>> I'm guessing that's three allocations. But that doesn't even work, it
>>> prints:
>>>
>>> ["3", "5", "5", "6", "8"]
>>
>> uniq needs sorted input:
>>
>> auto r = [5, 3, 5, 6, 8].sort.uniq.map!(x => x.to!string);
>> writeln(r);
>>
>> Tested with dmd 2.059.
>> I think the above should be one allocation (except for the strings).
>>
>> Maybe uniq should require a SortedRange?
>
> Yes, please file a bug. Thanks!
>
> Andrei

Actually I take that back. One may use uniq to remove duplicates in unsorted ranges.

Andrei

July 10, 2012
On 7/10/12 9:59 AM, H. S. Teoh wrote:
> On Tue, Jul 10, 2012 at 09:28:51AM -0400, Andrei Alexandrescu wrote:
>> On 7/10/12 2:50 AM, Jacob Carlborg wrote:
>>> On 2012-07-09 22:16, Andrei Alexandrescu wrote:
>>>
>>>> So foo is a range of strings, because each element of it is a
>>>> string.  Then you want to chain a range of strings with a string,
>>>> which is a range of dchar. That doesn't work, and I agree the error
>>>> message should be more informative.
>>>
>>> Is that by design or something that can be fixed?
>>
>> We can arrange things in the library that a custom message is issued,
>> or in the compiler to do it once for all.
>
> Please don't do it in the compiler. Custom messages should be in the
> library. Tying the compiler to phobos is a bad idea; druntime should be
> the only dependency.

The idea there being that the compiler could give good details about what part of a complex constraint has failed.

Andrei

July 10, 2012
On 07/10/2012 02:53 PM, Dmitry Olshansky wrote:
> On 10-Jul-12 15:37, Jacob Carlborg wrote:
>> On 2012-07-10 12:05, Dmitry Olshansky wrote:
>>
>>> and what type has the return of map ? Let me guess - array.
>>
>> Yes, and that is what I _want_.
>
> Too bad, as there is no need to make an array when you map something.
>
> I have no need for streaming data from
>> the network into a linked list, filter it and then convert it to an
>> array (or something similar). I want to start with an array and end with
>> an array.
>>
>
> Then you need something like transform. Anyway the result of map should
> be sortable it's a bug.
>

What would sort do? Special case the result of map and then call
schwartzSort on the underlying range?

July 10, 2012
On 10-Jul-12 19:00, Timon Gehr wrote:
> On 07/10/2012 02:53 PM, Dmitry Olshansky wrote:
>> On 10-Jul-12 15:37, Jacob Carlborg wrote:
>>> On 2012-07-10 12:05, Dmitry Olshansky wrote:
>>>
>>>> and what type has the return of map ? Let me guess - array.
>>>
>>> Yes, and that is what I _want_.
>>
>> Too bad, as there is no need to make an array when you map something.
>>
>> I have no need for streaming data from
>>> the network into a linked list, filter it and then convert it to an
>>> array (or something similar). I want to start with an array and end with
>>> an array.
>>>
>>
>> Then you need something like transform. Anyway the result of map should
>> be sortable it's a bug.
>>
>
> What would sort do? Special case the result of map and then call
> schwartzSort on the underlying range?
>
It may be a good idea actually. I once found myself in a need to sort mapped range. I think I just sorted original with "mapped" predicate it could get slow but in my case it was ok. Then assumeSorted(map!(...)).

-- 
Dmitry Olshansky


July 10, 2012
Jacob Carlborg , dans le message (digitalmars.D:171685), a écrit :
> I mean, is it possible to have the original code work?
> 
> auto bar = foo.chain("bar");
> 
> Or perhaps more appropriate:
> 
> auto bar = foo.append("bar");

What is wrong with foo.chain(["bar"])?

If you do not want the heap allocation of the array, you can create a one-element range to feed to chain (maybe such a thing could be placed in phobos, next to takeOne).

struct OneElementRange(E)
{
  E elem;
  bool passed;
  @property ref E front() { return elem; }
  void popFront() { passed = true; }
  @property bool empty() { return passed; }
  @property size_t length() { return 1-passed; }
  //...
}

You can't expect chain to work the same way as run-time append. A compile-time append would be very inefficient if misused.

> https://github.com/jacob-carlborg/dstep/blob/master/dstep/translator/Translator.d#L217

you might try this (untested)


string function(Parameter) stringify = (x)
{
 return (x.isConst? "const("~x.type~")": x.type)
    ~ (x.name.any?" "~translateIdentifier(x.name):"");
}

auto params = parameters
  .map!stringify()
  .chain(variadic? []: ["..."])
  .joiner(", ");

context ~= params;

I am not sure this will be more efficient. joiner may be slowed down by the fact that it is called with a chain result, which is slower on front. But at leat you save yourself the heap-allocation of the params array*.

I would use:
context ~= parameters.map!stringify().joiner(",  ");
if (variadic) context ~= ", ...";

To make the best implementation would require to know how the String context works.

*Note that here, stringify is not lazy, and thus allocates. It could be a chain or a joiner, but I'm not sure the result would really be more efficient.
July 10, 2012
Dmitry Olshansky , dans le message (digitalmars.D:171679), a écrit :
> Because uniq work only on sorted ranges? Have you tried reading docs?
> "
> Iterates unique consecutive elements of the given range (functionality
> akin to the uniq system utility). Equivalence of elements is assessed by
> using the predicate pred, by default "a == b". If the given range is
> bidirectional, uniq also yields a bidirectional range.
> "

Not, as the doc says, uniq work on any range, but remove only the consecutive elements. It you want to remove all duplicates, then you need a sorted range.


July 10, 2012
On Tuesday, July 10, 2012 10:21:23 Andrei Alexandrescu wrote:
> On 7/10/12 5:35 AM, Jacob Carlborg wrote:
> > On 2012-07-10 08:59, Dmitry Olshansky wrote:
> >> Can you do it in other languages?
> > 
> > Sure, in Ruby, but that only works on arrays:
> > 
> > p [5, 3, 5, 6, 8].uniq.map{ |e| e.to_s }.sort
> 
> This is very inefficient.
> 
> I agree that if efficiency wasn't a concern for std.algorithm, its API would have been different. As things are, I think std.algorithm strikes a very good balance between efficiency and usability.

The other thing that affects a lot is infinite ranges. The functions with lazy results work wonderfully with infinite ranges but would generally result in infinite loops if used with functions with eager results.

auto vals = map!"a % 10"(rndGen());

works great, but you'd be forced to use take directly on rndGen pretty much all the time you wanted to do something like that if functions like map were lazy.

But I suspect that the sort of people who will be complaining about map not returning an array are also the sort of people who won't be all that familar with operating on infinite lists and at least initially probably won't care.

- Jonathan M Davis
July 10, 2012
"Simen Kjaeraas" , dans le message (digitalmars.D:171678), a écrit :
>> Well, I haven't been able to use a single function from std.algorithm without adding a lot of calls to "array" or "to!(string)". I think the things I'm trying to do seems trivial and quite common. I'm I overrating std.algorithm or does it not fit my needs?
>>
> 
> bearophile (who else? :p) has suggested the addition of eager and in-place versions of some ranges, and I think he has a very good point.

That would have been useful before UFSC.
Now, writing .array() at the end of an algorithm call is not a pain.

int[] = [1, 2, 2, 3].uniq().map!toString().array();

July 10, 2012
On 7/10/12 9:56 AM, Jacob Carlborg wrote:
> On 2012-07-10 15:28, Andrei Alexandrescu wrote:
>
>> We can arrange things in the library that a custom message is issued, or
>> in the compiler to do it once for all. At any rate whenever there's an
>> error pointing somewhere in the library's code that's an insufficient
>> template constraint that should be fixed.
>
> I mean, is it possible to have the original code work?
>
> auto bar = foo.chain("bar");
>
> Or perhaps more appropriate:
>
> auto bar = foo.append("bar");

It would be possible to chain a single element to the end of a range. One related thing to do is to define singletonRange(x) that returns a range with exactly one element, namely x.

>> I understand. So you need to use array() to convert the lazy map result
>> into an eager array. I disagree this is unintuitive, if it were then
>> very little of D would make sense are lazy, non-array ranges are
>> everywhere.
>
> Tell me what is the point of std.algorithm and ranges if I have to
> convert every single result of an algorithm to an array before I can use
> it with an other algorithm? I thought the whole idea was to avoid
> allocations between different usages of algorithms.

Ranges and std.algorithm obey simple, mathematical realities deriving from algorithm and storage topology constraints. For example sort works in place so it generally can't work on mapped stuff because there's no place to put the sorted contents. Also sort needs a random-access range to work with so it can't work e.g. with the result of filter, which necessarily yields a non-random-access range. And so on.

Now I understand if you come from a place where there's no concern over hidden allocations and extra work for the benefit of convenience, you may find std.algorithm less easy to work with. But drawing the conclusion that std.algorithm is badly designed or gratuitously difficult to use would be a mistake. I opine I can recognize a good vs. bad design even when it's mine, and in my opinion std.algorithm is a good design and that most of your opposing impressions derive from a misunderstanding of its charter.


Andrei