May 11, 2012
On Friday, 11 May 2012 at 18:33:06 UTC, Mehrdad wrote:
> But just because the *reasons* are correct that doesn't mean it's more intuitive.
>
> ("Intuitive", by definition, means that you have a good chance of getting it right without needing to look it up. Binary searching in D failed this miserably for me.)

You want a language that you can program in without ever looking at docs? How exactly would that work? o_O
May 11, 2012
On Friday, 11 May 2012 at 19:01:25 UTC, jerro wrote:
>> Just a note: I believe I *had* seen SortedRange in the docs, but I'd never realized there's something called assumeSorted() that I was supposed to call... so I was searching up and down for how to search an *arbitrary* container, not how to search something which was already pre-sorted for me.
>> (In retrospect, I probably should've just coded binary search myself...)
>> It's very counterintuitive to have to make a new object (or struct) just to do binary search on an array...
>
> Maybe the documentation changed since, but currently the
> documentation for SortedRange says:
>
> "To construct a SortedRange from a range r that is known to be already sorted, use assumeSorted described below."
>
> And there is assumeSorted in the example.

Yeah, either I missed, or I just didn't look at it, and skipped it entirely just by the header (I don't remember). The point was that it simply wasn't what/where I expected to be.
May 11, 2012
On Friday, 11 May 2012 at 19:03:56 UTC, Chris Cain wrote:
> On Friday, 11 May 2012 at 18:33:06 UTC, Mehrdad wrote:
>> But just because the *reasons* are correct that doesn't mean it's more intuitive.
>>
>> ("Intuitive", by definition, means that you have a good chance of getting it right without needing to look it up. Binary searching in D failed this miserably for me.)
>
> You want a language that you can program in without ever looking at docs? How exactly would that work? o_O

lol I think you're exaggerating my point. :P

I said a "reasonable chance".

