Re: Non-ugly ways to implement a 'static' class or namespace?

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

On 1/29/23 22:09, RTM wrote:
> On Saturday, 28 January 2023 at 23:19:35 UTC, ProtectAndHide wrote:
>
>> That is, you can do OOP without classes
>
> How so?

OOP is about putting objects (data) and behavior (functions) together.

> Every OOP definition includes classes

OOP is possible in C, which does not have classes:

  void sing(Animal * animal);

That top-level sing function will do something like this:

  animal->sing(animal);

Every object has their own sing function pointer as a member. (Or one 
can go to a vtbl pointer approach with different pros and cons; I used 
all of this as an interview topic at some point.)


Programming languages just make it easy.

> (encapsulation + inheritance).

Encapsulation is available even in C as well. Inheritance can be 
achieved manually.


And I used C just because it does not provide any special OOP features.

Ali



Re: How to get the body of a function/asm statement in hexadecimal

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

On 1/29/23 14:19, max haughton wrote:

> it is not trivial to find where the *end* of a
> function is

I suspected as much and did run ...

> objdump

... to fool myself into thinking that 0xc3 was . Well, arguments 
e.g. pointer values can have 0xc3 bytes in them. So, yes, I am fooled! :)


Ali



Re: How to get the body of a function/asm statement in hexadecimal

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

On 1/29/23 13:45, Ruby the Roobster wrote:

> Of course, function pointers cannot be dereferenced.

Since you want to see the bytes, just cast it to ubyte*. The following 
function dumps its own bytes:


import std;

void main() {
enum end = 0xc3;
for (auto p = cast(ubyte*)&_Dmain; true; ++p) {
writefln!" %02x"(*p);
if (*p == end) {
break;
}
}
}

(It can be written more elegantly as a range expression.)

> Furthermore, I would like to be able to do the same for an `asm` 
statement.


I don't know how to get the address of asm blocks.

Ali



Re: std.logger issue

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

On 1/26/23 12:08, Krzysztof Jajeśnica wrote:
> On Thursday, 26 January 2023 at 17:17:28 UTC, o3o wrote:
>> how can I enable `trace` level?
>
> Set `sharedLog.logLevel` instead of `globalLogLevel`.

Good catch. I had tried the following without success:

   stdThreadLocalLog.logLevel = LogLevel.all;

> // Note: the cast is needed because sharedLog is shared
> (cast()sharedLog).logLevel = LogLevel.all;

I did not think casting that way would be the right thing to do.

Although I've never used std.logger, and without remembering who 
implemented it (sincere aplogies), given how simple the use cases of 
logging are, I found its implementation very complicated. For example, 
the following function is one I stumbled upon while debugging the OP's 
issue:


bool isLoggingEnabled()(LogLevel ll, LogLevel loggerLL,
LogLevel globalLL, lazy bool condition = true) @safe
{
return ll >= globalLL
&& ll >= loggerLL
&& ll != LogLevel.off
&& globalLL != LogLevel.off
&& loggerLL != LogLevel.off
&& condition;
}

I don't think it is possible to entagle usage issues with functions with 
that semantic complexity.


Ali



Re: Non-ugly ways to implement a 'static' class or namespace?

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

On 1/22/23 16:21, thebluepandabear wrote:

> Again, stuffing it into a module is not the same thing as a namespace.

That is correct but it is also one answer of D's to namespaces. There 
are others. For example, structs and classes provide namespacing as well.


> The user can just bypass this by writing `drawLine`, there's nothing in
> the language currently that would 'force' the user to write in a
> namespace-like/static-class-like fashion, and that's the biggest problem.

I agree with Adam here. The language should provide solutions and the 
programmer should pick appropriate ones.


Later you added that you were talking about library design. There is no 
problem in the library providing an awesome and very usable API but the 
programmers still picking some other method that works better for them.[1]


I would like to add to your C++ examples:

  Keyboard::Key.A// Fine
  Key.A  // Fine
  foo// Fine

That last line can exactly be the same as the previous two in C++.

OOP is always a solution where it makes sense. I've been very happy with 
writing free-standing functions and dumb data types that the functions 
operate on... until... some invariant matters. Then I make the function 
a member, etc.


Perhaps because I don't buy into the "everything is a class" anymore, I 
am very happy with D's approach. Mostly structs and functions for me. 
But I use classes as well when they make sense.


Having said all that, I realize that your asking specifically for static 
classes made me think of a solution around classes. However, doesn't D 
has the equivalent in structs? Isn't the following what you are looking for?


struct Algo {
static void drawLine(Canvas c, Pos from, Pos to) { .. };
}

