Re: Address of a class object

2023-01-04 Thread Ali Çehreli via Digitalmars-d-learn

On 1/4/23 13:43, H. S. Teoh wrote:

> You do realize that the compiler is free to reorder local variables on
> the stack, right? ;-)

Of course. :)

I was trying different strategies to catch the compiler (dmd here) in a 
single act of 8-byte object alignment as reported by .alignof.


Another thing the compiler is free for class members is to reorder them. 
I also theorized perhaps the compiler was also considering the alignment 
of a member. But as expected, char[1] does have 1 alignment and it can't 
be the reason in this case. (Again, there is no problem here; we are 
just learning.)


> implementation-specific details

RazvanN or Dennis may chime in on that.

Ali



Re: Address of a class object

2023-01-04 Thread Ali Çehreli via Digitalmars-d-learn

On 1/4/23 12:02, Steven Schveighoffer wrote:
> On 1/4/23 2:27 PM, Ali Çehreli wrote:

>> I put the objects into a 2-length
>> static array but the difference was still 0x20. (?)
>
> Are you putting the class *references* in a 2-length static array?

I lied. As I could not put the objects in a static array, I put them on 
the stack with the 'scope' keyword and the difference was still 0x20. 
(Of course, I could emplace the objects myself in my static array but 
that wouldn't prove anything about why the current alignment appears to 
be 0x20.)


> stop worrying about the addresses
> given out by the GC

No worries; just trying to explain...

Ali



Re: Address of a class object

2023-01-04 Thread Ali Çehreli via Digitalmars-d-learn

On 1/4/23 11:27, Ali Çehreli wrote:

>  writeln("hidden 0: ", hiddenValue(addr, 0));
>  writeln("hidden 1: ", hiddenValue(addr, 1));

Silly me! :) Those members have names:

writeln("__vptr  : ", obj.__vptr);
writeln("__monitor   : ", obj.__monitor);

  https://dlang.org/spec/abi.html#classes

Ali



Re: Address of a class object

2023-01-04 Thread Ali Çehreli via Digitalmars-d-learn

On 1/4/23 10:48, H. S. Teoh wrote:

> Allocations are not necessarily consecutive; the GC may have its own
> strategy of allocation that doesn't follow a linear sequence.

That was one of my guesses. So, I put the objects into a 2-length static 
array but the difference was still 0x20. (?)


> Furthermore, GC-allocated blocks may be larger than the request size
> because there may be some extra management information stored in the
> block (but outside the pointer range returned).

Good point. I think the minimum size of a dynamically allocated memory 
of the current GC implementation is 32 bytes.


I've just realized that I was confusing myself by thinking the object 
pointer that cast(void*) produces was the first member's address. I was 
wrong: That is the address of the first of the two hidden members (the 
vtbl pointer and the monitor).


My current guess is, although it could be a void*, the alignment of the 
first of those hidden members is 16.


Now that I have a more correct understanding, the following program 
prints those hidden members. One of the examples shows the monitor of an 
object used with 'synchronized' is non-null.


import std.stdio, std.traits;

class MyClass {
char[1] c;
}

void main() {
writeln(" Size  Alignment  Type\n",
"=");

size_t size = __traits(classInstanceSize, MyClass);
size_t alignment = classInstanceAlignment!MyClass;
writefln("%4s%8s  %s",size, alignment, MyClass.stringof);

// Apologies for using lower-cased variable names. :)
auto a = new MyClass();
auto b = new MyClass();

printObject!a;
printObject!b;

auto withMonitor = new MyClass();

synchronized (withMonitor) {
// This object's "hidden 1" (the monitor) will not be 'null'
printObject!withMonitor;
}

// This object's "hidden 0" (vtbl pointer) will be different:
class SubClass : MyClass {
}
auto sub = new SubClass();
printObject!sub;
}

void printObject(alias obj)() {
writeln("\n");
writeln("name: ", obj.stringof);

const addr = cast(void*)obj;
writeln("address : ", addr);
writeln("hidden 0: ", hiddenValue(addr, 0));
writeln("hidden 1: ", hiddenValue(addr, 1));
}

void* hiddenValue(const(void)* obj, size_t index) {
alias HiddenType = void*;
auto ptrToHiddens = cast(HiddenType[2]*)obj;
return (*ptrToHiddens)[index];
}

Here is the output:

 Size  Alignment  Type
=
  17   8  MyClass


name: a
address : 7F4009D48000
hidden 0: 558A1E172520
hidden 1: null


name: b
address : 7F4009D48020
hidden 0: 558A1E172520
hidden 1: null


name: withMonitor
address : 7F4009D48040
hidden 0: 558A1E172520
hidden 1: 558A20164B80  <-- non-null monitor


name: sub
address : 7F4009D48060
hidden 0: 558A1E172630  <-- Different vtbl for sub-class
hidden 1: null

Ali



Re: Address of a class object

2023-01-04 Thread Ali Çehreli via Digitalmars-d-learn

On 1/3/23 20:01, Paul wrote:

