Re: "in" operator gives a pointer result from a test against an Associative Array?

2024-05-09 Thread Meta via Digitalmars-d-learn

On Friday, 10 May 2024 at 00:18:16 UTC, Andy Valencia wrote:
tst7.d(6): Error: cannot implicitly convert expression `e in 
this.members` of type `bool*` to `bool`
tst7.d(15): Error: template instance `tst7.Foo!uint` error 
instantiating


I'm getting this for this bit of source (trimmed from the 
bigger code).  I switched to this.members.get(e, false) and 
that works fine, but I'm still curious:


struct Foo(T) {
bool[T] members;

bool
has(T e) {
return (e in this.members);
}
}

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

auto t = Foo!uint();
writeln(t.has(123));
}


Yes. The reason for this is that it avoids having to essentially 
do the same check twice. If `in` returned a bool instead of a 
pointer, after checking for whether the element exists (which 
requires searching for the element in the associative array), 
you'd then have to actually *get* it from the array, which would 
require searching again. Returning a pointer to the element if it 
exists (or `null` if it doesn't) cuts this down to 1 operation.


Re: Fix template parameter

2022-08-09 Thread Meta via Digitalmars-d-learn

On Monday, 8 August 2022 at 12:02:02 UTC, Dom Disc wrote:

Hello.
I found in the documentation functions declared like this:

```D
pure @nogc @safe BigInt opAssign(T : BigInt)(T x);
```


This is a template function, even if T is constrained to always 
be BigInt (it may also include anything that is a subtype of 
BigInt... I've received different answers on what exactly `(T: 
SomeType)` means in this context). This means that it cannot be 
virtual, you can't take its address, and as bauss said, it won't 
show up in the object file if it's not used.


As far as I know, there's no advantage to doing this over 
`opAssign(BigInt x)`, UNLESS `(T: BigInt)` means "BigInt and any 
subtype of BigInt", in which case the advantage is similar to 
doing ` void opAssign(T val)` in Java 
(referring to polymorphism; this won't give you virtual dispatch 
like it does in Java).





Re: A look inside "filter" function defintion

2022-08-09 Thread Meta via Digitalmars-d-learn

On Monday, 1 August 2022 at 23:35:13 UTC, pascal111 wrote:
This is the definition of "filter" function, and I think it 
called itself within its definition. I'm guessing how it works?


'''D
template filter(alias predicate)
if (is(typeof(unaryFun!predicate)))
{
/**
Params:
range = An $(REF_ALTTEXT input range, isInputRange, 
std,range,primitives)

of elements
Returns:
A range containing only elements `x` in `range` for
which `predicate(x)` returns `true`.
 */
auto filter(Range)(Range range) if 
(isInputRange!(Unqual!Range))

{
return FilterResult!(unaryFun!predicate, Range)(range);
}
}
'''

I think this line needs explanation:

'''D
return FilterResult!(unaryFun!predicate, Range)(range);
'''


To give a vastly simplified answer, the term "eponymous template" 
essentially means that if you have an item declared inside a 
template that has a same name as the template:

```D
template SomeTemplate(T)
{
alias SomeTemplate = T;
}
```

It is not a compile error. Instead, when you use the template:
```D
SomeTemplate!int n;
```

The compiler rewrites your code like to:
```D
SomeTemplate!int.SomeTemplate n;
```

Because normally when you instantiate a template, you have to 
refer to the declarations inside it by name:

```D
template SomeOtherTemplate(T)
{
alias SomeAlias = T;
}

//SomeOtherTemplate!int n; Error: `SomeOtherTemplate!int` is used 
as a type

SomeOtherTemplate!int.SomeAlias n; //Ok
```

Except in the special case I outlined above. It's essentially a 
hack that was brought over from C++. It makes using templates 
more ergonomic.




Re: Alternative to C++ macro in D

2019-11-03 Thread Meta via Digitalmars-d-learn
On Sunday, 3 November 2019 at 16:55:36 UTC, Vinod K Chandran 
wrote:

Hi all,
I can do this in C++. #include 
using namespace std ;

#define end };
#define log(x)  cout << x << endl
#define wait std::cin.get()


int main() {
log("Trying to avoid the visual clutter aused by closing 
curly braces") ;

string myStr = "Now, code looks more elegant" ;
log(myStr) ; mixin template cToD(string code)


`log` and `wait` are straightforward. Just write a function:

import std.stdio;
void log(T)(T x) { writeln(x); }
void wait() { readln(); }

However, you can't do things like `#define end }`. The D language 
intentionally disallows doing stuff like this. If you *really* 
want to do this, you can sort of emulate it with mixins:


mixin template cToD(string code)
{
import std.array: replace;
mixin(code.replace("end", "}"));
}

mixin cToD!`
int main() {
log("Trying to avoid the visual clutter aused by closing 
curly braces") ;

string myStr = "Now, code looks more elegant" ;
log(myStr) ;
wait ;
return 0;
end
`;

But I would strongly recommend against it.


Re: Unexpectedly nice case of auto return type

2019-12-03 Thread Meta via Digitalmars-d-learn

On Tuesday, 3 December 2019 at 17:45:27 UTC, H. S. Teoh wrote:
The thing is, `void` means "no return type" (or "no type" in 
some contexts), i.e., void == TBottom in that case.


Not *quite* correct. void is not a bottom type; it's a unit type, 
meaning that it's a type with only 1 value (as is null, 
interestingly). void does not mean "no return type"; it means 
"there's only 1 possible value that can be returned". A function 
returning TBottom means that the function will never return, 
e.g., it loops forever, or throws an exception, etc.


I agree with the OP that it's silly not to give typeof(null) a 
name. As null is a unit type, we could easily have `null` stand 
in for typeof(null) as well. A type that contains only one value 
can be synonymous with that value (see also, Rust's unit type (), 
which has one value, ()).





Re: Unexpectedly nice case of auto return type

2019-12-03 Thread Meta via Digitalmars-d-learn

On Tuesday, 3 December 2019 at 22:11:39 UTC, Meta wrote:

On Tuesday, 3 December 2019 at 17:45:27 UTC, H. S. Teoh wrote:
The thing is, `void` means "no return type" (or "no type" in 
some contexts), i.e., void == TBottom in that case.


Not *quite* correct. void is not a bottom type; it's a unit 
type, meaning that it's a type with only 1 value (as is null, 
interestingly). void does not mean "no return type"; it means 
"there's only 1 possible value that can be returned". A 
function returning TBottom means that the function will never 
return, e.g., it loops forever, or throws an exception, etc.


Whoops, skimmed over the post already mentioning this.


Re: Using map result type

2019-12-11 Thread Meta via Digitalmars-d-learn

On Sunday, 8 December 2019 at 01:10:21 UTC, AA wrote:
I'd like to accept the return type of map. From some previous 
questions that I should accept a template?

So for something like:

```
void mapAccepter(Range)(Range r)
{
import std.array : array;
import std.stdio : writeln;

auto collected = r.array;
writeln(collected);
}

void main()
{
import std.algorithm.iteration : map;

int[] nums = [1, 2, 3];
auto evenness = map!(n => n % 2 == 0)(nums);
mapAccepter(evenness);
}
```


1) Is there any way I can make `mapAccepter` not a templated 
function?


Yes (mostly, anyway), using the interfaces in 
std.range.interfaces:

https://dlang.org/phobos/std_range_interfaces.html

import std.algorithm;
import std.range;

void mapAccepter(E)(InputRange!E r)
{
import std.array: array;
import std.stdio: writeln;

auto collected = r.array;
writeln(collected);
}

void main()
{
int[] nums = [1, 2, 3];
auto evenness = inputRangeObject(map!(n => n % 2 == 0)(nums));
mapAccepter(evenness);
}

`mapAccepter` still needs to be templated on the element type of 
the range,
but there are ways to avoid that as well, if desired. I wouldn't 
recommend it,

however, as it wouldn't be that useful in this case.

2) Is there any way if I need to make `mapAccepter` templated 
to constrain Range to be a range of booleans.


Yup, there are two ways that you you primarily do that. Either
constraining E in the template declaration, or adding a constraint
on the template. Generally option 2 is the more idiomatic D way.

Option 1: constrain E to be of type bool:
void mapAccepter(E: bool)(InputRange!E r);

OR

void mapAccepter(E)(InputRange!E r)
if (is(E == bool));

There's not much difference between these two, but the latter is 
probably preferred.


Option 2: use std.traits and a template constraint:
void mapAccepter(E)(InputRange!E r)
if (is(ElementType!r == bool));



Re: Using map result type

2019-12-11 Thread Meta via Digitalmars-d-learn

On Wednesday, 11 December 2019 at 20:08:37 UTC, Meta wrote:

import std.algorithm;
import std.range;

void mapAccepter(E)(InputRange!E r)
{
import std.array: array;
import std.stdio: writeln;

auto collected = r.array;
writeln(collected);
}

void main()
{
int[] nums = [1, 2, 3];
auto evenness = inputRangeObject(map!(n => n % 2 == 
0)(nums));

mapAccepter(evenness);
}


I guess I should mention, that if you are expecting a range of 
booleans, you can of course write  mapAccepter as a non-templated 
function:


void mapAccepter(InputRange!bool r);

But if you want to support any type of input range, the function 
needs to at least be templated on the element type of the range.


Re: `in` parameters optimization

2019-12-25 Thread Meta via Digitalmars-d-learn

On Wednesday, 25 December 2019 at 01:24:52 UTC, Adnan wrote:
Does the compiler automatically pass values by reference if 
possible with `in` parameters in higher level of optimization 
flags? I would normally use `in ref` but sometimes it's not 
compatible with different types.


