Re: Removing an element from an array

2022-11-10 Thread Alexander Zhirov via Digitalmars-d-learn
On Friday, 11 November 2022 at 05:36:37 UTC, Alexander Zhirov 
wrote:
On Friday, 11 November 2022 at 00:02:09 UTC, Alexander Zhirov 
wrote:

```d
import std.algorithm;
arr = arr.remove(arr.countUntil(fragment));
```


And will this method work?

```d
A[] arr;
A fragment = new A;
...
remove(current => current == fragment)(arr);
```


And it will be even more accurate so as not to cause an error:

```d
A[] arr;
A fragment = new A;
...
arr = remove(current => current == fragment)(arr);
```


Re: Removing an element from an array

2022-11-10 Thread Alexander Zhirov via Digitalmars-d-learn
On Friday, 11 November 2022 at 00:02:09 UTC, Alexander Zhirov 
wrote:

```d
import std.algorithm;
arr = arr.remove(arr.countUntil(fragment));
```


And will this method work?

```d
A[] arr;
A fragment = new A;
...
remove(current => current == fragment)(arr);
```


Re: aa.keys, synchronized and shared

2022-11-10 Thread cc via Digitalmars-d-learn

On Friday, 11 November 2022 at 01:09:54 UTC, torhu wrote:

On Thursday, 10 November 2022 at 21:55:26 UTC, torhu wrote:

I'm trying to make a more thread-safe wrapper for AA's:

```
synchronized final class SyncAA(K, V) ///


I chose to fix this by just using `synchronized (this)` inside 
each method instead, for now. Still interested in cleaner 
solutions, but I guess synchronized/shared is a bit of a rabbit 
hole...


That's about what I ended up with, and just declaring my 
references __gshared.  I don't know what's going on with 
shared/synchronized but it sounds like it's unfinished and people 
can't agree on what they're actually supposed to mean.  
__gshared, it just works.
Previous thread: [synchronized/shared associative array .require 
error](https://forum.dlang.org/post/hcbrgpmdufjgjtxtu...@forum.dlang.org)
Also: [synchronized - shared but actually 
useful](https://forum.dlang.org/thread/drrlgymevccozrqms...@forum.dlang.org)


```d
class SyncTable(KEY, VAL) {
private VAL[KEY] table;
auto opIndexAssign(VAL value, KEY key) {
synchronized(this) {
return table[key] = value;
}
}
int opApply(int delegate(ref KEY, ref VAL) dg) {
synchronized(this) {
foreach (key, val; table) {
if (dg(key, val)) return 1;
}
return 0;
}
}
auto opBinaryRight(string op)(KEY key) if (op == "in") {
synchronized(this) {
return key in table;
}
}
auto opDispatch(string s, SA...)(SA sargs) {
synchronized(this) {
static if (SA.length == 0) {
mixin(format("return table.%s;", s));
} else {
mixin(format("return table.%s(%s);", s, sargs.stringof[6 .. 
$-1])); // tuple(_param_0)

}
}
}
}
```

With synchronized on the class, I had to do something like:
```d
synchronized class SyncTable(KEY, VAL) {
// Anything that mutates must reassign unshared back to table!
auto opIndexAssign(VAL value, KEY key) {
auto unshared = cast(T) table;
unshared[key] = value;
table = cast(shared) unshared;
return value;
}
auto require(KEY key) {
auto unshared = cast(T) table;
auto r = unshared.require(key);
table = cast(shared) unshared;
return r;
}
/* ... */
}
```
and it just doesn't feel right.

For mutexes without synchronized, there's also:
```d
struct Lock {
private shared Mutex _mtx;
this(shared Mutex mtx) {
_mtx = mtx;
_mtx.lock();
}
this(this) @disable;
~this() {
if (_mtx)
_mtx.unlock();
_mtx = null;
}
}
class SyncTable(KEY, VAL) {
private VAL[KEY] table;
shared Mutex mtx;
this() {
mtx = new shared Mutex;
}
auto opIndexAssign(VAL value, KEY key) {
auto lock = Lock(mtx);
return table[key] = value;
}
/* ... */
}
```



ImportC linking issue

2022-11-10 Thread confuzzled via Digitalmars-d-learn
Wondering if someone can help me with this. Mr. Adam D. Ruppe got 
me 90% there, but I'm a little lost after reaching the 99% mark. 
I want to use XLSX I/O to manipulate excel spreadsheets.


I've cloned, built, and installed the library. And with the help 
of Adam, I am now able to import it and link to D program (as 
long as I'm not using anything from the lib). Wanted to continue 
the discussion with Adam, but I realize the announce forum isn't 
the place to ask for help.


Anyway, the library has two dependencies:

- [expat](http://www.libexpat.org/) (only for libxlsxio_read)
- [minizip](http://www.winimage.com/zLibDll/minizip.html) or 
libzip (libxlsxio_read and libxlsxio_write)


Since I'm on a Mac, I installed them using homebrew. In a demo.d 
file I have the following:


```d
import xlsxio_read;
import std.stdio;