For example, in std.algorithm, "joiner" is NOT what I expected
the method to be called -- I expected "join". (Again, I *do*
understand why it's called that.)

Or in std.range, no one in a million years expects to see a
method called "moveFront()". You're not "moving" a range...
What we call "moveFront()" should, IMO, have been called
"popFront()". Or maybe just "next()". But of course that was
taken, so there wasn't a choice. Still, not intuitive.

Heck, even C# has a more intuitive name for setDifference():
it's called "Except".
(Like, items.except(otherItems).)

Or e.g. C#'s "Any()" method tells you whether the collection is empty, whereas D's "any()" method takes in a predicate. I find C#'s *slightly* more intuitive.

D's std.algorithm.completeSort() definitely does NOT have an intuitive name.


etc.


(But, actually, what you said WOULD work if you had a good enough
IDE, like Visual Studio, that gave you the descriptions right
there, instantly. That wasn't my point though.)
May 11, 2012
On Friday, 11 May 2012 at 19:01:26 UTC, Chris Cain wrote:
> I really have to disagree on this. I programmed in C++ for awhile and templates were always a huge stumbling block for me.
> [...]

Yes, D's templates are a great improvement over C++'s. I completely agree. Just pointing out why there are still a few things confusing about them, though.


> Hilariously, this style also makes the code look more magical.

Yup, that's what attracted me to D when I learned about it. :)
May 11, 2012
On Fri, May 11, 2012 at 09:02:52PM +0200, Mehrdad wrote:
> On Friday, 11 May 2012 at 18:53:57 UTC, H. S. Teoh wrote:
> >On Fri, May 11, 2012 at 08:38:41PM +0200, Mehrdad wrote:
> >>On Friday, 11 May 2012 at 18:21:24 UTC, H. S. Teoh wrote:
> >>>Templates are stencils for generating code. There's nothing confusing about that.
> >>
> >>
> >>"Stencils for generating code"? _This_??! :O
> >>
> >>  template hasMember(T, string name)
> >>  { enum hasMember = __traits(hasMember, T, name); }
> >>
> >>
> >>Imagine a new user's confusion when seeing something like this. (Not sure I got it exactly right, but my point is there.)
> >
> >Yes, that's exactly how stencils work. You're essentially generating a declaration of the form:
> >
> >	enum hasMember = ...;
> >
> ><snip>
> 
> 
> That's not how you see it when you're learning though.

Well, it *should* be seen that way. The fact that it isn't means that the user didn't get a proper introduction to the concept.


> It's more like, I can imagine someone asking these:
> 
> 1. Why the heck do I see "hasMember" twice?

It should be more like, "there's a template keyword, I wonder what it means -- <look up docs, which has a proper intro to the concept> -- ohhh so that's what it means.

The fact that this first step failed means the documentation has failed.


> 2. What does this have to do with enums?
> 3. Where is anything getting "returned"???

Return? Why should templates return anything?


> 4. So you mean templates are THINGS?? I thought you needed a template SOMETHING, like a template struct, template function, etc...

A stencil is a thing. What you stamp out depends on what's in it.


> 5. What the heck is TypeTuple!()? Where's the blueprint?
[...]

Now, TypeTuples are a completely different kettle o' fish. They need their own proper introduction. :-) Trying to understand TypeTuple before you understand templates is like trying to run before you can stand.


T

-- 
"A man's wife has more power over him than the state has." -- Ralph Emerson
May 11, 2012
On Fri, May 11, 2012 at 09:01:25PM +0200, Chris Cain wrote: [...]
> I really have to disagree on this. I programmed in C++ for awhile and templates were always a huge stumbling block for me. The syntax didn't sync up for me and they were extremely difficult to implement well, which made any generic programming I attempted feel half-hearted (IMO).

Yeah, I remember when I first read about template metaprogramming and expression templates and stuff, and I was all riled up about finally being able to write matrix expressions in an intuitive way and still have peak performance... until I actually sat down to code the thing. Let's just say I didn't get very far before I got completely lost in deep jungle that is C++ template syntax.


> When I started looking at D's templates, I was _afraid_ that it would be as much of a pain in the ass. After putting it off and shying away from it, I decided to dive in and discovered that they were significantly easier to work with ... and more importantly, it was nearly straightforward to implement them _well_. It's absolutely no problem specifying that data type with certain properties should use this function and everything else should use this other function. In C++, you have to learn complicated, arbitrary idioms such as SFINAE to get any serious work done at all ... and it looks like all of it was written in another language when you're done, making maintenance a nightmare.

Yeah, one of the biggest problems with C++ template syntax is that it looks like an alien language. I remember going, "wait, you have to type *that* to achieve what can written as a simple loop in normal C++ code?!"

I couldn't tell you how delighted I was when I saw D's much cleaner and clearer template syntax. I mean, it looks just like normal, non-template code! Gee, what a concept!


> It's not surprising that entire C++ books are dedicated to teaching the absurd complexities of C++ templates. If anything, my experience with C++ templates hindered me.

Or the absurdity of C++ itself.

What started out as C with classes started acquiring this feature and that feature until the whole thing is just a haphazard heap of misfitting self-contradictory pieces, which requires an enormous amount of essentially-arbitrary rules just to clarify something as simple as, for example, automatic type conversions.


[...]
> There's definitely not enough info on how to get stuff done with ranges. I knew about assumeSorted and the fact that std.algorithm.sort returns a sorted range, but only because I carefully combed through the libraries looking for stuff like that.

Again, helpful tutorials like Ali's book really need to be on the forefront of D. Newbies *need* to read that stuff before they get dunked into the deep end of the pool that is the current dlang.org docs.


> That said, the D way is actually very well designed once you discover it. Like Andrei said, the code clarifies its intentions.
> 
> Hilariously, this style also makes the code look more magical. You want to say something is unique and, thus, can be legitimately made immutable? assumeUnique. Oh, you want to have a memoized version of funct? memoize!funct. I leave my friends wondering how D knew how to do all this stuff just by being "told" to. Magic API, that's how.

+1. Sufficiently advanced programming language syntax is indistinguishible from magic. ;-)


T

-- 
"Computer Science is no more about computers than astronomy is about telescopes." -- E.W. Dijkstra
May 11, 2012
On Friday, 11 May 2012 at 19:39:55 UTC, H. S. Teoh wrote:
> On Fri, May 11, 2012 at 09:01:25PM +0200, Chris Cain wrote:
>> There's definitely not enough info on how to get stuff done  with ranges. I knew about assumeSorted and the fact that  std.algorithm.sort returns a sorted range, but only because I carefully combed  through the libraries looking for stuff like that.
>
> Again, helpful tutorials like Ali's book really need to be on  the forefront of D. Newbies *need* to read that stuff before they  get dunked into the deep end of the pool that is the current dlang.org  docs.

 I remember reading from that book a bit on the ranges, and it all made wonderful sense when I did. That was something like a year ago, now I can't remember anything on it except it was good. Not having a good link to it does hinder your work quite a bit.



>> That said, the D way is actually very well designed once you discover it. Like Andrei said, the code clarifies its  intentions.
>> 
>> Hilariously, this style also makes the code look more magical.  You want to say something is unique and, thus, can be legitimately  made immutable? assumeUnique. Oh, you want to have a memoized  version of funct? memoize!funct. I leave my friends wondering how D knew  how to do all this stuff just by being "told" to. Magic API, that's  how.
>
> +1. Sufficiently advanced programming language syntax is indistinguishible from magic. ;-)

 http://freefall.purrsia.com/ff300/fv00255.htm

 Safe to say documentation needs to be updated and added to. Here's a catch-22 we have here. We need those that know the system and language and compiler to work on it and give us a working set of tools, but we need those people to update and make the documentation for everyone that wants to use it or it will be a dead language.

 Hmmm... Unfortunately I don't have sufficient knowledge of all of D to make documentation for updated and newer changes to the language. :(
