Re: what is the mean that call function start with a dot.

2019-09-21 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 22 September 2019 at 04:15:53 UTC, lili wrote:

Hi:
   yesterday I saw some d code, where is an .fn() call syntax, 
what is it mean.


It means that `fn` is looked up in the module's top-level scope.

Source: https://dlang.org/spec/expression.html#identifier


what is the mean that call function start with a dot.

2019-09-21 Thread lili via Digitalmars-d-learn

Hi:
   yesterday I saw some d code, where is an .fn() call syntax, 
what is it mean.


Re: Looking for a Simple Doubly Linked List Implementation

2019-09-21 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, September 21, 2019 12:52:23 PM MDT Dennis via Digitalmars-d-
learn wrote:
> Since I marked the method as const, `auto a = head` got the type
> const(Node!T) and `a = a.next` no longer compiled. With structs
> you can declare a const(Node!T)* (mutable pointer to const node),
> but I don't know if I can declare a mutable reference to a const
> class, so I switched to structs.

You have to use std.typecons.Rebindable if you want to have the equivalent
of const(T)* for class references, because the type system doesn't
distinguish between a class and a reference to a class. As it is, Rebindable
is pretty much a hack that's questionably legal per the type system (but
it's in Phobos, so I'm sure that it will continue to work). Ideally, there
would be a way to do it in the language, but the assumptions that the
compiler currently makes when dealing with classes makes that difficult.

In general though, if you're not going to use inheritance, then there isn't
much point in using a class instead of a struct unless you want to force it
to live on the heap (and that only really matters if you're dealing with
something that's publicly available for others to muck with, whereas nodes
in a linked list are normally private to the list, so it's easy to ensure
that they're only ever on the heap even if they're structs).

- Jonathan M Davis





Re: Looking for a Simple Doubly Linked List Implementation

2019-09-21 Thread Ron Tarrant via Digitalmars-d-learn

Sorry. I posted the wrong file. This is the one that works:

```
import std.stdio;
import std.conv;

class TabList
{
private:
Tab _head;
int _lastUniqueID = 0;
string labelText;

this()
{
append();
}


void append()
{
string labelText = "Tab " ~ _lastUniqueID.to!string();
Tab current;

if(_head is null)
{
_head = new Tab(_lastUniqueID, labelText);
_head.setPrev(null);
_head.setNext(null);
}
else
{
current = _head;
//writeln("before the while loop");
//current.showThings();

while(current.getNext() !is null)
{
//  writeln("in the while loop...");
//  current.showThings();

//  if(current.getPrev() !is null)
//  {
//  writeln("prev = ", 
current.getPrev().getTabID());
//  }
//  else
//  {
//  writeln("prev = null");
//  }
current = current.getNext();
}
//writeln("out of the while loop\n");
Tab tab = new Tab(_lastUniqueID, labelText);
current.setNext(tab);
tab.setPrev(current);
}

_lastUniqueID++;

} // append()


Tab getHead()
{
return(_head);

} // getHead()


void removeTab(int uniqueID)
{
// get the head
Tab current = _head;

// walk the list to find the Tab with the uniqueID
while(current.getNext() !is null)
{
// if the uniqueID matches the head's ID
if(current.getTabID() is uniqueID)
{
// destroy the Tab object
current.destroy(uniqueID);
break;
}

// go to the next Tab
current = current.getNext();
}


} // removeTab()

} // class TabList


class Tab
{
private:
int _tabID;
string _label;
Tab _prev = null, _next = null;

public:
this(int uniqueID, string labelText)
{
_tabID = uniqueID;
_label = labelText;

} // this()


void showThings()
{
writeln("Tab = ", getTabID());

if(getPrev() !is null)
{
writeln("Tab.prev = ", getPrev().getTabID());
}
else
{
writeln("Tab.prev is null");
}

if(getNext() !is null)
{
writeln("Tab.next = ", getNext().getTabID());
}
else
{
writeln("Tab.next = null");
}

} // showThings()


void destroy(int id)
{
if(_tabID is id)
{
// destroy the TextView
// destroy the Label
_prev.setNext(_next);
_next.setPrev(_prev);
}

} // destroy()


Tab getNext()
{
return(_next);

} // getNext()


Tab getPrev()
{
return(_prev);

} // getPrev()


int getTabID()
{
return(_tabID);

} // getTabID()


void setNext(Tab tab)
{
_next = tab;

} // setNext()


void setPrev(Tab tab)
{
_prev = tab;

} // setPrev()  

} // class Tab


void main(string[] args)
{
TabList tabList;

tabList = new TabList();

for(int i = 0; i < 7; i++)
{
//  writeln("building Tab #", i);
tabList.append();
//  writeln("--");
}


Re: Looking for a Simple Doubly Linked List Implementation

2019-09-21 Thread Ron Tarrant via Digitalmars-d-learn

On Saturday, 21 September 2019 at 18:52:23 UTC, Dennis wrote:
On Saturday, 21 September 2019 at 08:34:09 UTC, Ron Tarrant 
wrote:
Thanks, Dennis. Not performant... It doesn't work? I was 
hoping for a complete, working example, but maybe this'll help.


Bad word choice (it appears it's debatable whether 'performant' 
even is a word), I meant it was a simple implementation not 
optimized for speed / memory efficiency.
Making it 'complete' is a bit hard since I can think of tens of 
methods and operator overloads you could use, but if I include 
them all it's no longer minimal and it just becomes 
std.container.dlist.


Does a doubly-linked list always have to be done with structs? 
Can it be classes instead?


My example originally included classes actually. It was mostly 
the same, except that Node!T* was just Node!T. The only problem 
was with const:


```
size_t length() const {
size_t result = 0;
for(auto a = head; a !is null; a = a.next) result++;
return result;
}