>   Size  Alignment  Type
> =
>17   8  MyClass
>
> MyClassObj1 MyClassObj2
> 27727202000 27727202020
> ```
> If my size is 17 bytes and my alignment is 8 bytes, shouldn't my
> MyClassObj2 in this example be @ 277272020**18** ?

Good question.

I made some guesses about object layouts, GC allocation schemes, etc. 
but did not like any of them.


Ali



Re: Why does this code only work with `T` and not `typeof(T)`?

2023-01-03 Thread Ali Çehreli via Digitalmars-d-learn

On 1/3/23 20:11, thebluepandabear wrote:

> if I replace the `isDrawable` template with the
> following (using `typeof`), the code does not compile:

It must be because T is already a type. It's the same reason why the 
following code fails to compile:


void main() {
alias T = int;
alias TT = typeof(T);
}

Error: type `int` is not an expression

And the error message tells us typeof requires an expression. What you 
can do is to use T.init and the code should now work like the following 
does:


alias TT = typeof(T.init);

Ali



Re: Is there a way to enforce UFCS?

2023-01-03 Thread Ali Çehreli via Digitalmars-d-learn

On 1/3/23 19:42, thebluepandabear wrote:

>  @property {

As your post proves, that feature is at most half-baked and is 
discouraged. Today, there is just one known obscure effect of using it.


>  void name(string name) {
>  _name = name;
>  }

>  d.name = "Poodle";

> In the code we can see that we have utilized UFCS (universal function
> call syntax)

UFCS is for calling free-standing functions as if they are member 
functions. Since your example already uses member functions, this 
feature is not UFCS. And I don't think it has a name.


It is always possible to pass a single-argument with the assignment syntax:

void foo(int i) {}

void main() {
foo = 42;
}

Pretty wild! :) But that's what makes your assignment above work. (Not 
UFCS.)


> not enforced [...] we can
> do the following in our code:

>  d.name("poodle");

I don't see a problem with that. :)

> I am disappointed that `@property` does not

Many people are disappointed that @property is pretty much useless.

> is there a way to enforce

D gives us the tools to do that but it's not trivial. The function can 
return an object that represents a variable (member variable or not). 
And an assignment to that representative object can set the actual variable.


However, I tried to achieve it with an intermediary object but failed 
because the same ="Poodle" syntax broke it and demanded that we type the 
empty parenthesis. So, I think what you want does not exist.


// I have a feeling something similar exists in Phobos
// but I could not find it.
//
// This is a reference to any variable.
struct MyRef(T) {
T * ptr;

void opAssign(T value) {
*ptr = value;
}

void toString(scope void delegate(in char[]) sink) const {
sink(*ptr);
}
}

// This is a convenience function template so that
// the users don't have to say e.g. MyRef!string
// themselves. (See name() below.)
auto myRef(T)(ref T var) {
return MyRef!T();
}

class Dog {
@property name() {
return myRef(_name);
}

private {
string _name;
}
}

void main() {
Dog d = new Dog();


// Great: The following won't work.
// d.name("poodle");


// However, now there is the empty parenthesis. :(
d.name() = "Poodle";

import std.stdio;
writeln(d.name);
}

Ali



Re: Address of a class object

2023-01-01 Thread Ali Çehreli via Digitalmars-d-learn

On 1/1/23 01:01, Paul wrote:

> ...on my laptop it prints...
> ```
>   Size  Alignment  Type
> =
> 9   4  MyClass
>
> 4FFB20  4FFB24
> ```

> If the size of MyClass is 9 bytes why do MyClassO1 & O2 addresses only
> differ by 4 bytes?

As matheus said, classes are reference types, meaning, class variables 
are implemented as pointers. The values above are the addresses of those 
pointers. The fact that those values are different by 4 tells us that 
the code was compiled for 32 bits.


On the other hand, matheus's values were 8 apart because that 
compilation was 64 bits.


> So, I guess my question is actually how do I print out the addresses of
> the MyClassO1 & O2 objects themselves?

You must have missed my earlier answer: You need to cast the variable to 
'void*'. That special operation will give you the address of the object. 
I am adding the following last line to matheus's example:


// ...
writeln("\n",&(MyClassO1.c),"\t",&(MyClassO2.c));
writeln("\n",cast(void*)MyClassO1,"\t",cast(void*)MyClassO2);

The output:

[...]
7F125FE770107F125FE77030  <-- The addresses of the 'c' members

7F125FE770007F125FE77020  <-- The addresses of the objects

The reason why objects are 0x10 bytes before the 'c' members is because 
a class object has two hidden initial members: the vtbl pointer and the 
monitor, both of which are size of a pointer (4 on your system, and 8 on 
matheus's system and mine).


Additionally, if you define the class as extern(C++), there will not be 
the monitor member. The reason for that is C++ does not have that 
concept and it would break interoperability.


Ali



Re: Compile time vs run time -- what is the difference?

2022-12-31 Thread Ali Çehreli via Digitalmars-d-learn

On 12/31/22 16:42, H. S. Teoh wrote:

> "runtime"

Going off topic, I've settled on three different spelling of that 
(those? :) ):


- run time: As in this topic, things can happen at run time.

- run-time: Adjective, as in run-time value of something.

- runtime: The D runtime.

Ali



Re: Address of a class object

2022-12-31 Thread Ali Çehreli via Digitalmars-d-learn

On 12/31/22 16:35, Paul wrote:

> Can I acquire the address of a class object,

Answering that question literally, yes, you can by casting the class 
variable to void*. But note: 'class object' means the instance of class 
in D.


> not a class variable (i.e.
> the instantiations of the class)

D terminology is different there: A class variable is a reference to the 
class object (that carries the member variables, etc. of a class instance.)


  auto c = new C();

'c' is the *variable*, providing access to the *object* in dynamic memory.

> but the object definition itself?

As H. S. Teoh answered, Python etc. can do that but not D's compilation 
model.


The following program tries to demonstrate that the members are offset 
two void* sizes further from the address of the object:


class C {
int i;
}

void main() {
auto c = new C();

const likelyOffsetOfMembers = 2 * (void*).sizeof;

// HERE:
const objectAddrInDynamicMemory = cast(void*)c;

assert(objectAddrInDynamicMemory + likelyOffsetOfMembers == );
}

If the class is defined as extern(C++), then you must replace 2 above 
with 1:


extern(C++) class C {
int i;
}

Ali



Re: dChar Error

2022-12-30 Thread Ali Çehreli via Digitalmars-d-learn

On 12/30/22 17:22, Salih Dincer wrote:

> I guess there is no other way but to overload.

Since the bodies of all three overloads are the same except some types, 
they can easily be templatized.


> This is both the safest and the fastest.

I didn't think Values is fast with string copies that it makes. ;) I 
think it was only for showing the byte values but you can do the same by 
casting to ubyte[] as well.


Also, your Fun could work only with string literals; so I used function 
parameters.


import std.traits : isSomeString;

// isSomeString may or may not be useful below. (?)

auto Fun(S)(S str)
if (isSomeString!S) {
import std.traits : Unqual;
import std.conv : to;

alias T = Unqual!S;

// Note: The following may or may not copy the string
//   depending on whether S is the same as T.
return str.to!T;
}

void printBytes(S)(S str) {
import std.stdio : writefln;
import std.conv  : to;

// The following cast does not copy anything.
writefln!"%(%02X-%)"(cast(ubyte[])str);
}

void main()
{
printBytes(Fun("β€Ş"));  // CE-B2-E2-82-AC-C5-9E
printBytes(Fun("β€Ş"w)); // B2-03-AC-20-5E-01
printBytes(Fun("β€Ş"d)); // B2-03-00-00-AC-20-00-00-5E-01-00-00
}

Ali



Re: dChar Error

2022-12-30 Thread Ali Çehreli via Digitalmars-d-learn

On 12/30/22 13:54, matheus wrote:

> But yes I think it will generate a copy (mutable) based on this test:

In this case it does copy but in the case of dchar[] to dchar[], there 
will be no copy. Similarly, there is no copy from immutable to immutable.


> the address is different

Good test. :)

> But I couldn't find if the target will be mutable, but I think it will
> be,

The target will always be the type the programmer specifies explicitly. 
(dchar[] in this case.)


Ali



Re: Compile time vs run time -- what is the difference?

2022-12-28 Thread Ali Çehreli via Digitalmars-d-learn

On 12/28/22 08:04, Ali Çehreli wrote:

> I don't think any of them can run the program though because
> the program can be in a state that could harm its environment
> like deleting unwanted files.

I was too eager there. Likely no IDE goes that far. All they need is to 
understand the code enough to give help. They must stop at some point in 
the following steps of compilation:


- preprocessing (does not exist for D)

- lexical analysis

- parsing

- semantic analysis

I copied those items from Wikipedia:

  https://en.wikipedia.org/wiki/Compiler

It lists the later stages of compilation as

- intermediate representation

- code optimization

- code generation

Ali



Re: Compile time vs run time -- what is the difference?

2022-12-28 Thread Ali Çehreli via Digitalmars-d-learn

On 12/27/22 18:31, thebluepandabear wrote:

> What I do understand is that compile time and run time are the two
> processes that your code goes through to be executed natively.

There is a confusion: Compile time ends when the compiler generates the 
executable program, one that will be executed natively.


Run time is each time when the user starts the executable program by 
typing its name followed by the Enter key, double clicking on it, etc.


For a program that was extremely simple, bug-free, lucky, etc. there may 
be as few as a single compilation and infinite number of executions (run 
times).


On the other hand, for a program that could never be compiled 
successfully, there may be infinite number of compilations and zero run 
times.


> In Java and some other languages, during compile time the code gets
> executed into Java bytecode. This also happens for C#. I don't know if
> there is an equivalent 'intermediate' language for D that your code gets
> translated to.

No, D does not use that model.

Copying a comment of yours:

> Before even running the code I get an IDE warning
> (IntelliJ). Does IntelliJ compile the code in the background?

Yes, many IDEs continuously compile the code as you type the source code 
to understand it to give you such help. I don't think any of them can 
run the program though because the program can be in a state that could 
harm its environment like deleting unwanted files.


Ali



Re: Can you simplify nested Indexed types?

2022-12-27 Thread Ali Çehreli via Digitalmars-d-learn

On 12/27/22 07:09, Sergei Nosov wrote:

> Basically, my idea is to apply `indexed` to an array several times and
> have all the intermediaries saved in the same variable.

There may be other ways of achieving the same goal without assigning to 
the same variable.


> I wonder, if there's a way to "collapse" or "simplify" the
> `Indexed!(Indexed!(int[], Result), Result)` type to just
> `Indexed!(int[], Result)` ?

If what you are looking for is a way of defining a variable for "any 
InputRange that produces a specific type (size_t in this case)", then 
there is inputRangeObject, which uses OOP:


  https://dlang.org/phobos/std_range_interfaces.html#InputRange

I have an additional example here:


http://ddili.org/ders/d.en/ranges_more.html#ix_ranges_more.inputRangeObject

Ali



Re: Confusion about `Random`

2022-12-24 Thread Ali Çehreli via Digitalmars-d-learn

On 12/24/22 09:58, jwatson-CO-edu wrote:

>> ~static this()

Should be 'static ~this()'.

>> ~shared static this()

Should be 'shared static ~this()'.

> thank you all

Happy to be helpful...

Ali



Re: Confusion about `Random`

2022-12-24 Thread Ali Çehreli via Digitalmars-d-learn

On 12/24/22 08:18, jwatson-CO-edu wrote:
> On Friday, 23 December 2022 at 07:25:23 UTC, Salih Dincer wrote:
>> You can try using static this.
>>
>> ```d
>> import std.random;
>>
>> static this() { } // can try using

static this() blocks: executed when a thread a starts (the program has 
at least one thread: the main thread); so you can put initializations here


~static this() blocks: counterparts of 'static this', executed once for 
each thread that is terminating


shared static this() blocks: executed once per program (executed by the 
main thread)


~shared static this() blocks executed once per program when the program 
is terminating


>> "rand" : () => new Atom(rand01)

That's the lambda (ananymous function) syntax.

The "rand" key of an associative array is being associated with the 
function after the ':' character. In the code above, the function 
creates a new Atom object. So, when the following code is executed:


  primitiveSymbols["rand"]

the same lambda would be returned but the execution of that lambda as 
the following


  primitiveSymbols["rand"]()

would return a new Atom which would make a call to the rand01() function 
and get a new random number from the same 'rnd' object.


Ali



Re: Does 'ref' turn into a pointer during compile time?

2022-12-21 Thread Ali Çehreli via Digitalmars-d-learn

On 12/21/22 16:43, thebluepandabear wrote:
> Say you have the following function that takes in a `ref` parameter:
>
> ```D
> void modify(ref int num) {
>  num += 5;
> }
> ```
>
> Does the compiler turn that into the code below?
>
> ```D
> void modify(int* num) {
>  num += 5;

Rather:

  *num += 5;

> }
> ```
>
> I was just wondering whether or not this is the case because I don't
> think this was touched in the book about D I am reading.

Yes, references are realized by pointers by CPUs; so that's how the code 
is compiled as well.


Pointers are considered to be one of the most difficult concepts for 
beginners (who the book was supposed to target). That's why I tried to 
hold it off as much as possible. I think once the concept of a reference 
is understood, pointers should be easy to understand.


That's why I say "Behind the scenes, D's higher-level concepts (class 
variables, slices, associative arrays, etc.) are all implemented by 
pointers." only later in the book on the pointers page:


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

Ali



Re: Is there such concept of a list in D?

2022-12-19 Thread Ali Çehreli via Digitalmars-d-learn

On 12/19/22 14:14, thebluepandabear wrote:

> Yeah I am sure it was on this thread. One of the posts was at
> https://forum.dlang.org/post/kzvnajixjdnlcupsl...@forum.dlang.org, it
> now shows 'Not Found'.

Then I don't know. (?)

However, I realize my ThunderBird "evidence" is useless because if the 
disapparance happened before my ThunderBird connected since its last 
time, it wouldn't have a copy of the posts.


(My ThunderBird does not connect automatically especially when the 
laptop lid is closed. :) )


Ali



Re: Is there such concept of a list in D?

2022-12-19 Thread Ali Çehreli via Digitalmars-d-learn

On 12/19/22 13:45, thebluepandabear wrote:
> On Monday, 19 December 2022 at 21:41:45 UTC, thebluepandabear wrote:
>> Why did my replies here to someone else get deleted?
>
> Myself and this other person's reply to this thread randomly got removed
> for no reason, I would appreciate an explanation 

Are you sure it was this thread? What were in those posts? Perhaps they 
were posted on another thread?


I follow these newsgroups with ThunderBird, which naturally keeps local 
copies of the posts. I've just gone through all posts in this thread and 
I see no difference between ThunderBird's cache and the forum 
interface's cache.


Note that ThunderBird does not delete any post even if a moderator 
removes a posting from the newsgroup. For example, when a spam gets 
posted, my ThunderBird will show the post even after it's been deleted 
from the newsgroup server.


Ali



Re: No need opUnary

2022-12-19 Thread Ali Çehreli via Digitalmars-d-learn

On 12/18/22 08:21, Salih Dincer wrote:
> Don't you think it's interesting that it doesn't need unary operator
> overloading?

Yes, it is interesting. I put comments to explain it to myself:

import std.stdio;