May 11, 2012
"Mehrdad" <wfunction@hotmail.com> wrote in message news:ynstshvzpaiusjyyoipo@forum.dlang.org...
> On Friday, 11 May 2012 at 18:21:24 UTC, H. S. Teoh wrote:
>> Templates are stencils for generating code. There's nothing confusing about that.
>
>
> "Stencils for generating code"? _This_??! :O
>

Geez, I think I need a vacation: My mind parsed that as a ternary operator expression. Only when it tried to apply semantics did reality snap into focus.


May 11, 2012
"Mehrdad" <wfunction@hotmail.com> wrote in message news:oksltzwvkdrrjidcnqnm@forum.dlang.org...
> On Friday, 11 May 2012 at 18:16:02 UTC, Alex Rønne Petersen wrote:
>> On 11-05-2012 20:05, Mehrdad wrote:
>>> 6. The 'in' operator returns a pointer (instead of a boolean). Which is fine, except that it's not what you'd expect in any languages other than C/C++. i.e. Non-intuitive
>> I've always found it very intuitive actually... and it saves me from having to write extra code to do the actual lookup (speed isn't even the point here, I just want concise code).
>
> Yes, I agree, but consider that D users should NOT have to work with pointers to do something so basic, like testing to see if something is in an associative array!
>
> The mere fact that it uses a pointer makes it unintuitive to a large number of people coming from C#/Java/Python/etc.
>

I use 'in' all the time, and I never even think about it returning a pointer. I just do:

if(foo in bar)

And it just works. So I don't see a particularly big problem here.


May 11, 2012
On Friday, May 11, 2012 21:15:53 Mehrdad wrote:
> Or e.g. C#'s "Any()" method tells you whether the collection is
> empty, whereas D's "any()" method takes in a predicate. I find
> C#'s *slightly* more intuitive.

That's definitely an example of something that depends on your background. std.algorithm.any does _exactly_ what it would do in a functional language. How intuitive an API is depends a lot on how much the person writing the API thinks like you. It's definitely something to strive for, but the best that you can generally do is hit the majority of your target audience. You can never hit everyone.

- Jonathan M Davis