```

Since I marked the method as const, `auto a = head` got the 
type const(Node!T) and `a = a.next` no longer compiled. With 
structs you can declare a const(Node!T)* (mutable pointer to 
const node), but I don't know if I can declare a mutable 
reference to a const class, so I switched to structs.


I have no idea, either.

But I did come up with something that works, so for anyone else 
looking for a full, working version (nothing fancy, mind you) 
here's my code with lots of 'proofs' dumped to the command line:


```
import std.stdio;
import std.conv;

class TabList
{
private:
Tab _head;
int _lastUniqueID = 0;
string labelText;

this()
{
append();
}


void append()
{
string labelText = "Tab " ~ _lastUniqueID.to!string();
Tab current;

if(_head is null)
{
_head = new Tab(_lastUniqueID, labelText);
_head.setPrev(null);
_head.setNext(null);
}
else
{
current = _head;
writeln("before the while loop");
current.showThings();

while(current.getNext() !is null)
{
writeln("in the while loop...");
current.showThings();

if(current.getPrev() !is null)
{
writeln("prev = ", 
current.getPrev().getTabID());
}
else
{
writeln("prev = null");
}
current = current.getNext();
}
writeln("out of the while loop\n");
Tab tab = new Tab(_lastUniqueID, labelText);
current.setNext(tab);
tab.setPrev(current);
}

_lastUniqueID++;

} // append()


Tab getHead()
{
return(_head);

} // getHead()


void removeTab(int uniqueID)
{
// get the head
Tab current = _head, prev, next;

// walk the list to find the Tab with the uniqueID
while(current.getNext() !is null)
{
// if the uniqueID matches the head's ID
if(current.getTabID() is uniqueID)
{
// destroy the Tab object
current.destroy(uniqueID);
}
// else
else
{
// go to the next Tab
current = current.getNext();
}
}

} // removeTab()

} // class TabList


