Re: alias and __VERSION__ condition doesn't play well

2022-01-17 Thread vit via Digitalmars-d-learn

On Tuesday, 18 January 2022 at 04:42:45 UTC, frame wrote:

At the very top of my module I have this declaration:

```d
static if (__VERSION__ >= 2098)
{
alias Foo = TypeA;
}
else
{
alias Foo = TypeB;
}
```

No problem inside the module itself but this doesn't work when 
imported from another module:

Error: undefined identifier `Foo`

While this workaround works:

```d
template getAlias()
{
static if (__VERSION__ >= 2098)
{
alias getAlias = TypeA;
}
else
{
alias getAlias = TypeB;
}
}
alias Foo = getAlias!();
```

Is there a reason for that?


static ifs and mixins need semantic analysis to expand, but when 
you import module, the semantic analysis doesn't run yet (depends 
on order).


Beter workaround is:
```d
import std.traits : Select;

alias Foo  = Select!(__VERSION__ >= 2098, TypeA, TypeB);
```


Re: Linker error under Ubuntu

2022-01-17 Thread murphybeck via Digitalmars-d-learn
Most of the time these are dependency-issues. You need to install 
a package called python-dev. This package includes header files, 
a static library and development tools for building Python 
modules, extending the Python interpreter or embedding Python in 
applications. When encountering this error please note before the 
error it may say you are missing a package or header file — you 
should find those and install them and verify if it works


For Python 2.x use:

$ sudo apt-get install python-dev

If you using 
[python](http://net-informations.com/python/iq/default.htm)3, try 
to replace python-dev with python3-dev


For a specific version of Python 3, replace x with the minor 
version in


$ sudo apt-get install python3.x-dev




alias and __VERSION__ condition doesn't play well

2022-01-17 Thread frame via Digitalmars-d-learn

At the very top of my module I have this declaration:

```d
static if (__VERSION__ >= 2098)
{
alias Foo = TypeA;
}
else
{
alias Foo = TypeB;
}
```

No problem inside the module itself but this doesn't work when 
imported from another module:

Error: undefined identifier `Foo`

While this workaround works:

```d
template getAlias()
{
static if (__VERSION__ >= 2098)
{
alias getAlias = TypeA;
}
else
{
alias getAlias = TypeB;
}
}
alias Foo = getAlias!();
```

Is there a reason for that?


Re: Improve a simple event handler

2022-01-17 Thread Salih Dincer via Digitalmars-d-learn

On Saturday, 15 January 2022 at 23:15:16 UTC, JN wrote:

I am writing a simple event handler object for observer pattern.

https://gist.github.com/run-dlang/d58d084752a1f65148b33c796535a4e2

(note: the final implementation will use an array of listeners,


Did you especially make an effort not to use money DI (Dependency 
injection)? Your codes will be more delicious if you implement 
DI. You can find its simple implementation 
[here.](https://forum.dlang.org/post/roqnezzxcuorscnma...@forum.dlang.org)


If you get the ConnectionSetup working, you can setup without 
knowing the service parameters.


Salih


Re: number ranges

2022-01-17 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, Jan 17, 2022 at 10:35:30PM +, forkit via Digitalmars-d-learn wrote:
> On Monday, 17 January 2022 at 22:28:10 UTC, H. S. Teoh wrote:
> > 
> > If I ever needed to foreach over 1-based indices, I'd write it this
> > way in order to avoid all confusion:
> > 
> > foreach (i; 1 .. 5 + 1)
> > {
> > }
> > 
> > This will immediately make whoever reads the code (i.e., myself
> > after 2 months :D) wonder, "why +1?" And the answer will become
> > clear and enlightenment ensues. ;-)
[...]
> If I were able to write a compiler, my compiler would warn you:
> 
> "This is ill-advised and you should know better! Please rewrite this."

:-D  If *I* were to write a compiler, it'd come with a GC built-in. It'd
throw up 90% of programs you feed it with the error "this program is
garbage, please throw it away and write something better". :-D


T

-- 
If blunt statements had a point, they wouldn't be blunt...


Re: number ranges

2022-01-17 Thread forkit via Digitalmars-d-learn

On Monday, 17 January 2022 at 22:28:10 UTC, H. S. Teoh wrote:


If I ever needed to foreach over 1-based indices, I'd write it 
this way in order to avoid all confusion:


foreach (i; 1 .. 5 + 1)
{
}

This will immediately make whoever reads the code (i.e., myself 
after 2 months :D) wonder, "why +1?" And the answer will become 
clear and enlightenment ensues. ;-)



T


If I were able to write a compiler, my compiler would warn you:

"This is ill-advised and you should know better! Please rewrite 
this."




Re: number ranges

2022-01-17 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, Jan 17, 2022 at 10:22:19PM +, forkit via Digitalmars-d-learn wrote:
[...]
> I think it's fair to say, that I'm familiar with 0-based indexing ;-)
> 
> my concern was with the 1..5 itself.
> 
> In terms of what makes sense, it actually makes more sense not to use
> it, at all ;-)