struct S
{
int value;

/* The folowing declaration allows objects of this type to be
   implicitly convertible to 'int' (the return type of
   'opCall').

   In other words, since opCall returns 'int', now we know S
   objects can implicitly be used in place of an int. The
   value will be determined by calling opCall.

   For those of us who may not know opCall, it allows an
   object to be used as a function. For example, when you
   have an 'obj', you can do 'obj()'. (And as seen below, it
   returns 'int' for this struct.)

   (Note: It confused me for a bit because there are two
   opCall definitions below and they both return
   'int'. However, there is no ambiguity because the compiler
   picks the one that takes no parameter for the following
   alias this.)  */
   alias opCall this;

this(int i) {
value = i;
}

/* I didn't know one could do the following. You are giving a
   new name (opAssign) to opCall. I wonder whether the
   compiler considers opCall for the assignment operation or
   whether it looks for a proper opAssign definition. (Too
   lazy to check...)  */
alias opAssign = opCall;

/* This is the function call operator that takes an 'int',
  supporting usages like obj(42). */
@property opCall(int x) {
return value = x;
}

/* This is the function call opCall that takes nothing,
   supporting usages like obj(). */
@property opCall() inout {
return value;
}

/* This is the operator overload for usages like 'obj += 42'. */
@property opOpAssign(string op)(int x) {
write(":"); // came here before
mixin("return value"~op~"=x;");
}
// no need: opUnary(string op)();
}

void main()
{
/* Ok, this is regular object construction. */
S a = S(10),

/* Using a comma above is something I would never do but 'b' is
  another object being constructed regularly. */
  b = S(-1);

/* Since S does not define the '+' operation, I think the
   compiler looks and finds an implicit conversion, which
   happens to be to 'int'. I think the following expression
   is addition of two ints: 10 + (-1)' */
writeln(a + b); // 9

/* Although S does not support the ++ operator, the D
   compiler finds the += operation and replaces ++ with
   a+=1. And then a is implicitly converted to 'int', gets the
   value 11. Again, the expression is an int addition of 11 +
   (-1). */
writeln(++a + b); // :10

/* This uses opOpAssign. */
a += 10; // :

/* This result makes sense. */
assert(a == 21);

writeln("\n--");

writeln(-b); // 1
}

Ali



Re: How is this code invalid?

2022-12-16 Thread Ali Çehreli via Digitalmars-d-learn

On 12/16/22 18:20, H. S. Teoh wrote:

> scratch space for computations, called the runtime
> stack.

I called it "function call stack" where I gave a very simplistic view of 
it here:


  https://www.youtube.com/watch?v=NWIU5wn1F1I=236s

> (2) Use @safe when possible so that the compiler will tell you when
> you're doing something wrong and potentially dangerous.

Unfortunately, @safe is not as prominent in the book as it should be. 
Part of the reason is I think its implementation is not complete 
especially how it changes with -dip1000.


Ali



Re: Unique!struct bug - Re: unique_ptr | Unique for autoclose handle

2022-12-15 Thread Ali Çehreli via Digitalmars-d-learn

On 12/15/22 11:31, Nick Treleaven wrote:
> On Wednesday, 14 December 2022 at 17:41:07 UTC, Ali Çehreli wrote:
>> I've never used Unique but I think it has a bug (or a design issue?):
>> Its destructor is the following:
>>
>> ~this()
>> {
>> if (_p !is null)
>> {
>> destroy(_p);
>> _p = null;
>> }
>> }
>>
>> Because _p is a pointer, destroy(_p) will not dereference and destroy
>> what it points to. I think this is a bug with Unique. I think it
>> should do
>>
>>   destroy(*_p);
>
> Now filed:
> https://issues.dlang.org/show_bug.cgi?id=23561

Thanks. I was hoping others more experienced with Phobos implementation 
chime in. But to me, the intention is to destroy the object. One never 
wants to destroy a pointer as there is no operation there.


As a minor proud moment, I do cover this issue:

  http://ddili.org/ders/d.en/memory.html#ix_memory.destroy

> Do you think it's OK to just fix this or

I think this is a bug because the documentation clearly talks about 
destroying the object:


  https://dlang.org/library/std/typecons/unique.html

"When a Unique!T goes out of scope it will call destroy on the
resource T that it manages, unless it is transferred. One
important consequence of destroy is that it will call the
destructor of the resource T."

>  do we need to do some kind of deprecation?

The behavior is so different from the intention that I don't think 
anybody is using Unique anyway. :o)


Ali



Re: unique_ptr | Unique for autoclose handle

2022-12-14 Thread Ali Çehreli via Digitalmars-d-learn

On 12/14/22 09:41, Ali Çehreli wrote:

> // According to documentation, the handler must be created 
dynamically:

> // We make a unique owner for it:

Ignore that part. It's a leftover from my experiments with Unique!Handle.

Ali



Re: unique_ptr | Unique for autoclose handle

2022-12-14 Thread Ali Çehreli via Digitalmars-d-learn

On 12/14/22 05:58, Vitaliy Fadeev wrote:
> On Wednesday, 14 December 2022 at 11:30:07 UTC, Vitaliy Fadeev wrote:
>> How to define HANDLE var ?  What to return from procedure? How to call
>> CloseHandle( h ) when variable destroyed?

An obvious way is an RAII type where the destructor calls CloseHandle.

> struct SafeHandle
> {
>  Unique!void _safe;

So you made Unique a member of SafeHandle. I've never used Unique but I 
think it has a bug (or a design issue?): Its destructor is the following:


~this()
{
if (_p !is null)
{
destroy(_p);
_p = null;
}
}

Because _p is a pointer, destroy(_p) will not dereference and destroy 
what it points to. I think this is a bug with Unique. I think it should do


  destroy(*_p);

In any case, I would use a Handle RAII type that calls CloseHandle in 
its destructor. Here is the code that made sense to me:


import std;

// Some values and types to make the code compile:
alias HANDLE = void*;
alias LPCWSTR = string;
enum INVALID_HANDLE_VALUE = null;
enum FILE_SHARE_READ = 1;
enum FILE_SHARE_WRITE = 2;
enum NULL = null;
enum OPEN_EXISTING = 1000;

// Some mocks of system functions
HANDLE CreateFileW(LPCWSTR path, int, int, void*, int, int, void*) {
auto handle = cast(HANDLE)(new int(42));
writeln("Created ", handle);
return handle;
}

int CloseHandle(HANDLE handle) {
writeln("Closing ", handle);
return 0;
}

// This is the RAII type for closing system handles
struct Handle {
HANDLE value;

// Disabling copying and assignment
@disable this(this);
@disable typeof(this) opAssign(const(typeof(this)));

this(HANDLE value) {
this.value = value;
writeln("Constructed Handle with ", value);
}

~this() {
const ret = CloseHandle(value);
if (ret) {
stderr.writefln!"Failed to close handle %s"(value);
}
}
}

Handle open_keyboard_device2( LPCWSTR path, int* error_number )
{
   // ...
   HANDLE dev_handle =
CreateFileW(
path,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);

   // According to documentation, the handler must be created dynamically:
   // We make a unique owner for it:
   auto result = Handle(dev_handle);
   writeln("Exiting open_keyboard_device2");
   return result;

// if ( dev_handle.get() != INVALID_HANDLE_VALUE ) {
// // ...
// }
   // ...
}

void processDevice( ... )
{
int err;
auto dev_handle = open_keyboard_device2("foo",  );
// set_keyboard_indicator2( dev_handle, KEYBOARD_CAPS_LOCK_ON );
// ...
writeln("Exiting processDevice");
}

void main() {
processDevice();
writeln("Exiting main");
}

The output of the program looks acceptable to me:

Created 7F1BD5A7D000
Constructed Handle with 7F1BD5A7D000
Exiting open_keyboard_device2
Exiting processDevice
Closing 7F1BD5A7D000
Exiting main

Ali



Re: Is there such concept of a list in D?

2022-12-13 Thread Ali Çehreli via Digitalmars-d-learn

On 12/13/22 14:21, areYouSureAboutThat wrote:
> On Saturday, 10 December 2022 at 15:59:07 UTC, Ali Çehreli wrote:
>>
>> ... Object orientation don't go well with collections
>
> On what basis do you make that assertion?

You stripped my answer.

> i.e. Which aspect of OOP programming 'don't go well with collections'?
>
> Is it encapsulation?
>
> Is it inheritance?
>
> Is it polymorphism?
>
> Is it generics? (which is an integral part of OOP these days)

I am impressed with the questions. Waiting for your answers...

> As evidence against your assertion (just to start with):
> C# -> System.Collections
> C# -> System.Collections.Generic
> C# -> System.Collections.Concurrent
>
> Only when you provide related proofs, can you come up with such an axiom.

Or I can tell what I think, you counter, and we all learn. Proofs... 
Axioms... Pfft...


Ali

P.S. I apologize for everything I've done to you in the past. Don't 
forget: You can always forkit!


Re: Why can't rvalues be passed to a 'ref' parameter?

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

On 12/11/22 01:25, zjh wrote:
> On Sunday, 11 December 2022 at 04:36:45 UTC, thebluepandabear wrote:
>
>> "The main reason for this limitation is the fact that a function
>> taking a ref
>> parameter can hold on to that reference for later use, at a time when
>> the rvalue
>> would not be available."
>>
>
>
> I only know that `rvalue` is a temporary value that will not be used,

Temporary values can be used but they should not be stored for later. In 
this context, if the ref parameter were also 'scope', we should be able 
to pass rvalues. (See below.)


> while `ref` is omitting a pointer.

Yes, although it is still a pointer behind the scenes, 'ref' is syntax 
that avoids pointers.


However, the situation has changed in D: It has been possible to pass 
rvalues by reference through the magic of 'in' parameters. This 
currently requires the -preview=in compiler switch, which makes 'in' 
parameters imply 'const scope':


  https://dlang.org/spec/function.html#in-params

import std.stdio;

struct S {
string id;
}

void foo(in S s) {
writeln("foo received ", s.id);
}

void main() {
auto s = S("lvalue");
foo(s);
foo(S("rvalue"));
}

Prints

foo received lvalue
foo received rvalue

On can add a copy constructor to S to see whether 'in' is by-copy or 
by-value.


Ali



Re: Function template as template parameter

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

On 12/11/22 05:54, Salih Dincer wrote:
> On Sunday, 11 December 2022 at 09:43:34 UTC, Andrey Zherikov wrote:
>> Note that callback parameter must be compile-time parameter as it
>> represents a member of a type during introspection done by `foo`.
>
> I can't quite understand the question, this already works:

I think the OP is trying to create an anonymous template. I don't think 
it's possible.


The following works because the template has the name 'print':

// Named template:
static void print(int i)() {
import std;
writeln(i);
}

void main() {
foo!print;
}

The following does not work when one attempts to use the template 
anonymously. Just trying to pass a template just like a lambda:


foo!((int i)() {
import std;
writeln(i);
});

Note how '(int i)()' is hoping to define a template.

Ali



Re: Is there such concept of a list in D?

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

On 12/9/22 22:11, thebluepandabear wrote:

> I was wondering more if there is an object oriented way of creating
> arrays,

Every collection has its own special interface. Object orientation don't 
go well with collections. For example, you wouldn't want indexing 
operator for a linked list.


> like in Java there is an `ArrayList`, in C++ there is
> `std::vector`, etc.

They are all dynamic arrays behind the scenes.

Arrays are so much better than linked lists that linked lists don't have 
much use outside of interviews.


- Arrays use less memory

- Provide constant time element access

- Amortized constant time element addition

- Constant time element removal in some cases (move the last element in 
place of the removed one)


- Ability to sort to find elements in logN time later on

- Arrays get special help from the CPU (e.g. cache prefetches)

There isn't a single point in favor of linked lists.

Ali



Re: printf, writeln, writefln

2022-12-08 Thread Ali Çehreli via Digitalmars-d-learn

On 12/8/22 08:21, Salih Dincer wrote:

> void stringCopy(Chars)(string source,
>  ref Chars target)

>sample.stringCopy = cTxt;  // disappeared ? char

Nothing disappeared on my system. (?)

Going off-topic, I find the expression above extremely confusing. I am 
used to assignment expression changing the value of the left hand side, 
but that expression changes cTxt. Very confusing...


Such obfuscations make it very hard for me to understand what the code 
is trying to demonstrate.


Ali



Re: gcc -E -dD; dstep; sqlite3

2022-12-08 Thread Ali Çehreli via Digitalmars-d-learn

On 12/8/22 06:28, johannes wrote:

> enum __FLT128_MAX__ = 1.18973149535723176508575932662800702e+4932F128;

That literal is not legal D. The "F128" characters at the end are extra.

Besides, D does not have a 128-bit floating point type.

Ali

(Sorry for double e-mail.)



Re: printf, writeln, writefln

2022-12-07 Thread Ali Çehreli via Digitalmars-d-learn

On 12/6/22 15:07, johannes wrote:

> 'write' prints out the address
> of the first byte. This is odd to me because printf does the job
> correctly.

printf behaves as what you expect because %s means dereferencing the 
pointer values and printing the char contents until printf sees '\0'.


> But I think to understand that write in D interpretes char*
> as a pointer to a byte.

Because it is. :) char* is nothing but a pointer to char. ('byte' exists 
as well, so I user 'char'.)