class Tab
{
private:
int _tabID;
string _label;
Tab _prev = null, _next = null;

public:
this(int uniqueID, string labelText)
{
_tabID = uniqueID;
_label = labelText;

} // this()


void showThings()
{
writeln("Tab = ", getTabID());

if(getPrev() !is null)
{
writeln("Tab.prev = ", getPrev().getTabID());
}
else
{
writeln("Tab.prev is null");
}

  

Re: Looking for a Simple Doubly Linked List Implementation

2019-09-21 Thread Dennis via Digitalmars-d-learn

On Saturday, 21 September 2019 at 08:34:09 UTC, Ron Tarrant wrote:
Thanks, Dennis. Not performant... It doesn't work? I was hoping 
for a complete, working example, but maybe this'll help.


Bad word choice (it appears it's debatable whether 'performant' 
even is a word), I meant it was a simple implementation not 
optimized for speed / memory efficiency.
Making it 'complete' is a bit hard since I can think of tens of 
methods and operator overloads you could use, but if I include 
them all it's no longer minimal and it just becomes 
std.container.dlist.


Does a doubly-linked list always have to be done with structs? 
Can it be classes instead?


My example originally included classes actually. It was mostly 
the same, except that Node!T* was just Node!T. The only problem 
was with const:


```
size_t length() const {
size_t result = 0;
for(auto a = head; a !is null; a = a.next) result++;
return result;
}

```

Since I marked the method as const, `auto a = head` got the type 
const(Node!T) and `a = a.next` no longer compiled. With structs 
you can declare a const(Node!T)* (mutable pointer to const node), 
but I don't know if I can declare a mutable reference to a const 
class, so I switched to structs.


Re: Looking for a Simple Doubly Linked List Implementation

2019-09-21 Thread Ron Tarrant via Digitalmars-d-learn

Thanks for all the responses, y'all.

I got it figured out thanks to ag0aep6g pointing out something I 
forgot about the nature of class objects in D (Damn my failing 
memory). The results will show up on the gtkDcoding blog sometime 
in (I'm guessing) November as part of the the Notebook discussion 
series.




Re: initialize float4 (core.simd)

2019-09-21 Thread Stefan Koch via Digitalmars-d-learn

On Saturday, 21 September 2019 at 13:42:09 UTC, Bogdan wrote:

Well, this seems to be working:


float[4] doSimd(float[4] values, float delta)
{
  float4 v_delta = delta;

  float4 v_values = __simd(XMM.ADDPS,
   __simd(XMM.LODAPS, values[0]),
   v_delta);

  return [v_values[0], v_values[1],v_values[2],v_values[3]];
}


Not sure if it's correct though.


float4 x;
float x1, x2, x3, x4;
x[0] = x1;
x[1] = x2;
x[2] = x3;
x[3] = x4;



Re: initialize float4 (core.simd)

2019-09-21 Thread Bogdan via Digitalmars-d-learn

Well, this seems to be working:


float[4] doSimd(float[4] values, float delta)
{
  float4 v_delta = delta;

  float4 v_values = __simd(XMM.ADDPS,
   __simd(XMM.LODAPS, values[0]),
   v_delta);

  return [v_values[0], v_values[1],v_values[2],v_values[3]];
}


Not sure if it's correct though.


Re: initialize float4 (core.simd)

2019-09-21 Thread Bogdan via Digitalmars-d-learn

Here's a cleaned up version:

```
import std.stdio;
import core.simd;

void main()
{
  float[4] values = [1.0f, 2.0f, 3.0f, 4.0f];
  float delta = 15.0f;

  writeln(doSimd(values, delta));

}

float[4] doSimd(float[4] values, float delta)
{
  float4 v_delta = delta;
  float4 v_values = values;

  v_values = __simd(XMM.ADDPS, v_values, v_delta);

  return [v_values[0], v_values[1],v_values[2],v_values[3]];
}
```

The problem is with initializing v_values.


initialize float4 (core.simd)

2019-09-21 Thread Bogdan via Digitalmars-d-learn
I'm trying to understand how to use the `core.simd` 
functionality, and I'm having trouble initializing a float4 
vector.


Here's my example code:

```
import std.stdio;
import core.simd;

void main()
{
  float[4] values = [1.0f, 2.0f, 3.0f, 4.0f];
  float delta = 15.0f;

  writeln(doSimd(values, delta));

}

float[4] doSimd(float[4] values, float delta)
{
  float4 v_delta = delta;
  float4 v_values = values;

  // ... do SIMD ...

  return [v_delta[0], v_delta[0],v_delta[0],v_delta[0]];
}
```

Compilation is failing with the following error:

```
source/app.d(16,21): Error: cannot implicitly convert expression 
values of type float[4] to __vector(float[4])

dmd failed with exit code 1.
```
How do you initialize a float4 with some useful data?




Re: Looking for a Simple Doubly Linked List Implementation

2019-09-21 Thread Alex via Digitalmars-d-learn

On Friday, 20 September 2019 at 20:26:03 UTC, Ron Tarrant wrote:

Hi guys,

I've been banging my head on the screen with this one for the 
last week or so. For whatever reason, I'm having major problems 
understanding how to implement a doubly-linked list in D. I 
don't know if it's because I'm losing my ability to sort these 
things or if it's just that different from C.


If someone could please post a minimal example (if there's 
extra stuff in there, I'll get confused; I'm getting that old, 
dammit) I'd be ever so grateful.


rosetta code is quite good for such problems

http://rosettacode.org/wiki/Doubly-linked_list/Definition#D


Re: Looking for a Simple Doubly Linked List Implementation

2019-09-21 Thread Tobias Pankrath via Digitalmars-d-learn

On Saturday, 21 September 2019 at 09:03:13 UTC, Ron Tarrant wrote:
Ah! Thanks, ag0aep6g. I was wondering about that when I was 
writing the code. (If I already knew this, I'd forgotten.) I 
did as you suggested, took out all '*' and '&' and it works 
perfectly.


Is this what you want?
---
current.setPrev(current);
---


dub with sub packages: sub package with targetType "executable" builds with configuration ""

2019-09-21 Thread Tobias Pankrath via Digitalmars-d-learn

Hi,

I've got a dub package with the following configuration file

---
{
   "description": "A minimal D application.",
   "license": "proprietary",
   "authors": [
  "me"
   ],
   "copyright": "Copyright © 2019, me",
   "name": "test",
   "targetType"  : "none",

   "dependencies": {
   "test:mylib"  : "*"
  ,"test:myexe1" : "*"
   },

   "subPackages": [
  {
  "name": "mylib"
 ,"targetType"  : "library"
 ,"sourcePaths" : ["mylib/source"]
 ,"importPaths" : ["mylib/source"]
  }
  ,{
  "name"   : "myexe1"
 ,"targetType" : "executable"
 ,"sourcePaths": ["myexe1/source"]
 ,"importPaths": ["myexe1/source"]
 ,"dependencies": {
   "test:mylib" : "*"
 }
  }
   ]
}
---

when building this, dub gives me

---
 dub build --force
Performing "debug" build using /usr/bin/dmd for x86_64.
test:mylib ~master: building configuration "library"...
test:myexe1 ~master: building configuration ""...
Linking...
---

Note that the configuration of myexe1 is "". I want it to be 
'application', just like this:


---
% dub build test:myexe1
Building package test:myexe1 in /home/tobias/projects/test/
Performing "debug" build using /usr/bin/dmd for x86_64.
test:mylib ~master: target for configuration "library" is up to 
date.

test:myexe1 ~master: building configuration "application"...
Linking...
To force a rebuild of up-to-date targets, run again with --force.
---

Background: the project will contain multiple executables that 
use vibe-d. If they are not build as 'application' the version 
VibeDefaultMain seems to have no effect.


What's the best way to configure this?


Re: Looking for a Simple Doubly Linked List Implementation

2019-09-21 Thread Ron Tarrant via Digitalmars-d-learn

On Saturday, 21 September 2019 at 08:49:48 UTC, ag0aep6g wrote:

On 21.09.19 10:34, Ron Tarrant wrote:

Here's a question for the room:

Does a doubly-linked list always have to be done with structs? 
Can it be classes instead? (Maybe that's why I can't get it to 
work, because I've been trying to make an OOP version?)


It can be done with classes.

When I run the following code, it gets through creating the 
list head and the first node, then seems to get stuck in an 
infinite loop. Here's the code:

[...]

class Tab
{

[...]

 Tab* _prev = null, _next = null;

[...]

 Tab* getNext()

[...]

 Tab* getPrev()

[...]

 void setNext(Tab* tab)

[...]

 void setPrev(Tab* tab)

[...]

} // class Tab


Your mistake is that you're using pointers. `Tab` is a class. 
That means values of the type are already references. There is 
no need for `Tab*`. Just use `Tab` wherever you have `Tab*` 
now, and get rid of any addr-ofs (``) and dereferendces 
(`*bar`) you have.


Ah! Thanks, ag0aep6g. I was wondering about that when I was 
writing the code. (If I already knew this, I'd forgotten.) I did 
as you suggested, took out all '*' and '&' and it works perfectly.


Re: Looking for a Simple Doubly Linked List Implementation

2019-09-21 Thread ag0aep6g via Digitalmars-d-learn

On 21.09.19 10:34, Ron Tarrant wrote:

Here's a question for the room:

Does a doubly-linked list always have to be done with structs? Can it be 
classes instead? (Maybe that's why I can't get it to work, because I've 
been trying to make an OOP version?)


It can be done with classes.

When I run the following code, it gets through creating the list head 
and the first node, then seems to get stuck in an infinite loop. Here's 
the code:

[...]

class Tab
{

[...]

 Tab* _prev = null, _next = null;

[...]

 Tab* getNext()

[...]

 Tab* getPrev()

[...]

 void setNext(Tab* tab)

[...]

 void setPrev(Tab* tab)

[...]

} // class Tab


Your mistake is that you're using pointers. `Tab` is a class. That means 
values of the type are already references. There is no need for `Tab*`. 
Just use `Tab` wherever you have `Tab*` now, and get rid of any addr-ofs 
(``) and dereferendces (`*bar`) you have.


Re: Looking for a Simple Doubly Linked List Implementation

2019-09-21 Thread Ron Tarrant via Digitalmars-d-learn

On Friday, 20 September 2019 at 20:35:41 UTC, H. S. Teoh wrote:

Not a minimal example by any means, but Phobos *does* come with 
a doubly-linked list implementation: std.container.dlist.


Thanks, H.S. I did come across that in my search. Trouble is, 
with all the extra stuff in there, I'm having trouble separating 
what I need from what I don't.


On Friday, 20 September 2019 at 21:34:08 UTC, Dennis wrote:
Below is a simple doubly linked list with Garbage Collected 
memory.
It's not performant or complete by any means, just a minimal 
example in D like you wanted.


Thanks, Dennis. Not performant... It doesn't work? I was hoping 
for a complete, working example, but maybe this'll help.


You probably also want methods for removing nodes or inserting 
in the middle (else why don't you use an array?)


Yup. That's where I'm running into trouble.

I think you can think of an implementation for those yourself 
(or look them up, there should be plenty examples online).


I thought I could, too. And I thought there'd be lots of examples 
online, too. (Otherwise, I wouldn't have embarrassed myself in 
public like this.) But if there are, I can't find them... not in 
D. And it seems that D is just different enough from the other 
examples I'm finding so that I can't use them as a guide.


Here's a question for the room:

Does a doubly-linked list always have to be done with structs? 
Can it be classes instead? (Maybe that's why I can't get it to 
work, because I've been trying to make an OOP version?)


When I run the following code, it gets through creating the list 
head and the first node, then seems to get stuck in an infinite 
loop. Here's the code:


import std.stdio;
import std.conv;

class TabList
{
Tab _head;
int lastUniqueID = 0;
string labelText;

this()
{
append();
}


void append()
{
string labelText = "Tab " ~ lastUniqueID.to!string();
Tab* current;

if(_head is null)
{
_head = new Tab(lastUniqueID, labelText);
}
else
{
current = &_head;

while(current.getNext())
{
current = current.getNext();
}

Tab tab = new Tab(lastUniqueID, labelText);
current.setNext();
current.setPrev(current);
}

lastUniqueID++;

} // append()


Tab* getHead()
{
return(&_head);

} // getHead()

} // class TabList


class Tab
{
private:
int _tabID;
string _label;
Tab* _prev = null, _next = null;

public:
this(int uniqueID, string labelText)
{
_tabID = uniqueID;
_label = labelText;

} // this()


void destroy(int id)
{
if(_tabID is id)
{
_prev.setNext(_next);
_next.setPrev(_prev);
}

} // destroy()


Tab* getNext()
{
return(_next);

} // getNext()


Tab* getPrev()
{
return(_prev);

} // getPrev()


int getTabID()
{
return(_tabID);

} // getTabID()


void setNext(Tab* tab)
{
_next = tab;

} // setNext()


void setPrev(Tab* tab)
{
_prev = tab;

} // setPrev()  

} // class Tab


void main(string[] args)
{
TabList tabList;

tabList = new TabList();

for(int i = 0; i < 7; i++)
{
tabList.append();
}

writeln();
writeln();

Tab* tab = tabList.getHead();

} // main()



Re: Why must a bidirectional range also be a forward range?

2019-09-21 Thread Jonathan M Davis via Digitalmars-d-learn
On Friday, September 20, 2019 7:08:03 AM MDT Joseph Rushton Wakeling via 
Digitalmars-d-learn wrote:
> On Thursday, 19 September 2019 at 22:55:55 UTC, Jonathan M Davis
>
> wrote:
> > For better or worse, ranges were more or less set up as a
> > linear hierarchy, and it's unlikely that use cases for
> > bidirectional ranges which aren't forward ranges are common. I
> > expect that it's a bit like infinite, bidirectional ranges. In
> > theory, they could be a thing, but the use cases for them are
> > uncommon enough that we don't really support them. Also, I
> > expect that most range-based algorithms which operate on
> > bidirectional ranges would require save anyway. A lot of
> > algorithms do to the point that basic input ranges can be
> > incredibly frustrating to deal with.
> >
> > [ ... ]
>
> Thanks for the characteristically thorough description of both
> the design considerations and the history involved.
>
> On reflection it occurs to me that the problem in my thinking may
> be the idea that `save` should result in a full deep copy.  If
> instead we go by how `save` is implemented for dynamic arrays,
> it's only ever a shallow copy: it's not possible to make valid
> assumptions of reproducible behaviour if the original copy is
> modified in any way.
>
> If instead we assume that `save` is only suitable for temporary
> shallow-copies that are made under the hood of algorithms, then
> my problems go away.

save is supposed to result copies that can be independently iterated over.
So, code such as

foreach(r; range.save)
{}
auto arr = r.save.array();
assert(equal(arr, r));

should work. How that's implemented underneath the hood doesn't really
matter. However, none of that really takes into account mutation of the
elements. The range API pretty much assumes that you don't ever modify any
of the elements in the range as you iterate over them. So, if you do
something like

auto orig = range.save;
range.front = 42;

whether orig.front is then 42 is implementation-dependent. So, if you're
modifying elements as you go, then the behavior you get is going to be
highly dependent on what you're doing with the ranges, and certainly, if
you're only using a range within a very specific context, it can be
implemented in a way that works in that context but doesn't work with
range-based functions in general. You just run the risk of problems if you
then later modify the code to use other range-based functions which don't
necessarily work with whatever you've done with the range.

As for temporary, shallow copies, IIRC, isForwardRange requires that save
returns exactly the same type as the original. So, while you can certainly
have a range referring to a data structure without owning any of the data
(after all, that's what happens with dynamic arrays), you can't have a range
of one type that owns the data and then have save return a range type which
just refers to the data unless the range is written in a way that you can
have both within the same type.

One example of avoiding the need to deep-copy with save where one range is
at least sort of the owner whereas the others aren't is how dxml's stax
parser works. The ranges share a context that keeps track of how far into
the range the farthest range is, and popFront only does the validation when
the range that popFront is being called on is the farthest of any range.
That way, the stuff related to validating end tags didn't need to be
deep-copied, but save always returns exactly the same type, and you get
exactly the same behavior regardless of which range gets iterated farther
first (or even if one is iterated farther and then another is iterated
beyond it).

If popFront every throws, then that range becomes invalid, but the others
are fine. The validation other than that for matching end tags currently all
gets done every time, so all ranges would throw in the same place for errors
other than end tags that don't match, but the same is also true for when the
end tags don't match, because even though that validation is only done for
the farthest range, if it fails, the shared context is left in exactly the
same state, and any other ranges that reach that point would then throw like
the first range did.

Without realizing that the validation for the end tags didn't have to be
done for every instance of the range but only the one which was farthest
along, I would have been screwed with regards to save, because deep-copying
would have been required. I'm not sure that that particular trick is widely
applicable, but it is an example of how save can do something other than a
deep copy even though having each range do exactly the same work would have
required a deep copy.

> > Assuming we were redesigning the range API (which may happen if
> > we do indeed end up doing a Phobos v2), then maybe we could
> > make it so that bidirectional ranges don't have to be forward
> > ranges, but honestly _any_ ranges which aren't forward ranges
> > are a bit of a problem. We do need to