Re: Why is Phobos `Flag` so overthought ?

2024-05-06 Thread Julian Fondren via Digitalmars-d-learn

On Monday, 6 May 2024 at 17:55:49 UTC, user1234 wrote:

I think this just works:

```d
enum Flag : bool
{
no,
yes
}

alias AllowVancancy = Flag; // example usage
```


```d
import std.stdio : writeln;

enum Flag : bool { no, yes }
alias Traditional = Flag;
alias Color = Flag;

void hello(Traditional traditional, Color color) {
if (traditional && color) {
writeln("\x1b[31;1mhello world\x1b[0m");
} else if (traditional && !color) {
writeln("hello world");
} else if (!traditional && color) {
writeln("\x1b[31;1mHello, world!\x1b[0m");
} else {
writeln("Hello, world!");
}
}

void main() {
hello(Color.yes, Traditional.yes); // this is wrong, but 
accepted

}
```


Re: Challenge Tuples

2024-04-27 Thread Julian Fondren via Digitalmars-d-learn

On Friday, 26 April 2024 at 13:25:34 UTC, Salih Dincer wrote:
You have a 5-item data tuples as Tuple(1, 2, 3, [1, 3], 5) and 
implement the sum (total = 15) with the least codes using the 
sum() function of the language you are coding...


Nim:

```nim
import std/[math, typetraits, macros]

macro unrollRange(low, high: static int; name, body: untyped) =
  result = newStmtList()
  for i in low ..< high:
result.add(newBlockStmt(newStmtList(
  newConstStmt(name, newLit i),
  copy body
)))

let t = (1, 2, 3, @[1, 3], 5)
var arr: seq[int]
unrollRange(0, t.tupleLen, i):
  arr.add t[i]
doAssert arr.sum == 15
```

vs. D

1. there's no `each` on tuples
2. there's no static for loop, so a macro is needed for the tuple 
indices

3. `add` is making use of the same overload as D's `~=`


Re: macOS Sonoma Linker Issue

2023-12-21 Thread Julian Fondren via Digitalmars-d-learn

On Thursday, 21 December 2023 at 22:19:07 UTC, Renato wrote:
LDC is slow and makes huge multi-MB binaries (is that normal?). 
DMD seemed much better to me.


But at least LDC works :) so will use that for now.


On my setup ldc generates small binaries and dmd generates huge 
ones. The difference is about dynamically linking Phobos or not. 
Try ldc with --link-defaultlib-shared


Re: Changing behavior of associative array

2023-12-16 Thread Julian Fondren via Digitalmars-d-learn

On Sunday, 17 December 2023 at 00:10:56 UTC, Kevin Bailey wrote:
instead it seems like 'm' is a pointer to a std::map, that is 
initialized on use if null. (I think it's that latter part that 
gives the illusion of being already initialized.)


Yes: 
https://dlang.org/spec/hash-map.html#construction_and_ref_semantic


Re: Changing behavior of associative array

2023-12-16 Thread Julian Fondren via Digitalmars-d-learn

On Saturday, 16 December 2023 at 22:44:16 UTC, Dennis wrote:
That's because `m[f] = 1` initializes the associative array to 
something non-null. If you pass a `null` AA to a function which 
adds things, the caller will still have a null pointers.


I've gotten this error in deployed Perl. Whenever the ceremony of 
creating a data structure is reduced, people can lose sight of 
when that happens.


Here's a less common gotcha:

```d
void main() {
import std.stdio : writeln;

int force_realloc(ref int[] seq) {
foreach (int i; 1 .. 1_000_000) {
seq ~= i;
}
return 1234;
}

int[] a = [4321];
writeln(a[0]);  // 4321, of course
a[0] = force_realloc(a);
writeln(a[0]);  // still 4321
}
```

The `a[0]` on the left of the assignment is decided early, and 
then force_realloc() changes what the location should be.


Re: surviving wasm

2023-12-13 Thread Julian Fondren via Digitalmars-d-learn