> it seems the
> formatting "%s" has another meaning in D ?

Yes. %s means the string representation of the variable. Sring 
representation of a pointer happens to be the hexadecimal representation 
of its value.


User-defined types can define a toSring() member function to decide how 
their string representation should be.


%s is the default: write(x) or writeln(x) would print like %s would.

This all works because these functions are templates, taking advantage 
of type deduction: They know the exact type of what they are printing. 
So, %s is known for that type.


printf that came from C is not templatized, so the programmer has to 
tell it what to do like with %s.


Ali



Re: Confused about something in the D book relating to precision

2022-12-04 Thread Ali Çehreli via Digitalmars-d-learn

On 12/4/22 18:57, thebluepandabear wrote:

> I am not understanding why Ali said there is a decimal mark if precision
> is nonzero?
>
> How can a number have zero precision?

That "precision" is referring to how many digits are printed after the 
decimal mark in the formatted output.


> "the required digits after the decimal mark, the number of which is
> determined
> by precision (default precision is 6)"

So, if we print with %e, we get 6 digits:

enum f = 1.23456789;
writefln!"%e"(f);

Prints

1.234568e+00

There are 6 digits after the decimal point.

Now 3 digits of precision:

writefln!"%.3e"(f);

Prints

1.235e+00

Now 0 precision, where the decimal point will disappear:

writefln!"%.0e"(f);

Prints

1e+00

> Well double has a precision of 15

Different meanings for the same word...

> I feel like this section was explained poorly and it's confusing.

I have to agree. Nobody really knows these by heart. Once you know 
what's available, you just come back and pick what you need for that 
occasion.


Ali



Re: Idiomatic D using GC as a library writer

2022-12-04 Thread Ali Çehreli via Digitalmars-d-learn

On 12/4/22 15:25, Adam D Ruppe wrote:

> which would trigger the write barrier. The thread isn't
> allowed to complete this operation until the GC is done.

According to my limited understanding of write barriers, the thread 
moving to 800 could continue because order of memory operations may have 
been satisfied. What I don't see is, what would the GC thread be waiting 
for about the write to 800?


Would the GC be leaving behind writes to every page it scans, which have 
barriers around so that the other thread can't continue? But then the 
GC's write would finish and the other thread's write would finish.


Ok, here is the question: Is there a very long standing partial write 
that the GC can perform like: "I write to 0x42, but I will finish it 2 
seconds later. So, all other writes should wait?"


> The GC finishes its work and releases the barriers.

So, it really is explicit acquisition and releasing of these barriers... 
I think this is provided by the CPU, not the OS. How many explicit write 
barriers are there?


Ali



Re: Idiomatic D using GC as a library writer

2022-12-04 Thread Ali Çehreli via Digitalmars-d-learn

On 12/4/22 12:17, Adam D Ruppe wrote:

On Sunday, 4 December 2022 at 17:53:00 UTC, Adam D Ruppe wrote:
Interesting... you know, maybe D's GC should formally expose a mutex 
that you can synchronize on for when it is running.


.. or compile in write barriers. then it doesn't matter if the 
thread is unregistered, the write barrier will protect it as-needed!


That's way beyond my pay grade. Explain please. :)

Ali



Re: Idiomatic D using GC as a library writer

2022-12-04 Thread Ali Çehreli via Digitalmars-d-learn

On 12/4/22 06:27, Sergey wrote:

> if it will be possible to write
> library in D and use it from
> C/++/Python/R/JVM(JNI)/Erlang(NIF)/nameYourChoice smoothly it will be a
> win.

Years ago we tried to call D from Java. I realized that it was very 
tricky to introduce the calling thread to D's GC. D's GC needed to stop 
the world, which meant it would have to know what threads were running. 
You can never be sure whether your D library function is being called 
from a thread you've known or whether the Java runtime (or other user 
code) just decided to start another thread.


We failed and D was replaced with C++.

Ali



Re: Idiomatic D using GC as a library writer

2022-12-04 Thread Ali Çehreli via Digitalmars-d-learn

On 12/4/22 05:58, vushu wrote:

> I was worried if my library should be GC free

May I humbly recommend you question where that thinking comes from?

Ali

P.S. I used to be certain that the idea of GC was wrong and the creators 
of runtimes with GC were simpletons. In contrast, people like me, people 
who could understand C++, were enlightened. Then I learned.




Re: Why can't D store all UTF-8 code units in char type? (not really understanding explanation)

2022-12-02 Thread Ali Çehreli via Digitalmars-d-learn

On 12/2/22 13:18, thebluepandabear wrote:

> But I don't really understand this? What does it mean that it 'must be
> represented by at least 2 bytes'?

The integral value of Ğ in unicode is 286.

  https://unicodeplus.com/U+011E

Since 'char' is 8 bits, it cannot store 286.

At first, that sounds like a hopeless situation, making one think that Ğ 
cannot be represented in a string. The concept of encoding to the 
rescue: Ğ can be encoded by 2 chars:


import std.stdio;

void main() {
foreach (c; "Ğ") {
writefln!"%b"(c);
}
}

That program prints

11000100
1000

Articles like the following explain well how that second byte is a 
continuation byte:


  https://en.wikipedia.org/wiki/UTF-8#Encoding

(It's a continuation byte because it starts with the bits 10).

> I don't think it was explained well in
> the book.

Coincidentally, according to another recent feedback I received, unicode 
and UTF are introduced way too early for such a book. I agree. I hadn't 
understood a single thing when the first time smart people were trying 
to explain unicode and UTF encodings to the company where I worked at. I 
had years of programming experience back then. (Although, I now think 
the instructors were not really good; and the company was pretty bad as 
well. :) )


> Any help would be appreciated.

I recommend the Wikipedia page I linked above. It is enlightening to 
understand how about 150K unicode characters can be encoded with units 
of 8 bits.


You can safely ignore wchar, dchar, wstring, and dstring for daily 
coding. Only special programs may need to deal with those types. 'char' 
and string are what we need and do use predominantly in D.


Ali



Re: Why can't D store all UTF-8 code units in char type? (not really understanding explanation)

2022-12-02 Thread Ali Çehreli via Digitalmars-d-learn

On 12/2/22 13:44, rikki cattermole wrote:

> Yeah you're right, its code unit not code point.

This proves yet again how badly chosen those names are. I must look it 
up every time before using one or the other.


So they are both "code"? One is a "unit" and the other is a "point"? Sheesh!

Ali



Re: Syntax Sugar for Initializing a Fixed float Array as void*?

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

On 11/30/22 16:48, Ali Çehreli wrote:


Functions are syntax sugar. :)


And I remembered std.array.staticArray. One its overloads should be useful:

import std;

void main() {
auto v3 = staticArray!(0.1f.repeat(5));
auto v4 = staticArray!5(0.1f.repeat);

writeln(v3);
writeln(v4);
}

Ali



Re: Syntax Sugar for Initializing a Fixed float Array as void*?

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

On 11/30/22 16:39, jwatson-CO-edu wrote:
Is there a way to write a single statement that creates a void pointer 
that points to an initialized float array?  See below:

```d
float* arr = cast(float*) new float[4];
arr[0] = 0.1;
arr[1] = 0.1;
arr[2] = 0.1;
arr[3] = 0.1;
void* value = cast(void*) arr;
```


Functions are syntax sugar. :)

import std;

void* inittedArray(T)(T value, size_t count) {
auto arr = new T[count];
arr[] = value;
return arr.ptr;
}

void main() {
auto v = inittedArray(0.1f, 5);

// or something a little crazy:
auto v2 = 0.1f.repeat(5).array.ptr.to!(void*);
}

Ali



Re: Thinking about the difference between fixed and 'dynamic' arrays.

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

