Re: std.logger issue

2023-01-26 Thread Krzysztof Jajeśnica via Digitalmars-d-learn

On Thursday, 26 January 2023 at 17:17:28 UTC, o3o wrote:

how can I enable `trace` level?


Set `sharedLog.logLevel` instead of `globalLogLevel`.

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

Explanation: logging functions (`trace`, `log`, etc.) called 
without a logger perform the logging using a global logger called 
`sharedLog`. `sharedLog` uses `LogLevel.info` by default, which 
is why your trace messages were not showing.


Re: what wrong with this alias

2023-01-08 Thread Krzysztof Jajeśnica via Digitalmars-d-learn

On Sunday, 8 January 2023 at 05:42:46 UTC, Qusatlegadus wrote:

auto s = 1234.to!string.map!q{a - '0'}.sum;
works fine.


but if i do an alias

alias comb = to!string.map!q{a - '0'}

Error: unknown, please file report on issues.dlang.org

What's wrong with this


## Simple explanation

`to!string` is a function expecting 1 argument, which you're not 
providing in your alias. Convert your alias to a lambda 
expression:


```D
alias comb = x => x.to!string.map!q{a - '0'}
```

## Complicated explanation

`to` is a template defined like this:

```D
// https://github.com/dlang/phobos/blob/master/std/conv.d
template to(T)
{
T to(A...)(A args)
if (A.length > 0)
{
return toImpl!T(args);
}
// some overloads omitted for brevity
}
```

`to` needs at least 2 template arguments - the first one for the 
outer template is passed explicitly (what you did with 
`to!string`), the other ones are inferred from the arguments 
passed to the `to` function. Since you did not pass an argument 
to `to!string`, the inner template doesn't get instantiated.


Basically what happens is you're trying to pass an uninstantiated 
template as argument to `map`. This is quite an exotic situation, 
so probably there isn't a dedicated error message for it or 
you're hitting a bug in the compiler (hence the unknown error 
message).


Re: DConf '22: No-Allocated 0-terminated path strings

2022-10-21 Thread Krzysztof Jajeśnica via Digitalmars-d-learn

On Friday, 21 October 2022 at 14:34:47 UTC, ag0aep6g wrote:
Nitpick: You cannot iterate a true input range twice. You need 
a forward range for that.


Nitpick²: you don't actually need to iterate the range twice

```d
//version=AllowMalloc;
auto toCStringThen(alias dg, Range)(Range src) /*nothrow*/ if 
(isInputRange!Range && !isInfinite!Range) {


char[10] small = void;
size_t i = 0;

while(!src.empty && i < small.length) {
small[i++] = src.front;
src.popFront;
}

if(i == small.length) {
version(AllowMalloc) {
import std.container.array;
Array!char large = small[];
large ~= src;
large ~= '\0';
return dg(large.data);
} else {
throw new Exception(
"C string buffer overflow (%s >= %s)"
.format(i+src.walkLength, small.length-1)
);
}
} else {
small[i] = '\0';
return dg(small[0..i]);
}
}
```
Unfortunately this version does multiple allocations if contents 
of the range do not fit into the small buffer, but you could 
avoid that by detecting if `src` is a forward range/defines 
`.length` and doing `large.reserve` or something similar.


Re: Does D actually support flexible array members?

2022-08-18 Thread Krzysztof Jajeśnica via Digitalmars-d-learn
No, D does not support flexible array members or dynamically 
sized structs.


`char[]` is a D slice, which is NOT equivalent to a C array.
A slice is basically a pointer+length pair:
```d
// you can't actually name a struct `char[]`, it's just for 
explanation purposes

struct char[] {
char* ptr; //pointer to first element
size_t length;
}
```

Also the allocation code probably only worked by accident and 
will likely cause memory corruption:

```d
void* result = cast(void*)( + ar.currInd);
```
`` doesn't give you a pointer to the first 
slice element - it gives you a pointer to the slice itself (the 
`char[]` "struct"). To get a pointer to the first element you can 
use `ar.currChunk.memory.ptr`, although since the end goal is to 
get a pointer to the `ar.currInd` element it's preferable to 
replace the entire line with this:

```d
void* result = [ar.currInd];
```
(this way you get bounds checking on slice indexing so you can't 
get a pointer past the last element of the slice).


Also `void[]` is a more appropriate type for a raw memory array 
than `char[]` (`char[]` in D is used almost exclusively as 
"mutable string", and depending on the implementation the garbage 
collector may not scan `char[]` elements for pointers).


Re: Execute the Shell command and continue executing the algorithm

2022-05-30 Thread Krzysztof Jajeśnica via Digitalmars-d-learn

On Monday, 30 May 2022 at 11:18:42 UTC, Alexander Zhirov wrote:
I want to run a command in the background during the execution 
of the algorithm, and without waiting for its actual execution, 
because it is "infinite", while continuing the execution of the 
algorithm and then, knowing the ID of the previously launched 
command, kill the process. So far I have done so:


```d
// Here a long program is launched, as an example `sleep`
executeShell("(sleep 1 && echo \"SLEEP\" >> log) &");

while (!interrupted)
{
// some algorithm is executed here, for example `echo`
executeShell("(echo \"OK\" >> log) &");
if (here is my condition termination of the program)
{
// Here is the termination of the running program
}
Thread.sleep(1.seconds);
}
```

How to organize such an algorithm correctly?


You could use 
[`spawnShell`](https://dlang.org/phobos/std_process.html#spawnShell) instead of `executeShell` to spawn the long-running process. `spawnShell` will return the PID of the spawned process, which you can later use to kill it with the `kill` function.

```d
import core.stdc.signal : SIGINT;
import std.process;

/* note: with spawnShell you don't need & at the end of command,
   because spawnShell doesn't wait for spawned process to 
complete */


Pid pid = spawnShell("(sleep 1 && echo \"SLEEP\" >> log)");

while (!interrupted)
{
// some algorithm is executed here, for example `echo`
executeShell("(echo \"OK\" >> log) &");
if (here is my condition termination of the program)
{
/* Kill the previously spawned process using SIGINT 
signal */

kill(pid, SIGINT);
/* Wait for the killed process to shutdown */
wait(pid);
}
Thread.sleep(1.seconds);
}
```