pragma(lib, "libxlsxio_read.a");
pragma(lib, "libexpat.a");
pragma(lib, "libminizip.a");

string filename = "logistic_regression.xlsx";

void main (string[] args)
{
if (args.length > 1)
filename = args[1];

xlsxioreader xlsxioread;

writef("XLSX I/O library version %s\n", 
xlsxioread_get_version_string());

}
```

And in xlsxio_read.c (probably should call it something else), I 
simply import the library header:

```c
#include 
```

When I try to compile it, I get a slew of errors about undefined 
symbols. It wasn't finding libexpat and libminizip so I copied 
those to my work directory and tried again. With that, most of 
the errors disappeared. The remaining ones are:


```
dmd demo.d xlsxio_read.c
ld: warning: ignoring file libminizip.a, building for 
macOS-x86_64 but attempting to link with file built for 
macOS-x86_64

Undefined symbols for architecture x86_64:
  "_unzClose", referenced from:
  _xlsxioread_close in libxlsxio_read.a(xlsxio_read.c.o)
  "_unzCloseCurrentFile", referenced from:
  _expat_process_zip_file in libxlsxio_read.a(xlsxio_read.c.o)
  _xlsxioread_sheetlist_close in 
libxlsxio_read.a(xlsxio_read.c.o)

  _xlsxioread_sheet_close in libxlsxio_read.a(xlsxio_read.c.o)
  "_unzGetCurrentFileInfo", referenced from:
  _iterate_files_by_contenttype_expat_callback_element_start 
in libxlsxio_read.a(xlsxio_read.c.o)

  "_unzGetGlobalInfo", referenced from:
  _iterate_files_by_contenttype_expat_callback_element_start 
in libxlsxio_read.a(xlsxio_read.c.o)

  "_unzGoToFirstFile", referenced from:
  _iterate_files_by_contenttype_expat_callback_element_start 
in libxlsxio_read.a(xlsxio_read.c.o)

  "_unzGoToNextFile", referenced from:
  _iterate_files_by_contenttype_expat_callback_element_start 
in libxlsxio_read.a(xlsxio_read.c.o)

  "_unzLocateFile", referenced from:
  _XML_Char_openzip in libxlsxio_read.a(xlsxio_read.c.o)
  "_unzOpen", referenced from:
  _xlsxioread_open in libxlsxio_read.a(xlsxio_read.c.o)
  "_unzOpen2", referenced from:
  _xlsxioread_open_filehandle in 
libxlsxio_read.a(xlsxio_read.c.o)

  _xlsxioread_open_memory in libxlsxio_read.a(xlsxio_read.c.o)
  "_unzOpenCurrentFile", referenced from:
  _XML_Char_openzip in libxlsxio_read.a(xlsxio_read.c.o)
  "_unzReadCurrentFile", referenced from:
  _expat_process_zip_file in libxlsxio_read.a(xlsxio_read.c.o)
  _expat_process_zip_file_resume in 
libxlsxio_read.a(xlsxio_read.c.o)

ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to 
see invocation)

Error: linker exited with status 1
```
From the first line of the error message, I gather I'm using the 
wrong minizip but I'm not sure how or why. What does **"building 
for macOS-x86_64 but attempting to link with file built for 
macOS-x86_64"** even mean?


Thanks,
confuzzled!!!


Re: aa.keys, synchronized and shared

2022-11-10 Thread torhu via Digitalmars-d-learn

On Thursday, 10 November 2022 at 21:55:26 UTC, torhu wrote:

I'm trying to make a more thread-safe wrapper for AA's:

```
synchronized final class SyncAA(K, V) ///