On 11/29/22 15:25, DLearner wrote:

> 'dynamic array' is
> not a reasonable description for a construct that behaves like
> VarArr2[3] becoming 40.

I agree with you: It has always bothered me to call the following a 
dynamic array:


  int[] arr;

'arr' is not a dynamic array but the slice interface. Dynamic arrays are 
owned by the D runtime and are always nameless.


Ali



Re: Is there a formula for overflow?

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

On 11/29/22 19:07, thebluepandabear wrote:

> But the book doesn't talk about why the D compiler came up with these
> results

The compiler doesn't do anything special. It's all about the lack of 
bits to store the value. If the result needs 33 bits but the type has 
only 32 bits, the contribution of the highest bit is simply lost.


Ali



Re: dirEntries removes entire branches of empty directories

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

On 11/14/22 14:41, kdevel wrote:

> the ftw version gets the whole information from readdir alone.

Created an enhancement request:

  https://issues.dlang.org/show_bug.cgi?id=23512

Ali



Re: Assigning parameter on entry to a function and assigning back on exit

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

On 11/25/22 05:06, Victor Porton wrote:

>> A function argument that is both input and output, may be passed to
>> the function either as reference or do two assignments: on entry of
>> the function it is assigned to the parameter, on exit it is assigned
>> back.

The way I understand it with C, C++, and D, if there were such an 
assignment back, that could only be performed by the caller. I don't 
think the ABIs of those languages support that behavior.


I think there is only pass by reference for out parameters.

Ali



Re: Is defining get/set methods for every field overkill?

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

On 11/20/22 14:37, [] () {} () wrote:

> so, as I understand it, your're against the use of private, against the
> use of class, and against the use of encapsulation.

I never implied any of that.

> .. good luck with your career as a software engineer (but please, for
> all our sakes, don't work on any safety-related systems, and especially
> not the ones running in my car).

I haven't written any code that runs on the car yet but I did and still 
do work in autonomous vehicle projects:



https://techcrunch.com/2017/04/04/daimler-and-bosch-fully-autonomous-cars-within-5-years/

(That partnership is no more at this time.)

And coincidentally, to reply to your post that included Autosar, MISRA, 
etc. I am very well aware of those standards because I did contribute to 
the team that wrote our coding standards by going through every single 
one of their rules.


As one would expect, there was no argument on whether to use getters and 
setters or direct public access for that project: We decided no public 
access to members.


This discussion came to this point because you and I understood the 
question differently: I took the OP's question literally: "Is defining 
get/set methods for every field overkill?"


You took the question as whether to define them for class hierarchies, 
safety-critical systems, etc.


Ali



Re: Is defining get/set methods for every field overkill?

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

On 11/20/22 23:01, [] () {} () wrote:

> On that basis, I might be tempted to agree with you're point of view ->
> never, ever, ever, ever, use classes in D.

That's not my point of view.

Ali



Re: Is defining get/set methods for every field overkill?

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

On 11/20/22 00:31, [] () {} () wrote:

> Quoted from that video (the one that you agree with):
>
> "I don't ever think that private .. private is like just .. shouldn't
> even be used."
>
> "so I don't even use classes I just use struct so that everything is
> always public .. and that in my opinion is the correct method."

Yes, still agreeing with it.

> If anyone wants to learn more about why encapsulated types
> (classes) have shown to be so useful in my many years of programming,

Hm. 'private' is about access control. Encapsulation is something else.

> they can first pay me my fee.

If I could, I would like to pay to have less of that please. :)

Ali



Re: Is defining get/set methods for every field overkill?

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

On 11/19/22 01:43, [] () {} () wrote:

> do it your way for the next 10 years, and
> I bet you will eventually come to a different point of view ;-)

Hm... I am responding without reading the rest of the thread so I don't 
know whether you've mentioned the 10 years more but here it goes: I hope 
11 years will be sufficient to stop following guidelines blindly. 
Especially this specific one where a posted video has shown how wasteful 
it can be.


> if you're just a hobyist programmer, then you're really free to do as
> you please.

I am a professional programmer and I do not write public accessors 
blindly. As stated before, they are written only when there is an 
invariant to protect.


> but if you are a software engineer employed by a company, within a team
> of other software engineers, then you have to a have framework that you
> *all* work against.

Agreed.

> anyone who says otherwise, doesn't know what they're talking about.

Agreed.

> In my team, 'classes' do not have public member variables. not ever.

I am not working there! :) And what about structs? ;)

> another team is free to do as it pleases of course ;-)

Thanks. :)

> but members of that team will have a hard time getting into my team.

Mutual feelings there...

Ali



Re: Is defining get/set methods for every field overkill?

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

On 11/19/22 01:05, [] () {} () wrote:

> All this because some programmer wanted to save a few key strokes, or
> did not anticipate change, or did not anticipate the need to ensure data
> is valid before assigning it, or returning it.
>
> So no. It's not overkill. It's called software engineering.

I disagree. Engineering is about applying different solutions to 
different problems. Blindly following guidelines whether it is fit for 
purpose would be dogmatic, not pragmatic.


Ali



Re: Is defining get/set methods for every field overkill?

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

On 11/18/22 20:13, [] () {} () wrote:

> after 10 years of doing all that, you may well come to the conclusion
> that public member variables are not such a great idea afterall ;-)

It depends. Majority of my structs are pure data. When there is no 
invariant to protect, then there is no reason to write any accessor.


If 10 years is mentioned to prove a point, I currently have 33 years of 
professional programming experience (37 including pure hobby years), so 
I must be right. ;)


Ali



Re: Is defining get/set methods for every field overkill?

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

On 11/18/22 19:35, [] () {} () wrote:

> I like to see an example, of a 'class type' with 'public' member
> variables, somehow magically converted into both getter and setter using
> UFCS, without breaking client code.

UFCS was mentioned before in the same context but I think what is meant 
was the D feature where functions can be called without parenthesis.


Let's say, we have a pure data type:

struct Point {
int x;
int y;
}

void clientCode() {
auto p = Point();
p.y = p.x + 42;
}

void main() {
clientCode();
}

It took me 20 years to first think that public access to members 
was extremely wrong to then realize that there may not be any problem 
with it at all. As you said, "business logic" (I prefer "invariants") 
warrants limiting access to members. Without anything to protect, it is 
just extra work for no reason at all. (I fully agree with the posted video.)



Ok, let's say that the business requirements changed and we wanted to 
perform some business logic. Thanks to D's pragmatism, clientCode() does 
not change at all:


struct Point {
int x_;// Rename
int y_;// Rename

auto x() {// Getter
return x_ + y_;
}

auto y(int value) {  // Setter
x_ = value * 2;
y_ = value / 2;
}
}

void clientCode() {
auto p = Point();
p.y = p.x + 42;
}

void main() {
clientCode();
}

There: clientCode() is not broken.

Ali



Re: Is defining get/set methods for every field overkill?

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

On 11/16/22 20:39, thebluepandabear wrote:

> I am debating whether or not I should add getter methods to these
> properties.

If you are debating, then the answer is easy: you should not. :)

Less code written means less bugs, more cohesion, easier refactoring, 
cleaner code, all good stuff...


Even if a design requires e.g. a 'length' method, the default one should 
be a getter. A setter will come in the future only if 'length = 42' is 
clearly better than e.g. 'expandTo(42)'.


> in other languages like Java it is a good practice:

I've seen so many tutorials where any user-defined type immediately 
defines getters and setters. It is never good style to do that. There 
are good examples of where doing that is clearly wrong. For example, can 
a Date class really provide a setMonth() setter? It would be so wrong, I 
don't even know where to begin. (I remember talks by Kevlin Henney where 
he would use that example.)


The guidelines I follow are simple in the following order:

- Don't write any code until it makes sense :)

- Don't write a getter until it makes sense

- Don't write a setter until it makes sense

Ali



Re: Actual lifetime of static array slices?

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

On 11/15/22 06:05, Siarhei Siamashka wrote:

> Ali commented that "the
> compiler cannot do anything about it in all cases and we wouldn't want
> it to spend infinite amount of time to try to determine everything".

Yes, that's my understanding.

> This sounds like he justifies the compiler's failure and accepts this as
> something normal.

Despite my lack of computer science education, I think the compiler's 
failure in analyzing source code to determine all bugs is "normal". I 
base my understanding on the "halting problem" and the "separate 
compilation" feature that D supports.


> The https://dlang.org/spec/memory-safe-d.html page also provides a
> rather vague statement: "@safe functions have a number of restrictions
> on what they may do and are intended to disallow operations that may
> cause memory corruption". Which kinda means that it makes some effort to
> catch some memory safety bugs.

Exactly. My understanding is that @safe attempts to remove memory 
corruptions. @live is being worked on to improve the situation by 
tracking liveness of data.


> This weasel language isn't very
> reassuring, compared to a very clear Rust documentation.

That's spot on.

Ali



Re: Actual lifetime of static array slices?

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

On 11/14/22 19:05, Elfstone wrote:

>  @safe
>  int[] foo()
>  {
>  int[1024] static_array;
>  // return static_array[]; // Error: returning `static_array[]`
> escapes a reference to local variable `static_array`

That is trivial for the compiler to catch.

>  return null;
>  }
>
>  @safe
>  A bar()
>  {
>  int[1024] static_array;
>  return new A(static_array[]);

That one requires the computer to analyze the code to a deeper level. 
Yes, we are passing a slice to the A constructor but we don't know 
whether the constructor will store the slice or simply use it. Even the 
following can be safe but impossible to detect by the compiler:


class A
{
@safe
this(int[] inData)
{
data = someCondition() ? new int[42] : inData; // (1)
// ...
if (someOtherCondition()) {
data = null;   // (2)
}
}
// ...
}

(1) Whether we use inData depends on someCondition(). It may be so that 
bar() is never called depending on someCondition() in the program at all.


(2) data may never refer to 'static_array' after the constructor exits 
depending on someOtherCondition()


The code above may not be using good coding practices and humans may see 
the bugs if there are any but only a slow (infinetely?) compiler can see 
through all the code. (I think @live will help with these cases.) 
Further, the support for "separate compilation" makes it impossible to 
see through function boundaries.


Additionally, we don't want the compiler to force us to copy all stack 
variables just in case.


In summary, you are right but the compiler cannot do anything about it 
in all cases and we wouldn't want it to spend infinite amount of time to 
try to determine everything.


Ali



Re: dirEntries removes entire branches of empty directories

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

On 11/11/22 08:00, Ali Çehreli wrote:

> It may have to do something with the performance of the hard disk.

I meant "the reason you got a much better improvement" may have to do 
something with the performance differences of your hard disk and mine.


Ali



Re: dirEntries removes entire branches of empty directories

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

On 11/11/22 05:13, kdevel wrote:

> dmd -O compiled patched (see below!) version applied to /usr/bin on my
> desktop
> yields:
>
> ftw   : 363 ms, 750 ÎŒs, and 5 [*]
> dirEntries: 18 secs, 831 ms, 738 ÎŒs, and 3 [*]

Great. I did not use -O with my test. It may have to do something with 
the performance of the hard disk.


ftw wins big time. Being just a D binding of a C library function, its 
compilation should be quick too.


>> entries ~= DirectoryEntry(entry, entry.getSize);
>> }
>
> strace reports that entry.getSize invokes stat on the file a second
> time. Isn't
> the stat buf saved in the entry?

