Re: alias and __VERSION__ condition doesn't play well
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
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
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
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
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
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
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
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
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
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
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
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
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
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;