On Wednesday, 13 December 2023 at 20:40:20 UTC, monkyyy wrote:
so long term planning on wasm raylib; I want compatibility with 
the good parts of the std, the std is causal about using libc 
while ldc-wasm half-baked implication is missing a bunch of 
basically worthless symbols but given the std is 1 million 
lines of code it will be a perennial problem that I make 
something work natively, I try it in wasm, it breaks citing a 
random core lib at a random line; the options I know about are:


1. use a "team betterc" personal std that doesn't have the apis 
I want, apis I know and probably limited
2. merge "use libc less" upstream to a std that has been slow 
to merge changes and probably doesnt care about wasm

3. fork the std
4. maintain patches to the std that go in and rewrite them live 
with root :D what could go wrong
5. make my own personal std that matches the std api of the 
parts I use


I hate all these options


6. statically build against musl and include it in the wasm 
binary. Since phobos is slow to change, its libc dependencies 
will also be slow to change, and you can work on reducing how 
much musl goes into the binary. Musl's MIT-licensed and D has 
ImportC; maybe this can be upstreamed as a pseudo-libc-less build 
option. People who don't care about wasm may still care about 
dodging glibc due to binary portability hassles with deployment 
to older servers. ldc already uses musl on Alpine Linux, popular 
with containers.


Re: Advent of Code 2023

2023-12-03 Thread Julian Fondren via Digitalmars-d-learn
On Monday, 4 December 2023 at 03:50:47 UTC, Siarhei Siamashka 
wrote:

On Monday, 4 December 2023 at 03:07:07 UTC, matheus wrote:

import std.stdio;
import std.algorithm;
import std.array;
import std.format;
import std.conv;
import std.string;
...


Why do you do multiple imports instead of one import std;?

I means is there any difference in CT?


The code indeed compiles faster with fewer imports and this 
pays off in the long run for the actively developed large 
projects. Additionally, it's a good idea not to pollute the 
namespace with the functions that the developer has no 
intention to use.


```
  dmd -betterC hellobc.d ran
6.18 ± 0.33 times faster than dmd hellosel.d
   19.76 ± 1.06 times faster than dmd hellostd.d
```
26ms, 136ms, 470ms.
16MB, 56MB, 154MB.
-betterC with selected import of core.stdc.stdio
selected import of std.stdio.writeln
import std.

D has the capability to compile extremely quickly. dmd compiles 
itself in a second or two. But it also gives you plenty of 
opportunities to trade that for convenience.


Re: Advent of Code 2023

2023-12-03 Thread Julian Fondren via Digitalmars-d-learn

On Sunday, 3 December 2023 at 23:44:43 UTC, Julian Fondren wrote:

```d
if (str[i..$].startsWith(key)) return value;
```


Corrected. The other doesn't compile, unless you never run it 
with -version=Part2 ...


Re: Advent of Code 2023

2023-12-03 Thread Julian Fondren via Digitalmars-d-learn
On Saturday, 2 December 2023 at 13:33:33 UTC, Johannes 
Miesenhardt wrote:
I am a bloody beginner so if there are any things that are very 
wrong with this please point them out.
The fact that I need a template for accepting both a string and 
a char[] is very weird but I went with it. I am also curious if 
there is a better way for the reversible for-loop to happen. I 
saw foreach and foreach_reverse but I don't think that helps me 
here, since I swap them out based on a runtime argument.


Rather than putting `version = Part2;` in the source, you can 
specify that on the commandline. This doesn't work with rdmd, but 
these work:


```
$ dmd -run day1.d
$ dmd -version=Part2 day1.d
$ ldc2 --d-version=Part2 --run day1.d
$ gdc -fversion=Part2 day1.d && ./a.out
```

Rather than the template you could only accept 
`immutable(char)[]` and use `str.representation.assumeUTF` to get 
that from a string, without any extra allocation. There's a table 
at 
https://d.minimaltype.com/index.cgi/wiki?name=string+type+conversions that might be helpful (although I notice the unicode tests have some bitrot due to increased safety in the language.)


