On 6/28/20 9:07 AM, Denis wrote:

> * foreach is the actual iterator,

Yes. foreach is "lowered" to the following equivalent:

  for ( ; !range.empty; range.popFront()) {
    // Use range.front here
  }

A struct can support foreach iteration through its opCall() member function as well. opCall() takes the body of the foreach as a delegate. Because it's a function call, it can take full advantage of the function call stack. This may help with e.g. writing recursive iteration algorithms.


http://ddili.org/ders/d.en/foreach_opapply.html#ix_foreach_opapply.opApply

> the instantiation of a struct is the
> range.

Yes.

> * When a constructor is not used, the arguments in the call to
> instantiate the range (in this case, `hello` in letters(`hello`)) are
> mapped sequentially to the member variables in the struct definition
> (i.e. to letters.str).

Yes, that is a very practical struct feature. I write my structs with as little as needed and provide a constructor only when it is necessary as in your case.

> * When a constructor is used, the member variables in the struct
> definition are in essence private.

Not entirely true. You can still make them public if you want.

  http://ddili.org/ders/d.en/encapsulation.html

> The arguments in the call to
> instantiate the range are now mapped directly to the parameters in the
> definition of the "this" function.

Yes.

> * The syntax and conventions for constructors is difficult and
> non-intuitive for anyone who hasn't learned Java (or a derivative).

C++ uses the name of the class as the constructor:

// C++ code
struct S {
  S();     // <-- Constructor
  S(int);  // <-- Another one
};

The problem with that syntax is having to rename more than one thing when the name of struct changes e.g. to Q:

struct Q {
  Q();
  Q(int);
};

And usually in the implementation:

Q::Q() {}
Q::Q(int) {}

D's choice of 'this' is productive.

> The
> linked document provides a simplified explanation for the "this"
> keyword, which is helpful for the first read:
> https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html.

I like searching for keywords in my index. The "this, constructor" here links to the constructor syntax:

  http://ddili.org/ders/d.en/ix.html

> * In some respects, the Java syntax is not very D-like. (For example, it
> breaks the well-established convention of "Do not use the same name to
> mean two different things".)

Yes but it competes with another goal: Change as little code as possible when one thing needs to be changed. This is not only practical but helps with correctness.

> However, it does need to be learned,
> because it is common in D source code.

I like D. :p

> Here is the complete revised code for the example (in condensed form):
>
>    import std.stdio;
>
>    struct letters {
>
>      string str;
>      int pos = 1;        // Assign here or in this())
>
>      this(string param1) {    // cf. shadow str
>        str = param1;        // cf. this.str = param1 / this.str = str
>        writeln(`BEGIN`); }
>
>      char front() { return str[pos]; }
>      void popFront() { pos ++; }
>      bool empty() { return pos == str.length; }
>
>      ~this() { writeln("\nEND"); }}
>
>    void main() {
>      foreach (letter; letters(`hello`)) {
>        write(letter, ' '); }}
>
> At this point, I do have one followup question:
>
> Why is the shadow str + "this.str = str" the more widely used syntax in
> D, when the syntax in the code above is unambiguous?

Because one needs to come up with names like "param7", "str_", "_str", "s", etc. I like and follow D's standard here.

> One possible reason that occurred to me is that "str = param1" might
> require additional GC, because they are different names.

Not at all because there is not memory allocation at all. strings are implemented as the equivalent of the following struct:

struct __D_native_string {
  size_t length_;
  char * ptr;
  // ...
}

So, the "str = param1" assignment is nothing but two 64 bit data transfer, which can easily by optimized away by the compiler in many cases.

> But I wouldn't
> think it'd make any difference to the compiler.

Yes. :)

>
> Denis

Ali

Reply via email to