Re: How do you peek a variant containing a complex value?

2020-02-23 Thread Vinay Sajip via Digitalmars-d-learn

On Saturday, 22 February 2020 at 18:32:06 UTC, nullptr wrote:


The type in v isn't Complex, it's Complex!double.



Ah, great. Thanks! Missed that.


How do you peek a variant containing a complex value?

2020-02-22 Thread Vinay Sajip via Digitalmars-d-learn
The following program won't compile if I uncomment the if 
statement:


void main()
{
Variant v = complex(1.0, 1.0);

//if (v.peek!(Complex)) {
//writeln("Complex");
//}
writeln(v);
}

I get the same error with v.peek!(complex), which is:

Error: template instance peek!(Complex) does not match template 
declaration peek(T)()


The variant can clearly hold a complex value. Someone please tell 
me - what am I doing wrong in the peek call?


Re: How does one cast to an array type?

2019-10-17 Thread Vinay Sajip via Digitalmars-d-learn

On Thursday, 17 October 2019 at 12:40:33 UTC, Adam D. Ruppe wrote:

On Thursday, 17 October 2019 at 12:19:03 UTC, Vinay Sajip wrote:

Are arrays and objects part of a unified type system?


No, they are separate. You can define a class that contains an 
array, but it doesn't work like that automatically.


You'll want to use a wrapper class or a variant type or a 
template or something for this depending on your exact use case.


The use case is that I have a specialised comparator function 
that takes any two objects, including potentially array  of 
objects, and processes things accordingly. Perhaps a Variant will 
be the best bet, as the decision as to how to process has to be 
made at run time rather than compile time, and effectively based 
on user inputs.


Thanks for the suggestions,

Vinay Sajip


How does one cast to an array type?

2019-10-17 Thread Vinay Sajip via Digitalmars-d-learn
Are arrays and objects part of a unified type system? 
Specifically, if I do


void foo(Object x) {
if (typeid(x) == typeid(Object[])) {
auto a = cast(Object[]) x;
}
}

I get a compilation error:

onlineapp.d(3): Error: cannot cast expression x of type 
object.Object to Object[]


What's the way to achieve the cast, which should be safe given 
the typeid check?


Thanks and regards,

Vinay Sajip


Re: Fields with the same name not causing a warning?

2018-11-16 Thread Vinay Sajip via Digitalmars-d-learn

On Friday, 16 November 2018 at 19:12:42 UTC, Dennis wrote:
If something is definitively wrong, then it should be an error. 
If it's not definitively wrong, then the compiler shouldn't say 
anything about it, and it should be left up to a linter tool of 
some kind like dcd."


https://forum.dlang.org/post/mailman.3986.1537881312.29801.digitalmar...@puremagic.com



Thanks for that link, it helps to understand the thinking behind 
the way things are.


The language design could be fixed by requiring the use of the 
`override` keyword  like in C#. However, in D it *might* make 
generic code (with mixins) more complicated, though I 
personally have never found a use for hiding member variables 
so I don't know the rationale.


More complicated for the compiler writers, or users of 
mixins/generics? In any case, the example I showed was more 
commonplace than mixins and templates. Perhaps the default should 
be to fail compilation with an error, and allow `override` when 
someone actually wants to hide/shadow members in base classes, 
for whatever reason. I suggested "warning" rather than "error" in 
the OP, because I didn't know the philosophy behind warnings in D 
that you've now made me aware of. But presumably making it an 
error would potentially be a breaking change?


Re: Fields with the same name not causing a warning?

2018-11-16 Thread Vinay Sajip via Digitalmars-d-learn

On Friday, 16 November 2018 at 17:35:13 UTC, Basile B. wrote:
D is not a compiler that warns much. You can still open an 
issue asking for this (and the warning must be easy to add at 
first glance), but the policy applied to warnings is "compilers 
warnings are a sign of design flaws so instead of emitting one 
we should rather fix the flaw".


Design flaws in what? In this case, the flaw was in my code, but 
I would expect some help from the compiler in catching such an 
ambiguity, and so fixing the flaw in my code. That it didn't try 
to help me might itself be considered a design flaw in the 
compiler ;-)




Re: Fields with the same name not causing a warning?

2018-11-16 Thread Vinay Sajip via Digitalmars-d-learn

On Friday, 16 November 2018 at 17:08:00 UTC, Basile B. wrote:

I agree that this is almost a case of shadowing but i don't 
know the exact rationale for allowing this.