You may still want a template though, to specialize on the 
`reverse` variable. That only changes these lines:


```d
int findNum(bool reverse)(immutable(char)[] str) {
...
auto firstNum = findNum!false(str.representation.assumeUTF);
auto secNum = findNum!true(str.representation.assumeUTF);
```

Bonus from using a dynamic array: it would be much more annoying 
to have `reverse` as a template argument if you were still 
relying on an implicit `T` parameter at the callsite.


And, `unittest {}` is a great feature of d. Instead of editing 
your code to run tests, changing things while working with the 
real input, not realizing that you broke your tests, then getting 
timed out when you submit your answer to AoC, you can doublecheck 
just before submission that `dmd -unittest -run day1.d` still 
passes.


In your loop over numberMap, you could use

```d
if (str[i..$].startsWith(key) == key) return value;
```

Otherwise, I think it's fine good. People might differ on style, 
but it doesn't look bad at all compared to some other 
implementations I've seen. The several ternary operators are the 
only awkward bit. Since you're a beginner you might find it 
interesting to implement a range that yields chars in reverse 
order, and have `findNum` take a range.


Re: D: Convert/parse uint integer to string. (@nogc)

2023-11-28 Thread Julian Fondren via Digitalmars-d-learn

On Tuesday, 28 November 2023 at 08:51:21 UTC, Mark Davies wrote:

I did it this way ...


You always print the full array of bytes this way. Output piped 
to `od -c` is


```
000   1   2   3   4   5 377 377 377 377 377  \n   -   1   2   
3   4

020   5 377 377 377 377  \n
```

Those 377s are `char.init`, 0xFF.

On Tuesday, 28 November 2023 at 09:43:47 UTC, Dom DiSc wrote:
For a 'long' 10 characters is likely to be not enough (long max 
is 9223372036854775808 which has 19 chars, and you should 
reserve additional one for the sign and one for the terminating 
null), so I would at least recommend using char[21].


Signed max is all bits but the sign bit set, so 7FFF..., so 
signed max is always an odd number. d can confirm:


```
$ rdmd --eval 'writeln(long.max)'
9223372036854775807
$ rdmd --eval 'writeln(2+to!string(long.max).length)'
21
```

There's no terminating NUL here, which might be an oversight.

with char[10] your function becomes a big hole in your 
security, as it can easily be misused to write 10 bytes of 
freely selectable garbage behind your allocated memory.


This is D though, so without separately disabling bounds checks, 
there's an error:


```
core.exception.ArrayIndexError@d1.d(22): index [18] is out of 
bounds for array of length 10

```

or with -betterC:

```
d1: d1.d:21: Assertion `array index out of bounds' failed.
Aborted
```

Here's a minimal edit to fix the `char.init` output:

```d
char[] longToString(long n) @nogc
{
static char[21] x;
size_t length;
ulong power;

x[0] = '-'*(n<0);

long t = (n<0)*-n + (n>0)*n ;

while (n != 0)
{
power++;
n /= 10;
}

length = power;
power -= (x[0] != '-');

while (t > 0)
{
x[power] = (t % 10) + '0';
power--;
t /= 10;
}

return x[0 .. length];
}
```

As you can see, slices from this longToString are good until the 
next call to it. The other C-like way to manage memory is to pass 
in the buffer to use, which in D can be a slice of a static array 
on the caller's stack. You'll probably have a much better time 
with manual memory management if you use custom allocators.


Re: D: Declaring empty pointer variables that return address inside function calls?

2023-11-23 Thread Julian Fondren via Digitalmars-d-learn

On Thursday, 23 November 2023 at 20:13:59 UTC, BoQsc wrote:
Nothing wrong. It would be just a more concise compact way to 
do the same.


Also I mostly wanted to know if something like that is already 
possible in D language.


It's not a huge loss if it is not possible.


This is possible in Go: you dereference a literal constructor and 
it's either built on the stack or the heap depending on escape 
analysis. Example:


```go
package main