I chose to fix this by just using `synchronized (this)` inside 
each method instead, for now. Still interested in cleaner 
solutions, but I guess synchronized/shared is a bit of a rabbit 
hole...


Re: Removing an element from an array

2022-11-10 Thread Alexander Zhirov via Digitalmars-d-learn

On Thursday, 10 November 2022 at 23:36:29 UTC, H. S. Teoh wrote:
On Thu, Nov 10, 2022 at 11:26:45PM +, Alexander Zhirov via 
Digitalmars-d-learn wrote:
I have an array of self-written class `A`. I'm sorry for my 
tactlessness, but I'm confused about the modules. How do I 
correctly find a specific object `fragment` inside the array 
and delete it? I don't quite understand which modules to use 
to do this optimally.


```d
A[] arr;
A fragment = new A;
...
arr.remove(fragment);  // Something like
```


I would do something like this:

// Warning: untested code
import std.algorithm;
arr = arr.remove(arr.countUntil(fragment));


T


As always - simple and compact. Thank you:)


Re: Removing an element from an array

2022-11-10 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Nov 10, 2022 at 11:26:45PM +, Alexander Zhirov via 
Digitalmars-d-learn wrote:
> I have an array of self-written class `A`. I'm sorry for my tactlessness,
> but I'm confused about the modules. How do I correctly find a specific
> object `fragment` inside the array and delete it? I don't quite understand
> which modules to use to do this optimally.
> 
> ```d
> A[] arr;
> A fragment = new A;
> ...
> arr.remove(fragment);  // Something like
> ```

I would do something like this:

// Warning: untested code
import std.algorithm;
arr = arr.remove(arr.countUntil(fragment));


T

-- 
Change is inevitable, except from a vending machine.


Removing an element from an array

2022-11-10 Thread Alexander Zhirov via Digitalmars-d-learn
I have an array of self-written class `A`. I'm sorry for my 
tactlessness, but I'm confused about the modules. How do I 
correctly find a specific object `fragment` inside the array and 
delete it? I don't quite understand which modules to use to do 
this optimally.


```d
A[] arr;
A fragment = new A;
...
arr.remove(fragment);  // Something like
```

In the pros, I would do it this way, for example via lambda

```c++
arr.erase(std::find_if(arr.cbegin(), arr.cend(), [&](const 
std::reference_wrapper &item)

{
return &item.get() == &fragment;
}));
```


aa.keys, synchronized and shared

2022-11-10 Thread torhu via Digitalmars-d-learn

I'm trying to make a more thread-safe wrapper for AA's:

```
synchronized final class SyncAA(K, V) ///
{
///
V opIndex(K key) { return data_[key]; }

///
V opIndexAssign(V value, K key) { return data_[key] = value; }

///
K[] keys() const { return data_.keys; }

///
void remove(K key) { data_.remove(key); }

/// There is no `in` operator, it would not be thread-safe.
V get(K key, lazy V defaultValue=V.init)
{
auto p = key in data_;
return p ? *p : defaultValue;
}

///
int opApply(scope int delegate(inout ref V) dg) const
{
int result = 0;
foreach (value; data_) {
result = dg(value);
if (result)
break;
}
return result;
}

///
int opApply(scope int delegate(K, inout ref V) dg) const
{
int result = 0;
foreach (key, value; data_) {
result = dg(key, value);
if (result)
break;
}
return result;
}

private:
V[K] data_;
}
```

In another file:
`__gshared serverListCache = new SyncAA!(string, ServerList);`

I'm using `keys` in a regular function, this is the error i get:

C:\prog\dmd\windows\bin\..\..\src\druntime\import\object.d(3245,36): Error: 
cannot implicitly convert expression `aa` of type 
`shared(const(ServerList[string]))` to `const(shared(ServerList)[string])`
src\syncaa.d(17,36): Error: template instance 
`object.keys!(shared(const(ServerList[string])), 
shared(const(ServerList)), string)` error instantiating
src\serveractions.d(45,33):instantiated from here: 
`SyncAA!(string, ServerList)`
src\serveractions.d(50,17): Error: `shared` `const` method 
`syncaa.SyncAA!(string, ServerList).SyncAA.keys` is not callable 
using a non-shared mutable object