I'm not saying it shouldn't be allowed - just that the compiler 
could warn you about what might very well be a mistake (as it was 
in my case) - hard to debug with printf debugging, and source 
level debug for D is a bit thin on the ground, ISTM.


Fields with the same name not causing a warning?

2018-11-16 Thread Vinay Sajip via Digitalmars-d-learn

This code should IMO give at least a warning, but it doesn't:

abstract class A {
int kind;
}

class B : A {
int kind;

this(int k) {
kind = k;
}
}

In my actual code, the declaration of field "kind" in B was left 
in accidentally. Surprisingly, however, no warning was emitted 
when I compiled this, leading to B having two fields called kind 
which are distinct from one another. The complete program


import std.stdio;

abstract class A {
int kind;
}

class B : A {
int kind;

this(int k) {
kind = k;
}
}

void main()
{
auto b = new B(4);
A a = b;

writeln(b.kind);
writeln(a.kind);
}

prints

4
0

Given that this is the kind of thing that is easily done, surely 
the default behaviour should be for the compiler to emit at least 
a warning that field "kind" is ambiguous in B? This behaviour 
occurs even when the field is declared as "public" or "protected" 
in both classes. What am I missing?


Re: Using decodeFront with a generalised input range

2018-11-09 Thread Vinay Sajip via Digitalmars-d-learn
On Friday, 9 November 2018 at 11:24:42 UTC, Jonathan M Davis 
wrote:
decode and decodeFront are for converting a UTF code unit to a 
Unicode code point. So, you're taking UTF-8 code unit (char), 
UTF-16 code unit (wchar), or a UTF-32 code unit (dchar) and 
decoding it. In the case of UTF-32, that's a no-op, since 
UTF-32 code units are already code points, but for UTF-8 and 
UTF-16, they're not the same at all.


I would advise against doing much with decode or decodeFront 
without having a decent understanding of the basics of Unicode.




I think I understand enough of the basics of Unicode, at least 
for my application; my unfamiliarity is with the D language and 
standard library, to which I am very new.


There are applications where one needs to decode a stream of 
bytes into Unicode text: perhaps it's just semantic quibbling 
distinguishing between "a ubyte" and "a UTF-8 code unit", as 
they're the same at the level of bits and bytes (as I understand 
it - please tell me if you think otherwise). If I open a file 
using mode "rb", I get a sequence of bytes, which may contain 
structured binary data, parts of which are to be interpreted as 
text encoded in UTF-8. Is there something in the D standard 
library which enables incremental decoding of such (parts of) a 
byte stream? Or does one have to resort to the `map!(x => 
cast(char) x)` method for this?


Re: Using decodeFront with a generalised input range

2018-11-09 Thread Vinay Sajip via Digitalmars-d-learn

On Friday, 9 November 2018 at 10:26:46 UTC, Dennis wrote:

On Friday, 9 November 2018 at 09:47:32 UTC, Vinay Sajip wrote:
std.utf.decodeFront(Flag useReplacementDchar = 
No.useReplacementDchar, S)(ref S str) if (isInputRange!S && 
isSomeChar!(ElementType!S))


This is the overload you want, let's check if it matches:
ref S str - your InputRange can be passed by reference, but you 
specified S = dchar. S here is the type of the inputRange, and 
it is not of type dchar. It's best not to specify S so the 
compiler will infer it, range types can be very complicated. 
Once we fix that, let's look at the rest:


isInputRange!S - S is an inputRange
isSomeChar!(ElementType!S) - ElementType!S is ubyte, but 
isSomeChar!ubyte is not true.


The function wants characters, but you give bytes. A quick fix 
would be to do:

```
import std.algorithm: map;
auto mapped = r.map!(x => cast(char) x);
mapped.decodeFront!(No.useReplacementDchar)();
```

But it may be better for somefn to accept an InputRange!(char) 
instead.


Note that if you directly do:
```
r.map!(x => cast(char) 
x).decodeFront!(No.useReplacementDchar)();

```
It still won't work, since it wants `ref S str` and r.map!(...) 
is a temporary that can't be passed by reference.


As you can see, ensuring template constraints can be really 
difficult. The error messages give little help here, so you 
have to manually check whether the conditions of the overload 
you want hold.