import "fmt"

type T struct {
data [5]byte
}

func usebuffer(a *T) *T {
a.data[0] = 1
a.data[4] = 10
return a
}

func f() *T {
return usebuffer({}) // <--
}

func main() {
fmt.Println(f())
}
```

which is very close to this D that is explicitly allocating on 
the heap:


```d
class T {
byte[5] data;
}

T usebuffer(T a) {
a.data[0] = 1;
a.data[4] = 10;
return a;
}

T f() {
return usebuffer(new T()); // <--
}

void main() {
import std.stdio : writeln;
writeln(f().data);
}
```

Which if you want stack allocation, is very similar to:

```d
class T {
byte[5] data;
}

T usebuffer(T a) {
a.data[0] = 1;
a.data[4] = 10;
return a;
}

void main() {
import std.stdio : writeln;
import std.typecons : scoped;

writeln(usebuffer(scoped!T).data);
}
```

but, I don't actually know if this is safe.


Re: mixin under -betterC

2023-11-23 Thread Julian Fondren via Digitalmars-d-learn

On Thursday, 23 November 2023 at 17:46:55 UTC, DLearner wrote:
I just find it surprising that your suggestion worked, but the 
(slightly simpler) earlier version did not.


The `enum` answer? That also works, but you have to make a change 
at the callsite as well, to `mixin(mxnTest!("Var_A", "Var_B"));` 
- passing the strings as template rather than functional 
arguments.


Re: mixin under -betterC

2023-11-23 Thread Julian Fondren via Digitalmars-d-learn

On Thursday, 23 November 2023 at 16:33:52 UTC, DLearner wrote:
Why is this so, bearing in mind the concatenations are executed 
at

compile, not run, time?


If you compile without -betterC, it'll work, but if you examine 
the result you'll find that the mxnTest function is still 
compiled into the result. D makes it so convenient to use 
functions at compile-time that there's no clear distinction for 
functions that should only exist at compile-time.


Make mxnTest a template:

```d
string mxnTest()(string strVar1, string strVar2) {
  ^^
```


Re: What parser generator can let me run arbitrary code in its match rules?

2023-11-20 Thread Julian Fondren via Digitalmars-d-learn
On Monday, 20 November 2023 at 23:50:24 UTC, Dmitry Ponyatov 
wrote:

- not abandoned years ago
- documentation and commented samples presenets
- CTFE the best


https://code.dlang.org/packages/pegged


Re: What is :-) ?

2023-11-20 Thread Julian Fondren via Digitalmars-d-learn

On Monday, 20 November 2023 at 16:09:33 UTC, Antonio wrote:

**Why this is a function and not a delegate?**

```auto createCounter = (int nextValue) => (int dummy) => 
nextValue++;```


Syntactically I dont see any difference:


`createCounter` is a function, and not a delegate, as it doesn't 
close over any variables. It returns a delegate as the variable 
`nextValue` is closed over. There's no difference in syntax. The 
difference is however important as an environment must be 
retained for the closed-over variables and passed along with the 
pointer, making delegates both more expensive and incompatible 
with function pointers on the C ABI. Note that `f` and `g` are 
obviously not pointing to the same `nextValue`:


```d
auto createCounter = (int nextValue) => () => nextValue++;

void main() {
import std.stdio : writeln;

auto f = createCounter(5);
auto g = createCounter(0);
writeln(f()); // 5
writeln(g()); // 0
writeln(f()); // 6
writeln(g()); // 1
}
```

What "breaks" my mind is that a compiler decision (treat a 
piece of code as function or delegate) is not completely 
transparent


D is trying to be convenient (by offering delegates at all, and 
by making the syntax so light) while offering fine control (by 
letting you distinguish between function pointers and delegates). 
It'd be a much simpler language if it dropped one of those aims, 
but such languages also already exist.


Similarly D also distinguishes between "numbers" (`int`) and 
"numbers" (`double`) and this can also be transparent and also 
cause 'side effects'. Someone educated in mathematics but not 
familiar with computing might complain about


```d
void main() {
import std.stdio : writefln;
auto n = 1;
writefln!"%d"(n);
}
```

breaking when "all I did was bump n by one-tenth, to 1.1".

I'm not trying to be mean with this example, and I don't think 
it's shameful either to know mathematics but not computing. But D 
expects you to be familiar with such things for you to not be 
surprised by how it behaves.


Re: D: How to check if a function is chained? a().b().c();

2023-11-18 Thread Julian Fondren via Digitalmars-d-learn

On Saturday, 18 November 2023 at 07:47:19 UTC, BoQsc wrote:

`program("someProgramName").pipe("someOtherProgramName");`
Executes and pipes output to another program.

`program();` - Only executes the program.


Serious answer: have a function handle this, instead of the 
semicolon.


`program("p1").pipe("p2").run;` - does that
`program("p1").run;` - does the other

Supposedly this is the "builder pattern" but the wikipedia entry 
seems to be deliberately bad.


Unserious answer, especially unsuitable for your concrete example 
where you probably want subprocesses to run reliably and in 
order: do something with object lifetime functions.


```d
import std.stdio : writeln;

class Program {
string program;
bool used;
this(string p) { program = p; }
~this() { if (!used) writeln("You forgot to chain program: ", 
program); }

}

Program a(string p) {
return new Program(p);
}

void b(Program p) {
p.used = true;
writeln("using program: ", p.program);
}

void main() {
a("2");
a("1").b();
}
```


Re: What are the best available D (not C) File input/output options?

2023-11-02 Thread Julian Fondren via Digitalmars-d-learn

On Thursday, 2 November 2023 at 15:46:23 UTC, confuzzled wrote:
I've ported a small script from C to D. The original C version 
takes roughly 6.5 minutes to parse a 12G file while the port 
originally took about 48 minutes. My naïve attempt to improve 
the situation pushed it over an hour and 15 minutes. However, 
replacing std.stdio:File with core.stdc.stdio:FILE* and 
changing my output code in this latest version from:


outputFile.writefln("%c\t%u\t%u\t%d.%09u\t%c", ...)

to
fprintf(outputFile, "%c,%u,%u,%llu.%09llu,%c\n", ...)

reduced the processing time to roughly 7.5 minutes. Why is 
File.writefln() so appallingly slow? Is there a better D 
alternative?


First, strace your program. The slowest thing about I/O is the 
syscall itself. If the D program does more syscalls, it's going 
to be slower almost no matter what else is going on. Both D and C 
are using libc to buffer I/O to reduce syscalls, but you might be 
defeating that by constantly flushing the buffer.




I tried std.io but write() only outputs ubyte[] while I'm 
trying to output text so I abandoned idea early.


string -> immutable(ubyte)[]: alias with 
std.string.representation(st)


'alias' meaning, this doesn't allocate. If gives you a byte slice 
of the same memory the string is using.


You'd still need to do the formatting, before writing.

Now that I've got the program execution time within an 
acceptable range, I tried replacing core.stdc.fread() with 
std.io.read() but that increased the time to 24 minutes. Now 
I'm starting to think there is something seriously wrong with 
my understanding of how to use D correctly because there's no 
way D's input/output capabilities can suck so bad in comparison 
to C's.





Re: Weird RDMD error when trying to import source file from subfolder.

2023-11-01 Thread Julian Fondren via Digitalmars-d-learn

On Wednesday, 1 November 2023 at 16:24:04 UTC, BoQsc wrote:

**Error:**

```
rdmd testimport.d
testimport.d(2): Error: module `next` from file waffle\next.d 
must be imported with 'import next;'

```


You import 'waffle.next', but the module is inferred to be 
'next'. If put `module waffle.next;` at the top of next.d, this 
works.