That's my bad. entry.size is the cached version of the file size.

> This also gives rise for a complication with symlinks pointing to the
> directory
> which contain them:
>
> $ pwd
> /tmp/k/sub
> $ ln -s . foo
> $ ../direntrybenchmark .
> 
std.file.FileException@8[...]/linux/bin64/../../src/phobos/std/file.d(1150): 
./foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo/foo: 
Too many levels of symbolic links


So, ftw does not have that problem? Perhaps because of its default 
symlink behavior? There is also the more capable nftw, where the caller 
can specify some flags. And yes, there it is:


 FTW_PHYS
If set, do not follow symbolic links.  (This is what you  want.)
If not set, symbolic links are followed, but no file is reported
twice.

If FTW_PHYS is not set, but FTW_DEPTH is set, then the  function
fn()  is never called for a directory that would be a descendant
of itself.

> -const dir = buildNormalizedPath("/home/ali/dlang");
> +const dir = buildNormalizedPath(args[1]);

That one, and I had switched the arguments on the following call. One 
more example where string interpolation would be useful:


writefln!"Ignoring type %s file: %s\n(See 'man nftw')b"(
path, typeflag);

I meant the arguments in the reverse order there.

OT: And there is a 'b' character at the end of that format string which 
almost certainly appeared when I botched a Ctrl-b command in my editor. :)


Ali



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, , 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 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"



Re: dirEntries removes entire branches of empty directories

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

On 11/9/22 11:05, Ali Çehreli wrote:

> Can you think of a workaround to achieve that?

Me, me, me! :) I've learned about the Posix function 'nftw' (but I am 
using its sibling 'ftw').


It was pretty easy to use but there is a quality issue there: They 
failed to support a 'void*' context for the user! You can walk the tree 
but can't put the results into your local context! Boo!


I guess it was designed by someone who is happy with global variables. 
:) At least D makes it easy to guard access to module variables with 
'synchronized', shared, etc.


Ali



Re: dirEntries removes entire branches of empty directories

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

On 11/9/22 11:48, Imperatorn wrote:

> That's not the behaviour I get in Windows.

Windows users deserve it! :p (At least it is better in this case. :) )

> When I create the subdirectory, I see it even if it's empty

struct DirIteratorImpl has different implementations for Windows, etc.

Ali



dirEntries removes entire branches of empty directories

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

In case it matters, the file system is ext4.

1) Create a directory:

  mkdir deleteme

and then run the following program:

import std;

void main() {
foreach (e; dirEntries(absolutePath("./deleteme"), SpanMode.breadth)) {
writeln(e.name);
}
}

Understandably, the top level directory 'deleteme' will not be printed.

2) Make a sub-directory:

  mkdir deleteme/a

Running the program shows no output; 'a' is not visited as a directory 
entry.


3) Create a file inside the sub-directory:

  touch deleteme/a/x

Now the program will show 2 entries; the branch is accessible:

/home/ali/d/./deleteme/a
/home/ali/d/./deleteme/a/x

Imagine a program that wants to make sure the directory structure is 
intact, even the empty directories should exist. Can you think of a 
workaround to achieve that?


Do you think this is buggy behavior for dirEntries?

Ali


Re: Passing a string by reference

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

On 11/8/22 04:53, Alexander Zhirov wrote:
> On Tuesday, 8 November 2022 at 12:43:47 UTC, Adam D Ruppe wrote:
>> Just use plain `string`.
>
> So it's always working with thick pointers?

Yes, D's arrays are fat pointers. strings are arrays of immutable(char).

>> nope, an object isn't created there at all. you should use `new C`.
>
> If I create just `A c`, then is it an empty pointer?

Yes. Classes are reference types in D. Class variables are implemented 
as pointers. Their default value is null.


Ali



Re: What's the correct way of creating an instance of class in D?

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

On 11/3/22 08:40, H. S. Teoh wrote:

> D does not have the equivalent of C++'s allocating a class instance on
> the stack.

Not by default but we have two different ways, either may be discouraged:

import std.typecons : scoped;
import std.stdio;

class C {
int i;
}

void main() {
// Either this:
// auto c = scoped!C();

// Or this:
scope c = new C();

writeln("If the address values are close, then the object is on the 
stack:");

writeln();
writeln();
}

Ali



Re: Unit testing a function returning void

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

On 11/3/22 03:00, Bruno Pagis wrote:

>void print() {
>  writeln("array = ", this.array);
>}

Similar to Paul Backus's program but I would try to avoid the file 
system for unit tests when possible. In this case, you can print into a 
sink, which can be useful in other ways as well:


import std.stdio;

class A
{
int[] a;

this(int[] a) { this.a = a; }

void toString(scope void delegate(in char[]) sink) const {
import std.conv : text;
sink("array = ");
sink(this.a.text); // or this.a.to!string

// The following alternative may be a little heavier weight:
// import std.format : formattedWrite;
// sink.formattedWrite!"array = %s"(this.a);
}

void print() {
writeln(this);
}
}

unittest {
import std.file;

A a = new A([1, 2]);

import std.conv : text;
assert(a.text == "array = [1, 2]");
}

void main() {}

toString is the textual representation of the object. If you don't want 
the same output for that purpose, you can use a different name from 
toString but you have to use an explicit "sink" but I really think the 
above is what you want. :)


Ali



Re: save() feature for iota

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

On 11/3/22 04:58, Paul Backus wrote:

> https://issues.dlang.org/show_bug.cgi?id=23453

Even though iterating over UTF value ranges don't make sense in general, 
they would work for some values including the ASCII range.


Ali



Re: druntime thread (from foreach parallel?) cleanup bug

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

On 11/1/22 10:27, H. S. Teoh wrote:

> Maybe try running Digger to reduce the code for you?

Did you mean dustmite, which is accessible as 'dub dustmite 
' but I haven't used it.


My guess for the segmentation fault is that the OP is executing 
destructor code that assumes some members are alive. If so, the code 
should be moved from destructors to functions to be called like 
obj.close(). But it's just a guess...


Ali



Re: CTFE in betterC needs the GC

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

On 10/29/22 20:41, arandomonlooker wrote:

> string exampleCTFE(string a, string b) {
>  return a ~ b;
> }

Although you need that function only at compile time, it is an ordinary 
function that could be called at run time as well. The function needs GC 
for that concatenation in the general case.


One way of solving your issue would be to change the function to a 
function template and pass the strings as template parameters 
(compile-time parameters):


string exampleCTFE(string a, string b)() {
return a ~ b;
}

which would require explicit function template instantiation:

enum example = exampleCTFE!("A", "BCDE");

which would cause code bloat because exampleCTFE would be instantiated 
for every string combination that was used. For example, the following 
two uses would require two separate instantiations:


enum example1 = exampleCTFE!("A", "BCDE");
enum example2 = exampleCTFE!("A", "BCDEX");