If I ever needed to foreach over 1-based indices, I'd write it this way
in order to avoid all confusion:

foreach (i; 1 .. 5 + 1)
{
}

This will immediately make whoever reads the code (i.e., myself after 2
months :D) wonder, "why +1?" And the answer will become clear and
enlightenment ensues. ;-)


T

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


Re: number ranges

2022-01-17 Thread forkit via Digitalmars-d-learn

On Monday, 17 January 2022 at 22:06:47 UTC, H. S. Teoh wrote:


Basically,

foreach (i; a .. b)

is equivalent to:

for (auto i = a; i < b; i++)

Just think of that way and it will make sense.



I think it's fair to say, that I'm familiar with 0-based indexing 
;-)


my concern was with the 1..5 itself.

In terms of what makes sense, it actually makes more sense not to 
use it, at all ;-)




Re: number ranges

2022-01-17 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, Jan 17, 2022 at 09:37:31PM +, forkit via Digitalmars-d-learn wrote:
> On Monday, 17 January 2022 at 11:58:18 UTC, Paul Backus wrote:
> > 
> > This kind of half-open interval, which includes the lower bound but
> > excludes the upper bound, is used in programming because it lets you
> > write
> > 
> > foreach (i; 0 .. array.length) writef("%s ", array[i]);
> > 
> > ...without going past the end of the array.
> 
> Yes. But the intent here is clearly stated and cannot be misunderstood
> -> array.length
> 
> Whereas 1..5 is just an opportunity to shoot yourself in the foot.

The compiler cannot discern intent. Both `5` and `array.length` are
expressions, as far as the compiler is concerned. So is `5 +
(array.length - sin(x))/2*exp(array2.length)`, for that matter.  The
compiler does not understand what the programmer may have intended; it
simply follows what the spec says.

Of course, to a *human* the semantics of `1..5` can be totally confusing
if you're not used to it.  The bottom-line is, in D (and in other C-like
languages) you just have to get used to 0-based indexing, because
ultimately it actually makes more sense than the 1-based counting scheme
we were taught in school. 1-based counting schemes are full of
exceptions and off-by-1 errors; it's needlessly complex and hard for the
mortal brain to keep track of all the places where you have to add or
subtract 1.  Whereas in 0-based index schemes, you *always* count from
0, and you always use `<` to check your bounds, and you can do
arithmetic with indices just by adding and subtracting as usual, without
off-by-1 errors.

Basically,

foreach (i; a .. b)

is equivalent to:

for (auto i = a; i < b; i++)

Just think of that way and it will make sense.

And never ever write 1..n unless you actually intend to skip the first
element. Remember: 0-based counting, not 1-based counting. You always
start from 0, and count up to (but not including) n.  Which also means
you should always write `<`, never write `<=`. So your upper bound is
always the element *past* the last one. I.e., it's the index at which a
new element would be added if you were appending to your list. I.e., the
index at which a new element should be added is simply array.length (not
array.length+1 or array.length-1 or any of that error-prone crap that
nobody can remember).

If you adhere to these simple rules, you'll never need to add or
subtract 1 to your counters, loop indices, and lengths (because nobody
can remember when to do that, so not having to do it significantly
reduces the chances of bugs).


T

-- 
People say I'm arrogant, and I'm proud of it.


Re: number ranges

2022-01-17 Thread forkit via Digitalmars-d-learn

On Monday, 17 January 2022 at 11:58:18 UTC, Paul Backus wrote:


This kind of half-open interval, which includes the lower bound 
but excludes the upper bound, is used in programming because it 
lets you write


foreach (i; 0 .. array.length) writef("%s ", array[i]);

...without going past the end of the array.


