Re: How to disable assigning a value to a property?

2021-07-06 Thread Tejas via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 10:06:11 UTC, Jack Applegame wrote:




Here's another way using ``` std.typecons ```

```d
import std.stdio;
import std.typecons;
alias input = Typedef!int; //new code
struct Field {
void opAssign(int a) {
writefln("Field.opAssign(%s)", a);
}
}

struct Register {
Field clock(input a) {
writefln("Register.clock(%s)", cast(int)a); //note the 
cast

return Field();
}
}


void main() {
input ip = 1;
Register register;
register.clock(ip) = 10; // works, good
//register.clock = 10;// works too, how to disable it?
EDIT: Now it doesn't work :)

}
```

You will have to either cast your literal, or provide a variable 
with the new type as input though,  so it is also not perfect.


Re: to compose or hack?

2021-07-06 Thread Jon Degenhardt via Digitalmars-d-learn
On Wednesday, 7 July 2021 at 01:44:20 UTC, Steven Schveighoffer 
wrote:
This is pretty minimal, but does what I want it to do. Is it 
ready for inclusion in Phobos? Not by a longshot! A truly 
generic interleave would properly forward everything else that 
the range supports (like `length`, `save`, etc).


But it got me thinking, how often do people roll their own vs. 
trying to compose using existing Phobos nuggets? I found this 
pretty satisfying, even if I didn't test it to death and maybe 
I use it only in one place. Do you find it difficult to use 
Phobos in a lot of situations to compose your specialized 
ranges?


I try to compose using existing Phobos facilities, but don't 
hesitate to write my own ranges. The reasons are usually along 
the lines you describe.