> int main() {

I think you also need to specify main() as extern(C):

extern (C)
int main() {
  // ...
}

Ali



Re: ubyte + ubyte = int

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

On 10/26/22 14:19, Ali Çehreli wrote:

>https://dlang.org/spec/type.html#integer-promotions

Reading "Value Range Propagation" further down that link, I learned that 
e.g. masking 'decimal' with 0xf makes the code compile:


return ((decimal & 0xf) + ubyte('0'));

return ((decimal & 0xf) - ubyte(10) + ubyte('A'));

Ali



Re: ubyte + ubyte = int

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

On 10/26/22 14:10, 0xEAB wrote:

> I guess, this fancy behavior is inherited from C.

Yes. It is called integer promotions:

  https://dlang.org/spec/type.html#integer-promotions

(The next section is related as well.)

> I know this is advanced stuff, but the compiler *could* even prove that
> the calculation(s) won’t go beyond `ubyte.max`.

Apparently it does not go that far but there is Value Range Propagation:

  https://www.digitalmars.com/articles/b62.html

That article links to this forum post:


https://www.digitalmars.com/d/archives/digitalmars/D/Value_Preservation_and_Polysemy_80224.html#N80293

Ali



Re: Replacing tango.text.Ascii.isearch

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

On 10/25/22 22:49, Siarhei Siamashka wrote:

> Unicode is significantly simpler than a set of various
> incompatible 8-bit encodings

Strongly agreed.

> I'm surely
> able to ignore the peculiarities of modern Turkish Unicode

The problem with Unicode is its main aim of allowing characters of 
multiple writing systems in the same text. When multiple writing systems 
are in play, conflicts and ambiguities will appear.


> and wait for
> the other people to come up with a solution for D language if they
> really care.

I solved my problem by writing an Alphabet hierarchy in the past. I 
don't like that code but it still works:



https://bitbucket.org/acehreli/ddili/src/4c0552fe8352dfe905c9734a57d84d36ce4ed476/src/alphabet.d#lines-50

It handles capitalization, ordering, etc. I use it when preparing the 
Index section of the Turkish edition of "Programming in D":


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

One of the ambiguities is what came up on this thread: Should a word 
that starts with I (capital i) be listed under I (because it's Turkish) 
or under İ (because it's English)? So far, I am lucky because the only 
word that starts with I happens to be the English "IDE", so it goes 
under i (which appears as İ in the Turkish edition) and would make sense 
to a Turkish reader because a Turkish reader might (really?) accept it 
as the capital of ide.


It's confusing but it seems to work. :) It doesn't matter. Life is 
imperfect and things will somehow work in the end.


Ali



Re: Is "auto t=T();" not the same as "T t;"?

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

On 10/25/22 19:25, Salih Dincer wrote:

> with static in main():

If 'static' makes a difference on your side as well, it is your turn to 
create a bug report. :) (Last time you discovered a bug, I was too quick 
to report it. :/)


Ali



Re: Is "auto t=T();" not the same as "T t;"?

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

On 10/25/22 17:16, Salih Dincer wrote:

> Excuse me, but they still write in purple prose about dynamic
> array literature here!

I've heard positive things about D's arrays from people who use D in 
production. Especially slices...


> I've known D for more than 10 years, but the topic we're talking about
> still seems strange to me.

Your example makes it more complicated and potentially exposes a bug.

> The explanations given are not enough for
> me, I'm sorry.

There may be a number of different concepts to list but I don't think 
there is anything inherently complicated with these topics (again, your 
example is more complicated).


> Can anyone tell me what happens when I change the location of the
> structure?

What you mean is, you see different behaviour depending on struct X is 
nested or not. The difference is, nested structs carry a context 
pointer. This may be related to a bug for the different outputs that we see.


> So the X structure must be in the stack when it is in
> main(), and the following must be in the heap, right?

To nit-pick: The struct is just a definition. Not the struct but its 
objects can be on the stack or on the heap.


But yes, all objects you have are on the stack.

> //void main() {

So when you uncomment that line and comment-out the following main() 
line in the program, you see a different output.


I tested: If you make X a 'static struct', then you see the same output.

I think the difference is due to a bug.

Ali



Re: auto scope question?

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

On 10/25/22 15:07, WhatMeWorry wrote:

> auto screen = executeShell(cmdLine);
> auto s;

That can't work because there is no information to infer the type of 
's'. Judging from the return type of getPath, perhaps it's string[]:


string[] s;

This is the question we should answer first: What should happen when 
executeShell fails?


a) It is an error; the program should not continue. Then we can use 
'enforce' (this is my way of coding):


string[] getPath(string cmdLine)
{
import std.exception : enforce;

auto screen = executeShell(cmdLine);
enforce(screen.status == 0, format!"%s failed:\n%s"(cmdLine, 
screen.output));


writeln("screen.output = ", screen.output);
auto s = screen.output.findSplit("REG_SZ");
writeln("s[0] = ", s[0]);
writeln("s[1] = ", s[1]);
writeln("s[2] = ", s[2]);

return (s.split(';'));
}

b) It is not an error; getPath() should return empty array:

string[] getPath(string cmdLine)
{
string[] result;
auto screen = executeShell(cmdLine);

if (screen.status != 0)
{
writeln(cmdLine, " failed");
return null;  // <-- HERE (null converts to any array type)
}
else
{
// ...
// Now, 'return' is where 's' is defined:
return (s.split(';'));
}
}

Ali



Re: Is "auto t=T();" not the same as "T t;"?

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

On 10/25/22 13:36, matheus wrote:
> On Tuesday, 25 October 2022 at 20:12:25 UTC, Paul Backus wrote:

>> Static arrays are value types.

What that means is, when we say float[3], there are just 3 floats 
without any overhead.


>> Dynamic arrays are reference types.

That phrase can be confusing because we often use the terms "dynamic 
array" and "slice" interchangably.


I find the following simpler to understand (can still be confusing):

- Dynamic arrays are expandable arrays that are owned by the D runtime 
(the GC). Dynamic arrays don't have names.


- The names (symbols) that we see in source code are slices that are 
references to elements of arrays. Such arrays can be static or dynamic.


When we add an element to a slice that has no room (.capacity <= 
.length) then a fresh dynamic array is created from the copies of the 
elements of the slice.


> if this is a case the generate more problem understanding this rules,

I think all these array complexities are inherent. Other examples from 
two other languages that I know:


- In C, arrays that are members of user-defined types are value types. 
Arrays that are parameters are reference types (pointer to the first 
element). Confusing.


- In C++, std::vector is a value type, which would be copied if passed 
by value. So there came std::array, std::string_view, std::span, etc. to 
address value versus reference complexities.


I don't think D could do anything better with arrays. They seem to work 
pretty well and are among the favorite features of many D programmers.


Ali



Re: Is "auto t=T();" not the same as "T t;"?

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

On 10/25/22 13:12, Paul Backus wrote:

> In order to create a copy of a static array

Although .dup works for static arrays as well, you meant "dynamic array" 
and everyones knows it. :)