Yes. But the intent here is clearly stated and cannot be 
misunderstood -> array.length


Whereas 1..5 is just an opportunity to shoot yourself in the foot.

"the heretic must be cast out not because of the probability that 
he is wrong but because of the possibility that he is right." - 
Edsger W. Dijkstra


Re: Improve a simple event handler

2022-01-17 Thread Sebastiaan Koppe via Digitalmars-d-learn

On Sunday, 16 January 2022 at 20:01:09 UTC, JN wrote:

On Saturday, 15 January 2022 at 23:15:16 UTC, JN wrote:


Is there some way I could improve this with some D features? 
My main gripes with it are:




Managed to dramatically simplify it to 10 lines of code with 
variadic templates.


```d
import std.stdio;

struct Event(T...)
{
void function(T)[] listeners;

void addListener(void function(T) handler)
{
listeners ~= handler;
}

void emit(T args)
{
foreach (listener; listeners)
{
listener(args);
}
}
}

void onResize(uint newWidth, uint newHeight)
{
writefln("Resized: %d %d", newWidth, newHeight);
}

void main()
{
Event!(uint, uint) windowResizeEvent;
windowResizeEvent.addListener();

windowResizeEvent.emit(1000, 2000);
}
```

I am very happy with this solution.


Looks good. But do note that with larger applications it 
inevitably becomes a ball of spaghetti, making it hard to 
understand why a certain widget behaves the way it does (or 
doesn't).


The other problem - already apparent in this small example - is 
the absence of `removeListener`. It is a very crucial and often 
overlooked part that often only gets written afterwards. The 
problem is that it ties into lifetime which is hard to bolt on.


For small things though, it works wonderfully.


Re: number ranges

2022-01-17 Thread Salih Dincer via Digitalmars-d-learn

On Monday, 17 January 2022 at 11:58:18 UTC, Paul Backus wrote:

On Monday, 17 January 2022 at 10:24:06 UTC, forkit wrote:
Edsger W. Dijkstra, a well-known academic computer scientist, 
has written in more detail about the advantages of this kind of 
interval: 
https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html


Thank you for this valuable information you have given. There is 
a nice feature used in uniform():

```d
import std;

enum a = 9;
enum b = 10;

void main() {
  auto sonYok = generate!(() => uniform!"[)"(a, b)).take(10);
   sonYok.writeln; // only 9 (default)

  auto ilk_son = generate!(() => uniform!"[]"(a, b)).take(10);
   ilk_son.writeln; // may contain 9 & 10

  auto orta = generate!(() => uniform!"()"(a, b + 1)).take(10);
   orta.writeln; // only 10

  auto ilkYok = generate!(() => uniform!"(]"(a, b + 1)).take(10);
   ilkYok.writeln; // Does not contain 9
}
```
It would be nice if this feature, which we set up with templates, 
could be applied everywhere in D. Because sometimes it is needed.


As for other, I never used this feature until I got used to it. 
Of course, it's practical like this, it will do 10 reps:


```foreach(_;0..11)```

Salih


Re: number ranges

2022-01-17 Thread Paul Backus via Digitalmars-d-learn

On Monday, 17 January 2022 at 10:24:06 UTC, forkit wrote:

so I'm wondering why the code below prints:

1 2 3 4

and not

1 2 3 4 5

as I would expect.

foreach (value; 1..5) writef("%s ", value);


This kind of half-open interval, which includes the lower bound 
but excludes the upper bound, is used in programming because it 
lets you write


foreach (i; 0 .. array.length) writef("%s ", array[i]);

...without going past the end of the array.

Edsger W. Dijkstra, a well-known academic computer scientist, has 
written in more detail about the advantages of this kind of 
interval: 
https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html



also, why is this not possible:

int[] arr = 1..5.array;


The `lower .. upper` syntax only works in foreach loops. If you 
want to create a range of numbers like this in another context, 
you must use the library function std.range.iota:


import std.range: iota;
int[] arr = iota(1, 5).array;

(Why "iota"? Because in APL, the Greek letter iota (ι) is used to 
create a range of numbers like this.)


number ranges

2022-01-17 Thread forkit via Digitalmars-d-learn

so I'm wondering why the code below prints:

1 2 3 4

and not

1 2 3 4 5

as I would expect.

foreach (value; 1..5) writef("%s ", value);

also, why is this not possible:

int[] arr = 1..5.array;