No. "in" is short for "const scope" 
(https://dlang.org/spec/function.html#param-storage). The only 
mechanism D has for expressing "pass this argument by ref if 
possible, and by value otherwise" is "auto ref" 
(https://dlang.org/spec/function.html#auto-ref-functions), which 
requires your function to be templated.


Re: Discord bot written in D

2020-04-07 Thread Meta via Digitalmars-d-learn

On Monday, 6 April 2020 at 21:23:22 UTC, Quantium wrote:
Are there any libraries to creade a simple discord bot using D? 
And if you know these libraries, could you day me their pros 
and cons?


I've used https://github.com/b1naryth1ef/dscord to build a 
Discord bot, a little over a year ago. However, it didn't even 
seem that actively maintained back then; I had to patch over at 
least one bug. Other than that, though, it worked smoothly and 
was easy to get started with.


Re: Checked!({short, ushort, byte, char}, Throw): compilation fails

2020-04-16 Thread Meta via Digitalmars-d-learn
Unlike C/C++, char is not a numeric type in D; It's a UTF-8 code 
point:


import std.traits;

void main()
{
pragma(msg, isNumeric!char); //Prints false
}


Re: Retrieve the return type of the current function

2020-05-05 Thread Meta via Digitalmars-d-learn

On Tuesday, 5 May 2020 at 17:11:53 UTC, learner wrote:

On Tuesday, 5 May 2020 at 16:41:06 UTC, Adam D. Ruppe wrote:


typeof(return)


Thank you, that was indeed easy!

Is it possible to retrieve also the caller return type? 
Something like:


```
int foo() {
return magic();
}

auto magic(maybesomedefaulttemplateargs = ??)() {
alias R = __traits(???); // --> int!
}
```

Mixin templates maybe?


You *can* use mixin templates to access the caller's scope, which 
means typeof(return) will refer to the caller's return type, 
instead of the callee's. However, there's no way to both mixin 
and call the mixin template in a single line, so it's not DRY:


int foo()
{
mixin magic;
return magic();
}

mixin template magic()
{
alias CallerRet = typeof(return);
CallerRet magic()
{
return CallerRet.init;
}
}

void main()
{
foo();
}

Maybe somebody else knows a way to get around having to first 
mixin magic.


Re: Retrieve the return type of the current function

2020-05-05 Thread Meta via Digitalmars-d-learn

On Tuesday, 5 May 2020 at 18:19:00 UTC, Meta wrote:

mixin template magic()
{
alias CallerRet = typeof(return);
CallerRet magic()
{
return CallerRet.init;
}
}


Small edit: you can remove the "CallerRet" alias by doing the 
following:


mixin template magic()
{
typeof(return) magic()
{
return typeof(return).init;
}
}


Though I wouldn't really recommend it as it's very confusing, 
IMO. This works because "typeof(return)" in the return position 
here refers to the caller's scope, while "typeof(return)" inside 
the function refer's to the function's scope.




Re: Should a parser type be a struct or class?

2020-06-18 Thread Meta via Digitalmars-d-learn

On Wednesday, 17 June 2020 at 11:50:27 UTC, Per Nordlöw wrote:
Should a range-compliant aggregate type realizing a parser be 
encoded as a struct or class? In dmd `Lexer` and `Parser` are 
both classes.


In general how should I reason about whether an aggregate type 
should be encoded as a struct or class?


IMO it doesn't need to be. However, it's worth saying that range 
semantics aren't a great fit for parsers - at least that's been 
my experience. Parsers need to be able to "synchronize" to 
recover from syntax errors, which does not fit into the range API 
very well. You can probably fit it in somewhere in popFront or 
front or empty, as your implementation permits, but I find it's 
just easier to forego the range interface and implement whatever 
primitives you need; *then* you can add a range interface over 
top that models the output of the parser as a range of 
expressions, or whatever you want.


Re: opBinary : Static ifs or specialization?

2020-06-23 Thread Meta via Digitalmars-d-learn

On Tuesday, 23 June 2020 at 23:53:36 UTC, claptrap wrote:
So you have opBinary and half a dozen operators to implement. 
Do you use a separate method for each operator or do you have 
one method and a big static if else if to select code path?


I assume they are functionally equivalent? So its just about 
style?


An idiomatic example:

import std.algorithm: among;

struct Test
{
int payload;

Test opBinary(string op)(Test other)
if (op.among!("+", "-", "*", "/")) //Limit supported ops
{
mixin("return Test(payload " ~ op ~ "other.val);");
}

int opBinary(string op)(int n)
//No constraint; support the full range of integer operations
{
mixin("return payload " ~ op ~ "n;");
}
}


Very confusing error message when calling a class method from an invariant

2021-03-09 Thread Meta via Digitalmars-d-learn

class Human {
static immutable MAX_AGE = 122;

bool alive = true;
int age = 0;
//Error: mutable method onlineapp.Human.checkAge is not 
callable using a const object

invariant(checkAge());

void growOlder()
in(alive)
out(; checkAge())
{
age++;
if (age > MAX_AGE)
die();
}

void die()
in(alive)
out(; !alive) {
alive = false;
}

bool checkAge() {
return age >= 0 && age <= MAX_AGE || !alive;
}
}

void main() {
Human h = new Human();
h.growOlder();
}

What the hell does this even mean, and where does it come from? 
Adding `inout` to `checkAge` actually does cause it to compile 
and run too. WTF?


Re: Very confusing error message when calling a class method from an invariant

2021-03-09 Thread Meta via Digitalmars-d-learn

On Wednesday, 10 March 2021 at 04:57:19 UTC, Paul Backus wrote:

On Wednesday, 10 March 2021 at 03:39:15 UTC, Meta wrote:

class Human {
static immutable MAX_AGE = 122;

bool alive = true;
int age = 0;
//Error: mutable method onlineapp.Human.checkAge is not 
callable using a const object

invariant(checkAge());

[...]


What the hell does this even mean, and where does it come 
from? Adding `inout` to `checkAge` actually does cause it to 
compile and run too. WTF?


From the language spec [1]:


The invariant is in the form of a const member function.


So, inside the invariant, the object is treated as const, which 
means you can't modify it and can only call const methods.


[1] https://dlang.org/spec/class.html#invariants


Now that you mention it, I'm pretty sure I've run into this 
before; I must've forgotten about it. I understand the rationale 
behind this, but it doesn't really make sense IMO that only 
invariants treat the object as const, and not pre/post conditions 
as well. Ah well. Thanks for quick answer.


Re: Immutable

2021-03-27 Thread Meta via Digitalmars-d-learn

On Saturday, 27 March 2021 at 20:44:12 UTC, Brad wrote:
I was looking through lots of sample code on Rosetta Code.  D 
has a lot of solutions out there.  That is really nice but it 
has me wondering - coming from other languages that do not 
support the concept of immutability - do real world programmers 
and/or hobbyists really use it as much as I see it on Rosetta 
Code?  I know it adds a layer of security to your code, but I 
am still thinking "why?".


Thanks for entertaining a newbie question.


FYI, most of those examples were written by someone who goes by 
"Bearophile", and their style of writing D uses 
immutable/const/pure/nothrow/etc. wherever possible. It's not 
necessarily the style that all D programmers use, though there 
are a number of people that do.


As for advantages, when it comes to the basic value types (int, 
float, bool, etc.), it's not all that useful. Where immutable can 
become very useful, though, is with types that have indirections 
(i.e. pointers). D's `string` type, for example, is actually a 
simple alias in Druntime:


alias string = immutable(char)[];

Meaning "a mutable array of immutable chars". This means that you 
can modify the array itself, such as changing its length, 
appending to it, etc., but you cannot its individual elements. 
E.g., the following will work:


string s1 = "this is a string";
s1 ~= '.';
assert(s1 == "this is a string.");

But this will NOT work:

string s2 = "this is a string ";
s2[$ - 1] = '.'; Error: cannot modify immutable expression 
s2[__dollar - 1LU]


This is just a simple example, but it allows the compiler to do 
some major optimizations on string handling code. Something that 
is usually very slow in C/C++ is such code, because strings are 
mutable arrays of mutable characters. Thus, they have to be 
copied around everywhere, which is slow and uses a lot of memory 
unnecessarily.


Not so in D; because strings are mutable arrays of immutable 
characters, you can freely pass out references to the whole 
string, or a subrange of it. This would be very dangerous in 
C/C++, but in D you don't have to worry about the string changing 
out from under you by some code somewhere else in the program 
that you gave a reference to. Thus, string handling code is far 
faster in D than in C/C++.


That is just one example, but you can see how immutable makes 
possible a lot of optimizations that would simply be impossible 
in languages without it.


Re: Is this bug ? format %(%)

2021-04-07 Thread Meta via Digitalmars-d-learn

On Wednesday, 7 April 2021 at 17:31:09 UTC, Paul Backus wrote:

On Wednesday, 7 April 2021 at 17:04:56 UTC, novice2 wrote:

On Wednesday, 7 April 2021 at 13:43:18 UTC, Paul Backus wrote:

So, you should change your code to

writefln("%-(%s, %)", s);


sorry i dont read docs so carefully
thanks


It's not your fault--this is a pretty obscure feature, and it's 
not documented very well. Even after you've found the correct 
page in the documentation (the page for `formattedWrite` [1]), 
you have to scroll down past multiple examples to find the text 
that explains it.


[1] https://dlang.org/phobos/std_format.html#formattedWrite


I have created a pull request that will hopefully make this more 
prominent on the doc page:

https://github.com/dlang/phobos/pull/7944


Re: Is there a more elegant way to do this in D?

2021-04-08 Thread Meta via Digitalmars-d-learn

On Thursday, 8 April 2021 at 12:19:29 UTC, WebFreak001 wrote:


```d
string to01String(int[] x) @safe
{
auto conv = x.to!(ubyte[]); // allocates new array, so 
later cast to string is OK
conv[] += '0'; // assume all numbers are 0-9, then this 
gives the correct result

return (() @trusted => cast(string)conv)();
}
```


The @trusted lambda can also be replaced with 
[std.exception.assumeUnique](https://dlang.org/library/std/exception/assume_unique.html).


Re: Is there a more elegant way to do this in D?

2021-04-08 Thread Meta via Digitalmars-d-learn

On Thursday, 8 April 2021 at 18:01:56 UTC, Meta wrote:

On Thursday, 8 April 2021 at 12:19:29 UTC, WebFreak001 wrote:


```d
string to01String(int[] x) @safe
{
auto conv = x.to!(ubyte[]); // allocates new array, so 
later cast to string is OK
conv[] += '0'; // assume all numbers are 0-9, then this 
gives the correct result

return (() @trusted => cast(string)conv)();
}
```


The @trusted lambda can also be replaced with 
[std.exception.assumeUnique](https://dlang.org/library/std/exception/assume_unique.html).


Never mind me, assumeUnique is @system (or at least it's inferred 
as @system), and anyway, you can't implicitly convert 
`immutable(ubyte)[]` to `immutable(char)[]`.


Re: nothrow and std.exception.ifThrown

2021-04-29 Thread Meta via Digitalmars-d-learn

On Thursday, 29 April 2021 at 16:02:20 UTC, novice2 wrote:

Hello.
I need use std.format.format() in nothrow function.
format() can throw.
For this case i have special default string.
I don't want embrace format into try..catch block,
and i found elegant std.exception.ifThrown.
But DMD say "ifThrown not nothrow"

https://run.dlang.io/is/kXtt5q
```d
nothrow string foo(int x, string def) {
import std.format: format;
import std.exception: ifThrown;

return format("%d", x).ifThrown(def);
}

Error: function std.exception.ifThrown!(Exception, string, 
string).ifThrown is not nothrow

```

What i can use instead of ifThrown, or how it can be changed to 
nothrow?

Thanks.


The reason for this, apparently, is in the definition of 
`ifThrown`:

```
CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, 
T2)(lazy scope T1 expression, lazy scope T2 errorHandler) nothrow

```

It's not marked as `nothrow` in the function's definition, so 
even if the delegate passed to ifThrown _is_ nothrow, the 
compiler can't tell. There's no easy way around this that I can 
think of OTOH that doesn't involve some effort on your part. One 
thing you can do is wrap ifThrown with 
`std.exception.assumeWontThrow`:

```
import std.exception: ifThrown, assumeWontThrow;
import std.functional: pipe;

alias ifThrown = pipe!(std.exception.ifThrown, assumeWontThrow);

nothrow string foo(int x, string def) nothrow {
import std.format: format;

return format("%d", x).ifThrown(def);
}

```


Re: nothrow and std.exception.ifThrown

2021-04-30 Thread Meta via Digitalmars-d-learn
On Friday, 30 April 2021 at 13:05:00 UTC, Steven Schveighoffer 
wrote:

On 4/29/21 1:50 PM, Meta wrote:



The reason for this, apparently, is in the definition of 
`ifThrown`:

```
CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, 
T2)(lazy scope T1 expression, lazy scope T2 errorHandler) 
nothrow

```

It's not marked as `nothrow` in the function's definition, so 
even if the delegate passed to ifThrown _is_ nothrow, the 
compiler can't tell. There's no easy way around this that I 
can think of OTOH that doesn't involve some effort on your 
part.


Wait, I don't get what you are saying. You mean it should be 
marked nothrow? It's a template, so it *should* be inferred 
nothrow if it were actually nothrow.


The current definition is not marked nothrow as you alluded, 
and when I do mark it nothrow, it complains that the lazy 
parameter used for the exception handler is not nothrow.


It seems there's no way to infer the throwing of the lazy 
parameter, lazy parameters are never nothrow.


The higher order function DIP would I think help with this.

-Steve


Change it to a delegate and it's the same thing. ifThrown being a 
template is irrelevant in this case because it is accepting the 
handler as a function argument, not a template argument. You:


1. Need to make it a delegate instead of a lazy argument.

2. Need to mark the delegate as nothrow.

For the function to be inferred as nothrow.


Re: nothrow and std.exception.ifThrown

2021-04-30 Thread Meta via Digitalmars-d-learn

On Thursday, 29 April 2021 at 20:00:23 UTC, novice2 wrote:

i dont understand why (templates too dificult for me yet),
but if i comment "lazy" from T2,
then compiler allow add "nothrow" to "ifThrown"

```d
CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, 
T2)(lazy scope T1 expression, /*lazy*/ scope T2 errorHandler) 
nothrow

```
https://run.dlang.io/is/KTdd3G


This is because marking a function parameter as `lazy` is just 
syntax sugar for the following:

```
CommonType!(T1, T2) ifThrown(E: Throwable = Exception, T1, 
T2)(scope T1 delegate() expression, scope T2 delegate() 
errorHandler);


string def = "some string";
auto s = format("%d", x).ifThrown({ return def; });
```

Behind the scenes, a `lazy` parameter is not really a value - 
it's a function that _returns_ a value. The problem is that this 
function is not `nothrow`, and can't be marked as such (this is 
arguably a gap in the language). Removing `lazy` changes 
`errorHandler` to be a plain old value again - which cannot throw 
an exception, of course - so `ifThrown` can be marked `nothrow`. 
However, you lose all the benefits of `errorHandler` being lazily 
computed.


Re: nothrow and std.exception.ifThrown

2021-04-30 Thread Meta via Digitalmars-d-learn
On Friday, 30 April 2021 at 13:42:49 UTC, Steven Schveighoffer 
wrote:

On 4/30/21 9:24 AM, Meta wrote:

My point is that I think marking the *function* nothrow is not 
correct, it's the second parameter that dictates the throwing 
of the result.


And you can probably fix the second parameter to be a templated 
delegate:


```d
CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, 
T2)(lazy scope T1 expression, scope T2 errorHandler) if 
(is(typeof(errorHandler(E.init

```

And of course, we get into chicken-and-egg problems with this 
because if you pass in a lambda, there's no types for it to 
figure this stuff out. Another option is to overload on the 
delegate, but meh. I'd really like to see a language change 
that says "infer the attributes of this function based on the 
fact that it calls the delegate passed in."


-Steve


Now that you mention it, I don't see why lazy parameters can't 
have their attributes inferred. What happened to the DIP to 
replace lazy parameters with automatic conversion of passed 
values to delegates, anyway? I.e.:

```
CommonType!(T1, T2) ifThrown(E: Throwable = Exception, T1, 
T2)(scope T1 delegate() expression, scope T2 delegate() 
errorHandler);


//getString() and "some string" automatically converted to 
`string delegate()`

auto s = getString().ifThrown("some string");
```


Re: What is the meaning of @future ?

2021-09-17 Thread Meta via Digitalmars-d-learn

On Friday, 17 September 2021 at 10:31:34 UTC, bauss wrote:

On Thursday, 16 September 2021 at 20:53:34 UTC, Elmar wrote:

Hello D community.

I was browsing the `__traits` keywords and I found `isFuture` 
whose descriptions says something about `@future`-annotated 
variables.


[link](https://dlang.org/spec/traits.html#isFuture)

I didn't find anything about `@future` for the D programming 
language. I only found that this annotation is used in Apex to 
denote futures (a.k.a. promises) as programming concept.


Is this something which exists, existed, was abandoned early 
as an idea? I remember I had read that D uses a "fiber" 
library to provide coroutines and such.


Maybe somebody knows an answer for this.


It's just another "useless" attribute that the language has 
added before fixing any of the real problems :)


Basically it reserves a symbol for the future.

It's similar to creating ex. an empty function that throws an 
error or something like "Not implemented"


While I understand why it was added and what purpose it serves 
then I fail to see why that  was prioritized over actual issues.


It's solving an almost non-existing issue.


I think the main reason it was added is because Sociomantic asked 
for it, but they are of course not around anymore.


Re: split Error - no overload matches

2022-02-15 Thread meta via Digitalmars-d-learn

A trick i use often:

```D
import std;

void main()
{
import uni =  std.uni;
writeln("Learning D is fun".split!(uni.isWhite));
}

```

Under-rated way of importing things, you don't bloat your scope 
anymore





Re: https://run.dlang.io/ vs All dmd compilers (2.060 - latest)

2022-02-27 Thread meta via Digitalmars-d-learn

Is the source of 'run.dlang.io' available somewhere?


Re: Colors in Raylib

2022-03-01 Thread meta via Digitalmars-d-learn
If the type is ``Color`` I think the compiler should allow 
``GRAY`` if it is a member of ``Color``, isn't how strong 
statically typed language should work? I wonder what is the 
rational against it? How hard would it be to allow it?


Re: Colors in Raylib

2022-03-01 Thread meta via Digitalmars-d-learn
On Tuesday, 1 March 2022 at 12:29:56 UTC, Steven Schveighoffer 
wrote:

On 3/1/22 7:22 AM, meta wrote:
If the type is ``Color`` I think the compiler should allow 
``GRAY`` if it is a member of ``Color``, isn't how strong 
statically typed language should work? I wonder what is the 
rational against it? How hard would it be to allow it?


The problem is how the original source works.

The only way to define a manifest constant for a struct 
instance in C is to #define it.


So I'm sure that if raylib could put that inside the `Color` 
type it would, but it can't.


What a D binding should do is exactly what Mike said -- provide 
a complete binding as expected, and then add machine-generated 
nicer APIs.


I actually have an open issue, in case anyone is interested in 
working on it: https://github.com/schveiguy/raylib-d/issues/8


-Steve


Oh I was talking with regard to D's enum, not about the binding, 
allowing it via D, would make interfacing with C code easier


enum Color
{ GRAY }

void setColor(Color color);

setColor(GRAY);




Re: Colors in Raylib

2022-03-03 Thread meta via Digitalmars-d-learn

On Tuesday, 1 March 2022 at 15:37:55 UTC, Ali Çehreli wrote:

On 3/1/22 07:19, Mike Parker wrote:
> On Tuesday, 1 March 2022 at 13:15:09 UTC, meta wrote:
>
>>
>> enum Color
>> { GRAY }
>>
>> void setColor(Color color);
>>
>> setColor(GRAY);
>
> Then that defeats the purpose of having named enums.

Yes and no.

meta is pointing at a difference between the above and the 
following:


  writeln(GRAY);

In the latter case, the compiler has no clue whether I intended 
to type GRAM. But in the former case, the type is Color. What 
remains is whether the compiler should be looking deep into 
Color and have a list of values to lower GRAY to Color.GRAY.


We heard this before for the switch statement: When the 
variable is Color, the case values can be accepted as Color as 
well (without the qualifier). (Yes, 'with' works as well, but 
the idea is the same.)


It feels the same for even int because we don't write int(42) 
when passing an int argument:


void foo(int) {}

foo(int(42));  // works
foo(42);   // works as well

So the lack of this compiler help does not bother me but still, 
I think the request is meaningful.


Ali


Yes, that's exactly the point I was trying to make, thanks Ali!


Re: Warning on self assignment

2018-04-24 Thread Meta via Digitalmars-d-learn

On Wednesday, 25 April 2018 at 02:32:32 UTC, Per Nordlöw wrote:
On Wednesday, 25 April 2018 at 02:23:04 UTC, Mike Franklin 
wrote:
Are people using self assignment of structs as a way of 
force-running the postblit?  Is there a valid use case for 
that?


Mike


If they are, there should be a better way of force-running the 
postblit.


You can call __postblit or __xpostblit (I think the latter is a 
postblit introduced via a mixin or template mixin).


Re: Add property-like Function to Type ?

2018-04-24 Thread Meta via Digitalmars-d-learn

On Tuesday, 24 April 2018 at 21:36:19 UTC, Rubn wrote:
I was wondering if I could create my own property in a way that 
can be used the same way as something like "T.sizeof". Right 
now I have the following to replace length:


uint length32(T)(T[] array)
{
return cast(uint)array.length;
}

I want something similar to be able to do the following:


uint size = T.sizeof32;

The closest I can think of is doing:

uint size = sizeof32!T


That's the best I can do, which is fine but I was wondering if 
there's any other way around that?


If you don't control T and can't add members, then the best thing 
you can probably do is instead write T.init.sizeof32. Actually, 
though, you can be sneaky about it and use a local function to 
shadow Test, but this is probably more trouble than it's worth:


import std.stdio;

struct Test
{
}

@property sizeof32(Test t) { return 1; }

void main()
{
@property Test() { return .Test.init; }
writeln(Test.sizeof32);
}

This is really annoying, though, because you have to declare the 
Test function in every function or struct/class definition you 
use it in. You can create a mixin that does it automatically, but 
you'd still have to do `mixin(testProperties)` (where 
testProperties is an enum you've defined that's just the function 
definition).


Re: Create variable for RedBlackTree range

2018-05-02 Thread Meta via Digitalmars-d-learn

On Wednesday, 2 May 2018 at 10:39:29 UTC, ag0aep6g wrote:

On 04/28/2018 06:36 PM, Gerald wrote:
What is the appropriate way to create a variable for the range 
returned by RedBlackTree lowerBound and upperBound. For 
example, given this code:


```
RedBlackTree!long promptPosition = redBlackTree!long();

long row = to!long(vte.getVadjustment().getValue());
RBRange!(RBNode!long*) range;

[...]

}
```

The second line where I declare the range variable as 
RBRange!(RBNode!long*) the compiler complains with the 
following warning:


Deprecation: std.container.rbtree.RBRange(N) is not visible 
from module terminal


Which makes sense since RBRange is a private struct.


RedBlackTree also has public range types: Range, ConstRange, 
ImmutableRange. And `RedBlackTree!long.Range` is an alias for 
`RBRange!(RBNode!long*)`.


So:

RedBlackTree!long promptPosition = redBlackTree!long();
RedBlackTree!long.Range range;


For completeness' sake, and if you don't want to re-specify the 
template parameters you passed to RedBlackTree, you can write:


promptPosition.Range range;


Re: Ambiguous template parameter names

2018-05-02 Thread Meta via Digitalmars-d-learn

On Wednesday, 2 May 2018 at 20:32:43 UTC, jmh530 wrote:
In the function below, there is a template parameter and a 
normal parameter both with the same name. However, the function 
returns the normal parameter. The template parameter is 
effectively ignored. I was surprised by this behavior.


Is this a bug or intentional? I did not see it documented 
anywhere.



```
int foo(int val)(int val)
{
return val;
}

void main()
{
assert(foo!1(2) == 2);
}
```


It's not a big per se. It's a consequence of the declaration 
expanding to the real template function form (I can't type it all 
out as I'm on my phone), thus the inner `val` from the function 
shadows the one from the template.


Re: Ambiguous template parameter names

2018-05-02 Thread Meta via Digitalmars-d-learn

On Thursday, 3 May 2018 at 02:48:10 UTC, jmh530 wrote:

On Thursday, 3 May 2018 at 00:52:58 UTC, Meta wrote:

[snip]

It's not a big per se. It's a consequence of the declaration 
expanding to the real template function form (I can't type it 
all out as I'm on my phone), thus the inner `val` from the 
function shadows the one from the template.



That makes sense. Before creating the example, I would have 
assumed that when you instantiate it as foo!1, then the `val=1` 
would flow through to the inner foo function.


template foo(int val)
{
int foo(int val)
{
return val;
}
}


If you want that, you might be able to do `int val = val` on the 
inner function, though I'm not sure that'll work.


Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-09 Thread Meta via Digitalmars-d-learn

On Wednesday, 9 May 2018 at 14:07:37 UTC, Per Nordlöw wrote:

Why (on earth) does

struct S
{
@disable this(this);
int* _ptr;
}
pragma(msg, typeof(S.tupleof));

prints

(int*, void*)

when

struct S
{
int* _ptr;
}
pragma(msg, typeof(S.tupleof));

prints

(int*)

?!!!


I wasn't able to reproduce it on dmd-nightly: 
https://run.dlang.io/is/9wT8tH


What version of the compiler are you using?


Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-09 Thread Meta via Digitalmars-d-learn

On Wednesday, 9 May 2018 at 18:04:40 UTC, Per Nordlöw wrote:

On Wednesday, 9 May 2018 at 17:52:48 UTC, Meta wrote:
I wasn't able to reproduce it on dmd-nightly: 
https://run.dlang.io/is/9wT8tH


What version of the compiler are you using?


Ahh, the struct needs to be in a unittest block for it to 
happen:


struct R
{
@disable this(this);
int* _ptr;
}
unittest
{
struct S
{
@disable this(this);
int* _ptr;
}
struct T
{
int* _ptr;
}
pragma(msg, "R: ", typeof(R.tupleof));
pragma(msg, "S: ", typeof(S.tupleof));
pragma(msg, "T: ", typeof(T.tupleof));
}

prints

R: (int*)
S: (int*, void*)
T: (int*)

Why is that?


It's a context pointer to the enclosing function/object/struct. 
Mark the struct as static to get rid of it.


Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

2018-05-10 Thread Meta via Digitalmars-d-learn

On Thursday, 10 May 2018 at 12:55:36 UTC, Uknown wrote:

On Thursday, 10 May 2018 at 11:06:06 UTC, Per Nordlöw wrote:

On Wednesday, 9 May 2018 at 21:09:12 UTC, Meta wrote:
It's a context pointer to the enclosing 
function/object/struct. Mark the struct as static to get rid 
of it.


Ok, but why an extra void* for `S.tupleof` and not for 
`T.tupleof` which is also scoped inside a unittest?


I'm guessing T is a POD, so it doesn't need a context pointer, 
whereas S is not counted as a POD since a member function was 
@disabled.


Yes, exactly. From my tests, if you add _any_ member method to a 
struct, it becomes non-POD. When you think about it, this makes 
perfect sense, as there's no possible way to access anything 
through a context pointer if there is no executable code within 
the struct's scope.


As far an @disabled postblit:

Plain Old Data
A struct or union is Plain Old Data (POD) if it meets the 
following criteria:


it is not nested
it has no postblits, destructors, or assignment operators
it has no ref fields or fields that are themselves non-PO

https://docarchives.dlang.io/v2.079.0/spec/struct.html#POD

Now if you do this:

struct R
{
@disable this(this);
int* _ptr;
}
unittest
{
struct S
{
@disable this(this);
int* _ptr;
}
struct T
{
int* _ptr;
}
pragma(msg, "R: ", typeof(R.tupleof));
pragma(msg, __traits(allMembers, R));

pragma(msg, "S: ", typeof(S.tupleof));
pragma(msg, __traits(allMembers, S));

pragma(msg, "T: ", typeof(T.tupleof));
pragma(msg, __traits(allMembers, T));
}

It prints:

R: (int*)
tuple("__postblit", "_ptr", "__xpostblit", "opAssign")

S: (int*, void*)
tuple("__postblit", "_ptr", "this", "__xpostblit", "opAssign")

T: (int*)
tuple("_ptr")

So it looks like disabling a struct's postblit actually counts as 
having a __postblit and __xpostblit function (don't ask me why), 
in addition to a construction and opAssign... no idea why, and 
maybe this is a bug, but I bet there's a good reason for it.


Anyway, as per my first point, this means it'll need a context 
pointer unless you mark the struct as static.


Re: Creating a template mixin for explicit casts.

2018-05-17 Thread Meta via Digitalmars-d-learn

On Thursday, 17 May 2018 at 15:25:37 UTC, Sjoerd Nijboer wrote:

Given the following code
`struct Foo(T)
if(isNumeric!T)
{
T t;
.. other code
}

struct Bar(T)
if(isNumeric!T)
{
T t;
.. other code
}

Foo!float foo_float;

Foo!double foo_double;

Bar!float bar_float;
`

I want to make a template mixin that is able to cast one of 
these generic structs to the other explicitly. I have a bunch 
of these structs and therefore I thought it would make sense to 
do it by template mixin. I just don't know what language or 
library features I need to use and how to apply them.


`
fooDouble = cast (Foo!double) foo_float;		// case [1] if 
possible, done by

// an implicit cast. 
Else by
//explicit.

fooFloat = cast (Foo!float) foo_double; // case [2]

barFloat = cast (Bar!float) foo_float;  // case [3]
`

How would I do this in D?


Before you write anything yourself, check whether 
std.conv.castFrom does what you need:


https://dlang.org/phobos/std_conv.html#castFrom


Re: try & catch / repeating code - DRY

2018-05-22 Thread Meta via Digitalmars-d-learn

On Tuesday, 22 May 2018 at 18:20:43 UTC, Robert M. Münch wrote:

I see that I'm writing

try {
... different code ...
} catch (myException e) {
... same handling code ...
}

over and over again.

Of course I can put the exception handling code into a function 
to not duplicate it. However, I still need to write this 
construct over and over again. Is there a way to handle it more 
generic? Like:


??? (... code ...);

or

??? { ... code ...};

Where ??? would do the try and re-use the exception handling 
code everytime? I hope this is understandable.


Have you looked at std.exception.ifThrown? You could define a 
handler function and pass it to ifThrown for each expression that 
may throw. If it's a statement, I believe you could wrap it in a 
lambda which is immediately called, then append 
.ifThrown(handler).


Re: how to define infix function

2018-06-03 Thread Meta via Digitalmars-d-learn

On Saturday, 2 June 2018 at 23:17:48 UTC, Simen Kjærås wrote:

On Saturday, 2 June 2018 at 22:09:49 UTC, Neia Neutuladh wrote:

On Saturday, 2 June 2018 at 21:44:39 UTC, greatsam4sure wrote:

Sorry for the typo

is it possible to define infix function in D

3.min(5)// 3: where min is a function, works in D
3 min 5 // does not work.

thanks in advance


This is a horrible abuse of D's operator overloading 
discovered by FeepingCreature in the distant past.


You have to delimit your custom infix operator with slashes; 
you can't make `3 min 5` work, but you can make `3 /min/ 5` 
work.


Observe:

struct Min
{
MinIntermediate!T opBinaryRight(string op, T)(T value) if 
(op == "/")

{
return MinIntermediate!T(value);
}
}
struct MinIntermediate(T)
{
T value;
T opBinary(string op, T)(T value2) if (op == "/")
{
if (value < value2) return value;
return value2;
}
}
Min min;
void main()
{
writeln(1 /min/ 2);
}


And of course, this can be generalized:

struct Operator(alias fn, string operator = "/")
{
static auto opBinaryRight(string op : operator, T...)(T 
value1)

{
struct Result
{
auto opBinary(string op : operator, U...)(U value2)
if (__traits(compiles, fn(value1, value2)))
{
return fn(value1, value2);
}
}

Result result;
return result;
}
}

unittest
{
import std.algorithm.comparison;

alias min = Operator!(std.algorithm.comparison.min);

assert(1 /min/ 3 == 1);
}

Note also the use of static opBinaryRight, allowing one to 
eschew the 'min' variable.


All of this said, I would suggest not using this in prod - it's 
a neat trick that shows off some of D's power, but I don't see 
a case where this would be easier to understand than a 
straightforward function call.


--
  Simen


That is interesting. I don't know yet whether it's good or bad, 
but certainly, it's interesting.


Re: What is the point of nothrow?

2018-06-11 Thread Meta via Digitalmars-d-learn

On Monday, 11 June 2018 at 04:11:38 UTC, Bauss wrote:

On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis wrote:
On Sunday, June 10, 2018 23:59:17 Bauss via 
Digitalmars-d-learn wrote:
What is the point of nothrow if it can only detect when 
Exception is thrown and not when Error is thrown?


It seems like the attribute is useless because you can't 
really use it as protection to write bugless, safe code since 
the nasty bugs will pass by just fine.


I'm aware that it's a feature that nothrow can throw Error, 
but it makes the attribute completely useless because you 
basically have no safety to guard against writing code that 
throws Error.


To an extend @safe works, but there are tons of stuff that 
throws Error which you can only detect and guard against 
manually.


So what is the point of nothrow when it can only detect 
exceptions you'd catch anyway.


To me it would be so much more useful if you could detect 
code that could possibly throw Error.


Why do you care about detecting code that can throw an Error? 
Errors are supposed to kill the program, not get caught. As 
such, why does it matter if it can throw an Error?


Now, personally, I'm increasingly of the opinion that the fact 
that we have Errors is kind of dumb given that if it's going 
to kill the program, and it's not safe to do clean-up at that 
point, because the program is in an invalid state, then why 
not just print the message and stack trace right there and 
then kill the program instead of throwing anything? But 
unforntunately, that's not what happens, which does put things 
in the weird state where code can catch an Error even though 
it shouldn't be doing that.


As for the benefits of nothrow, as I understand it, they're 
twofold:


1. You know that you don't have to worry about any Exceptions 
being thrown from that code. You don't have to worry about 
doing any exception handling or having to ensure that anything 
gets cleaned up because of an Exception being thrown.


2. If the compiler knows that a function can't throw an 
Exception, then it doesn't have to insert any of the Exception 
handling mechanism stuff that it normally does when a function 
is called. It can assume that nothing ever gets thrown. If an 
Error does get thrown, then none of the proper clean-up will 
get done (e.g. constructors or scope statements), but because 
an Error being thrown means that the program is in an invalid 
state, it's not actually safe to be doing clean-up anyway. So, 
the fact that a function is nothrow gives you a performance 
benefit, because none of that extra Exception handling stuff 
gets inserted. How large a benefit that is in practice, I 
don't know, but it is a gain that can't be had with a function 
that isn't nothrow.


- Jonathan M Davis


Well at least from my point of view I would care about code 
that can throw Error, because if say nothrow could detect that 
then you could prevent writing that code that throws jt at all 
and thus you'd be writing less error prone code.


Maybe not necessarily nothrow, but something else that could 
ensure that your code is "100% safe" to run without any errors 
happening from ex. Accessing out of bounds, accessing invalid 
memory, attempting to access the member of an uninitialized 
class etc. Like you'd have to handle each such cases. Writing 
code in D today you have to think about each statement you 
write and whether it could possibly throw Error because you 
have little to no tools that helps you preventing writing such 
code.


I'm very well aware that Error is not supposed to be caught and 
that the program is in an invalid state, but ehat I'm trying to 
get at is that if nothrow or at least a feature similar existed 
that could detect code that may throw Error, then you could 
prevent writing code that throws it in the first place.


It would be a great tool to writing bugless code.


There's nothing unsafe about Error getting thrown in your code. 
Error makes your program more safe, because it terminates the 
program immediately instead of letting it do stuff like corrupt 
memory or crash the system.


Error getting thrown denotes a logic error in your program. Some 
base assumption you've made is not actually true, and thus the 
program is in an invalid state and must exit immediately. The 
reason why nothrow cannot help you here is because these are 
logic errors that are only detectable at runtime. If it was 
possible to detect these types of errors at compile time, then 
there would be no need for Error.


Re: foreach DFS/BFS for tree data-structure?

2018-06-14 Thread Meta via Digitalmars-d-learn

On Thursday, 14 June 2018 at 11:31:50 UTC, Robert M. Münch wrote:

I have a simple tree C data-structure that looks like this:

node {
node parent:
vector[node] children;
}

I would like to create two foreach algorthims, one follwing the 
breadth first search pattern and one the depth first search 
pattern.


Is this possible? I read about Inputranges, took a look at the 
RBTree code etc. but don't relly know/understand where to start.


While it's possible to do with input ranges, it's not pretty and 
I'm not sure that it's as performant as the traditional method. I 
would recommend going with one of the other suggestions in this 
thread.


Re: Why tuples are not ranges?

2018-06-28 Thread Meta via Digitalmars-d-learn

On Thursday, 28 June 2018 at 17:00:37 UTC, Mr.Bingo wrote:
I mean, if you think about it, the memory layout of a tuple is 
sequential types:


T1
T2
...

So, to popFront a tuple is just changing the starting offset.


You're right; it can definitely be done.

struct TupleRange(T...)
{
size_t index;
Tuple!T store;

@property length()
{
assert(index <= store.length);
return store.length - index;
}

Algebraic!T front()
{
assert(length > 0);
return typeof(return)(store[index]);
}

void popFront()
{
assert(length > 0);
index++;
}
}


Re: Implement Interface Using Super

2019-01-28 Thread Meta via Digitalmars-d-learn
On Monday, 28 January 2019 at 22:17:56 UTC, Steven Schveighoffer 
wrote:

On 1/28/19 3:28 PM, Jonathan Levi wrote:

On Sunday, 27 January 2019 at 09:31:46 UTC, bauss wrote:
On Sunday, 27 January 2019 at 05:37:57 UTC, Jonathan Levi 
wrote:

This works in LDC *but not* DMD?
. . .
Is this a bug in DMD *or* in LDC?


There is no bug here.


So... LDC is the one that is bugged?


Yeah, that's odd. It should be the same result, as they both 
have the same semantics for the front end.


I'll defer to an LDC developer to answer that, but in truth, it 
really should be the way LDC implements it, even if that's not 
how the language spec is.


I think it would have been nice to have a way of explicitly 
use the super method to implement an interface without having 
to rewrite the whole signature.  I thought I remember seeing a 
way once, but I must have been dreaming.


I agree.

BTW, the typeof(super) requirement is super-annoying. alias x = 
super.x; is clear, I don't see why we need to specify 
typeof(super) in this context at least.


-Steev


It's because aliases do not support context pointers, I'm pretty 
sure.


Re: Implement Interface Using Super

2019-01-29 Thread Meta via Digitalmars-d-learn
On Wednesday, 30 January 2019 at 01:02:37 UTC, Jonathan M Davis 
wrote:

Yeah. It would be like trying to do something like

alias x = this.x;

As it stands, I believe that super is always either used as a 
function call to the constructor or to mean the this pointer 
for the base class. I don't think that it ever means the type 
of the base class - just like this never means the type of the 
current class or struct. And their usage is pretty much 
identical. They're both either used for calling a constructor 
or for accessing the pointer/reference of the object. It's just 
that one of them is for the current class or struct, whereas 
the other is for a base class of the current class. The only 
difference in syntax that I can think of between them at the 
moment is that this is also used to name constructors when 
they're declared, whereas super is not used in that sort of way 
(since any constructor that would be referenced by super would 
be declared with this, not super).


- Jonathan M Davis


Current, you *can* use `super` to mean the type of the base 
class, but it's been deprecated in a recent release (IIRC):


class Super
{
}

class Sub
{
super test()
{
return new Super();
}
}

void main()
{
(new Sub()).test();
}

From DPaste:

Up to  2.080.1: Success and no output
Since  2.081.2: Success with output: onlineapp.d(7): 
Deprecation: Using `super` as a type is deprecated. Use 
`typeof(super)` instead


Re: Query for -dip1000

2019-02-11 Thread Meta via Digitalmars-d-learn

On Sunday, 10 February 2019 at 20:04:29 UTC, Per Nordlöw wrote:
Is there a way to query if the -dip1000 flag has been passed to 
the compiler? I need it for enabling certain DIP-1000 escape 
analysis tests only when -dip1000 has been passed.


For instance

static assert(!__traits(compiles, {
char[] f()
{
char[2] x;
return x[].splitterASCII!(_ => _ == ' 
').front;

}
}));

at

https://github.com/nordlow/phobos-next/blob/bd2fe42978aab2313977042c858d77c5766538e8/src/splitter_ex.d#L110

Or do I have to write a trait myself?


https://issues.dlang.org/show_bug.cgi?id=19669


Re: Block statements and memory management

2019-03-15 Thread Meta via Digitalmars-d-learn

On Saturday, 16 March 2019 at 03:47:43 UTC, Murilo wrote:
Does anyone know if when I create a variable inside a scope as 
in

{int a = 10;}
it disappears complete from the memory when the scope finishes? 
Or does it remain in some part of the memory? I am thinking of 
using scopes to make optimized programs that consume less 
memory.


I'd recommend against these sorts of micro-optimizations. 
Compilers are every good at doing this kind of thing manually so 
you don't have to worry about it and can concentrate on the 
actual logic of your program.


Re: How to debug long-lived D program memory usage?

2019-04-17 Thread Meta via Digitalmars-d-learn

On Wednesday, 17 April 2019 at 22:37:38 UTC, Adam D. Ruppe wrote:
On Wednesday, 17 April 2019 at 19:07:46 UTC, Jacob Carlborg 
wrote:

Perhaps try some of these flags [1] and [2].


oooh, those are very interesting too.

What I was kinda hoping is it would have stats for which file 
and line of code was responsible for most allocations; a 
detailed profile. But even so, this is an interesting gem.


Not at all what you want, but it may be useful for figuring out 
where the leaks are. Have you tried compiling with -vgc? 
https://dlang.org/dmd-windows.html#switch-vgc





Re: Elegant way to test if members of array A are present in array B?

2019-06-12 Thread Meta via Digitalmars-d-learn

On Tuesday, 11 June 2019 at 17:12:17 UTC, Robert M. Münch wrote:
Is there a simple and elegant way to do this? Or is just using 
a foreach(...) with canFind() the best way?


There are two versions of find that can find a range within 
another:


https://dlang.org/phobos/std_algorithm_searching.html#.find
https://dlang.org/phobos/std_algorithm_searching.html#.find.3


Re: Fiber based UI-Toolkit

2017-07-09 Thread Meta via Digitalmars-d-learn

On Sunday, 9 July 2017 at 21:12:24 UTC, bauss wrote:

On Sunday, 9 July 2017 at 19:43:14 UTC, Christian Köstlin wrote:
I wonder if there is any fiber based / fiber compatible 
UI-Toolkit out for dlang. The second question is, if it would 
make sense at all to have such a thing?


christian


It doesn't really make sense to have that, because most (if not 
all) operating systems only allow rendering from a single 
thread and I believe OSX (possibly macOS too.) only allows it 
from the main thread. Which means the only thing you can really 
operate on other threads are events, but you'll always have to 
do callbacks to your UI thread in order to render.


Aren't all fibers executed from a single thread?


Re: replacement for squeeze and removechars.

2017-07-18 Thread Meta via Digitalmars-d-learn

On Tuesday, 18 July 2017 at 15:28:06 UTC, Antonio Corbi wrote:

Hi all,

I'm trying dmd-2.075.0-rc1 in one of my projects where I use 
`squeeze` and `removechars`. Both of them are flagged as 
obsolete and in the docs we are suggested to use functions from 
std.regex and/or std.algorithm.


Does any one kow a one-liner from std.regex or std.algorithm 
that can take the role of those deprecated functions?


Thank's
A. Corbi


As Seb somewhat undiplomatically put, there are replacements 
listed in the changelog.


Use std.regex.replaceAll to replace std.string.removechars:

import std.string;
import std.regex;

// old
"abc".removechars("a-z");

// new
"abc".replaceAll(regex("[a-z]"), "");



Use std.algorithm.iteration.uniq to replace std.string.squeeze:

import std.algorithm;
import std.string;

// old
"hello".squeeze;

// new
"hello".uniq;



Though it would be nice to have these alternatives listed right 
there in the deprecation message.


Re: Array of Template instantiations

2017-07-20 Thread Meta via Digitalmars-d-learn

On Thursday, 20 July 2017 at 13:11:56 UTC, Alex wrote:

On Thursday, 20 July 2017 at 12:33:43 UTC, Alex wrote:
The Problem is, i dont know what type WHAT_TYPE is / i don´t 
know how to build a loopable something of futures.


Ok, i think i understood now.

my function `load` returns `KpiResponseEntity`
so

Future!(KpiResponseEntity)[] futures;

seems to work


To get the type you can also use `typeof`.

alias ResponseType = typeof(async(&load , queryA ));
ResponseType[] futures;
futures ~= async( &load , queryA );
futures ~= async( &load , queryB );
futures ~= async( &load , queryC );


Re: Pass range to a function

2017-07-28 Thread Meta via Digitalmars-d-learn

On Thursday, 27 July 2017 at 21:16:03 UTC, Chris wrote:
I'm using regex `matchAll`, and mapping it to get a sequence of 
strings. I then want to pass that sequence to a function. What 
is the general "sequence of strings" type declaration I'd need 
to use?


In C#, it'd be `IEnumerable`. I'd rather not do a 
to-array on the sequence, if possible. (e.g. It'd be nice to 
just pass the lazy sequence into my categorize function.)


What is the value of `???` in the following program:


```
import std.stdio, std.regex, std.string, 
std.algorithm.iteration;


auto regexToStrSeq(RegexMatch!string toks) {
  return toks.map!(t => t[0].strip());
}

void categorize(??? toks) {
  foreach (t; toks) {
writeln(t);
  }
}

void main()
{
auto reg = 
regex("[\\s,]*(~@|[\\[\\]{\\}()'`~^@]|\"(?:.|[^\"])*\"|;.*|[^\\s\\[\\]{}('\"`,;)]*)");

auto line = "(+ 1 (* 2 32))";
auto baz = matchAll(line, reg);

categorize(regexToStrSeq(baz).array);
}
```


If for some reason you can't make categorize a template like Ali 
suggested, or you need runtime polymorphism, you can use 
std.range.interfaces:


import std.range.interfaces;

void categorize(InputRange!string toks)
{
foreach (t; toks) {
writeln(t);
}
}

void main()
{
//etc.
categorize(inputRangeObject(regexToStrSeq(baz)));
}


Re: Is std.xml seriously broken, or is it me?

2017-07-29 Thread Meta via Digitalmars-d-learn

On Sunday, 30 July 2017 at 02:58:09 UTC, Mike wrote:

I'm trying to use std.xml, and I can't get it to work.

I tried the simplest program I could think of:

import std.xml;
import std.stdio;

void main()
{
	auto parser = new DocumentParser("encoding=\"utf-8\"?>");

parser.onStartTag["device"] = (ElementParser parser)
{
writeln("device");
};
parser.parse(); 
}

https://dpaste.dzfl.pl/262597d2fda6

I used it before without any trouble.  Is it somehow seriously 
broken?  If not, what am I doing wrong?


Thanks,
Mike


I don't know about your code specifically, but std.xml has been 
on the chopping block for many years and is pretty much still 
around because nobody has written a replacement yet. I'd 
recommend using Adam Ruppe's DOM library instead:


https://github.com/adamdruppe/arsd/blob/master/dom.d


Re: Template mixins and selective imports

2017-08-03 Thread Meta via Digitalmars-d-learn

On Thursday, 3 August 2017 at 15:29:47 UTC, jmh530 wrote:
I am trying to create a vectorize function that mixes in a new 
version of function with the same name that applies the 
function (to an ndslice).


The code below compiles without error and has the behavior I 
would expect.


However, when I change the function import to a selective 
import (e.g. from import std.math; to import std.math : sin;), 
then I get errors implying that the overload is not actually 
created.


Ideally, I would like to get this working with any kind of 
import.


One thing I noticed is that the fullyQualifiedName of sin 
changes quite a bit depending on whether you use one or the 
other.


This may be related to either of the following:
https://issues.dlang.org/show_bug.cgi?id=16287
https://issues.dlang.org/show_bug.cgi?id=16023



---

import std.traits : isFunction;

private enum _vectorize(string f) = "
import mir.ndslice.slice : SliceKind, Slice;

auto " ~ f ~ "(SliceKind kind, size_t[] packs, Iterator)
   (Slice!(kind, packs, 
Iterator) slice)

{
import mir.ndslice.topology : map;
return slice.map!(f);
}
";

mixin template vectorize(alias f)
if (isFunction!f)
{
mixin(_vectorize!(__traits(identifier, f)));
}

unittest
{
import std.stdio : writeln;
import mir.ndslice.slice : sliced;
import mir.ndslice.topology : map;
import std.math; //import std.math : sin;

auto x = [0.0, 1.0, 2.0, 3.0].sliced;

auto y = x.map!(sin);
writeln(y);

mixin vectorize!(sin);
auto z = sin(x);
writeln(z);
}


I'm not 100% certain, but I believe you have to bring the 
vectorized overload of sin into the overload set, so first try 
`mixin vectorize!sin vsin; alias sin = vsin;` and see if it works.


https://dlang.org/spec/function.html#overload-sets


Re: Template mixins and selective imports

2017-08-03 Thread Meta via Digitalmars-d-learn

On Thursday, 3 August 2017 at 19:03:55 UTC, Meta wrote:

`mixin vectorize!sin vsin; alias sin = vsin;` and see if it


Should be `alias sin = vsin.sin;`




Re: if (auto x = cast(C) x)

2017-08-09 Thread Meta via Digitalmars-d-learn

On Wednesday, 9 August 2017 at 21:54:46 UTC, Q. Schroll wrote:
For a class/interface type `A` and a class `C` inheriting from 
`A` one can do


  A a = getA();
  if (auto c = cast(C) a)
  { .. use c .. }

to get a `C` view on `a` if it happens to be a `C`-instance.

Sometimes one cannot find a good new name for `c` while there 
is no advantage of accessing `a` when `c` is available. D does 
not allow to shadow `a` in the if-auto declaration for good 
reasons. How about relaxing the rule for cases like these, 
where the rhs is the lhs with a cast to derived?


  if (auto a = cast(C) a)
  { .. use a typed as C .. }

One can think of `a` being *statically* retyped to `C` as this 
is a (strictly) better type information. Internally, it would 
be a shadowing, but it does not matter as the disadvantages 
don't apply (if I didn't miss something).


One option is to use 
https://dlang.org/library/std/algorithm/comparison/cast_switch.html


Re: Why does stringof not like functions with arguments?

2017-08-10 Thread Meta via Digitalmars-d-learn

On Wednesday, 9 August 2017 at 01:39:07 UTC, Jason Brady wrote:

Why does the following code error out with:

app.d(12,10): Error: function app.FunctionWithArguments (uint 
i) is not callable using argument types ()


Code:

import std.stdio;

void FunctionWithoutArguments() {
}

void FunctionWithArguments(uint i) {
}

void main()
{
writeln(FunctionWithoutArguments.stringof);
writeln(FunctionWithArguments.stringof);
}


Welcome to optional parentheses hell. Please enjoy your stay.

Because function calls in D can optionally omit the parens, 
`FunctionWithArguments.stringof` is actually attempting to call 
`FunctionWithArguments` without any arguments, and then call 
`stringof` on the result. In other words, it's actually trying to 
do this:


writeln(FunctionWithArguments().stringof);

And the D compiler is rightly telling you that you can't call the 
function with no arguments. The easiest solution is to use 
__traits(identifier) instead:


writeln(__traits(identifier, FunctionWithArguments));

You can make a handy template helper to do this for you:

enum stringOf(alias symbol) = __traits(identifier, symbol);
writeln(stringOf!FunctionWithArguments);


Re: Why does stringof not like functions with arguments?

2017-08-10 Thread Meta via Digitalmars-d-learn

On Thursday, 10 August 2017 at 15:55:41 UTC, Jason Brady wrote:
Wow. That makes perfect sense. I forgot stringof works only 
with expressions


It works with symbols too. See the following:

template test(){}
pragma(msg, test.stringof);




Re: Automatic function body writing howto?

2017-08-16 Thread Meta via Digitalmars-d-learn
It's hard to tell offhand but I would recommend that you extract 
the inner string into a function that generates that string, 
allowing you to print out the finished product before mixing it 
in.


Re: Choosing between enum arrays or AliasSeqs

2017-08-24 Thread Meta via Digitalmars-d-learn

On Thursday, 24 August 2017 at 19:41:46 UTC, Nordlöw wrote:

Given

   enum e = ['a', 'b', 'c'];

   import std.meta : AliasSeq;
   enum a = AliasSeq!['a', 'b', 'c'];

is it somehow possible to convert (at compile-time) `e` to `a`?

Is it cheaper CT-performance wise to use AliasSeq instead of 
enum static arrays?


My use case is expressed by the TODOs in the following code 
snippet



import std.algorithm : among;

/** English indefinite articles. */
enum englishIndefiniteArticles = [`a`, `an`];

/** English definite articles. */
enum englishDefiniteArticles = [`the`];

/** English definite articles. */
enum englishArticles = englishIndefiniteArticles ~ 
englishDefiniteArticles;


/** Check if $(D c) is a Vowel. */
bool isEnglishIndefiniteArticle(C)(C c)
if (isSomeChar!C)
{
return cast(bool)c.among!(`a`, `an`); // TODO reuse 
englishIndefiniteArticles

}

/** Check if $(D c) is a Vowel. */
bool isEnglishDefiniteArticle(C)(C c)
if (isSomeChar!C)
{
return cast(bool)c.among!(`the`); // TODO reuse 
englishDefiniteArticles

}

/** Check if $(D c) is a Vowel. */
bool isEnglishArticle(C)(C c)
if (isSomeChar!C)
{
return cast(bool)c.among!(`a`, `an`, `the`); // TODO reuse 
englishArticles

}


https://dlang.org/phobos/std_meta.html#aliasSeqOf


Re: How to check if string is available at compile time

2017-09-21 Thread Meta via Digitalmars-d-learn
On Thursday, 21 September 2017 at 12:30:15 UTC, David Bennett 
wrote:
On Thursday, 21 September 2017 at 11:42:36 UTC, David Bennett 
wrote:

[snip]

```
string[] escapeCTFE(Args...)(){

static foreach (arg; Args){
static if(__traits(compiles, ###WHATDOIPUTHERE###)){
[snip]



So far the best I've come up with is :

```

enum isCTstring(alias arg) = (!isAssignable!(typeof(arg)) || 
__traits(compiles, mixin(` "foo" ~ `~__traits(identifier, 
arg;


string[] escapeCTFE(Args...)(){

static foreach (arg; Args){
static if(isCTstring!(arg)){
pragma(msg, "Do work on string: ", arg);
}else{
pragma(msg, __traits(identifier, arg), " can only 
be read at runtime");

}
}
return new string[32];
}

```

But this seems quite hackish... any better ideas?


Try __traits(compiles, { enum _ = arg; }). Creating an enum 
necessarily requires that its value is available at compile time.


Re: Alias on an array element

2017-10-12 Thread Meta via Digitalmars-d-learn

On Friday, 13 October 2017 at 01:12:38 UTC, solidstate1991 wrote:
On Friday, 13 October 2017 at 01:09:56 UTC, solidstate1991 
wrote:
I'm making a struct for easy color handling Here's a code 
sample:


ublic struct Color{
union{
		uint raw;	///Raw representation in integer form, also forces 
the system to align in INT32.
		ubyte[4] colors;	///Normal representation, aliases are used 
for color naming.

ubyte alpha, red, green, blue;
}
version(LittleEndian){
alias alpha = colors[0];
alias red = colors[1];
alias green = colors[2];
alias blue = colors[3];
}else{
alias alpha = colors[3];
alias red = colors[2];
alias green = colors[1];
alias blue = colors[0];
}
}

All the aliases are fail to compile, have not found anything 
about it in any of the documentations I checked.


Edit: ubyte alpha, red, green, blue; was added so I can 
continue debugging after the refactoring until I find a 
solution.


You can only create aliases for symbols, not expressions. You 
could create accessor functions that return the appropriate 
indices.


Re: Alias on an array element

2017-10-13 Thread Meta via Digitalmars-d-learn

On Friday, 13 October 2017 at 13:22:42 UTC, Adam D. Ruppe wrote:
* Use a @property ref function to return the array element and 
trust the compiler to inline it.


You could also use pragma(inline, true).


Re: std.algorithm

2017-11-30 Thread Meta via Digitalmars-d-learn
On Thursday, 30 November 2017 at 20:49:36 UTC, flamencofantasy 
wrote:

Hello,

I have the following csv text;

auto input = "Start Date,End Date,Subject,All day 
event,Categories,Show time as

1/1/2018,1/1/2018,New Year's Day,TRUE,Holiday,3
1/15/2018,1/15/2018,\"Martin Luther King, Jr. 
Day\",TRUE,Holiday,3

2/19/2018,2/19/2018,President's Day,TRUE,Holiday,3
5/28/2018,5/28/2018,Memorial Day,TRUE,Holiday,3
7/4/2018,7/4/2018,Independence Day,TRUE,Holiday,3
9/3/2018,9/3/2018,Labor Day,TRUE,Holiday,3
11/22/2018,11/22/2018,Thanksgiving Day,TRUE,Holiday,3
11/23/2018,11/23/2018,Day after Thanksgiving,TRUE,Holiday,3
12/24/2018,12/24/2018,Christmas Eve,TRUE,Holiday,3
12/25/2018,12/25/2018,Christmas Day,TRUE,Holiday,3";

What is the most clean compact efficient/lazy way to produce a 
range that removes the first line and then retains the second 
and third columns of the following lines, basically producing 
this;



"1/1/2018,New Year's Day
1/15/2018,\"Martin Luther King, Jr. Day\"
2/19/2018,President's Day
5/28/2018,Memorial Day
7/4/2018,Independence Day
9/3/2018,Labor Day,TRUE
11/22/2018,Thanksgiving Day
11/23/2018,Day after Thanksgiving
12/24/2018,Christmas Eve
12/25/2018,Christmas Day"

Thanks a bunch


This *almost* works:

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

void main()
{
auto input = "Start Date,End Date,Subject,All day 
event,Categories,Show time as

1/1/2018,1/1/2018,New Year's Day,TRUE,Holiday,3
1/15/2018,1/15/2018,\"Martin Luther King, Jr. 
Day\",TRUE,Holiday,3

2/19/2018,2/19/2018,President's Day,TRUE,Holiday,3
5/28/2018,5/28/2018,Memorial Day,TRUE,Holiday,3
7/4/2018,7/4/2018,Independence Day,TRUE,Holiday,3
9/3/2018,9/3/2018,Labor Day,TRUE,Holiday,3
11/22/2018,11/22/2018,Thanksgiving 
Day,TRUE,Holiday,3
11/23/2018,11/23/2018,Day after 
Thanksgiving,TRUE,Holiday,3

12/24/2018,12/24/2018,Christmas Eve,TRUE,Holiday,3
12/25/2018,12/25/2018,Christmas 
Day,TRUE,Holiday,3";


input.lineSplitter()
.dropOne()
.map!(l =>
l.splitter(',')
 .dropOne()
 .take(2)
 .joiner(","))
.each!writeln();
}

The only problem is the comma in Martin Luther King, Jr. Day, so 
that line comes out as `1/15/2018,"Martin Luther King`.


Re: Using enum types

2017-12-04 Thread Meta via Digitalmars-d-learn

On Monday, 4 December 2017 at 22:34:41 UTC, helxi wrote:

Why can't enums be used as types in this (simplified) example?

enum Positivity
{
Positive,
Negative
}

struct Wave
{
public:
Positivity slope;
}

enum Waves
{
Sin = Wave(Positivity.Positive),
Cos = Wave(Positivity.Negative)
}

int nth_value(T : Waves)(int n);

int nth_value(T : Waves.Sin)(int n)
{
return n % 2 ? 1 : -1;
}

int nth_value(T : Waves.Cos)(int n)
{
return n % 2 ? -1 : 1;
}


We Adam said, Waves.Sin and Waves.Cos are values, while Waves 
itself is the type. You want to do the following:


int nth_value(Waves w: Waves.Sin)(int n)
{
//Etc.
}

At least I *think* that's what you want. I'm on mobile and dpaste 
is down so I have no way to double check the syntax, which I can 
never remember.


Re: Alias example should supposedly be illegal, but runs fine

2017-12-18 Thread Meta via Digitalmars-d-learn

On Monday, 18 December 2017 at 23:44:46 UTC, Michael wrote:

Hello,

I have been looking at the following example found right at the 
end of the section here: 
https://dlang.org/spec/declaration.html#alias


struct S { static int i; }
S s;

alias a = s.i; // illegal, s.i is an expression
alias b = S.i; // ok
b = 4; // sets S.i to 4

and it runs fine to me, including if I add:

a = 3;

So, to me I don't see why either can't be valid, but either way 
something needs to be fixed to reflect that this is no longer 
illegal in DMD v2.077.1.


I think the reason that this works is because i is static, 
meaning that you don't need the `this` reference of S to access 
it and thus it can be aliased. Declaring a static class or struct 
variable is pretty much the same as declaring a global variable, 
just with a tighter scope. If you look at it that way, then this 
makes a lot more sense. If you declare a global variable i at 
module scope, of course you can create an alias for it.


Re: structs inheriting from and implementing interfaces

2018-01-01 Thread Meta via Digitalmars-d-learn

On Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote:

In C#, structs can inherit from and implement interfaces.


using System;

interface IPrint
{
void Print();
}

struct MyStruct : IPrint
{
public void Print()
{
Console.WriteLine(ToString());
}
}

public class Program
{
public static void Main()
{
MyStruct s = new MyStruct();
s.Print();
}
}

https://dotnetfiddle.net/lpXR1O

But in D it doesn't appear possible.

import std.stdio;

interface IPrint
{
void print();
}

// Error: base classes are not allowed for struct, did you mean 
;?
struct MyStruct : IPrint   // Error: base classes are not 
allowed for struct, did you mean ;?

{
void print()
{
writeln("MyStruct");
}
}

void main()
{
MyStruct s;
s.Print();
}

https://run.dlang.io/is/j4xwla

Is that simply because it hasn't been implemented or suggested 
yet for D, or was there a deliberate design decision?


Thanks for your insight,

Mike


You want wrap: https://dlang.org/phobos/std_typecons.html#wrap


Re: Cannot use local lambda as parameter to non-global template

2018-01-15 Thread Meta via Digitalmars-d-learn

On Monday, 15 January 2018 at 13:55:57 UTC, Nordlöw wrote:

Why do I get errors like

template instance remove!((_) => _ == 1) cannot use local 
'__lambda5' as parameter to non-global template remove()(in K 
key)


for

x.remove!(_ => _ == 1);

but not for

x.remove!"a == 11";

?

How are these two lambdas different?

The function `remove` is a templated member of a struct 
instance `x`.


Can you give a bit more context? The following code does not 
cause a compile error:


import std.stdio;
import std.algorithm;

void main()
{
auto arr = [1, 2, 3];
arr.remove!(_ => _ == 1);
writeln(arr);
}

Or was that code meant as an example?


Re: Rewriting a c++ template to D (replacing iterator with ranges "properly")

2018-01-26 Thread Meta via Digitalmars-d-learn

On Friday, 26 January 2018 at 14:16:04 UTC, aliak wrote:
1) I've seen some phobos code checking for assignability like 
this:


  is(typeof(range.front = false))

... is that an advantage of that over hasAssignableElements? Or 
is that just basically combining constraints 3 and 4 which I 
have above?


Where did you see this? That's got to be some very old code; I 
can't think of any instance where you would not want to use 
`hasAssignableElements` instead.


Re: Error in template instantiation from D-Cookbook example

2018-02-09 Thread Meta via Digitalmars-d-learn

On Friday, 9 February 2018 at 21:31:29 UTC, ShadoLight wrote:

writeln(parse(code));   // to aid with debugging
writeln(convertToD(parse(code)));   // debugging aid
..to..
writeln(parse(code)[]); // to aid with debugging
writeln(convertToD(parse(code))[]); // debugging aid


The problem becomes apparent once you uncomment one of these and 
paste the offending string ("5 5 + 3 - 2 * 1 + 3 /") in. 
`writeln(convertToD(parse("5 5 + 3 - 2 * 1 + 3 /"))[]);` prints 
the following:


push(5);
push(5);
push(call!+(pop(), pop()));
push(3);
push(call!-(pop(), pop()));
push(2);
push(call!*(pop(), pop()));
push(1);
push(call!+(pop(), pop()));
push(3);
push(call!/(pop(), pop()));

If you look at the definition of call:

int call(string op)(int a, int b) {
return mixin("b"~op~"a");
}

So it takes a string as its sole template argument. The problem 
is that the code in convertToD forgot to add the quotes around 
the operators that are supposed to be passed as strings to call. 
If you modify line 14 from the example you pasted to add these 
quotes to the mixin string, it works:


code ~= "push(call!"~piece~"(pop(), pop()));\n";

becomes

code ~= "push(call!\""~piece~"\"(pop(), pop()));\n";

Running the modified code, it prints:

push(5);
push(5);
push(call!"+"(pop(), pop()));
push(3);
push(call!"-"(pop(), pop()));
push(2);
push(call!"*"(pop(), pop()));
push(1);
push(call!"+"(pop(), pop()));
push(3);
push(call!"/"(pop(), pop()));

And `runDslCode!"5 5 + 3 - 2 * 1 + 3 /"();` prints `[5]`.


Re: opCast cannot implicitly convert a.opCast of type X to Y

2018-02-14 Thread Meta via Digitalmars-d-learn

On Monday, 12 February 2018 at 02:05:16 UTC, aliak wrote:
From spec: Cast expression: "cast ( Type ) UnaryExpression" 
converts UnaryExpresssion to Type.


And https://dlang.org/spec/operatoroverloading.html#cast makes 
no mention of the return type of opCast. One could think that 
the return type of opCast would be the return type. But it 
seems it must be the same as the template parameter of opCast 
else you get a compile error that seems like it can be much 
better.


---

import std.stdio;

struct B(T) {
T t;
}

struct A(T) {
T t;
auto opCast(U)() {
return B!U(cast(U)t);
}
}

void main() {
auto a = A!int(3);
auto b = cast(float)a; // error
}

Error: cannot implicitly convert expression a.opCast() of type 
B!float to float


Is this deliberate?

The use case I have is making an optional type that you can 
cast to a different type:


auto opCast(U)() const {
static if (isOptional!U)
{
alias V = OptionalTarget!U;
return empty ? no!V : some!V(cast(V)front); // it's a 
range so "front" is the raw value

}
else
{
return empty ? no!U : some!U(cast(U)front);
}
}

It would allow for scenarios like:

Optional!int a = 3;
auto b = cast(float)a;
// b == some!float


Cheers
- Ali


I think the best way to do this is to implement `map` for your 
optional type.


Optional!U map(U, alias f)()
{
return empty? no!U : some!U(f(t));
}

Optional!int a = 3;
auto b = a.map!(v => cast(float)v);
assert(is(typeof(b) == Optional!float));


Re: opCast cannot implicitly convert a.opCast of type X to Y

2018-02-14 Thread Meta via Digitalmars-d-learn

On Wednesday, 14 February 2018 at 23:46:30 UTC, aliak wrote:

On Wednesday, 14 February 2018 at 15:14:24 UTC, Meta wrote:


I think the best way to do this is to implement `map` for your 
optional type.


Optional!U map(U, alias f)()
{
return empty? no!U : some!U(f(t));
}

Optional!int a = 3;
auto b = a.map!(v => cast(float)v);
assert(is(typeof(b) == Optional!float));


Ooh yes, of course! Thank you :)


Even better:

import std.conv;

auto b = a.map!(to!float);


Re: opCast cannot implicitly convert a.opCast of type X to Y

2018-02-14 Thread Meta via Digitalmars-d-learn

On Thursday, 15 February 2018 at 00:27:40 UTC, Meta wrote:

On Wednesday, 14 February 2018 at 23:46:30 UTC, aliak wrote:

On Wednesday, 14 February 2018 at 15:14:24 UTC, Meta wrote:

Ooh yes, of course! Thank you :)


Even better:

import std.conv;

auto b = a.map!(to!float);


Actually, that won't quite work without redefining map a little:

Optional!U map(alias f, U = typeof(f(t.init)))()
{
etc...
}


Re: Going from string to identifier

2018-02-21 Thread Meta via Digitalmars-d-learn
On Wednesday, 21 February 2018 at 22:11:04 UTC, Jean-Louis Leroy 
wrote:

Here's what I am trying to do:

mixin template MakeFun(string ID, int X)
{
  int mixin(ID)() { return X; }
}

mixin MakeFun!("one", 1); // int one() { return 1; }

Alas I get:
makefunc.d(3): Error: no identifier for declarator `int`
makefunc.d(3): Error: found `{` when expecting `;`
makefunc.d(3): Error: declaration expected, not `return`
makefunc.d(4): Error: unrecognized declaration

Is there a shorter way than building the entire function 
definition as a string mixin? As in:


mixin template MakeFun(string ID, int X)
{
  import std.format;
  mixin(format("int %s() { return %s; }", ID, X));
}

mixin MakeFun!("one", 1);


Mixins have to be full declarations. You can't mix in bits and 
pieces... except when you can:


import std.stdio;

void main()
{
enum teste = "asdf";
string s = mixin("teste");
writeln(s); //Prints "asdf"
}

It looks like a grammar error as opposed to a semantic one. D's 
grammar just doesn't support `mixin` in the function name 
position. One way you can make it a little more palateable:


mixin template MakeFun(string ID, int X)
{
import std.format;
mixin(q{ int %s { return %s; } }.format(ID, X));
}

`q{}` denotes a token string that must contain valid tokens (I'm 
not sure if the available compiler implementations actually 
enforce this), and I _think_ token strings will be properly 
syntax-highlighted by most tools.


https://dlang.org/spec/lex.html#token_strings


Re: Issue with traits usability

2018-03-23 Thread Meta via Digitalmars-d-learn

On Wednesday, 21 March 2018 at 15:36:01 UTC, Márcio Martins wrote:

Hi!

How do I get past this?


static struct X {
int x;
private enum T = 1;
private alias M = string;
}

foreach (Member; __traits(allMembers, X)) {
	pragma(msg, __traits(getProtection, __traits(getMember, X, 
Member)));

}


Output:

public
private
c.d(1084): Error: argument string has no protection
c.d(1084):while evaluating pragma(msg, 
__traits(getProtection, string))



What I want to achieve essentially is skip all X's aliases and 
templates, but get everything else, like enums and data 
members. How would I go about this in a robust way?

I actually want to skip aliases, and templates.


In addition to Simen's answer, you can you 
std.traits.FieldNameTuple to get only the fields of your struct 
(which only includes struct members that are actually part of the 
struct's memory layout):


import std.traits;

static struct X {
int x;
private enum T = 1;
private alias M = string;
}

void main()
{
foreach (Member; FieldNameTuple!X) {
pragma(msg, __traits(getProtection, __traits(getMember, 
X, Member)));

}
}

This example prints "public" once.


Re: Better way to append to array than ~= ?

2018-04-03 Thread Meta via Digitalmars-d-learn
On Tuesday, 3 April 2018 at 19:02:25 UTC, Vladimirs Nordholm 
wrote:

Hello people.

I currently have a function which multiple times per second 
takes in arguments, and appends the argument as my special 
type. The following code should explain what I do more properly:


struct MySpecialType { char c; }

auto foo(Args...)(Args args)
{
MySpecialType[] bar;

foreach(ref arg; args)
{
static if(is(typeof(arg) == MySpecialType))
{
bar ~= arg;
}
else
{
foreach(c; to!string(arg))
{
bar ~= MySpecialType(c);
}
}
}

// do more stuff
}

Now, from my trace.log, some of the topmost things on the 
timing list are `std.array.Appender!(immutable(char).stuff>`. I also remember reading some years ago that ~= isn't 
optimal for speed.


So my question is: Is there a better and/or faster way of doing 
this, or is this the best approach?


In this specific case, since you know the length of `Args`, you 
can pre-allocate an array of that size and loop through it doing 
your initialization.


However, if you want really performant code, you should allocate 
a static array on the stack outside of the function and pass it 
in as a buffer.


Re: Better way to append to array than ~= ?

2018-04-03 Thread Meta via Digitalmars-d-learn
On Tuesday, 3 April 2018 at 20:02:46 UTC, Vladimirs Nordholm 
wrote:

On Tuesday, 3 April 2018 at 19:53:11 UTC, Meta wrote:
On Tuesday, 3 April 2018 at 19:02:25 UTC, Vladimirs Nordholm 
wrote:

[...]


In this specific case, since you know the length of `Args`, 
you can pre-allocate an array of that size and loop through it 
doing your initialization.


However, if you want really performant code, you should 
allocate a static array on the stack outside of the function 
and pass it in as a buffer.


I don't think I know the size of the arguments.

If I pass in "123" and MySpecialType('a'), the result should be:

assert(foo("123", MySpecialType('a')) == 
[MySpecialType('1'), MySpecialType('2'), MySpecialType('3'), 
MySpecialType('a')]);


What should the length of the pre-allocated array be?


You know the static types of the arguments, so it is not 
impossible. However, the more flexible you need to be, the more 
complex your code will have to be, and it probably won't be worth 
the added complexity. Anyway, sorry for derailing a bit. That's 
not really your question.


Using Appender!MySpecialType might be marginally faster than ~=, 
but from the looks of it you are already using Appender. I don't 
know if there's much more you can do to speed up appending 
without just rolling your own solution or restructuring your code.


Re: Tree datatype

2015-10-14 Thread Meta via Digitalmars-d-learn

On Wednesday, 14 October 2015 at 14:42:31 UTC, Namal wrote:

Hello,

I don't remember exactly but I think when I first saw D code 
there was tree datatype implemented without pointers. Is it 
possible to make a tree struct without pointers?


The answer is more or less no, unless you sort of fake it like in 
cym13's example. A tree is not possible without pointers due to 
its recursive nature. Even if it looks like the implementation 
doesn't use pointers, they're just hidden under some abstraction.


Re: Why does File.byLine() return char[] and not string

2015-10-16 Thread Meta via Digitalmars-d-learn
On Friday, 16 October 2015 at 10:38:52 UTC, Shriramana Sharma 
wrote:
Is there a particular reason that File.byLine() returns char[] 
and not string i.e. immutable(char)[]? Is it just to avoid 
being overly restrictive? It seems that having to .idup it is 
inefficient...


byLine reuses an internal buffer for each line which gets 
overwritten each iteration. The fact that it returns char instead 
of string is meant to signal this to the user, to tell them that 
the value they're getting back is mutable and subject to change.


Re: Why can't function expecting immutable arg take mutable input?

2015-10-16 Thread Meta via Digitalmars-d-learn
On Friday, 16 October 2015 at 10:35:23 UTC, Shriramana Sharma 
wrote:
Hello. I still haven't wrapped my mind around the 
const/immutable thing yet and am still stuck in C/C++ mode. :-(


A function that takes mutable arguments cannot be called with 
immutable input at the call site since it does not promise to 
*not* mutate the input. That's of course clear.


Why can't a function that takes an immutable argument be called 
with a mutable input at the call site?


IOW, why isn't mutable implicitly convertible to immutable?

I just finished writing a string processing module which calls 
multiple subroutines, and all of them carrying arguments with 
type `string` viz. `immutable(char)[]` IIUC, and I tried to 
pass it something which came from File.byLine(), then got the 
error:


function textattr.applyTextAttr (string text) is not callable 
using argument types (char[])


I understand that const can refer to either mutable or 
immutable, so does this mean I should replace all occurrences 
of `string` in arguments and return values of functions by 
`const(char)[]`?


This actually *is* possible, if the type you're passing is a 
value type with no indirections. Then you can just pass it by 
value and it will be implicitly convertible to immutable. This 
doesn't work for char because it has indirections (a pointer to 
its data).


Re: Why can't function expecting immutable arg take mutable input?

2015-10-16 Thread Meta via Digitalmars-d-learn

On Friday, 16 October 2015 at 12:48:42 UTC, Meta wrote:
This doesn't work for char because it has indirections (a 
pointer to its data).


Whoops, should be char[], not char.


Re: Idiomatic adjacent_difference

2015-10-16 Thread Meta via Digitalmars-d-learn

On Friday, 16 October 2015 at 15:02:54 UTC, anonymous wrote:

On Friday, October 16, 2015 02:03 PM, Per Nordlöw wrote:


zip(r, r.dropOne).map!((t) => t[1]-t[0]);


You should r.save one or both of those. The dropOne may affect 
both instances if you don't .save.


By the way, what's the point of `dropOne` over `drop(1)`? It's 
not shorter. Does it do anything subtly different?


The only difference is that dropOne calls popFront and drop calls 
popFrontN.


Re: Why does File.byLine() return char[] and not string

2015-10-18 Thread Meta via Digitalmars-d-learn

On Sunday, 18 October 2015 at 15:03:22 UTC, Suliman wrote:
Sorry, but could you explain more simply? I reread all 
information, bit can't understand about what buffer you are 
talking.


This is more or less how byLine works, simplified:

struct ByLine
{
File file;
char[] line;
char[] buffer;
char terminator;

bool empty() { return line is null; }
char[] front() { return line; }

void popFront()
{
line = buffer;
file.readLine(line, terminator); //This overwrites the 
current contents of line

if (line.length > buffer.length)
{
buffer = line;
}

if (line.empty) line = null;
}
}

auto byLine(string fileName, char terminator = '\n')
{
return ByLine(File(fileName), terminator);
}



And what is "signal"? How it's working?


It's just an expression that means "to convey information". So 
when ByLine.front returns char[], a mutable array of char, it's 
meant to convey to the programmer that since the return value is 
mutable, it could change and they should make a copy.


Re: std.algorithm.startsWith only predicate

2015-10-18 Thread Meta via Digitalmars-d-learn

On Sunday, 18 October 2015 at 17:48:20 UTC, Freddy wrote:

How do you call startsWith with only a predicate
---
import std.algorithm;
import std.ascii;

bool iden(string str)
{
return str.startsWith!(a => a.isAlpha || a == '_');
}
---


Is this a simplified use case of some actual code you have? 
Otherwise, you can just do:



bool iden(string str)
{
auto f = str.front;
return f.isAlpha || f == '_';
}


Re: Mimicing Python list of list

2015-10-26 Thread Meta via Digitalmars-d-learn

On Monday, 26 October 2015 at 18:46:45 UTC, Dandyvica wrote:

Hi all,

I'm trying to find out a solution to implement a generic tree 
or array container whose nodes

can either be elements or a subtree (or sub-array).

Pretty much like you can do in Python:

l = [1, 2, [1, 2, 3], 4]

l is a list of (integers or list of integers).

Any idea on how to do that?

Thanks.


It's a bit more involved than in Python as D is not a dynamically 
typed language.


import std.typecons;
import std.stdio;

struct Tree(T)
{
T payload;
Tree!T[] children;
}

Tree!T tree(T)(T payload, Tree!T[] children...)
{
return Tree!T(payload, children.dup);
}

//Convenience overload because typeof(null)
//does not implicitly convert to Tree!T[]
Tree!T tree(T)(T payload, typeof(null))
{
return Tree!T(payload, null);
}

void printTree(T)(Tree!T tree)
{
writeln(tree.payload);
foreach (child; tree.children)
{
printTree(child);
}
}

void main()
{
auto intTree = tree(0,
   tree(1,
   tree(2)),
   tree(3,
   tree(4,
   tree(5))),
   tree(6,
   tree(7)));

printTree(intTree);
}

Otherwise, you an use std.variant.Variant or 
std.variant.Algebraic.


Re: Mimicing Python list of list

2015-10-26 Thread Meta via Digitalmars-d-learn

On Monday, 26 October 2015 at 20:53:18 UTC, Dandyvica wrote:

Thanks Meta, great idea.

But does I'd like to have something like dynamic arrays and be 
able to do this:


class A(T) { T _v; this(T v) { _v = v; }  }

auto myContainer = MyContainerArray!(A!int)();

myContainer ~= new A!int(1);
myContainer ~= new A!int(2);

auto myInnerContainer = MyContainerArray!(A!int)();
myInnerContainer ~= new A!int(3);
myInnerContainer ~= new A!int(4);

myContainer ~= myInnerContainer;
myContainer ~= new A!int(5);

I don't know if your implementation allows this?


There is a Red Black Tree implement in std.container.rbtree 
(http://dlang.org/phobos/std_container_rbtree.html). I'm not sure 
if it supports the concatenation operator or not, though.


Re: very very thank you

2015-10-29 Thread Meta via Digitalmars-d-learn

On Thursday, 29 October 2015 at 06:13:17 UTC, guodemone wrote:

衷心的谢谢你,(very veryvery thank you in english)


请问,你是学生吧?你是哪个中国大学的学生?我也希望DLang可以进入中国的大学,祝你的OS好运!


Re: conver BigInt to string

2015-11-05 Thread Meta via Digitalmars-d-learn

On Thursday, 5 November 2015 at 16:29:30 UTC, Namal wrote:
Hello I am trying to convert BigInt to string like that while 
trying to sort it:


string s1 = to!string(a).dup.sort;

and get an error

cannot implicitly convert expression (_adSortChar(dup(to(a 
of type char[] to string


what do I do wrong?


Try this instead:

string s1 = to!string(a).idup.sort()

I suspect there are two things happening here. First, calling dup 
on a string yields char[], not string (the difference being that 
string is immutable and char[] is not). A char[] cannot 
implicitly convert to string due to the difference in 
immutability, although the compiler *should* realize that the 
result of dup is a "unique" expression and be able to implicitly 
convert it... It may be because you then pass it to sort, which 
must keep it as a char[].


The second issue is that using .sort instead of .sort() (note the 
parentheses) calls the built-in sort instead of 
std.algorithm.sort, which is strongly discouraged. You should 
always use std.algorithm.sort over the built-in sort, which you 
can do just by appending those parentheses.


Re: conver BigInt to string

2015-11-05 Thread Meta via Digitalmars-d-learn

On Thursday, 5 November 2015 at 20:45:45 UTC, TheGag96 wrote:
Whoa whoa whoa... This is the first time I've heard about this 
difference, and I've used .sort plenty of times... That seems 
like really, REALLY bad design, especially considering the 
language allows functions to be called without parentheses. I 
thought I was using std.algorithm's version the whole time.


It's a legacy issue that will hopefully be fixed someday. The 
issue is that ever since D1, arrays have had a .sort property 
that uses a built-in sorting function. The compiler will only 
recognize it as the std.algorithm version of sort if you use 
parentheses.


What's the difference between the implementations of arrays' 
.sort property and std.algorithm.sort()? And does sort() throw 
out that "unable to deduce function argument" error for a 
character array of all things?


The built-in sort is buggy and slow and should never be used. As 
far as I know it does not produce errors of its own, so any error 
messages you see like that are coming from the std.algorithm sort.


Re: std.variant.Algebraic, self referential types and delegate members

2015-11-08 Thread Meta via Digitalmars-d-learn

On Sunday, 8 November 2015 at 10:31:13 UTC, Panke wrote:

import std.variant, std.stdio;

---
struct NodeTypeA(T) { T[] children; }
struct NodeTypeB(T) { Tree children; }
struct Leaf(T) { T delegate() dg; }

alias Tree = Algebraic!(Leaf, NodeTypeA!This, NodeTypeB!This);

void main()
{
  Tree t;
}
---

yields

tmp.d(6): Error: functions cannot return opaque type This by 
value
tmp.d(8): Error: template instance tmp.Leaf!(This) error 
instantiating


This limitation seems arbitrary to me. What's the reason here?


The issue is because your delegate inside Leaf returns a T by 
value, and T in this case is
the type std.variant.This; it's an opaque struct type to allow 
for recursive structures. If it sees This* or This[] in the 
template argument list to Algebraic, it'll do some magic to 
replace this with another Variant. That magic is 
std.typecons.ReplaceType[1]. However, note the warning on 
ReplaceType:


"However, member types in `struct`s or `class`es are not replaced 
because there

are no ways to express the types resulting after replacement."

And thus it can't replace the T return type of your delegate with 
the proper type. The compiler sees that you're trying to return 
the opaque struct This by value and violently disagrees with that 
notion, refusing to compile. To make that particular compiler 
error go away you can change the return type of the delegate to 
T* or T[], but that's not particularly useful as you're still 
just returning a pointer to This, not the recursive type. I'm not 
completely sure what you're trying to do is possible in D, and 
definitely not without enhancements to ReplaceType.



1. 
https://github.com/D-Programming-Language/phobos/blob/245c7ab0b591cb48b3dbb239640dd54e0717110a/std/typecons.d#L6643


Re: What does the -betterC switch in dmd do?

2015-11-15 Thread Meta via Digitalmars-d-learn

On Sunday, 15 November 2015 at 15:34:19 UTC, Jacob Carlborg wrote:
I'm pretty sure that the only things that are excluded are 
module info and type info. It's still possible to use "new" and 
all the array features that requires support in the runtime 
(slicing, concatenation, appending and so on).


Don't those features require type info?


Re: Unable to call each on a lockstep range containing 2 or more ranges

2015-11-18 Thread Meta via Digitalmars-d-learn

On Wednesday, 18 November 2015 at 12:20:42 UTC, maik klein wrote:

https://stackoverflow.com/questions/33779822/unable-to-call-each-on-a-lockstep-range-containing-2-or-more-ranges

http://dpaste.dzfl.pl/76c79f1f12ab

void main(){
  import std.container;
  import std.stdio;
  import std.algorithm.iteration;
  import std.range;
  Array!int ai = [1,2,3,4];
  Array!int ai1 = [1,2,3,4];
  Array!int ai2 = [1,2,3,4];

  auto arange = lockstep(ai[],ai1[]);
  arange.each!((a,b) => writeln(a, b));

  auto arange2 = lockstep(ai[],ai1[],ai2[]);
  arange2.each!((a,b,c) => writeln(a, b, c));
}

Error: template std.algorithm.iteration.each cannot deduce 
function from argument types !((a, b, c) => writeln(a, b, 
c))(Lockstep!(RangeT!(Array!int), RangeT!(Array!int), 
RangeT!(Array!int))), candidates are: 
/opt/compilers/dmd2/include/std/algorithm/iteration.d(820):

std.algorithm.iteration.each(alias pred = "a")


"arange" works but "arange2" doesn't because the compiler is 
unable to deduce the the function. The error even appears if I 
explicitly add the argument types.


Which version of the compiler are you using?


Re: Unable to call each on a lockstep range containing 2 or more ranges

2015-11-18 Thread Meta via Digitalmars-d-learn

On Wednesday, 18 November 2015 at 17:40:21 UTC, maik klein wrote:

On Wednesday, 18 November 2015 at 17:22:52 UTC, Meta wrote:


Which version of the compiler are you using?

Linux - DMD64 D Compiler v2.069.0


https://issues.dlang.org/show_bug.cgi?id=15357
https://issues.dlang.org/show_bug.cgi?id=15358


Re: char[] == null

2015-11-18 Thread Meta via Digitalmars-d-learn
On Wednesday, 18 November 2015 at 23:53:01 UTC, Chris Wright 
wrote:

---
char[] buffer;
if (buffer.length == 0) {}
---


This is not true. Consider the following code:

import std.stdio;

void main()
{
int[] a = [0, 1, 2];
//4002E000 3
writeln(a.ptr, " ", a.length);
//Is not triggered, obviously
assert(a == null);

a.length = 0;
//4002E000 0
writeln(a.ptr, " ", a.length, " ", a);
//Is not triggered, not as obvious
assert(a == null);
}

There are cases when an array may have 0 length but a non-null 
pointer. If you want to check if an array's length is 0, you must 
explicitly check its length member. Checking if an array is equal 
to null only compares its pointer field to null. It does *not* 
check the length.


Re: char[] == null

2015-11-19 Thread Meta via Digitalmars-d-learn
On Thursday, 19 November 2015 at 06:57:20 UTC, Jack Applegame 
wrote:

Really? http://dpaste.dzfl.pl/b11346e8e341


Sorry, I said the exact opposite of what I meant to say. The 
`assert(a == null)` *is* triggered because the expression `a == 
null` fails, even though a.length == 0. You should not use `a == 
null` to check if an array is empty. Always use a.length == 0.


Re: char[] == null

2015-11-19 Thread Meta via Digitalmars-d-learn

On Thursday, 19 November 2015 at 13:49:18 UTC, Meta wrote:
On Thursday, 19 November 2015 at 06:57:20 UTC, Jack Applegame 
wrote:

Really? http://dpaste.dzfl.pl/b11346e8e341


Sorry, I said the exact opposite of what I meant to say. The 
`assert(a == null)` *is* triggered because the expression `a == 
null` fails, even though a.length == 0. You should not use `a 
== null` to check if an array is empty. Always use a.length == 
0.


Actually, no it's not. Never mind.


Re: `finally` is redundant?

2015-11-21 Thread Meta via Digitalmars-d-learn
On Saturday, 21 November 2015 at 05:45:25 UTC, Shriramana Sharma 
wrote:

The page http://dlang.org/exception-safe.html says:

"It's try-finally that becomes redundant."

IIUC this is because we have scope(exit).

Does this mean that `finally` should eventually be removed from 
the language?


The most important reason not to do this is that it makes it 
easier to port Java, C#, Python, Ruby, etc. to D.


  1   2   3   4   5   >