> with its own block of
> memory, separate from the original, you have to use the built-in `.dup`
> method:
>
> ```d
> int[] a = [1];
> int[] b = a.dup;

Ali



Re: Is "auto t=T();" not the same as "T t;"?

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

On 10/25/22 11:23, Steven Schveighoffer wrote:

>> Why do I say incorrect things like that? :)

> You were right actually.

As always! Now I'm confused. :o)

Ali



Re: Is "auto t=T();" not the same as "T t;"?

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

On 10/25/22 11:01, Ali Çehreli wrote:

> static arrays don't have .ptr to point
> to any member.

Why do I say incorrect things like that? :) Of course static arrays have 
.ptr as well but that always point to their own body of N elements. They 
own their elements... I move away from the keyboard now... :)


> Static arrays are "just elements side by side."

I still like that description though.

Ali



Re: Is "auto t=T();" not the same as "T t;"?

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

On 10/25/22 10:54, Salih Dincer wrote:

> So I don't understand why it causes problems with
> dynamic arrays!  So why is there nothing wrong with the static array in
> the example below?

The same rules as other uses of dynamic arrays...

>  //A[] a = [A.init];/*

In that case, there is a single instance of [A.init]. All A.a members 
point to it through their .ptr .length members.


>  A[1] a = [A.init];//*/

In that case, there is still a single instance of [A.init], which gets 
copied to each A.a member because static arrays don't have .ptr to point 
to any member. Static arrays are "just elements side by side."


In other words, there is no option but to copy to static arrays; they 
can't point to elements and they don't have any problem in this case.


Ali



Re: Is "auto t=T();" not the same as "T t;"?

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

On 10/25/22 08:50, Andrey Zherikov wrote:

> I'd like to tune default ctor but structs can't have custom one.
> Adding a ctor with parameter seems a hack to me

There is static opCall, which may be seen as a hack as well. :) The 
following all print the same thing now:


import std.stdio;

struct A
{
int[] i;
}
struct B
{
A[] a = [A.init];

static B opCall()
{
return B.init;
}
}
void main()
{
auto b1 = B.init;
b1.writeln;

B b2 = B();
b2.writeln;

B b3;
b3.writeln;
}

> This fails in run time

Not anymore with the above code.

Ali



Re: Is "auto t=T();" not the same as "T t;"?

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

On 10/25/22 07:53, Adam D Ruppe wrote:
> On Tuesday, 25 October 2022 at 13:51:30 UTC, Andrey Zherikov wrote:
>> A[] a = [A.init];
>
> This is a problem - this is referring to a static array instance, shared
> across all copies of B. You almost certainly don't want this.

Agreed. It should be fine when the elements are immutable as I've 
experimented with recently[1]:


struct Xml {
string beg;
string end = "/>";  // Shared by all instances;
// no allocation for some objects.
// ...
}

> As for why B() and B.init are different here... i don't know, probably
> some subtly of the compiler's implementation.

I think it's a bug.

Ali

[1] https://youtu.be/0JL9uT_XGZE?t=4260s



Re: Supporting foreach (k, v; T.init) for a user-defined (container) type

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

On 10/24/22 14:26, Per Nordlöw wrote:

What property of a container (type) `T` enables iteration as

```d
foreach (k, v; T.init)
{
     ...
}
```

? I thought it sufficed to define `T.byKeyValue` but its presence seem 
to have no effect.


Another option is to use range functions where front() returns a Tuple. 
We have an esoteric feature where a tuple expands automatically in 
foreach loops:


import std.typecons : tuple;
import std.conv : to;
import std.stdio : writeln;
import std.range : take;

struct S {
size_t count;
bool empty = false;

auto front() {
const key = count;
const value = key.to!string;
return tuple(key, value);// <-- HERE
}

void popFront() {
++count;
}
}

void main() {
foreach (k, v; S.init.take(10))
{
writeln(k, ": ", v);
}
}

Ali



Re: Find in assoc array then iterate

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

On 10/22/22 08:21, Kevin Bailey wrote:

> his claim that there was no value.

I think he was questioning the need for iterating from a point forward 
inside an unordered container. When the container is unordered, the 
elements that are accessed after a found element could be anything. I 
think that's the puzzling part in your question.


>  package main

Here is my interpretation of Paul Backus's solution:

module main;

import std.stdio;

void main() {
int[string] m;
m["key1"] = 7;
m["key2"] = 8;

auto iter = m.byKeyValue();
// Advance iterator
iter.popFront();
// Preserve position
auto iter2 = iter.save();
// Exhaust first iterator
foreach (kv; iter) {
writeln("iter: ", kv.key, " = ", kv.value);
}
// What does second iterator see?
foreach (kv; iter2) {
writeln("iter2: ", kv.key, " = ", kv.value);
}
}

May print (because its unordered):

iter: key2 = 8
iter2: key2 = 8

Ali



Re: Real simple question... for good programmers

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

On 10/22/22 14:53, WhatMeWorry wrote:
>
>
> string[] tokens = userSID.output.split!isWhite;
> writeln("tokens = ", tokens);

Could you please show minimal compilable code that demonstrates the 
issue. I spent some time with some guesses but failed (to get my code to 
compile with std.array.split).


Ali

P.S. Sorry for also sending email.


Re: Find in assoc array then iterate

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

On 10/21/22 15:03, Kevin Bailey wrote:

I'm trying to do this equivalent C++:

     unordered_map map;

     for (auto i = map.find(something); i != map.end(); ++i)
     ...do something with i...

in D, but obviously with an associative array. It seems that it's quite
easy to iterate through the whole "map", but not start from the middle.
Am I missing something obvious (or not so obvious) ?



Something like the following perhaps, which sorts the keys:

import std; // Sorry :(

void main() {
auto m = iota(20).map!(i => tuple(i, format!"value_%s"(i))).assocArray;

foreach (key; m.keys.sort.find(13)) {
writeln(m[key]);
}
}

Ali



Re: Catching C errors

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

On 10/19/22 09:47, data pulverizer wrote:

> It's okay, I've found a work around.

Do you simply check the return value?

Ali



Re: Catching C errors

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

On 10/19/22 07:05, data pulverizer wrote:

> I am calling code from a C API, and would like to know how to catch exit
> errors

If you are talking about the exit() Posix function, you can't do 
anything about that because its purpose is to cause "normal process 
termination".


Ali



Re: warning LNK4255 - How to solve this warning

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

On 10/18/22 12:26, Hipreme wrote:

> Is there any way to know which files produced this error or at least the
> symbol names that are clashing? I'm totally helpless about this error.

There is 'nm' on Posix systems that lists symbols in object files 
(including libraries and programs).


Ali



Re: parallel is slower than serial

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

On 10/18/22 06:24, Guillaume Piolat wrote:

> To win something with OS threads, you must think of tasks that takes on
> the order of milliseconds rather than less than 0.1ms.
> Else you will just pay extra in synchronization costs.

In other words, the OP can adjust work unit size. It is on the official 
documentation but I also mention it on slide 72 of the section that 
starts at the following point:


  https://youtu.be/dRORNQIB2wA?t=1327

Ali



Re: Reading and wiping notes also adding more notes

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

On 10/17/22 22:40, Joel wrote:

> I have two text fields. The one on the left has the whole text, new
> stuff being added to the bottom. The one on the right has text I've been
> wiping as I'm reading.

I think this can be modelled as a string array and an index showing 
where the active part starts:


import std;

struct Notes {
string[] whole;
size_t activeIndex;

void add(string line) {
whole ~= line;
}

string[] activeText() {
return whole[activeIndex..$];
}

void wipeText() {
++activeIndex;
}
}

void main() {
auto input = [ "I went for a walk and fell down a hole.",
   "There was a D guy on the roof.",
   "That was a tricky problem!", ];

Notes notes;

// add() to add()
input.each!(line => notes.add(line));

// activeText() will show the active part
// wipeText() will move forward
}

Ali



Re: probably a trivial question...

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

Changing the order of lines...

On 10/13/22 16:43, WhatMeWorry wrote:

> return s.split(';');  // single quotes

That one is a single character and very lightweigth because it's just an 
integral value. You can't put more than one character within single quotes:


 ';x' // ERROR

> return s.split(";");  // double quotes

That one is a string, which is the equivalent of the following "fat 
pointer":


struct Array_ {
  size_t length;
  char * ptr;
}

For that reason, it can be seen as a little bit more costly. 'length' 
happens to be 1 but you can use multiple characters in a string:


  ";x" // works

(Aside: There is also a '\0' character sitting next to the ';' in memory 
so that the literal can be passed to C functions as-is.)


Double-quoted strings have the property of escaping. For example, "\n" 
is not 2 characters but is "the newline character".


> return s.split(`;`);  // back ticks

They are strings as well but they don't do escaping: `\n` happens to be 
2 characters.


There is also strings that start with q{ and end with }:

  auto myString = q{
  hello
  world
  };

And then there is delimited strings that use any delimiter you choose:

auto myString = q"MY_DELIMITER
hello
world
MY_DELIMITER";

Some information here:

  http://ddili.org/ders/d.en/literals.html#ix_literals.string%20literal

Ali




Re: Replacing tango.text.Ascii.isearch

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

On 10/5/22 13:40, torhu wrote:


 auto sw = StopWatch();


Either this:

auto sw = StopWatch(AutoStart.yes);

or this:

auto sw = StopWatch();
sw.start();

Ali




Re: Remove elements without losing capacity

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

On 10/4/22 10:59, Riccardo M wrote:

> The inherent reason for `remove` to cancel previous capacity and
> requiring new allocations is exactly to prevent overwriting data that
> could be owned by something else?

Yes.

A related topic is how the "end slice" never loses that capacity:

void main() {
auto a = [ 1, 2 ];
auto b = a;

assert(a.capacity != 0);
assert(b.capacity != 0);

b.length--;
assert(b.capacity == 0);
assert(a.capacity != 0);// <-- Preserved
}

Aside: .capacity is an expensive operation that requires some levels of 
table lookups in the druntime. A data structure would benefit a lot if 
it kept its own capacity as a member variable.


Ali




Re: rotate left an array

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

On 10/3/22 17:00, Paul Backus wrote:
> On Monday, 3 October 2022 at 21:06:36 UTC, Ali Çehreli wrote:
>> On 10/3/22 13:48, Andrey Zherikov wrote:
>>> a "rotated view".
>>
>> Without indexes:
>>
>> import std.range : empty;
>>
>> auto rotatedView(R)(R range)
>> in (!range.empty)
>> {
>> import std.range : chain, front, only, popFront;
>> const fr = range.front;
>> range.popFront();
>> return chain(range, only(fr));
>> }
>
> Tiny nitpick: this should use
>
>  const fr = range.save.front;
>
> ...to ensure that `fr` is not invaliated or overwritten by the
> subsequent call to range.popFront (e.g., think of File.byLine here).

Good catch but I think what we want is a copy of the front element, at 
least for InputRanges (.save does not work for File.byLine :/).


What is the generic way of copying an element? I wonder whether we have 
to use isSomeString to take care of all element types.


Ali




Re: rotate left an array

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

On 10/3/22 13:48, Andrey Zherikov wrote:

a "rotated view".


Without indexes:

import std.range : empty;

auto rotatedView(R)(R range)
in (!range.empty)
{
import std.range : chain, front, only, popFront;
const fr = range.front;
range.popFront();
return chain(range, only(fr));
}

void main()
{
import std.algorithm : equal;
int[] arr1 = [ 1, 2, 3, 4 ];
assert(arr1.rotatedView.equal([ 2, 3, 4, 1 ]));

// Now this is getting a little expensive! :)
assert(arr1
   .rotatedView
   .rotatedView
   .equal([ 3, 4, 1, 2 ]));
}

Ali




Re: Stop writeln from calling object destructor

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

On 10/2/22 10:55, data pulverizer wrote:
> On Sunday, 2 October 2022 at 17:28:51 UTC, data pulverizer wrote:
>> Sorry I'll need to implement all the overloaded copy constructors and
>> see if that fixes it.
>
> I've got it, something weird happened to my copy constructor. This was
> my original attempt and was ignored (didn't run in the copy constructor):
>
> ```
> this(T)(ref return scope T original)
> if(is(T == RVector!(Type)))
> {
>  //... code ...
> }
> ```

I've just tested. That is used only for explicit constructor syntax:

auto b = RVector!int(a);// templatized

>
>
> But this now works:
>
>
> ```
> this(ref return scope RVector!(Type) original)
> {
>  //... code ...
> }
> ```

That one works for both syntaxes:

auto b = RVector!int(a);// templatized
auto c = a; // non-templatized

Certainly confusing and potentially a bug... :/

> No idea why. `Type` is a template parameter of the object.

Minor convenience: You can replace all RVector!(Type) with just RVector 
in the implementation of RVector because the name of the struct template 
*is* that specific instantiation of it:


struct RVector(Type) {
// RVector below means RVector!Type:
this(ref return scope RVector original)
{
// ...
}
}

Ali




Re: Stop writeln from calling object destructor

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

On 10/2/22 10:28, data pulverizer wrote:
> On Sunday, 2 October 2022 at 17:19:55 UTC, data pulverizer wrote:
>> Any reason why this could be?
>

What I noticed first in your original code was that it would be 
considered buggy because it was not considering copying. Every struct 
that does something in its destructor should either have post-blit (or 
copy constructor) defined or simpler, disallow copying altogether.


That's what I did here:

  https://github.com/acehreli/alid/blob/main/cached/alid/cached.d#L178

@disable this(this);

I think disabling copy constructor was unnecessary but I did that as well:

@disable this(ref const(typeof(this)));

The issue remains and bothers me as well. I think writeln copies objects 
because D disallows references to rvalue. We couldn't print rvalues if 
writeln insisted on 'ref'. Or, rvalues would be copied anyway if we used 
'auto ref'. Hence the status quo...


> Sorry I'll need to implement all the overloaded copy constructors and
> see if that fixes it.

The best solution I know is to disable copying and printing not the 
object but an explicit string representation of it:


Added:

@disable this(this);

Added (there are better ways of doing the same e.g. using a 'sink' 
parameter):


string toString() const {
import std.format : format;
return format!"id: %s"(id);
}

Called toString:

writeln("MyObject: ", obj.toString);

Ali




Re: Linker Error with Template Function

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

On 10/1/22 11:15, Kyle Ingraham wrote:

> storing structs as
> `void*` in a wrapper struct with information about their module and
> identifier saved elsewhere.

Perhaps unrelated but that part reminded me of the following discussion:

  https://forum.dlang.org/post/tfbn10$19nv$1...@digitalmars.com

Ali




Re: How can I get the "owner" of a method?

2022-09-30 Thread Ali Çehreli via Digitalmars-d-learn

On 9/30/22 14:11, solidstate1991 wrote:

> extern (C) public int registerDDelegate(alias Func,

That can be a lambda that takes ClassType. I wrote the following along 
with place holder as I assumed them to be:


class C {
string s;

void foo() {
import std.stdio : writeln;
writeln("Look ma: It was ", s, " but I am using it in D!");
}
}

auto luaGetFromIndex(C)() {
auto c = new C();
c.s = "created in Lua";
return c;
}

extern (C)
int registerDDelegate(alias Func)() {
import std.traits : Parameters;
alias ClassType = Parameters!Func[0];
auto c = luaGetFromIndex!ClassType();

Func(c);
return 0;
}

void main() {
// Here: The lambda takes a C:
registerDDelegate!((C c) => c.foo);
}

Ali




Re: Interfacing with basic C++ class

2022-09-29 Thread Ali Çehreli via Digitalmars-d-learn

On 9/29/22 01:28, Riccardo M wrote:

> if one should
> slightly rearrange C++ code as well.

Right. Additionally, the order of members must match (I am pretty sure, 
which means I am not :p).


> I am a recent addition to D
> language :)

Welcome! :)

> Do you know that this is documented somewhere? The examples in the
> official docs are rather limited

Manu Evans said at DConf 2022 that the documentation is very lacking 
compared to actual capability. People who know should update the docs.


Ali




<    1   2   3   4   5   6   7   8   9   10   >