For one, range creation is easy in D, consistent with the pro/con 
tradeoffs described in the thread/talk [Iterator and Ranges: 
Comparing C++ to D to 
Rust](https://forum.dlang.org/thread/diexjstekiyzgxlic...@forum.dlang.org). Another is that if application/task specific logic is involved, it is often simpler/faster to just incorporate it into the range rather than figure out how to factor it out of the more general range. Especially if the range is not going to be used much.


--Jon



to compose or hack?

2021-07-06 Thread Steven Schveighoffer via Digitalmars-d-learn
So I have this situation where I need to split a string, then where the 
splits are, insert a string to go between the elements making a new 
range, all without allocating (hopefully).


Looking around phobos I found inside the documentation of 
[roundRobin](https://dlang.org/phobos/std_range.html#.roundRobin) 
something that does *exactly* what I'm looking for.


Except... the provided `interleave` function iterates the original range 
twice, which means 2x the searching calls for splitter. Why does it do 
this? Because `roundRobin` will keep going as long as ANY range still 
has data left, so you need to make the "interleaving" range stop when 
the first one stops.


After struggling to think up ways to compose this (hm.., can  I make the 
ranges share a stopping point?) without the 2x penalty, I just decided 
to write my own interleave range which does exactly what I am looking for:


```d
auto interleave(R, U)(R src, U middles) if (isInputRange!R && is(U == 
ElementType!R))

{
static struct Result
{
R src;
U middles;
bool between = false;
auto front() {
assert(!empty);
return between ? middles : src.front;
}
void popFront() {
assert(!empty);
if(between)
between = false;
else
{
src.popFront;
between = true;
}
}
bool empty()
{
return src.empty;
}
}

return Result(src, middles);
}
```

This is pretty minimal, but does what I want it to do. Is it ready for 
inclusion in Phobos? Not by a longshot! A truly generic interleave would 
properly forward everything else that the range supports (like `length`, 
`save`, etc).


But it got me thinking, how often do people roll their own vs. trying to 
compose using existing Phobos nuggets? I found this pretty satisfying, 
even if I didn't test it to death and maybe I use it only in one place. 
Do you find it difficult to use Phobos in a lot of situations to compose 
your specialized ranges?


Oh, and if you do know of a better way to compose the range that doesn't 
require the double iteration, I'd be interested in seeing it.


-Steve


Re: Find a char among string (string.findAmong.char)

2021-07-06 Thread BoQsc via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 15:48:35 UTC, rassoc wrote:

You can also do:

```d
import std;
void main()
{
// https://dlang.org/phobos/std_ascii.html#.lowercase
"Book.".filter!(c => lowercase.canFind(c))
   .each!(c => writeln(c, " found"));

// Output:
// o found
// o found
// k found
}
```


I really don't like reading arrow functions.
It takes some more effort to understand, follow and get used to 
them.
I'd like something simple and effortless looking and feeling that 
would make code readable similarly to an english sentence.


Such as this, but as noted, this does not work as 
intended/assumed by me:

```
if (letter.findAmong(alphabet)){
 write("found");
 }
```


Re: Find a char among string (string.findAmong.char)

2021-07-06 Thread rassoc via Digitalmars-d-learn

You can also do:

```d
import std;
void main()
{
// https://dlang.org/phobos/std_ascii.html#.lowercase
"Book.".filter!(c => lowercase.canFind(c))
   .each!(c => writeln(c, " found"));

// Output:
// o found
// o found
// k found
}
```


Re: How to disable assigning a value to a property?

2021-07-06 Thread jfondren via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 15:24:37 UTC, jfondren wrote:
3. https://run.dlang.io/is/AJM6Vg - hybrid where ClockAssign 
has an unsafe pointer that the compiler complains about :/


4.

```d
import std.stdio;

struct Field {
void opAssign(int a) {
writefln("Field.opAssign(%s)", a);
}
}

struct ClockAssign {
Field[] clocks;
void opIndexAssign(int a, int b) {
writefln("Register.clock(%s)", a);
clocks ~= Field();
clocks[$-1] = b;
}
}

struct Register {
ClockAssign clock;
}


void main() {
Register register;
register.clock[1] = 10;
// register.clock = 10; // error
}
```


Re: How to disable assigning a value to a property?

2021-07-06 Thread jfondren via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 10:06:11 UTC, Jack Applegame wrote:
How to disable `register.clock = 10;` but allow 
`register.clock(1) = 10;`?

I want to get a compilation error on `register.clock = 10;`


Some options:

1. return a temporary struct with an opIndex

```d
import std.stdio;

struct Field {
void opAssign(int a) {
writefln("Field.opAssign(%s)", a);
}
}

struct ClockAssign {
Field opIndex(int a) {
writefln("Register.clock(%s)", a);
return Field();
}
}

struct Register {
ClockAssign clock() {
return ClockAssign();
}
}

void main() {
Register register;
register.clock[1] = 10; // works, good
//register.clock = 10; // error
}
```

2. https://run.dlang.io/is/bkV64U - keep track of fields and fail 
at runtime if a field was never initialized (because it was 
silently discarded in this case).


3. https://run.dlang.io/is/AJM6Vg - hybrid where ClockAssign has 
an unsafe pointer that the compiler complains about :/


Re: Getting resulting/return type from operation in templates

2021-07-06 Thread Rekel via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 15:00:24 UTC, Paul Backus wrote:

On Tuesday, 6 July 2021 at 14:43:26 UTC, Rekel wrote:
Is there any reason the function call in the alias is 
acceptable? I would imagine the () part would actually require 
2 parameters.


You're right, it does; that was a mistake on my part. It should 
work with `Lhs.init` and `Rhs.init` as arguments.


Hmm . . . doing that ironically brings me back to using:

```d
alias ResultType(Lhs, string op, Rhs) = typeof(mixin("Lhs.init" ~ 
op ~ "Rhs.init"));


auto opBinary(string op, R:
T2[], T2)(R right) const if (is(ResultType!(T, op, T2))) {
Vec!(ResultType!(T, op, T2), L) result;
static foreach (i; 0 .. L) {
mixin("result[i] = this[i] " ~ op ~ " right[i];");
}
return result;
}
```

Kind of ironic this is basically an alias of my old solution.
Strangely enough the nanF issue went away though, I guess I 
misinterpreted this.

Thanks for your help anyway 


Re: Getting resulting/return type from operation in templates

2021-07-06 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 14:43:26 UTC, Rekel wrote:
Is there any reason the function call in the alias is 
acceptable? I would imagine the () part would actually require 
2 parameters.


You're right, it does; that was a mistake on my part. It should 
work with `Lhs.init` and `Rhs.init` as arguments.


Re: How to disable assigning a value to a property?

2021-07-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/6/21 9:27 AM, Jack Applegame wrote:

On Tuesday, 6 July 2021 at 12:33:20 UTC, Adam D Ruppe wrote:

The language always allows `a = b;` to be rewritten as `a(b);`.


And that's sad. It should happen for properties only.



Yes, I lament that there is no way to control how people call your 
function. It can result in surprising things, and it means as a library 
designer you have to consider this usage when picking names.


There are a few "draft" DIP proposals (under the old DIP system) here: 
https://wiki.dlang.org/DIPs


But I think the time of being able to make such a disruptive change has 
passed. For better or worse we have the half-implemented near-useless 
meaning of `@property`, and basically it's unneeded.


-Steve


Re: Getting resulting/return type from operation in templates

2021-07-06 Thread Rekel via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 14:27:35 UTC, Paul Backus wrote:
Instead of having the template evaluate to a `bool`, have it 
evaluate to the type of the result:


```d
alias ResultType(Lhs, string op, Rhs) =
typeof(((Lhs lhs, Rhs rhs) => mixin("lhs", op, "rhs"))());

static assert(is(ResultType!(int, "+", double) == double));
static assert(is(ResultType!(string, "~", string) == string));
static assert(!is(ResultType!(string, "+", int))); // no valid 
result type

```

Then you can use `is()` in the template constraints to check 
whether the operation is supported:


```d
auto opBinary(string op, Rhs: T2[], T2) const
if (is(ResultType!(T, op, T2)))
{
Vec!(ResultType!(T, op, T2), L) result;
// etc.
}
```


Oh that's neat, thanks.
I guess that would make it:
```d
auto opBinary(string op, R)(R right) const if (is(ResultType!(T, 
op, R))) {

Vec!(ResultType!(T, op, R), L) result;
static foreach (i; 0 .. L) {
mixin("result[i] = this[i] " ~ op ~ " right;");
}
return result;
}
```

I guess I'll just have to take the result definition for what it 
is. At least the return type can use auto, haha. Imagine using 
ResultType!(T, op, R) thrice...


Is there any reason the function call in the alias is acceptable? 
I would imagine the () part would actually require 2 parameters.




Re: Getting resulting/return type from operation in templates

2021-07-06 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 14:12:48 UTC, Rekel wrote:
I recently found __traits(compiles, ...) can be used in 
template constraints.
(I first used `is(mixin("T.init"~op~"T2.init"))` but this cause 
problems related to nanF)


However I'm wondering if there is an easier way to do what I'm 
currently doing, especially since using typeof inside the 
result declaration is quite cumbersome. This is a bigger 
problem in my less-simplified code (using matrices), where it 
starts getting slightly unreadable.
It also assumes the presence of .vec[0] (not necessarily a 
problem here but it seems like a codesmell)


Simplified:
```d
template supported(A, string op, B) {
const bool supported = __traits(compiles, (A a, B b) {
mixin("return a" ~ op ~ "b;");
});
}
```


Instead of having the template evaluate to a `bool`, have it 
evaluate to the type of the result:


```d
alias ResultType(Lhs, string op, Rhs) =
typeof(((Lhs lhs, Rhs rhs) => mixin("lhs", op, "rhs"))());

static assert(is(ResultType!(int, "+", double) == double));
static assert(is(ResultType!(string, "~", string) == string));
static assert(!is(ResultType!(string, "+", int))); // no valid 
result type

```

Then you can use `is()` in the template constraints to check 
whether the operation is supported:


```d
auto opBinary(string op, Rhs: T2[], T2) const
if (is(ResultType!(T, op, T2)))
{
Vec!(ResultType!(T, op, T2), L) result;
// etc.
}
```


Getting resulting/return type from operation in templates

2021-07-06 Thread Rekel via Digitalmars-d-learn
I recently found __traits(compiles, ...) can be used in template 
constraints.
(I first used `is(mixin("T.init"~op~"T2.init"))` but this cause 
problems related to nanF)


However I'm wondering if there is an easier way to do what I'm 
currently doing, especially since using typeof inside the result 
declaration is quite cumbersome. This is a bigger problem in my 
less-simplified code (using matrices), where it starts getting 
slightly unreadable.
It also assumes the presence of .vec[0] (not necessarily a 
problem here but it seems like a codesmell)


Simplified:
```d
template supported(A, string op, B) {
const bool supported = __traits(compiles, (A a, B b) {
mixin("return a" ~ op ~ "b;");
});
}

struct Vec(T, uint L) {
T[L] vec;
alias vec this;

auto opBinary(string op, R:
T2[], T2)(R right) const if (supported!(T, op, T2)) {
Vec!(typeof(mixin("this[0]" ~ op ~ "right[0]")), L) result;
static foreach (i; 0 .. L) {
mixin("result[i] = this[i] " ~ op ~ " right[i];");
}
return result;
}

	auto opBinary(string op, R)(R right) const if (supported!(T, op, 
R)) {

Vec!(typeof(mixin("this[0]" ~ op ~ "right")), L) result;
static foreach (i; 0 .. L) {
mixin("result[i] = this[i] " ~ op ~ " right;");
}
return result;
}
}

void main(string[] args) {
Vec!(float, 4) v = Vec!(float, 4)([0, 1, 2, 3]);
auto w = v * 2.0;
auto x = v + v;
auto y = v + [1, 1, 1, 1];
pragma(msg, typeof(w)); // prints "Vec!(double, 4u)"
pragma(msg, typeof(x)); // prints "Vec!(float, 4u)"
pragma(msg, typeof(y)); // prints "Vec!(float, 4u)"
}
```


Re: How to disable assigning a value to a property?

2021-07-06 Thread Mike Parker via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 13:27:43 UTC, Jack Applegame wrote:


And that's sad. It should happen for properties only.


Totally disagree. This is one of my favorite D features.


Re: How to disable assigning a value to a property?

2021-07-06 Thread Jack Applegame via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 12:33:20 UTC, Adam D Ruppe wrote:

The language always allows `a = b;` to be rewritten as `a(b);`.


And that's sad. It should happen for properties only.



Re: How to disable assigning a value to a property?

2021-07-06 Thread Adam D Ruppe via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 10:06:11 UTC, Jack Applegame wrote:

How to disable `register.clock = 10;`


You don't. The language always allows `a = b;` to be rewritten as 
`a(b);`.


Best you can do is use different types for the two arguments. 
Maybe clock could take a struct Clock { int x; } or something 
instead.


Re: Find a char among string (string.findAmong.char)

2021-07-06 Thread Mike Parker via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 11:35:14 UTC, BoQsc wrote:

I tried out .canFind method, and to test it I removed the 
letter 'o' from the Alphabet.
Weirdly enough .canFind method still found 'o' letter among the 
Alphabet.


https://run.dlang.io/is/2Fvenf


Looks like it has something to do with the alias. Static arrays 
aren't ranges, so you should really be seeing the same error you 
would if you passed `letters` directly.


Change the `canFind` call to take a slice of the array:

```d
if (letters[].canFind(letter)){
```

And it outputs the following as expected:

```
k letter is found among the alphabet.
```

This warrants a bug report with a minimized example.


Re: Find a char among string (string.findAmong.char)

2021-07-06 Thread BoQsc via Digitalmars-d-learn

On Monday, 5 July 2021 at 19:48:13 UTC, jfondren wrote:

On Monday, 5 July 2021 at 19:34:14 UTC, BoQsc wrote:


But I really don't like how it looks less readable and makes 
less sense on first look.

`if (([letter].findAmong(alphabet)).length)`
I'd like to use some method on the `letter` instead of []
And `.length` does not make a lot of sense when reading like 
an english sentence.


I suggest canFind, like in my earlier example. findAmong is 
like "consume this range until you find one of these things, 
and then return the remainder of the range". It doesn't really 
fit your use.


I tried out .canFind method, and to test it I removed the letter 
'o' from the Alphabet.
Weirdly enough .canFind method still found 'o' letter among the 
Alphabet.


https://run.dlang.io/is/2Fvenf



Re: How to disable assigning a value to a property?

2021-07-06 Thread Jack Applegame via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 10:25:28 UTC, Dennis wrote:
We're [still awaiting formal assessment on 
dip1038](https://forum.dlang.org/thread/sojvxakgruzfvbigz...@forum.dlang.org), but if that gets in, you can mark `clock` or `Field` `@nodicard`. Otherwise I don't know of a way.


Yes, it would help.



Re: How to disable assigning a value to a property?

2021-07-06 Thread Dennis via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 10:06:11 UTC, Jack Applegame wrote:
How to disable `register.clock = 10;` but allow 
`register.clock(1) = 10;`?

I want to get a compilation error on `register.clock = 10;`


We're [still awaiting formal assessment on 
dip1038](https://forum.dlang.org/thread/sojvxakgruzfvbigz...@forum.dlang.org), but if that gets in, you can mark `clock` or `Field` `@nodicard`. Otherwise I don't know of a way.


Re: How to disable assigning a value to a property?

2021-07-06 Thread Jack Applegame via Digitalmars-d-learn

On Tuesday, 6 July 2021 at 10:24:45 UTC, drug wrote:
Something like using different types for arguments in 
`Register.clock` and `Field.opAssign`?


I've been thinking about it. Unfortunately, this is not always 
convenient.


Re: How to disable assigning a value to a property?

2021-07-06 Thread drug via Digitalmars-d-learn

06.07.2021 13:06, Jack Applegame пишет:

Code:
```d
import std.stdio;

struct Field {
     void opAssign(int a) {
     writefln("Field.opAssign(%s)", a);
     }
}

struct Register {
     Field clock(int a) {
     writefln("Register.clock(%s)", a);
     return Field();
     }
}


void main() {
     Register register;
     register.clock(1) = 10; // works, good
     register.clock = 10;    // works too, how to disable it?
}
```
How to disable `register.clock = 10;` but allow `register.clock(1) = 10;`?
I want to get a compilation error on `register.clock = 10;`



Something like using different types for arguments in `Register.clock` 
and `Field.opAssign`?


How to disable assigning a value to a property?

2021-07-06 Thread Jack Applegame via Digitalmars-d-learn

Code:
```d
import std.stdio;

struct Field {
void opAssign(int a) {
writefln("Field.opAssign(%s)", a);
}
}

struct Register {
Field clock(int a) {
writefln("Register.clock(%s)", a);
return Field();
}
}


void main() {
Register register;
register.clock(1) = 10; // works, good
register.clock = 10;// works too, how to disable it?
}
```
How to disable `register.clock = 10;` but allow 
`register.clock(1) = 10;`?

I want to get a compilation error on `register.clock = 10;`