Now the user is forced to use it like this:

  Algo.drawLine(new Canvas(), new Pos(5, 3), new Pos(7, 9));

or this:

  Algo().drawLine(/* ... */);

but that can be @disabled.

Ali

[1] It is interesting that limiting the programmer in some way seems to 
help with language marketing. And D is deficient in that marketing move 
because it does the opposite: Gives the programmer choices. I tried to 
show this point on this slide: https://youtu.be/0JL9uT_XGZE?t=701 The 
point "not taking anything away from the programmer" can be seen as a 
marketing issue.




Re: Function which returns a sorted array without duplicates

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

On 1/21/23 23:33, evilrat wrote:

> And IIRC you probably don't need `dup`

Unfortunately, no. Skipping .dup is only possible if we are allowed to 
sort the original array.


> as sort produces a lazy range.

sort() returns a SortedRange but it can't be lazy. Even if it were, the 
first call to .front would have to sort anyway. However...


There is an optimization possible for such requirements if not all 
elements but just a number of them are needed. For example, if only the 
first 10 elements are needed, then a binary heap may be faster:


  https://dlang.org/phobos/std_container_binaryheap.html

The usage would be similar to the following for "the first 10 unique 
elements":


  heapify(arr).uniq.take(10)

(Not tested.)

Ali



Re: Non-ugly ways to implement a 'static' class or namespace?

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

On 1/20/23 07:01, torhu wrote:

> But why not have drawLine just be a free function?

Exactly.

If I'm not mistaken, and please teach me if I am wrong, they are 
practically free functions in Java as well. That Java class is working 
as a namespace. So, the function above is the same as the following 
free-standing function in D, C++, C, and many other languages:


  void Algo_drawLine(Canvas c, Pos from, Pos to) { .. };

Ali



Re: What is the 'Result' type even for?

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

On 1/19/23 19:11, Ruby The Roobster wrote:

>  typeof(c).stringof.writeln;

> The program prints:
>
> ["a", "b", "c", "d", "e"]
> Result
>
> What is the purpose of this 'Result' type?

Just to make sure, 'Result' is what the programmer of a Phobos algorithm 
chose to name a struct type. It could be anything.


I will try to demonstrate it by naming my struct 'MyResult' below. The 
following range algorithm alternates between the two values it is called 
with.


The pragma(msg) inside 'main' prints MyResult.

auto alternate(T)(T a, T b) {
// This function will return an object
// of the following nested struct.
// (Note: This is for demonsration
// purposes only. Yes, this can be
// be more optimal.)
struct MyResult {
bool useB = false;

enum empty = false; // Infinite

T front() {
return useB ? b : a;
}

void popFront() {
// Flip the selector
useB = !useB;
}
}

// Here, an object of the struct is
// returned. It has single member (useB)
// that it uses as a selector.
// The values 'a' and 'b' are the actual
// function arguments.
return MyResult();
}

import std;

void main() {
auto myRange = alternate(42, 7);

// This prints 'MyResult' at compile time
pragma(msg, typeof(myRange));

const expected = [ 42, 7, 42, 7, 42 ];
assert(myRange.take(5).equal(expected));
}

> even when the type
> has the same inherent function:

Different instantiations of templates are distinct types. For example, 
if I called 'alternate' with two 'long' values, both alternate!int (as 
instantiated by the code above) and alternate!long would have different 
MyResult struct types.


Although they would have the same functionality, they would be compiled 
potentially with very different CPU instructions and would not be 
assignable.


Ali



Re: Problem with ImportC example?

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

On 1/18/23 08:04, DLearner wrote:

> Unfortunately, neither works:
> ```
> C:\Users\SoftDev>cl.exe
> 'cl.exe' is not recognized as an internal or external command,
> operable program or batch file.

That supports the theory that you don't have a C compiler installed that 
dmd can use for preprocessing C files.


Ali



Re: Problem with ImportC example?

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

On 1/17/23 12:02, DLearner wrote:

 C:\Users\SoftDev\Documents\BDM\D\ImportC>dmd ex01.c
 failed launching cl.exe /P /Zc:preprocessor [...]

I don't use Windows for development but that error message makes me 
think cl.exe is not found to be executed.


dmd relies on system compiler programs for its ImportC feature. cl.exe 
seems to be the compiler. I think it is the compiler.


Can you run that program from the command line?

Internet makes me think Visual Studio does not install it by default. 
(?) You may have to select C++ (or C?) when installing. (?)


> FWIW, now tried a few standard D programs, work fine.
> Suggesting VS is not the problem?

Standard D programs don't need a C compiler; dmd is the D compiler. It 
needs a C compiler (to preprocess C sources) for ImportC.


Ali



Re: Mixin helper help

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

On 1/13/23 18:51, bauss wrote:


That's a good one!


It looks like you liked it four years ago as well. :) I found where I 
remembered it from:


  https://forum.dlang.org/post/pvdoq2$1e7t$3...@digitalmars.com

Ali



Re: Mixin helper help

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

On 1/13/23 00:48, bauss wrote:

> 1. Change your mixin template to something like this:

There was a technique as a workaround for this template mixin limitation 
but I can't find it right now.


> 2. Change the place where you instantiate to this:

I think the workaround I am trying to remember would not require any 
change for the users.


Ok, it was something like this:

mixin template myStatement() {
auto doIt() {
import std.stdio : writeln;
writeln("hi");
return 0;
}

auto ignoreThis = doIt();
}

void main() {
mixin myStatement!();
mixin myStatement!();
}

Ali



Re: Creating a pointer/slice to a specific-size buffer? (Handing out a page/frame from a memory manager)

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

On 1/13/23 07:22, Gavin Ray wrote:
> Maybe it would be better to wrap the slice in a new class with an
> invariant?

Possibly but please check before using because I think 'invariant' 
requires presence of member functions:


  https://dlang.org/spec/struct.html#Invariant

> Because what I want to do is:
>
> 1. Ensure that the length of the underlying referenced/pointed-to data
> is `PAGE_SIZE`

My first thought was why not use a slice anyway?

Worth noting that static arrays are value types. Also, they all have 
different types from each other and have the potential to cause template 
bloat.


> class BufferPool

Off-topic, most D programmers use struct unless they need class.

>  Frame[BUF_POOL_NUM_PAGES] frames;

Makes sense to me.

Ali



Re: Creating a pointer/slice to a specific-size buffer? (Handing out a page/frame from a memory manager)

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

On 1/13/23 07:07, Gavin Ray wrote:

> This is "valid" D I hope?

Yes because static arrays are just elements side-by-side in memory. You 
can cast any piece of memory to a static array provided the length and 
alignment are correct.


However, such a cast is not allowed in @safe code.

Ali



Re: Creating a pointer/slice to a specific-size buffer? (Handing out a page/frame from a memory manager)

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

On 1/13/23 06:49, Gavin Ray wrote:

> I am curious if you can return something like `ubyte[PAGE_SIZE]*` or
> `ref ubyte[PAGE_SIZE]`?

A simple cast seems to work:

enum PAGE_SIZE = 4096;
enum BUF_POOL_NUM_PAGES = 1024;
alias frame_idx_t = size_t;

ubyte[10_000] data;

ubyte[PAGE_SIZE]* get_page(frame_idx_t frame_idx)
{
auto ptr = data.ptr + frame_idx * PAGE_SIZE;
return cast(ubyte[PAGE_SIZE]*)ptr;
}

void main() {
}

Ali



Re: enum functions

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

 TLDR 

Eponymous templates that define a function pointer does not transfer the 
function call parameter to the enclosing template for type deduction. 
(Note: The term "deduction" is used with template parameters, not 
"inference".)


Also note that I am replacing 'enum' with 'auto' below to show this is 
not related to 'enum' vs 'auto'.


template foo (T) {
auto foo = (T i) => i >> 1;
}

void main() {
foo(42); // <-- Compilation ERROR
}

Error: none of the overloads of template `deneme.foo` are callable using 
argument types `!()(int)`

   Candidate is: `foo(T)`

I am not sure whether this limitation is a bug.

 TLDR 

On 1/11/23 10:01, Salih Dincer wrote:

> void main()
> {
>  enum foo : char { a = 'H', b = 'i' }

That defines two values: foo.a is 'H' and foo.b is 'i'.

>  enum bar() { return new foo; }

That is a function that returns a dynamically allocated foo value. Since 
'new' makes pointers for value types like int and enum, I think the 
return type of 'bar' is foo*.


And that pointer is pointing at a foo.init, which happens to be the 
first value defined: 'H'.


>
>  import std.stdio;
>  foreach(char f; [bar.a, bar.b])

'bar' is a function call that returned a pointer. Hm. Finally I see what 
you are talking about.


Normally, one might have written (*bar) to get the value. Let's try by 
using the following array:


  [(*bar), (*bar)]

Ok, it's what I expect:

HH

Now the interesting part is what does (*bar).a and (*bar).b mean? Let's try:

  [(*bar).a, (*bar).b]

Ok, it gives

Hi

The interesting thing is, foo.a does not print 'H' but 'a':

writeln(foo.a);
writeln(foo.b);

a
b

Ah! Finally I see your explicit 'char' in the foreach loop. That is what 
makes your code print 'H' and 'i'. :)


>  f.write;
>
>  writeln; // Hi
> }

I've just learned something: You can reach different enum values 
directly from an value itself:


import std;

void main()
{
// A type:
enum foo : char { a = 'H', b = 'i' }

// A variable:
enum x = foo.a;

// Really?
writeln(x.b);
}

Ok, it kind of makes sense but I would have written the following e.g. 
in template code. (?)


writeln(typeof(x).b);

> I think this use of enums should be prohibited. So, can I get an answer
> about not being able to make a type inference? So I'm very curious about
> the second part of the my post.

Before looking at your example, here is what I tested. The code proves 
that type inference is the same for 'auto' and 'enum' functions:


auto foo(T)(T t) {
return t;
}

enum bar(T)(T t) {
return t;
}

struct S {}

import std.meta;

void main() {
alias functions = AliasSeq!(foo, bar);
alias types = AliasSeq!(int, double, S, string, const(float));

static foreach (type; types) {
pragma(msg, "Testing ", type);
static foreach (func; functions) {
static assert (is (typeof(func(type.init)) == type));
}
}
}

It uses two function templates and a few types and as expected, the 
return types of the functions are the same.


Ok, back to your code:

> template foo (T) {
> enum foo = (T i) => i >> 1;
> }

That local 'foo' is a literal value of an anonymous function. (The local 
'foo' is not a template.) Reminding myself: Literals are rvalues and 
they are not variables. For example, they don't have addresses.


> template bar (T) {
> auto bar (T i) => i >> 1;
> }

That's different: There was an equals sign after 'foo' but not here. So 
your example is different from e.g. the following two definitions:


auto x() {}
enum y() {}

If you are curious about this case, as Adam said, there is no difference 
between 'auto' and 'enum'.
But again, your code has that extra '=' character for 'foo' and that 
makes a difference.


Getting back to 'bar', so that local 'bar' is a function definition. 
Now, calling bar from the outside as bar(42) is the same as writing 
bar!int.bar(42). (This is the eponymous template convenience.)


> import std;

> void main()
> {
> assert(oneHalf(42) == 21);
> 42.foo!int.writeln; // no inference: "21"

Your "no inference" comment was confusing me. Now I see that you meant 
that you can't write the following:


  42.foo.writeln; // <-- Compilation ERROR

Although you can write the following:

> 42.bar.writeln; // "21"
> }

Ok, let's look at the problem with the understanding of 'foo' being a 
literal. Yes, I can demonstrate the issue that mix it with the concept 
of type inference:


import std;

void main() {
enum foo = {   // Note '='
writeln("foo");
};

auto bar() {
writeln("bar");
}

foo;  // <-- Compilation ERROR
bar;
}

foo line has a compilation error:

Error: `__lambda1` has no effect

Because it's a function pointer, one needs to call it with parenthesis:

foo();
bar;

Now it works.

The reason why 'bar' does not need the parenthesis is because functions 
have that 

Re: Coding Challenges - Dlang or Generic

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

On 1/9/23 16:17, Paul wrote:

> coding challenges

Perhaps the following two?

  https://rosettacode.org/

  https://adventofcode.com/

Ali



Re: Bug or feature? iota has different semantics for integer and float arguments

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

On 1/6/23 17:50, Arredondo wrote:

> Would anyone volunteer to file a bug report?

Me! Me! :)

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

Ali



Re: Bug or feature? iota has different semantics for integer and float arguments

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

On 1/6/23 15:23, Arredondo wrote:

> then you get an exception (incorrect startup parameters).

Although that difference is a bug, iota does have a special floating 
point implementation to prevent the accumulation of floating point 
errors. I mention it as item 4 here:


  https://www.youtube.com/watch?v=gwUcngTmKhg=634s

Briefly, iota's regular popFront() is a trivial

  front += step

but it is

  ++n

for floating types so that front can be

  begin + (n * step)

for them.

The iota discussion starts at an earlier point in the video here:

  https://www.youtube.com/watch?v=gwUcngTmKhg=558s

Ali



Re: Address of a class object

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

On 1/4/23 20:04, Paul wrote:
>> (Again, there is no problem here; we are just learning.)
>> Ali
>
> Do I have this much right?

> ..with this output?

Looks good to me.

While we're here, you can force the class objects to be on the stack as 
well:


scope MyClassVar1 = new MyClass();

I replaced 'auto' with 'scope'.

Ali



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



  1   2   3   4   5   6   7   8   9   10   >