Error C:\prog\dmd\windows\bin\dmd.exe failed with exit code 1.




Re: dirEntries removes entire branches of empty directories

2022-11-10 Thread Ali Çehreli via Digitalmars-d-learn

On 11/9/22 12:06, Ali Çehreli wrote:

> I am using its sibling 'ftw'

Now that we know that dirEntries works properly, I decided not to use ftw.

However, ftw performs about twice as fast as dirEntries (despite some 
common code in the implementation below). I am leaving it here in case 
somebody finds it useful. (Why don't I put it on github then; ok, some 
day I will.)


import core.sys.posix.sys.stat;
import std.algorithm;
import std.exception;
import std.file;
import std.path;
import std.range;
import std.string;

// The Posix "file tree walker" function
extern (C)
int ftw(const char *dirpath,
int function (const char *fpath, const stat_t *sb, int 
typeflag) fn,

int nopenfd);

enum TypeFlag {
FTW_F,   // regular file
FTW_D,   // directory
// See 'man nftw' or /usr/include/ftw.h for the other values
}

struct DirectoryEntry {
string name;
ulong size;
}

struct WalkResult {
DirectoryEntry[] entries;
string[] emptyDirs;
}

WalkResult directoryWalk_ftw(string root) {
WalkResult impl_() {
// These have to be 'static' because ftw() does not allow us to 
pass a

// context. And that's why this function must only be called from a
// synchronized block.
static DirectoryEntry[] entries;
static string[] dirs;

entries.length = 0;
entries.assumeSafeAppend();

dirs.length = 0;
dirs.assumeSafeAppend();

// This is the callback that ftw() uses.
extern (C)
int handler(const char *fpath, const stat_t *sb, int typeflag) {
const path = fpath.fromStringz.idup;

switch (typeflag) {
case TypeFlag.FTW_F:
entries ~= DirectoryEntry(path, sb.st_size);
break;

case TypeFlag.FTW_D:
dirs ~= path;
break;

default:
import std.stdio;
writefln!"Ignoring type %s file: %s\n(See 'man nftw')b"(
path, typeflag);
break;
}

return 0;
}

// The tree walk will be faster up-to this "search depth" (See 
'man nftw')

enum nopenfd = 32;

const ret = ftw(root.toStringz, &handler, nopenfd);
enforce(ret == 0,
format!"Failed walking the directory tree at %s; error: 
%s"(

root, ret));

string[] nonEmptyDirs = chain(entries.map!(e => e.name),
  dirs)
.map!dirName
.array
.sort
.uniq
.array;
sort(dirs);

string[] emptyDirs = setDifference(dirs, nonEmptyDirs)
 .array;

return WalkResult(entries.dup, emptyDirs);
}

synchronized {
return impl_();
}
}

WalkResult directoryWalk_dirEntries(string root) {
DirectoryEntry[] entries;
string[] dirs;

foreach (entry; dirEntries(root, SpanMode.depth)) {
if (entry.isDir) {
dirs ~= entry;

} else {
entries ~= DirectoryEntry(entry, entry.getSize);
}
}

string[] nonEmptyDirs = chain(entries.map!(e => e.name),
  dirs)
.map!dirName
.array
.sort
.uniq
.array;
sort(dirs);

string[] emptyDirs = setDifference(dirs, nonEmptyDirs)
 .array;

return WalkResult(entries.dup, emptyDirs);
}

int main(string[] args) {
import std.datetime.stopwatch;
import std.stdio;
import std.path;

if (args.length != 2) {
stderr.writefln!"Please provide the directory to walk:\n\n  %s 
\n"

(args[0].baseName);
return 1;
}

const dir = buildNormalizedPath("/home/ali/dlang");

auto timings = benchmark!({ directoryWalk_ftw(dir); },
  { directoryWalk_dirEntries(dir); })(10);

writefln!("ftw   : %s\n" ~
  "dirEntries: %s")(timings[0], timings[1]);

return 0;
}

Ali



Re: dirEntries removes entire branches of empty directories

