Re: Removing an element from an array
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
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
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
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
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
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
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
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
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
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
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
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)?
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)?
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)?
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
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"