View mode: basic / threaded / horizontal-split · Log in · Help
July 10, 2012
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
"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
Re: Why is std.algorithm so complicated to use?
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
2 3 4 5 6 7 8 9 10
Top | Discussion index | About this forum | D home