Thanks, that's helpful. My confusion seems due to my thinking 
that a decoding operation converts (unsigned) bytes to chars, 
which is not how the writers of std.utf seem to have thought of 
it. As I see it, a ubyte 0x20 could be decoded to an ASCII char ' 
', and likewise to wchar or dchar. It doesn't (to me) make sense 
to decode a char to a wchar or dchar. Anyway, you've shown me how 
decodeFront can be used, so great!


Supplementary question: is an operation like r.map!(x => 
cast(char) x) effectively a run-time no-op and just to keep the 
compiler happy, or does it actually result in code being 
executed? I came across a similar issue with ranges recently 
where the answer was to map immutable(byte) to byte in the same 
way.




Using decodeFront with a generalised input range

2018-11-09 Thread Vinay Sajip via Digitalmars-d-learn

According to the std.utf documentation,

decode will only work with strings and random access ranges of 
code units with length and slicing, whereas decodeFront will 
work with any input range of code units.


However, I can't seem to get such a usage to compile: the 
following code


import std.range;
import std.utf;

void somefn(InputRange!(ubyte) r) {
r.decodeFront!(No.useReplacementDchar, dchar)();
}

gives a compilation error:

onlineapp.d(5): Error: template std.utf.decodeFront cannot deduce 
function from argument types !(cast(Flag)false, 
dchar)(InputRange!ubyte), candidates are:
/dlang/dmd/linux/bin64/../../src/phobos/std/utf.d(1176):
std.utf.decodeFront(Flag useReplacementDchar = 
No.useReplacementDchar, S)(ref S str, out size_t numCodeUnits) if 
(!isSomeString!S && isInputRange!S && isSomeChar!(ElementType!S))
/dlang/dmd/linux/bin64/../../src/phobos/std/utf.d(1214):
std.utf.decodeFront(Flag useReplacementDchar = 
No.useReplacementDchar, S)(ref S str, out size_t numCodeUnits) if 
(isSomeString!S)
/dlang/dmd/linux/bin64/../../src/phobos/std/utf.d(1243):
std.utf.decodeFront(Flag useReplacementDchar = 
No.useReplacementDchar, S)(ref S str) if (isInputRange!S && 
isSomeChar!(ElementType!S))


I'm not sure what's wrong here. Also, the information in the 
error message seems to indicate that decodeFront isn't expecting 
to work on a generic InputRange interface, but rather a subset 
which comes from an actual string. Have I read that wrong? I get 
the same error with leaving out the useReplacementDchar flag, 
i.e. `r.decodeFront!(dchar)()`


Re: Creating InputRanges from strings, files etc.

2018-11-08 Thread Vinay Sajip via Digitalmars-d-learn
On Thursday, 8 November 2018 at 16:41:50 UTC, Steven 
Schveighoffer wrote:

I did this in a run.dlang.org playground:

pragma(msg, ElementType!(typeof(b)));
pragma(msg, ElementType!(typeof(d)));

I get:
immutable(ubyte)
ubyte

Which means they aren't the same type, and they don't define 
the same interface (InputRange!(ubyte) is not the same as 
InputRange!(immutable(ubyte)) ).


Other than simply using compile-time functions, and dropping 
the object interface as Alex suggests, the easiest thing I can 
recommend is wrapping representation into a casting input range 
such as map:


auto b = inputRangeObject(a.representation.map!(b => ubyte(b)));

You can see all this here:

https://run.dlang.io/is/1E6Uqj

-Steve


Thanks, guys, those are helpful pointers.


Re: Creating InputRanges from strings, files etc.

2018-11-08 Thread Vinay Sajip via Digitalmars-d-learn

On Thursday, 8 November 2018 at 14:38:37 UTC, Paul Backus wrote:
To pass these ranges around using the `InputRange` interface, 
use `inputRangeObject` to wrap them:


InputRange!ubyte r3 = inputRangeObject(r1);
InputRange!(immutable(ubyte)) r4 = inputRangeObject(r2);


I did a bit more digging, and it seems to work for strings but 
not for files: The program


import std.algorithm.iteration;
import std.format;
import std.range;
import std.stdio;
import std.string;

void somefn(InputRange!(immutable(ubyte)) r) {
writeln(format!"%s"(r));
}

void main()
{
auto a = "Hello, world!";
auto b = inputRangeObject(a.representation);
somefn(b);
auto c = stdin.byChunk(1024).joiner;
auto d = inputRangeObject(c);
//somefn(d);
}

compiles as given above, but if the somefn(d) line is 
uncommented, I get an error:


function onlineapp.somefn(InputRange!(immutable(ubyte)) r) is not 
callable using argument types (InputRangeObject!(Result))
onlineapp.d(18):cannot pass argument d of type 
std.range.interfaces.InputRangeObject!(Result) to parameter 
InputRange!(immutable(ubyte)) r


Do I need to do an explicit cast? If so, can someone tell me the 
precise incantation? How come it doesn't figure out that the 
underlying range is a ubyte range, or is it to do with 
immutability, or something else altogether?


Re: Creating InputRanges from strings, files etc.

2018-11-08 Thread Vinay Sajip via Digitalmars-d-learn

On Thursday, 8 November 2018 at 14:38:37 UTC, Paul Backus wrote:
You can iterate through a file one ubyte at a time using 
`byChunk` and `joiner`:


auto r1 = stdin.byChunk(1024).joiner;
assert(is(typeof(r1.front) == ubyte));

You can iterate through a string one ubyte at a time using 
`representation`:


auto r2 = "To be or not to be".representation;
assert(is(typeof(r2.front) == immutable(ubyte)));

To pass these ranges around using the `InputRange` interface, 
use `inputRangeObject` to wrap them:


InputRange!ubyte r3 = inputRangeObject(r1);
InputRange!(immutable(ubyte)) r4 = inputRangeObject(r2);


Aha - inputRangeObject was the thing I was missing. Thanks!


Creating InputRanges from strings, files etc.

2018-11-08 Thread Vinay Sajip via Digitalmars-d-learn
Excuse my ignorance, but from looking at the documentation on 
std.range and a quick skim of the guides mentioned there near the 
top, I can't see what the simple way is of creating an 
InputRange!(ubyte) from strings, files etc. I would have expected 
to find something in the DLang Tour about this, but couldn't find 
anything. Please can someone tell me how to do it? Just to be 
clear, I want to create an object which is an InputRange!(ubyte) 
and pass that around, rather than e.g. iterate over a string or a 
file.


Re: Reading binary streams with decoding to Unicode

2018-10-16 Thread Vinay Sajip via Digitalmars-d-learn

On Monday, 15 October 2018 at 22:49:31 UTC, Nicholas Wilson wrote:
Oh, sorry I missed that. Take a look at 
https://github.com/schveiguy/iopipe


Great, thanks.


Re: Reading binary streams with decoding to Unicode

2018-10-15 Thread Vinay Sajip via Digitalmars-d-learn

On Monday, 15 October 2018 at 19:56:22 UTC, Nicholas Wilson wrote:


import std.file : readText;
import std.uni : byCodePoint, byGrapheme;
// or import std.utf : byCodeUnit, byChar /*utf8*/, byWchar 
/*utf16*/, byDchar /*utf32*/, byUTF  /*utf8(?)*/;

string a = readText("foo");

foreach(cp; a.byCodePoint)
{
// do stuff with code point 'cp'
}


Your example shows reading an entire file into memory (string a = 
readText("foo")), then iterating over that. I know you can 
iterate over a string; I'm interested in iterating over a stream, 
which is perhaps read over a network or from another I/O source, 
where you can't assume you have access to all of it at once - 
just one Unicode character at a time.


Re: Reading binary streams with decoding to Unicode

2018-10-15 Thread Vinay Sajip via Digitalmars-d-learn

On Monday, 15 October 2018 at 17:55:34 UTC, Dukc wrote:
This is done automatically for character arrays, which includes 
strings. wchar arrays wil iterate by UTF-16, and dchar arrays 
by UTF-32. If you have a byte/ubyte array you know to be 
unicode-encoded, convert it to char[] to iterate by code points.


Thanks for the response. I was looking for something where I 
don't have to manage buffers myself (e.g. when handling buffered 
file or socket I/O). It's really easy to find this functionality 
in e.g. Python, C#, Go, Kotlin, Java etc. but I'm surprised there 
doesn't seem to be a ready-to-go equivalent in D. For example, I 
can find D examples of opening files and reading a line at a 
time, but no examples of opening a file and reading Unicode chars 
one at a time. Perhaps I've just missed them?




Reading binary streams with decoding to Unicode

2018-10-15 Thread Vinay Sajip via Digitalmars-d-learn
Is there a standardised way of reading over buffered binary 
streams (at least strings, files, and sockets) where you can 
layer a decoder on top, so you get a character stream you can 
read one Unicode char at a time? Initially UTF-8, but later also 
other encodings. I see that std.stream was deprecated, but can't 
see what other options there are. Can anyone point me in the 
right direction?