2022-11-10 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Nov 10, 2022 at 07:07:33PM +, Imperatorn via Digitalmars-d-learn 
wrote:
> On Thursday, 10 November 2022 at 16:34:53 UTC, Ali Çehreli wrote:
> > On 11/9/22 11:30, Vladimir Panteleev wrote:
> > > On Wednesday, 9 November 2022 at 19:05:58 UTC, Ali Çehreli
> > > wrote:
> > >> Running the program shows no output; 'a' is not visited as a
> > >> directory entry.
> > >
> > > That's not what happens for me:
> > 
> > Does not happen for me today either. (?) I must have confused myself
> > both with my actual program and with a trivial isolated program that I
> > had written to test it.
> > 
> > Unless others have seen the same behavior yesterday there is no bug here
> > today. :p
> > 
> > Ali
> > "walks away with a confused look on his face"
> 
> Oh, did you run the program on Wednesday? Fool!

I think it was because yesterday MSFT stock dipped, but today it rose by
15, so Windows is working properly again.

:-P


T

-- 
"You are a very disagreeable person." "NO."


Re: dirEntries removes entire branches of empty directories

2022-11-10 Thread Imperatorn via Digitalmars-d-learn

On Thursday, 10 November 2022 at 16:34:53 UTC, Ali Çehreli wrote:

On 11/9/22 11:30, Vladimir Panteleev wrote:
> On Wednesday, 9 November 2022 at 19:05:58 UTC, Ali Çehreli
wrote:
>> Running the program shows no output; 'a' is not visited as a
directory
>> entry.
>
> That's not what happens for me:

Does not happen for me today either. (?) I must have confused 
myself both with my actual program and with a trivial isolated 
program that I had written to test it.


Unless others have seen the same behavior yesterday there is no 
bug here today. :p


Ali
"walks away with a confused look on his face"


Oh, did you run the program on Wednesday? Fool!


Re: difference between x.atomicOp!"+="(1) and atomicFetchAdd(x, 1)?

2022-11-10 Thread mw via Digitalmars-d-learn

On Thursday, 10 November 2022 at 18:30:16 UTC, Paul Backus wrote:

On Thursday, 10 November 2022 at 17:04:31 UTC, mw wrote:

Hi,

Anyone can help explain what is the difference between 
x.atomicOp!"+="(1) and atomicFetchAdd(x, 1)?


Looking at the source in druntime, `atomicOp!"+="` forwards to 
`atomicFetchAdd` internally, so they should have the same 
behavior.


Thanks! Indeed:

https://github.com/dlang/dmd/blob/master/druntime/src/core/atomic.d#L582

(source is always your best friend :-)

and looks like atomicFetchAdd is more fundamental:

```
return cast(T)(atomicFetchAdd(val, mod) + mod);
```


Re: difference between x.atomicOp!"+="(1) and atomicFetchAdd(x, 1)?

2022-11-10 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 10 November 2022 at 17:04:31 UTC, mw wrote:

Hi,

Anyone can help explain what is the difference between 
x.atomicOp!"+="(1) and atomicFetchAdd(x, 1)?


Looking at the source in druntime, `atomicOp!"+="` forwards to 
`atomicFetchAdd` internally, so they should have the same 
behavior.


difference between x.atomicOp!"+="(1) and atomicFetchAdd(x, 1)?

2022-11-10 Thread mw via Digitalmars-d-learn

Hi,

Anyone can help explain what is the difference between 
x.atomicOp!"+="(1) and atomicFetchAdd(x, 1)?


From the doc, their return values are different

atomicOp
Performs the binary operation 'op' on val using 'mod' as the 
modifier.

Returns:
The result of the operation.


atomicFetchAdd
Atomically adds mod to the value referenced by val and returns 
the value val held previously. This operation is both lock-free 
and atomic.

Returns:
The value held previously by val.


Apart from this, any other difference, esp in a multithreaded 
program? Are they the same? Is atomicOp also lock-free?


Thanks.





Re: dirEntries removes entire branches of empty directories

2022-11-10 Thread Ali Çehreli via Digitalmars-d-learn

On 11/9/22 11:30, Vladimir Panteleev wrote:
> On Wednesday, 9 November 2022 at 19:05:58 UTC, Ali Çehreli wrote:
>> Running the program shows no output; 'a' is not visited as a directory
>> entry.
>
> That's not what happens for me:

Does not happen for me today either. (?) I must have confused myself 
both with my actual program and with a trivial isolated program that I 
had written to test it.


Unless others have seen the same behavior yesterday there is no bug here 
today. :p


Ali
"walks away with a confused look on his face"