Re: From the D Blog: Crafting Self-Evident Code in D

2023-10-26 Thread John Colvin via Digitalmars-d-announce

On Monday, 2 October 2023 at 17:28:19 UTC, Mike Parker wrote:
It's been a long, long while since I published anything on the 
blog. I do intend to get pick it up again down the road, but 
Walter recently surprised me with plans of his own. He's taken 
the topic of his DConf '23 talk and derived a blog post from it:


https://dlang.org/blog/2023/10/02/crafting-self-evident-code-with-d/

I guess he got impatient with the pace at which I'm getting the 
talk videos uploaded :-)


And for anyone who'd like to engage in any Reddit discussion 
that comes up:


https://www.reddit.com/r/programming/comments/16y2h36/crafting_selfevident_code_in_dlang/


Good talk.

Many very clever people would achieve more if they tried to 
understand why a v. experienced developer would care to spend so 
much time talking about what might appear to be such basic points.


The key challenge: If this stuff was so obvious & everyone did it 
or it didn't matter so much that they didn't, why would Walter 
care about it so much?


Re: mutable pointers as associative array keys

2023-04-11 Thread John Colvin via Digitalmars-d-learn
On Monday, 10 April 2023 at 20:31:43 UTC, Steven Schveighoffer 
wrote:

On 4/10/23 4:25 PM, Steven Schveighoffer wrote:
It's also completely useless. Having const keys does nothing 
to guarantee unchanging keys. Another half-assed attempt to be 
encode correct semantics but fails completely in its goal.


In case you wonder how old this is:

https://issues.dlang.org/show_bug.cgi?id=11477
https://issues.dlang.org/show_bug.cgi?id=12491#c2

-Steve


Oh dear.


mutable pointers as associative array keys

2023-04-10 Thread John Colvin via Digitalmars-d-learn

It seems that it isn't possible, am I missing something?

alias Q = int[int*];
pragma(msg, Q); // int[const(int)*]

Also, is this documented somewhere?


Re: text based file formats

2022-12-21 Thread John Colvin via Digitalmars-d-announce

On Wednesday, 21 December 2022 at 04:19:46 UTC, 9il wrote:

On Tuesday, 20 December 2022 at 19:46:36 UTC, John Colvin wrote:

On Tuesday, 20 December 2022 at 00:40:07 UTC, H. S. Teoh wrote:

[...]


We use this at work with some light tweaks, it’s done a lot 
work 


It has already been replaced with 
[mir.csv](https://github.com/libmir/mir-ion/blob/master/source/mir/csv.d). Mir is faster, SIMD accelerated, and supports numbers and timestamp recognition.


Hah, so it has! Well anyway, it did do a lot of hard work for us 
for a long time, so thanks :)


Re: text based file formats

2022-12-20 Thread John Colvin via Digitalmars-d-announce

On Tuesday, 20 December 2022 at 00:40:07 UTC, H. S. Teoh wrote:
On Mon, Dec 19, 2022 at 04:16:57PM -0800, Walter Bright via 
Digitalmars-d-announce wrote:

On 12/19/2022 4:35 AM, Adam D Ruppe wrote:
> On Monday, 19 December 2022 at 09:55:47 UTC, Walter Bright 
> wrote:

> > Curious why CSV isn't in the list.
> 
> Maybe std.csv is already good enough?


LOL, learn something every day! I've even written my own, but 
it isn't very good.


There's also my little experimental csv parser that was 
designed to be as fast as possible:


https://github.com/quickfur/fastcsv

However it can only handle input that fits in memory (using 
std.mmfile is one possible workaround), has a static limit on 
field sizes, and does not do validation.



T


We use this at work with some light tweaks, it’s done a lot work 


Re: Beerconf October 2022

2022-10-30 Thread John Colvin via Digitalmars-d-announce
On Sunday, 30 October 2022 at 01:50:33 UTC, Steven Schveighoffer 
wrote:

On 10/29/22 2:00 PM, FeepingCreature wrote:
On Saturday, 29 October 2022 at 10:14:31 UTC, rikki cattermole 
wrote:

And now for some good news!

Its almost Halloween, so grab your candy and any spooky brews 
you may have, and join us for a ghostly chat!


https://meet.jit.si/Dlang2022OctoberBeerConf


I wish you'd announce the time a bit in advance. :)


I don't want to announce a time, because I don't know what time 
it can be started. I'm in the US, so I'm usually asleep when 
it's started.


But I do try to announce 2 weeks before and then 2 days before.

-Steve


Quiet here, I’m around for a couple of hours, come say hi! 


Re: Symmetry looking for D programmers in Singapore/Hong Kong/Australia/New Zealand

2021-06-17 Thread John Colvin via Digitalmars-d-announce

On Wednesday, 16 June 2021 at 17:13:35 UTC, russhy wrote:

For what kind of project? need more info


It might help to look at https://jobs.symmetryinvestments.dev/ 
and https://github.com/symmetryinvestments/


Re: From the D Blog -- Interfacing D with C: Strings Part One

2021-05-24 Thread John Colvin via Digitalmars-d-announce
On Monday, 24 May 2021 at 16:16:53 UTC, Steven Schveighoffer 
wrote:

On 5/24/21 10:02 AM, Mike Parker wrote:
The latest post in the D and C series dives into the weeds of 
D and C strings: how they're implemented, when you need to 
NUL-terminate your D strings and when you don't, and how the 
storage of literals in memory allows you to avoid NUL 
termination in one case you might not have considered and 
another case that you shouldn't rely on but can in practice 
with the current compilers.


There are at least two more posts worth of information to go 
into on this topic, but everything in this post is enough to 
cover many use cases of D to C string interop.


The blog:
https://dlang.org/blog/2021/05/24/interfacing-d-with-c-strings-part-one/

Reddit:
https://www.reddit.com/r/programming/comments/njyf76/interfacing_d_with_c_strings_part_one/



Nice article!

Note that there is a huge pitfall awaiting you if you use 
`toStringz`: garbage collection. You may want to amend the 
article to identify this pitfall.


And I'm not talking about requiring `@nogc`, I'm talking about 
the GC collecting the data while C is still using it.


In your example:

```d
puts(s1.toStringz());
```

This leaves a GC-collectible allocation in C land. For `puts`, 
it's fine, as the data is not used past the call, but in 
something else that might keep it somewhere not accessible to 
the GC, you'll want to assign that to a variable that lasts as 
long as the resource is used.


-Steve


It’s worse than that, no? If the only reference to GC data isn’t 
on the stack of a tracked thread, in GC allocated memory or in a 
tracked root then it can be freed. Even in D:


void foo(int* a) {
int** b = cast(int**) malloc((int*).sizeof);
*b = a;
a = null;
GC.collect();
**b = 4; // whoops!!
}

foo(new int);

Right? Obviously that collection could be from calling another 
function (e.g. a callback from C to D code) or from another 
thread. Or am I missing something?


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread John Colvin via Digitalmars-d-announce

On Monday, 4 January 2021 at 17:22:55 UTC, John Colvin wrote:
On Monday, 4 January 2021 at 13:47:17 UTC, Ola Fosheim Grøstad 
wrote:

[...]


I have a longer reply I'm trying to write, but just to make 
sure I'm on the right track:


template Foo(T) {
alias Foo = T;
}

template Q(A : Foo!T, T) {
pragma(msg, A.stringof, " ", T.stringof);
}

alias X = Q!(Foo!int);

in your opinion, this should compile and msg `int int`, yes?

I'm trying to make a really concise example without using IFTI.


and presumably the same for
alias X = Q!(int);
yes?


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread John Colvin via Digitalmars-d-announce
On Monday, 4 January 2021 at 13:47:17 UTC, Ola Fosheim Grøstad 
wrote:

On Monday, 4 January 2021 at 12:35:12 UTC, John Colvin wrote:
What's the simplest example that doesn't work and is that 
simple example just indirection through an alias or is it 
actually indirection through a template that *when 
instantiated* turns out to be just an alias?


Indirection through a parametric alias. This is the simplest I 
have come up with so far:



  struct Foo(T) {}

  alias Bar(T) = Foo!T;

  void f(T)(Bar!T x) {}

  void main() {
f(Bar!int());
  }


I created a thread for it:

https://forum.dlang.org/post/nxrfrizqdmhzhivxp...@forum.dlang.org


I have a suspicion that what you're asking for here is the 
type-inference to have x-ray vision in to uninstantiated 
templates that works for a few simple cases. Am I wrong?


No, just substitute: "Bar!int" with "Foo!int".


To be clear, a really useful special case can be really useful 
and worthwhile, but I'm not convinced this is the principled 
"type system bug" you are saying it is.


Why are you not convinced?

An alias is a short hand. If it is possible to discriminate by 
the alias and the actual object then that it a semantic problem.


I have a longer reply I'm trying to write, but just to make sure 
I'm on the right track:


template Foo(T) {
alias Foo = T;
}

template Q(A : Foo!T, T) {
pragma(msg, A.stringof, " ", T.stringof);
}

alias X = Q!(Foo!int);

in your opinion, this should compile and msg `int int`, yes?

I'm trying to make a really concise example without using IFTI.


Re: Printing shortest decimal form of floating point number with Mir

2021-01-04 Thread John Colvin via Digitalmars-d-announce
On Monday, 4 January 2021 at 09:21:02 UTC, Ola Fosheim Grøstad 
wrote:
On Monday, 4 January 2021 at 09:18:50 UTC, Ola Fosheim Grøstad 
wrote:
On Monday, 4 January 2021 at 05:55:37 UTC, Ola Fosheim Grostad 
wrote:

On Monday, 4 January 2021 at 04:37:22 UTC, 9il wrote:
I suppose the answer would be that D doesn't pretend to 
support all C++ template features and the bug is not a bug 
because we live with this somehow for years.


But it is a bug even if there was no C++... An alias should 
work by simple substitution, if it does not, then it is no 
alias...


Here is an even simpler example that does not work:

struct Foo(T){}
void foo(T)(T!int x) {}

alias FooInt = Foo!int;

void main() {
foo(FooInt());
}


Oh, now wait, it does:

struct Foo(T){}
void foo(alias T)(T!int x) {}
alias FooInt = Foo!int;

void main() {
foo(FooInt());
}

My mistake.


What's the simplest example that doesn't work and is that simple 
example just indirection through an alias or is it actually 
indirection through a template that *when instantiated* turns out 
to be just an alias?


I have a suspicion that what you're asking for here is the 
type-inference to have x-ray vision in to uninstantiated 
templates that works for a few simple cases. Am I wrong?


To be clear, a really useful special case can be really useful 
and worthwhile, but I'm not convinced this is the principled 
"type system bug" you are saying it is.


Re: Printing shortest decimal form of floating point number with Mir

2020-12-24 Thread John Colvin via Digitalmars-d-announce

On Thursday, 24 December 2020 at 14:14:33 UTC, 9il wrote:

On Thursday, 24 December 2020 at 14:08:32 UTC, welkam wrote:

On Wednesday, 23 December 2020 at 18:05:40 UTC, 9il wrote:

It was a mockery executed by Atila

Read the all comments and didnt saw any mockery


Yes, it wasn't explicit. He didn't write bad words, he did a 
bad decision. Bad for D.


Big difference between bad decision and mockery. It's very 
possible he was wrong, but I don't think he wasn't taking it 
seriously.


Re: MIR vs. Numpy

2020-11-18 Thread John Colvin via Digitalmars-d-announce
On Wednesday, 18 November 2020 at 13:01:42 UTC, Bastiaan Veelo 
wrote:
On Wednesday, 18 November 2020 at 10:05:06 UTC, Tobias Schmidt 
wrote:

Dear all,

to compare MIR and Numpy in the HPC context, we implemented a 
multigrid solver in Python using Numpy and in D using Mir and 
perforemd some benchmarks with them.


You can find our code and results here:
https://github.com/typohnebild/numpy-vs-mir


Nice numbers. I’m not a Python guy but I was under the 
impression that Numpy actually is written in C, so that when 
you benchmark Numpy you’re mostly benchmarking C, not Python. 
Therefore I had expected the Numpy performance to be much 
closer to D’s. An important factor I think, which I’m not sure 
you have discussed (didn’t look too closely), is the compiler 
backend that was used to compile D and Numpy. Then again, as a 
user one is mostly interested in the out-of-the-box 
performance, which this seems to be a good measure of.


— Bastiaan.


A lot of numpy is in C, C++, fortran, asm etc

But when you chain a bunch of things together, you are going via 
python. The language boundary (and python being slow) means that 
internal iteration in native code is a requirement for 
performance, which leads to eager allocation for composability 
via python, which then hurts performance. Numpy makes a very good 
effort, but is always constrained by this. Clever schemes with 
laziness where operations in python are actually just composing 
operations for execution later/on-demand can work as an 
alternative, but a) that's hard and b) even if you can completely 
avoid calling back in to python during iteration you would still 
need JIT to really unlock the performance.


Julia fixes this by having all/most in one language which is JIT'd

D can do the same with templates AOT, like C++/Eigen does but 
more flexible and less terrifying code. That's (one part of) what 
mir provides.


Highlight general point about software dev and design in general.

2020-10-22 Thread John Colvin via Digitalmars-d-announce

On Tuesday, 20 October 2020 at 21:58:16 UTC, Johan Engelen wrote:

On Tuesday, 20 October 2020 at 20:21:56 UTC, aberba wrote:

On Tuesday, 20 October 2020 at 17:36:11 UTC, kinke wrote:

On Tuesday, 20 October 2020 at 16:08:47 UTC, aberba wrote:
It's an option but doesn't fill the need for an installer. 
Not sure why its hasn't been done.


See https://github.com/ldc-developers/ldc/issues/1754.


From the discussions, it seems you still don't see the value 
of an installer...backing it with the idea that LDC is for 
"developers". I'm a developer myself and I use installers all 
the time when on Windows...there are very few people I 
personally know who would go for an archive file to set it up 
themselves.


So not everyone is like you. The reason why I personally go 
for DMD over LDC is convenience (especially when introducing D 
to newbies)...even though LDC is more optimized for 
performance.


Unless what you guys are doing is an artificial barrier to get 
others to not use it.


Guys, all points have been made, there is no wrong and right 
here, let's stop arguing over this.


What is needed is someone who thinks it is useful to have an 
exe installer and wants to do the work. It cannot be done by 
someone who thinks it is not useful, because there are 
decisions to be made (like which folder to install it in, 
whether to overwrite old or not), that can only be made by 
someone who actually cares about it. There is no point in 
trying to convince kinke or me.


I'm sure noone will be against uploading the installer exe onto 
github release page once it's been made and checked.


-Johan


Johan hits an important nail right on the head here.

While it is possible to design for others who are unlike you, 
it's much harder than designing for yourself or those who have 
similar values and priorities w.r.t. the thing in question. A lot 
of talk about "we (and by we I mean you) should do this thing I 
think is important" isn't pushing in the most productive 
direction, because


_*_*_{
even if one becomes convinced that there is value in something, 
that does not mean one has the relevant understanding necessary 
for good design of that thing

}_*_*_

Either the person with the problem works on understanding the 
tools to fix the problem, or the person with the tools works on 
understanding the problem. When values and "user experience" and 
"ease of use" are in play, I think the latter usually gets harder 
than normal, because understanding what will be easy or pleasing 
for others who are unlike us is not something everyone is good 
at.* This shifts the balance towards preferring the former 
approach where the person with the problem works towards doing at 
least a significant part of the design.** There will always be 
other considerations of course, this is just one force out of 
many.


This is not to say that developers shouldn't be thoughtful about 
their users - they definitely should be - but that doing a good 
job of that when the users are unlike the developer is _hard_.


* Perhaps in practice that ability is negatively associated with 
a strong sense of personal taste, e.g. great musicians writing 
the music _they_ want, not trying to specifically please people; 
the magic isn't that they understand other people, it's that 
their particular tastes resonate with others strongly. Maybe 
truly great mass-market businesses come from people who both have 
that magic _and_ a strong ability to experience their work from 
other's perspectives, the combination being rare and the ability 
to integrate the two effectively being even rarer (Steve Jobs 
comes to mind).


** Design and implementation often don't separate very cleanly in 
practice, so this probably means implementing it too, at least to 
proof-of-concept quality.


Re: Beta 2.094.0

2020-09-18 Thread John Colvin via Digitalmars-d-announce
On Friday, 18 September 2020 at 13:35:34 UTC, Jacob Carlborg 
wrote:

On 2020-09-17 12:10, John Colvin wrote:

I personally think it's not so bad as long as the commit gets 
written to the dub.selections.json


It doesn't.


I know. But it should be.

But then again a lot of things “should be” with dub.


Re: Beta 2.094.0

2020-09-17 Thread John Colvin via Digitalmars-d-announce
On Wednesday, 16 September 2020 at 18:52:23 UTC, Jacob Carlborg 
wrote:

On 2020-09-16 19:20, mw wrote:


Why it's deprecated? can we revive it?


It was deprecated because it's a bad idea to not lock versions. 
Using `~master` would fetch the latest code from the "master" 
branch when compiling. You never know which version you get. 
You don't get reproducible builds.


I personally think it's not so bad as long as the commit gets 
written to the dub.selections.json


Re: Decimal string to floating point conversion with correct half-to-even rounding

2020-07-07 Thread John Colvin via Digitalmars-d-announce

On Tuesday, 7 July 2020 at 15:08:33 UTC, Adam D. Ruppe wrote:
On Tuesday, 7 July 2020 at 13:00:04 UTC, Steven Schveighoffer 
wrote:
Doing that these days would be silly. You can depend on a 
specific version of a repository without problems.


I always have problems when trying to do that. git submodules 
bring pretty consistent pain in my experience.


But it probably isn't so bad if the submodule rarely changes.

Just for 100% control anyway nothing beats copy/paste. Then 
there's zero difference between you writing it yourself.


I kinda wish the D upstream were more willing to do that. My 
view is it shouldn't be on independent developers to add stuff 
to Phobos, for example, instead the Phobos team should just be 
copying and testing modules they are interested in on their own.


git subtree

it's like submodules but also like copy-paste.


Re: Rationale for accepting DIP 1028 as is

2020-05-27 Thread John Colvin via Digitalmars-d-announce

On Wednesday, 27 May 2020 at 05:49:49 UTC, Walter Bright wrote:

On 5/26/2020 9:31 AM, Bruce Carneal wrote:
Currently a machine checked @safe function calling an 
unannotated extern C routine will error out during 
compilation. This is great as the C routine was not machine 
checked, and generally can not be checked.  Post 1028, IIUC, 
the compilation will go through without complaint.  This seems 
quite clear.  What am I missing?


Nothing at all.

But I doubt there is much legacy non-compiling code around.


The point isn't that incorrect legacy code that didn't compile 
now does (although that does matter a bit), it's that newly 
written code will compile when it shouldn't.


Existing code will be full of extern(C) declarations that are 
implicitly and correctly @system now and will become @safe with 
dip1028, which means that when I write new @safe code calling 
those (could be through a deep dependency chain of 
inferred-@safety APIs, multiple dub packages...) I could easily 
find my new code compiling when it shouldn't.



Effectively, by silently @safe-ing things you can't infer, you 
will be changing APIs from @system to @trusted without any checks.



Just in case there's any confusion, here's a timeline:

1. library A is written containing a dangerous but useful 
extern(C) declaration assuming @system by default.
2. application B is written for and compiled with dip1028, @safe: 
at the top of every file.
3. B adds a dependency on A. It continues to compile as @safe, 
calling an unsafe C function.



This seems like one of those things where it's either wrong or a 
showstopper.


Re: Objective C protocols

2020-05-17 Thread John Colvin via Digitalmars-d-learn

On Saturday, 16 May 2020 at 19:14:51 UTC, John Colvin wrote:

What's the best way to implement an Objective C protocol in D?

I see mention here 
https://dlang.org/changelog/2.085.0.html#4_deprecated_objc_interfaces but it's not clear where things are these days.


Based on some experimentation, I'm starting to wonder do 
protocols actually have any runtime component in Objective C? 
Because if I pass in an extern(Objective-C) class with the right 
interface to a function expecting a protocol everything just 
works.


Objective C protocols

2020-05-16 Thread John Colvin via Digitalmars-d-learn

What's the best way to implement an Objective C protocol in D?

I see mention here 
https://dlang.org/changelog/2.085.0.html#4_deprecated_objc_interfaces but it's not clear where things are these days.


Re: Luneta: terminal fuzzy finder

2020-05-05 Thread John Colvin via Digitalmars-d-announce

On Tuesday, 5 May 2020 at 07:31:18 UTC, Panke wrote:

On Monday, 4 May 2020 at 22:49:49 UTC, Felipe wrote:

Hi,

I develop an interactive terminal fuzzy finder in D with 
ncurses.

Feel free to check it out and contribute.

Any feedback is welcome.

Thanks, Felipe

[1] https://github.com/fbeline/luneta
[2] https://code.dlang.org/packages/luneta
[3] https://code.dlang.org/packages/fuzzyd


What's the difference to fzf?


Seems like this is being discussed here: 
https://github.com/fbeline/luneta/issues/28


Re: dmdcache

2020-04-25 Thread John Colvin via Digitalmars-d-announce

On Saturday, 25 April 2020 at 10:17:50 UTC, Ali Çehreli wrote:
A colleague of mine has written dmdcache which may be very 
useful for some projects:


  https://github.com/seeraven/dmdcache

It drops our build time

  from 8 minutes
  to 45 seconds

on a particular build environment for about half a dozen D 
programs, one of which ends up being a 2G executable! WAT! :) 
And the total cache size is 5.5G. Wow!


This build is with dmd 2.084.1 and that one particular 
application uses tons of template instantiations most of which 
are in generated source code. If I remember correctly, 2.084.1 
does not contain template symbol name improvements and that may 
be the reason for the large size.


Enjoy!

Ali


Perhaps I'm being very dumb, but how does this differ from just 
using make?


Re: DConf 2019 Pictures

2020-01-07 Thread John Colvin via Digitalmars-d-announce

On Tuesday, 7 January 2020 at 13:37:24 UTC, Ethan wrote:

On Tuesday, 7 January 2020 at 09:04:04 UTC, Ali Çehreli wrote:

This one is Laeeth introducing Andrei at Symmetry Investments:

  http://acehreli.org/photo/dconf_2019/DSC04839.html

Ali


And if you start here you get to the important bits: BeerConf!

http://acehreli.org/photo/dconf_2019/DSC04853.html


Damn... I miss beerconf.


Re: code.dlang.org downtime

2019-12-18 Thread John Colvin via Digitalmars-d-announce
On Wednesday, 18 December 2019 at 10:18:03 UTC, Sebastiaan Koppe 
wrote:
On Wednesday, 18 December 2019 at 09:29:50 UTC, John Colvin 
wrote:
This is still down for me, regardless of using the IP or 
address. I don't think it's just me either: 
https://stats.uptimerobot.com/6mQX4Crw2L/783838659


Anytime you see the metadata working you can add 
`--registry=https://dub.bytecraft.nl` to dub.


I am really tempted to cache the metadata as well. Although 
that brings up the question of how to purge it when new 
versions are released. (I could setup a job to import the dump 
every now and then, hmm).


This stuff just begs to be fixed.


can't get metadata, so no good right now.


Re: code.dlang.org downtime

2019-12-18 Thread John Colvin via Digitalmars-d-announce

On Monday, 16 December 2019 at 11:04:38 UTC, Sönke Ludwig wrote:
As you may have already noticed, the main registry server, 
code.dlang.org got unreachable yesterday. This was caused by an 
old VPS of mine getting terminated. The registry had already 
moved to a different server years ago, but, without me 
realizing it, the DNS entry still pointed to the old one, with 
a "temporary" HTTP proxy forwarding to the new server being set 
up.


By now the DNS entry has been corrected, an up-to-date TLS 
certificate is in place, and the registry is running stable. 
There are still reports of people not being able to access 
code.dlang.org, which is apparently caused by intermediate DNS 
servers still reporting the old IP address and should start 
working during the next few hours. A temporary workaround is to 
specify --registry=http://31.15.67.41/ on the dub command line.


Unfortunately both fallback servers have been down for a while 
now, so that this resulted in a total blackout. I plan to move 
the main registry to a powerful dedicated server in January, 
which will fix all memory resource related issues that 
sometimes show up, and could then keep the current VPS as a 
relatively reliable fallback server. Both together should 
guarantee virtually 100% uptime, although more fallback servers 
are of course highly desirable.


In addition to that, I plan to separate the repository polling 
process form the web and REST frontend, as the former appears 
to be the main cause for failures (a GC memory leak of some 
kind and a possibly codegen related crash when being compiled 
with DMD being the two known issues, which both need further 
investigation).


This is still down for me, regardless of using the IP or address. 
I don't think it's just me either: 
https://stats.uptimerobot.com/6mQX4Crw2L/783838659


Re: A proper WAT moment

2019-10-15 Thread John Colvin via Digitalmars-d-learn

On Monday, 14 October 2019 at 19:45:11 UTC, Paul Backus wrote:

On Monday, 14 October 2019 at 17:00:56 UTC, John Colvin wrote:
Different ability to access a property depending if I'm inside 
something else when I look?


[snip]


You're attempting to call one of S's member functions without 
an instance of S to call it on. Reduced version:


struct S
{
int a;
int e() @property { return a; }
}

void foo(S s)
{
pragma(msg, __LINE__, " ", __traits(compiles, S.e)); // 
true (???)

S.e; // Error: need `this` for `e` of type `@property int()`
}

struct C
{
void foo(S s)
{
pragma(msg, __LINE__, " ", __traits(compiles, S.e)); // 
false
S.e; // Error: `this` for `e` needs to be type `S` not 
type `C`

}
}

The real issue here is that the first `__traits(compiles)` 
check succeeds, even though the actual expression fails.


And all the other ones in my example that access members without 
an instance that also compile?


There's something pretty strange about the rules here.


A proper WAT moment

2019-10-14 Thread John Colvin via Digitalmars-d-learn
Different ability to access a property depending if I'm inside 
something else when I look?


struct S
{
int a;
static int b;
int c() { return a; }
static int d() { return 3; }
int e() @property { return a; }
static int f() @property { return 3; }
}

void foo(S s)
{
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "a")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "a")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "b")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "b")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "c")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "c")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "d")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "d")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "e")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "e")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "f")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "f")));

}

struct C(S)
{
void foo(S s)
{
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "a")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "a")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "b")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "b")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "c")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "c")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "d")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "d")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "e")));

// ALL True except for this one:
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "e")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "f")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "f")));

}
}

alias C0 = C!S;


How to find what is causing a closure allocation

2019-10-02 Thread John Colvin via Digitalmars-d-learn
I have a function that allocates a closure somewhere in it (as 
shown by the result of -profile=gc).


I can't make the function nogc as it calls a lot of other GC 
using code.


profilegc.log only gives me the line number of the function 
signature, which doesn't give me any hint as to where in the 
function the closure is allocated.


Anyone have any nice tricks to help narrow this down.


Re: Abstract classes vs interfaces, casting from void*

2019-08-11 Thread John Colvin via Digitalmars-d-learn

On Sunday, 11 August 2019 at 20:15:34 UTC, Alex wrote:

On Sunday, 11 August 2019 at 16:05:20 UTC, John Colvin wrote:
I'm trying to narrow down exactly what patterns work with each 
and how they overlap.


What I was trying to get at with the abstract method thing is 
that


abstract class C
{
void foo();
}

is an abstract class with a non-abstract method, whose 
implementation is going to come from somewhere else (not a 
common pattern in D).


class C
{
abstract void foo();
}

is an abstract class with an abstract method foo, which means 
you have to override it in a inheriting class to get a 
non-abstract class.


As I see this, everything you wrote is correct. :)

But you compared abstractness with interface usage, initially. 
So... I would say, interfaces are more like the abstract method 
case without any function body. But then, you will have to use 
"override" all across the inherited classes.


Ok. So that means the difference is pretty subtle, give or take a 
few extra keywords.


Which leaves multiple inheritance as the only significant 
difference?


From my perspective it looks like there are two massively 
overlapping features with some quite arbitrary feeling 
restrictions and differences. E.g. why can I not inherit from 
multiple 100% abstract empty classes? Wouldn't that be the same 
as inheriting from multiple interfaces?


Re: Abstract classes vs interfaces, casting from void*

2019-08-11 Thread John Colvin via Digitalmars-d-learn

On Sunday, 11 August 2019 at 15:16:03 UTC, Alex wrote:

On Sunday, 11 August 2019 at 13:09:43 UTC, John Colvin wrote:
Ok. What would go wrong (in D) if I just replaced every 
interface with an abstract class?


I think there's some confusion here, because B.foo is not 
abstract. abstract on a class is not inherited by its methods. 
https://dlang.org/spec/attribute.html#abstract


Now, I'm confused, as you asked about abstract classes. So, 
yes, you can define the abstractness of classes differently. 
And what is your point?


I'm trying to narrow down exactly what patterns work with each 
and how they overlap.


What I was trying to get at with the abstract method thing is that

abstract class C
{
void foo();
}

is an abstract class with a non-abstract method, whose 
implementation is going to come from somewhere else (not a common 
pattern in D).


class C
{
abstract void foo();
}

is an abstract class with an abstract method foo, which means you 
have to override it in a inheriting class to get a non-abstract 
class.


Re: Abstract classes vs interfaces, casting from void*

2019-08-11 Thread John Colvin via Digitalmars-d-learn

On Saturday, 10 August 2019 at 17:28:32 UTC, Alex wrote:


´´´
void main(){}
interface A { void fun(); }
abstract class B{ void fun(); }
class C : A{ void fun(){} }
class D : B{ /*override*/ void fun(){} }
´´´

case 1:
interface A and class C implementing interface A:
You don't need to "override" anything. You are forced to 
provide an implementation of the function inside the class.


case 2:
abstract class B and class D inheriting from it:
You can but not have to provide an implementation of a function 
inside the abstract class.
If I don't and do not provide any implementation inside D I get 
a linker error. Don't how this case behaves on your system.
If you provide an implementation inside the abstract class, you 
don't have to provide any in the derived one.
In any case, if you want to provide an implementation inside 
the derived class you have to literally "override", as in D 
implicit overrides are not allowed.


I think there's some confusion here, because B.foo is not 
abstract. abstract on a class is not inherited by its methods. 
https://dlang.org/spec/attribute.html#abstract




Re: Abstract classes vs interfaces, casting from void*

2019-08-11 Thread John Colvin via Digitalmars-d-learn

On Saturday, 10 August 2019 at 17:46:37 UTC, Timon Gehr wrote:

On 10.08.19 16:29, John Colvin wrote:


Ok. What would go wrong (in D) if I just replaced every 
interface with an abstract class?


interface A{}
interface B{}

class C: A,B{ }


Yes, I know, I guess it wasn't clear unless you read my previous 
question, I said "apart from multiple inheritance".


Re: Abstract classes vs interfaces, casting from void*

2019-08-10 Thread John Colvin via Digitalmars-d-learn

On Saturday, 10 August 2019 at 10:11:15 UTC, Alex wrote:

On Saturday, 10 August 2019 at 08:20:46 UTC, John Colvin wrote:

On Friday, 9 August 2019 at 13:39:53 UTC, Simen Kjærås wrote:




Thanks for the extra detail.

Is there a solid reason to ever use an interface over an 
abstract class? (Other than multiple inheritance).


I'm such a noob at anything related to OO.


The general question is tricky, as different languages differ 
in details what is forced and what is allowed for abstract 
classes and interfaces.


But roughly speaking, my opinion is: if you can/want to provide 
some default behavior than you are about to write an abstract 
class.
If you are about to provide information/restriction of 
behavior, then this is more like an interface.


Ok. What would go wrong (in D) if I just replaced every interface 
with an abstract class?


Re: Abstract classes vs interfaces, casting from void*

2019-08-10 Thread John Colvin via Digitalmars-d-learn

On Saturday, 10 August 2019 at 10:02:02 UTC, Antonio Corbi wrote:

On Saturday, 10 August 2019 at 08:20:46 UTC, John Colvin wrote:

On Friday, 9 August 2019 at 13:39:53 UTC, Simen Kjærås wrote:




Thanks for the extra detail.

Is there a solid reason to ever use an interface over an 
abstract class? (Other than multiple inheritance).


I'm such a noob at anything related to OO.


Hi John.

One reason could be data. Abstract classes can hold data, 
interfaces can't.


Antonio


That's a reason to use an abstract class, not a reason to use an 
interface.


Re: Abstract classes vs interfaces, casting from void*

2019-08-10 Thread John Colvin via Digitalmars-d-learn

On Friday, 9 August 2019 at 13:39:53 UTC, Simen Kjærås wrote:




Thanks for the extra detail.

Is there a solid reason to ever use an interface over an abstract 
class? (Other than multiple inheritance).


I'm such a noob at anything related to OO.


Re: Abstract classes vs interfaces, casting from void*

2019-08-10 Thread John Colvin via Digitalmars-d-learn

On Friday, 9 August 2019 at 13:39:53 UTC, Simen Kjærås wrote:
We're getting into somewhat advanced topics now. This is 
described in the Application Binary Interface page of the 
documentation[0]. In short: classes and interfaces both use a 
vtable[1] that holds pointers to each of their methods. When we 
cast a class instance to an interface, the pointer is adjusted, 
such that the interface's vtable is the first member. Casting 
via `void*` bypasses this adjustment.


Using `__traits(classInstanceSize)`, we can see that `C` has a 
size of 12 bytes, while `D` only is 8 bytes (24 and 16 on 
64-bit). This corresponds to the extra interface vtable as 
described above.


When we first cast to `void*`, no adjustment happens, because 
we're not casting to an interface. When we later cast the 
`void*` to an interface, again no adjustment happens - in this 
case because the compiler doesn't know what we're casting from.


If we use `__traits(allMembers, C)`, we can figure out which 
methods it actually has, and implement those with some extra 
debug facilities (printf):


class C : I
{
override void foo() { writeln("hi"); }
override string toString()   { writeln("toString"); 
return ""; }
override hash_t toHash() { debug printf("toHash"); 
return 0; }
override int opCmp(Object o) { writeln("opCmp"); return 
0; }
override bool opEquals(Object o) { writeln("opEquals"); 
return false; }

}

If we substitute the above in your program, we see that the 
`toString` method is the one being called. This is simply 
because it's at the same location in the vtable as `foo` is in 
`I`'s vtable.


When casting from a class to a superclass, no pointer 
adjustment is needed, as the vtable location is the same for 
both.


We can look closer at the vtable, and see that for a new 
subclass, additional entries are simply appended at the end:


class C {
void foo() {}
}

class D : C {
void bar() {}
}

unittest {
import std.stdio;

C c = new C();
D d = new D();

writeln("Pointer to foo(): ", ().funcptr);
writeln("Pointer to bar(): ", ().funcptr);

writeln("Pointer to foo() in C's vtable: ", c.__vptr[5]);

writeln("Pointer to foo() in D's vtable: ", d.__vptr[5]);
writeln("Pointer to bar() in D's vtable: ", d.__vptr[6]);
}

As we see, `foo()` has the position in the vtable for both `c` 
and `d`, while `D`'s new `bar()` method is added as the next 
entry.


--
  Simen

[0]: https://dlang.org/spec/abi.html
[1]: https://en.wikipedia.org/wiki/Virtual_method_table


Thanks for the extra detail.

Is there a solid reason to ever use an interface over an abstract 
class? (Other than multiple inheritance).


I'm such a noob at anything related to OO.


Re: Abstract classes vs interfaces, casting from void*

2019-08-09 Thread John Colvin via Digitalmars-d-learn

On Friday, 9 August 2019 at 13:19:14 UTC, kinke wrote:

On Friday, 9 August 2019 at 12:26:59 UTC, John Colvin wrote:

Why is there no "hi" between 0 and 1?


Because you are treating the unadjusted object pointer as 
interface pointer and then call the only virtual function of 
that interface, in the 2nd vtbl slot (after the TypeInfo ptr). 
Casting a class ref to an interface offsets the pointer, so 
that the interface ref points to the interface vptr for that 
object instance. This is missing in that line, and so you are 
invoking the first virtual function of class C, which is some 
base function in `Object`.


Ok, makes sense, thanks.


Abstract classes vs interfaces, casting from void*

2019-08-09 Thread John Colvin via Digitalmars-d-learn

import std.stdio;

interface I
{
void foo();
}

class C : I
{
override void foo() { writeln("hi"); }
}

abstract class AC
{
void foo();
}

class D : AC
{
override void foo() { writeln("hi"); }
}

void main()
{
auto c = new C();
writeln(0);
(cast(I)cast(void*)c).foo();
writeln(1);
(cast(C)cast(void*)c).foo();
writeln(2);
(cast(I)cast(C)cast(void*)c).foo();

auto d = new D();
writeln(3);
(cast(AC)cast(void*)d).foo();
writeln(4);
(cast(D)cast(void*)d).foo();
writeln(5);
(cast(AC)cast(D)cast(void*)d).foo();
}

This produces the output:

0
1
hi
2
hi
3
hi
4
hi
5
hi

Why is there no "hi" between 0 and 1?


Re: bolts meta programming library version 1.0.0 - including the from idiom

2019-07-16 Thread John Colvin via Digitalmars-d-announce

On Tuesday, 16 July 2019 at 18:18:50 UTC, Atila Neves wrote:

On Tuesday, 16 July 2019 at 00:10:19 UTC, Aliak wrote:

On Monday, 15 July 2019 at 21:20:16 UTC, Atila Neves wrote:

On Monday, 15 July 2019 at 11:13:10 UTC, aliak wrote:
I've been using a set of meta tools for a while now, so 
decided to release it as 1.0.0 with a few enhancements 
chucked on.


[...]


Nice! I'm working on something similar but with a different 
goal.


Thanks! How’s the thing similar and what’s the goal (if you 
don’t mind me asking)?


Similar: One-stop shop for reflection unifying the disparate 
APIs.
Goal: allow "regular" code for reflection purposes by (also) 
returning everything as strings.


Is this related to the talk Andrei gave at a recent dconf?


Re: Compiler/Phobos/Types problem — panic level due to timing.

2019-05-09 Thread John Colvin via Digitalmars-d-learn

On Wednesday, 8 May 2019 at 11:53:34 UTC, Russel Winder wrote:
On Mon, 2019-05-06 at 15:53 +, John Colvin via 
Digitalmars-d-learn wrote:

[…]

pretty please show people it with UFCS:

recurrence!((a, n) => a[n-1] + a[n-2])(zero, one)
 .dropExactly(n)
 .front


Any particular reason for preferring this form over the 
original?


Not big benefit in this case, very big benefit with longer chains.

It reads in the order of operations, as opposed to inside out.


Re: Compiler/Phobos/Types problem — panic level due to timing.

2019-05-06 Thread John Colvin via Digitalmars-d-learn

On Monday, 6 May 2019 at 13:05:27 UTC, Russel Winder wrote:

On Sunday, 5 May 2019 at 19:34:05 UTC, Nicholas Wilson wrote:

On Sunday, 5 May 2019 at 19:18:47 UTC, lithium iodate wrote:

[...]


Yep https://run.dlang.io/is/XsLrRz works for me, 
https://run.dlang.io/is/KxY0e9 doesn't.


Thanks people. I now have a working code. :-)


pretty please show people it with UFCS:

recurrence!((a, n) => a[n-1] + a[n-2])(zero, one)
.dropExactly(n)
.front


Re: shared - i need it to be useful

2018-10-22 Thread John Colvin via Digitalmars-d

On Monday, 22 October 2018 at 00:22:19 UTC, Manu wrote:
On Sun, Oct 21, 2018 at 2:35 PM Walter Bright via Digitalmars-d 
 wrote:


On 10/21/2018 2:08 PM, Walter Bright wrote:
> On 10/21/2018 12:20 PM, Nicholas Wilson wrote:
>> Yes, but the problem you describe is arises from implicit 
>> conversion in the other direction, which is not part of the 
>> proposal.

>
> It's Manu's example.

Then I don't know what the proposal is. Pieces of it appear to 
be scattered over numerous posts, mixed in with other text,


No no, they're repeated, not scattered, because I seem to have 
to keep repeating it over and over, because nobody is reading 
the text, or perhaps imaging there is a lot more text than 
there is.


I can go look at the original post - and I have - but while it 
may strictly speaking contain all the information I need, the 
amount of time and brain power it would take for me to comprehend 
the consequences is pretty large. I assume you have done a lot of 
that work already and could save everyone a lot of time by 
putting together a quick document that covers some of that, with 
good examples. I'm not going to read {1,2,3}00 messages full of 
irritated bidirectional miscommunication to try and understand 
this unless I really have to, and I assume others feel similarly.


Re: John Regehr on "Use of Assertions"

2018-09-03 Thread John Colvin via Digitalmars-d
On Monday, 3 September 2018 at 06:26:59 UTC, Jonathan M Davis 
wrote:
Well, if that were the intention, then -release could not 
remove assertions from @safe code. -release does not remove 
bounds checking from @safe code. You have to use 
-boundscheck=off to disable assertions in @safe code (which is 
of course discouraged, since it makes the code not @safe). So, 
if we were to decide that assertions had to be left in for code 
to stay @safe, then we would have to start leaving them in in 
@safe code when -release is used and only compile them out with 
a new flag specifically for compiling out assertions in @safe 
code. And that would have pretty far-reaching effects given 
that it's very much understood right now that -release removes 
assertions. And personally, I'd probably use assertions a lot 
less if they were going to be left in with -release. So, while 
I think that that's a better approach that allowing @system 
optimizations in @safe code when assertions are removed, I 
can't say that I think that it's a great idea - though the 
folks who pretty much always want assertions enabled would 
probably like it (though they can already just skip -release).


- Jonathan M Davis


Yes, the command line interface needs to make it easy and obvious 
to do the right thing.


Re: John Regehr on "Use of Assertions"

2018-09-02 Thread John Colvin via Digitalmars-d
On Sunday, 2 September 2018 at 02:32:31 UTC, Jonathan M Davis 
wrote:
On Saturday, September 1, 2018 2:15:15 PM MDT Walter Bright via 
Digitalmars- d wrote:

https://blog.regehr.org/archives/1091

As usual, John nails it in a particularly well-written essay.

"ASSERT(expr)
Asserts that an expression is true. The expression may or may 
not be
evaluated. If the expression is true, execution continues 
normally.

If the expression is false, what happens is undefined."

Note the "may or may not be evaluated." We've debated this 
here before. I'm rather pleased that John agrees with me on 
this. I.e. the optimizer can assume the expression is true and 
use that information to generate better code, even if the 
assert code generation is turned off.


Personally, my concern about letting the compiler optimize 
based on assertions has to do with whether it violates @safe. 
IMHO, it defeats the purpose of @safe if adding an assertion 
can result in @system code due to optimizations. I'm fine with 
it optimizing so long as the optimizations will not result in 
@safe code becoming @system in the case where the assertion 
would have failed if it were compiled in. If @safe allows 
@system optimizations than it isn't actually @safe, because 
while we don't want assertions to ever turn out to be false, 
they sometimes do turn out to be false, and if they're not 
compiled in, it's not going to be caught. That then is 
obviously a bug, but at least it isn't one that's going to 
corrupt memory (at least if it's in @safe code), but if the 
compiler is allowed to optimize based on the assertion to the 
point that the code could corrupt memory if the assertion would 
have failed, then that's a serious problem and a total 
violation of the promises made by @safe. And actually, it can't 
add @system optimizations even in @system code, because that 
completely defeats the ability of the programmer to verify the 
code for @safety in order to use @trusted.


If the compiler can add @safe optimizations based on 
assertions, then that's fine with me (though I know that some 
others don't agree), but they have to be @safe even when the 
assertion would have failed if it were compiled in. If they're 
ever @system, then @safe isn't actually @safe.


- Jonathan M Davis


I believe asserts are the general case of which bounds checking 
is a specific instance. @safe code is only @safe if 
bounds-checking is enabled for @safe.


void foo(int[] a) @safe
{
a[0] = 1;
}

is only really guaranteed safe if a bounds check is done, because 
[] is a valid array for a caller to pass.


void foo(int[] a) @safe
{
assert(a.length == 1);
a[0] = 1;
}

if asserts can be used as guarantees for the optimiser even when 
removed, this code is only @safe when asserts are enabled 
(because otherwise the bounds checks would be elided as they are 
guaranteed to pass).


So, essentially we just have to treat asserts like bounds checks 
and @safe will work as expected.



P.S.

// assert
debug assert(cond, msg);

// assume
assert(cond, msg);


Re: C++ Expected converted to idiomatic D

2018-08-28 Thread John Colvin via Digitalmars-d

On Thursday, 16 August 2018 at 20:37:33 UTC, Per Nordlöw wrote:

In

https://www.youtube.com/watch?v=nVzgkepAg5Y

Andrei describes his proposal for STL `Expected` planned to be 
included in C++20.


Have anybody converted the C++ proposal to idiomatic D, yet?

Hopefully without the pointer-legacy which unfortunately was 
allowed into `std:optional`.


Andrei claims we should it as return types for non-throwing 
variants of parse() and to() in the works at


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


I get the feeling from the talk that Andrei has some opinions 
about how it should be done that aren't completely in line with 
what has been proposed for the C++ standard.


Re: Dpp on run.dlang.io

2018-08-04 Thread John Colvin via Digitalmars-d-announce

On Saturday, 4 August 2018 at 01:27:49 UTC, Laeeth Isharc wrote:
Thanks to Seb and Atila it is now very easy to show  a D 
program just #includeing C headers.  If just works.  Modulo 
bugs.  In time I am hopeful Atila will start to have more of 
C++ headers working too.


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


Very cool.

It seems like it's on by default with no option to turn it off. 
Is that a good idea?


Also, it appears to have broken for me in the last couple of 
minutes. It worked initially, then I clicked the link again and 
ran it, got:


Error: Could not execute `dmd onlineapp.d -ofonlineapp`:
onlineapp.d(49): Error: no identifier for declarator `typedef`
onlineapp.d(49): Error: semicolon expected, not `int`
onlineapp.d(53): Error: semicolon expected, not `char`
onlineapp.d(54): Error: semicolon expected, not `short`
onlineapp.d(54): Error: no identifier for declarator `short`
onlineapp.d(55): Error: semicolon expected, not `int`
onlineapp.d(56): Error: semicolon expected, not `long`
onlineapp.d(56): Error: no identifier for declarator `long`
onlineapp.d(59): Error: semicolon expected, not `char`
onlineapp.d(60): Error: semicolon expected, not `char`
onlineapp.d(61): Error: semicolon expected, not `short`
onlineapp.d(61): Error: no identifier for declarator `short`
onlineapp.d(62): Error: semicolon expected, not `short`
onlineapp.d(62): Error: no identifier for declarator `short`
onlineapp.d(63): Error: semicolon expected, not `int`
onlineapp.d(64): Error: semicolon expected, not `int`
onlineapp.d(66): Error: semicolon expected, not `long`
onlineapp.d(66): Error: no identifier for declarator `long`
onlineapp.d(67): Error: semicolon expected, not `long`
onlineapp.d(67): Error: no identifier for declarator `long`

Program exited with code 1


Re: Bolts 0.4 meta programming library

2018-08-02 Thread John Colvin via Digitalmars-d-announce

On Thursday, 2 August 2018 at 08:40:55 UTC, John Colvin wrote:

On Thursday, 2 August 2018 at 07:47:19 UTC, aliak wrote:
Hi, just a release of a meta programming library 
(https://bolts.dub.pm) that has utilities that I use in 
personal projects, and that I find in phobos, and or in the 
forums. A notable difference is that functions here try to 
operate on any compile time entities if they can be resolved.


I.e.:

int i;
void g0(int) {}
struct S { void g1(int) {} }
alias g2 = (int a) => a;
static assert(isFunctionOver!(g0, int));
static assert(isFunctionOver!(S.g1, 3));
static assert(isFunctionOver!(g2, i));

And there's a "doth" super template that tries to contain most 
things under what I feel is a nicer api ("is" was taken, so i 
looked to Shakespearian gibberish :p) and also allows for 
easier use with meta functions:


E.g.:

int *pi = null;
static assert( doth!3.of!int);
static assert(!doth!pi.nullable);
static assert( doth!((a, b, c, d) => a).functionOver!(int, 
int, int, int));


int i;
import std.meta: allSatisfy;
static assert(allSatisfy!(doth!int.of, 3, 4, int, i));

Here's an example of a gem adapted from inside the 
forms/phobos sources as well:


alias a = AliasPack!(1, 2, 3);
alias b = AliasPack!(4, 5, 6);
alias c = AliasPack!(7, 8, 9);

alias d = staticZip!(a, b, c);

static assert(d.length == 3);

static assert(d.Unpack[0].equals!(1, 4, 7));
static assert(d.Unpack[1].equals!(2, 5, 8));
static assert(d.Unpack[2].equals!(3, 6, 9))

static assert(AliasPack!(d.UnpackDeep).equals!(1, 4, 7, 2, 5, 
8, 3, 6, 9));


Cheers,
- Ali


This looks cool. Lots of things that lots of people have 
reimplemented lots of times over the years, but all in one 
place and documented.


2 points:

1) Are you aware of this: 
https://github.com/dlang/phobos/blob/master/std/meta.d ? I 
think if a bunch of good motivating examples are given, making 
this public would be possible. Then everyone would be using the 
same one and your library would truly just be utilities.


woops, pressed send too early:

2) I don't think "doth" is synonymous with "is" how you're using 
it. "doth" is for doing, e.g.


"Methinks he doth protest too much" or "This code doth stink" is 
OK


"Green doth a colour" or "strstr doth a function" is not OK.


Re: Bolts 0.4 meta programming library

2018-08-02 Thread John Colvin via Digitalmars-d-announce

On Thursday, 2 August 2018 at 07:47:19 UTC, aliak wrote:
Hi, just a release of a meta programming library 
(https://bolts.dub.pm) that has utilities that I use in 
personal projects, and that I find in phobos, and or in the 
forums. A notable difference is that functions here try to 
operate on any compile time entities if they can be resolved.


I.e.:

int i;
void g0(int) {}
struct S { void g1(int) {} }
alias g2 = (int a) => a;
static assert(isFunctionOver!(g0, int));
static assert(isFunctionOver!(S.g1, 3));
static assert(isFunctionOver!(g2, i));

And there's a "doth" super template that tries to contain most 
things under what I feel is a nicer api ("is" was taken, so i 
looked to Shakespearian gibberish :p) and also allows for 
easier use with meta functions:


E.g.:

int *pi = null;
static assert( doth!3.of!int);
static assert(!doth!pi.nullable);
static assert( doth!((a, b, c, d) => a).functionOver!(int, int, 
int, int));


int i;
import std.meta: allSatisfy;
static assert(allSatisfy!(doth!int.of, 3, 4, int, i));

Here's an example of a gem adapted from inside the forms/phobos 
sources as well:


alias a = AliasPack!(1, 2, 3);
alias b = AliasPack!(4, 5, 6);
alias c = AliasPack!(7, 8, 9);

alias d = staticZip!(a, b, c);

static assert(d.length == 3);

static assert(d.Unpack[0].equals!(1, 4, 7));
static assert(d.Unpack[1].equals!(2, 5, 8));
static assert(d.Unpack[2].equals!(3, 6, 9))

static assert(AliasPack!(d.UnpackDeep).equals!(1, 4, 7, 2, 5, 
8, 3, 6, 9));


Cheers,
- Ali


This looks cool. Lots of things that lots of people have 
reimplemented lots of times over the years, but all in one place 
and documented.


2 points:

1) Are you aware of this: 
https://github.com/dlang/phobos/blob/master/std/meta.d ? I think 
if a bunch of good motivating examples are given, making this 
public would be possible. Then everyone would be using the same 
one and your library would truly just be utilities.


Re: Declaring a pointer to a function returning a ref

2018-07-31 Thread John Colvin via Digitalmars-d

On Tuesday, 31 July 2018 at 21:29:26 UTC, Jean-Louis Leroy wrote:
How do I declare a variable that contains a pointer to a 
function returning a reference?


  import std.stdio;

  int foo(return ref int a)
  {
a = 42;
return a;
  }

  ref int bar(return ref int a)
  {
a = 42;
return a;
  }

  void main()
  {
int x;
auto apf = 
writeln(typeid(apf)); // int function(return ref int)*
int function(return ref int) xpf = 

auto apb = 
writeln(typeid(apb)); // int function(return ref int) ref*

// int function(return ref int) ref xpb =  // Error: 
no identifier for declarator `int function(return ref int)`
// ref int function(return ref int) xpb =  // Error: 
variable `castfunc.main.xpb` only parameters or `foreach` 
declarations can be `ref`

  }


alias RefFuncT = ref int function(return ref int a);

or

alias RefFuncT = typeof();

then

RefFuncT xpb = 

or you can skip that and do

typeof() xpb = 


P.S. next time this sort of question would be more appropriate in 
the the Learn forum


Re: Moving druntime into the DMD repository

2018-07-27 Thread John Colvin via Digitalmars-d

On Friday, 27 July 2018 at 12:04:18 UTC, Jonathan M Davis wrote:
On Friday, July 27, 2018 5:03:50 AM MDT Seb via Digitalmars-d 
wrote:

What do you think?
--

- Has the dmd/druntime split being annoying you too?
- Do you have a better suggestion?
- Would this break your workflow in a drastic way?


It would break all existing tools and scripts that are used to 
build the existing repos - many of which are not official 
tools. So, yes, it would be very annoying. That's not 
necessarily a good enough reason not to do it, but IMHO, it 
really needs to provide solid benefits to rearrange things like 
that for it to be worth breaking all of the existing tools that 
anyone uses for building dmd, druntime, and Phobos.


Not necessarily. The druntime repo could just contain makefiles 
that forward to the dmd ones.


Re: Struct Initialization syntax

2018-07-23 Thread John Colvin via Digitalmars-d

On Monday, 23 July 2018 at 16:57:20 UTC, H. S. Teoh wrote:
On Mon, Jul 23, 2018 at 04:26:42PM +, Seb via Digitalmars-d 
wrote:

tl;dr: the currently proposed syntax options are:
---
struct S
{
int a = 2, b = 4, c = 6;
}
void foo()
{
bar(S({c: 10})); // Option 1
bar(S(c: 10));   // Option 2
bar(S{c: 10});   // Option 3
}
---

So the struct-initialization DIP has been stalled for too long 
and I think it's time we finally get this story done.


+1.


I personally prefer option 2, but this might be in conflict to 
named arguments which we hopefully see in the near future too.


Yeah.


Hence, I'm leaning forward to proposing Option 1 as the 
recommended Option for the DIP (that's also what the PoC DMD 
PR implements). What's your take on this?

[...]

I don't like option 1 because it resembles anonymous function 
syntax and AA initialization syntax, but is actually neither.


Seeing as we already have

S s = { c : 10 };

I'd say it would be fairer to say it resembles anonymous function 
syntax and AA initialisation syntax, but mostly it resembles the 
existing struct initialisation syntax.


Re: opCmp / opEquals do not actually support partial orders

2018-07-17 Thread John Colvin via Digitalmars-d

On Tuesday, 17 July 2018 at 18:21:26 UTC, H. S. Teoh wrote:
As we know, when opCmp is defined for a user type, then 
opEquals must also be defined in order for == to work, even 
though in theory the compiler could translate x==y into 
x.opCmp(y)==0.


In the past, it was argued that this was so that partial orders 
could be made to work, i.e., it could be the case that x and y 
are incomparable, then x.opCmp(y) would return 0, and 
x.opEquals(y) would be false. Supposedly, this would allow us 
to, say, model the subset relation (which is a partial order) 
using the comparison operators.


However, this supposition is in fact false.  The reason is that 
`<=` and `>=` *only* check the return value of opCmp(); they do 
not check opEquals at all.  So suppose we define a Set type, 
and we'd like to use the comparison operators to model the 
subset relation.  How would we define opCmp and opEquals?


opEquals is obvious, of course.  It's true if x and y have the 
same elements, false otherwise.


But opCmp turns out to be a tarpit.  Here's why:

- If x is a (strict) subset of y, then obviously we should 
return -1.


- If x is a (strict) superset of y, then obviously we return 1.

- If x and y have the same elements, then obviously we should 
return 0,
  since we'd like x <= y and x >= y to be true when x == y is 
true.


- If x and y are not subsets of each other, then what should we 
return?

  According to the original claim, it should also return 0, for
  "incomparable".  However, this leads to problems:

  - Since `x <= y` in D means `x.opCmp(y) <= 0`, this will 
return TRUE

when x and y are incomparable.

  - Similarly, `x >= y` in D means `x.opCmp(y) >= 0`, so it 
will also

return TRUE when x and y are incomparable.

  - Therefore, `x <= y` cannot distinguish between x being a 
non-strict
subset of y vs. x and y being incomparable.  Similarly for 
`x >= y`.


So we have the counterintuitive semantics that <= and >= will 
return true for non-comparable sets.


There is no return value of opCmp for which both <= and >= will 
be false, as we need it to be if we are to map <= to ⊆ and >= 
to ⊇.


Just do what std.typecons.Proxy does and return float.nan for the 
incomparable case.


std.experimental.allocator and const etc.

2018-07-15 Thread John Colvin via Digitalmars-d

Currently the API's don't support const(void)[], e.g.

import std.experimental.allocator : makeArray, theAllocator, 
dispose;

import std.experimental.allocator.mallocator : Mallocator;

void main()
{
const a = theAllocator.makeArray!ubyte(100);
theAllocator.dispose(a);
// can't call RCIAllocator.deallocate(void[] b) with 
const(ubyte)[]


const(void)[] b = Mallocator.instance.allocate(100);
Mallocator.instance.deallocate(b);
// can't call Mallocator.deallocate(void[] b) with 
const(void)[]

}

Is this deliberate? It's pretty annoying.


Re: Multiple functions, same signature

2018-07-11 Thread John Colvin via Digitalmars-d

On Wednesday, 11 July 2018 at 15:58:05 UTC, Luís Marques wrote:

I was surprised to find out today that this compiles:

void foo() {}
void foo() {}
void main() {}

Is it a bug, or just a weird design decision? "alphaglosined" 
on IRC seemed to think it was a regression. Please confirm, so 
that I can file a bug, or understand the design decision 
rationale.


Definitely a change, but it always compiled, it just used to fail 
to link


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


Re: string file = __FILE__ considered harmful (and solution)

2018-05-30 Thread John Colvin via Digitalmars-d
On Wednesday, 30 May 2018 at 14:40:50 UTC, Steven Schveighoffer 
wrote:

On 5/30/18 4:27 AM, FeepingCreature wrote:
There's a very common idiom where in order to report line 
numbers of an error or a log line at the callsite of a 
function, you pass __FILE__ and __LINE__ as default parameters:


void foo(string file = __FILE__, size_t line = __LINE__);

What's wrong with this?

Say you add a string parameter, such as

void foo(string msg, string file = __FILE__, size_t line = 
__LINE__);


foo("Hello World");

Now when you accidentally grab an old version of the library, 
your new code will still run, but it will believe that it's 
being called from file "Hello World", line 15. Not good.


Luckily there's a fix. Just stick this in some common header 
file in your project:


struct CallerInfo
{
   string file;
   size_t line;
}

void foo(string msg, CallerInfo caller = CallerInfo(__FILE__, 
__LINE__));


Now you cannot accidentally invoke foo with a string, or in 
fact any type except another instance of CallerInfo.


Awesome idea! Unfortunately, it doesn't work. The __FILE__ and 
__LINE__ there are not from the caller, but from the line that 
defines foo.


See here: https://run.dlang.io/is/siz9YZ



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

Less elegant, but solves the problem of accidental argument 
adding (CallerFile acts as a barrier). Unfortunately, while it 
works in theory, in practice the compiler crashes LOL


Re: T opImplCast(T)() so we can add @disable to it?

2018-05-24 Thread John Colvin via Digitalmars-d

On Thursday, 24 May 2018 at 07:37:40 UTC, Sjoerd Nijboer wrote:

On Thursday, 24 May 2018 at 07:06:03 UTC, Bastiaan Veelo wrote:

On Thursday, 24 May 2018 at 06:42:51 UTC, Sjoerd Nijboer wrote:
On Thursday, 24 May 2018 at 01:39:56 UTC, Jonathan M Davis 
wrote:
If you don't want an implict cast, then why did you declare 
an alias this?


Because I wanted an inconvertible type which was exactly like 
the int in the example but didn't want the implicit cast.


Doesn’t std.typecons.Typedef do that?
https://dlang.org/phobos/std_typecons.html#Typedef


I didn't know this existed. Cool!


If you need more control, use std.typecons.Proxy to build your 
own.


Re: Online impersonation

2018-05-24 Thread John Colvin via Digitalmars-d

On Thursday, 24 May 2018 at 06:32:23 UTC, Dukc wrote:
On Wednesday, 23 May 2018 at 17:31:40 UTC, Steven Schveighoffer 
wrote:
The IP address is included in the headers of the newsgroup. 
All of them came from the same IP. I have a filter on my 
thunderbird client to flag certain IPs, and his was added to 
the list recently.


Then again, it's possible they're family members or neighbours 
using the same IP. How likely this is, I won't comment.


I don't this is a case of inpersonation if you're right, since 
the aliases have not been trying to inpersonate any real, exact 
person. But dishonourable action nonetheless.


There was a post impersonating Steven, but I can't see it now so 
I guess it was removed.


Re: #include C headers in D code

2018-04-12 Thread John Colvin via Digitalmars-d-announce

On Wednesday, 11 April 2018 at 18:36:56 UTC, Walter Bright wrote:

On 4/11/2018 3:25 AM, Atila Neves wrote:
I did the best I could having seen some macros. It's likely 
there are cases I've missed, or that maybe the translation in 
the link above doesn't work even for what it's supposed to be 
doing (I have no confidence about catching all the C casts for 
instance).


If there are other cases, I'll fix them as they're 
encountered. It's possible some of them can't be fixed and the 
user will have to work around them. Right now I have a feeling 
it will probably be ok. Time will tell (assuming I have 
users!).



That's right. There is no general solution. One can only look 
for common patterns and do those. For example,


  #define X 15

is a common pattern and can be reliably rewritten as:

  enum X = 15;


If I understand it correctly, dpp doesn't do that.

Instead, it runs the pre-processor on the source code, just like 
in C, so


// test.dpp
#define X 15
int foo() { return X; }

becomes

// test.d
int foo() { return 15; }

The upside of this approach: all macros just work, unless they 
use C (not C pre-processor, C proper) features that dpp can't 
handle. `sizeof(...)` is a special case that is handled in 
dpp.cursor.macro.translateToD and more could be added.


The downside: macros can't be directly used outside .dpp files.


Re: I used to be able to use a bffer for toUTF operation, what happened ?

2018-04-11 Thread John Colvin via Digitalmars-d

On Wednesday, 11 April 2018 at 12:04:24 UTC, deadalnix wrote:

This used to be an option:

dchar val = ...;
char[4] buf;
toUTF8(buf, val);

Now I'm getting an error. Looking at the doc, it seems that 
there are only option returning a string, which I assume is 
allocated on the GC. Has the function moved somewhere else ? If 
not, what's going on ?


std.utf.encode ?


Re: DUB: Only fetch and cache packages in dub.json without running build

2018-04-10 Thread John Colvin via Digitalmars-d

On Tuesday, 10 April 2018 at 13:50:38 UTC, Clinton wrote:

Hi all,

I'm setting up a CircleCI config for my project. Right now I'm 
trying to cache dependencies before running builds. This way I 
can run "dub build --nodeps" immediately after the packages are 
cached to avoid extra network calls and speed it up.


I'm wondering if there's a way to isolate the part that 
downloads and caches all of the dependencies in dub.json 
without running the build.


Right now I have to run the build twice. First one, for the 
sake of downloading the dependencies and later for running if 
the cache exists. Having the build run the first time takes up 
a lot of time. I'm going for the "npm install" type of effect.


The reason the cache needs to be rebuilt each time is because 
CircleCI runs docker images. Once the deployment is finished, 
the image fs is destroyed so there's no way to hold onto the 
cache for future builds.


As far as I understand it, `dub describe` fetches everything. 
Then you can cache `~/.dub/packages/`.


Alternatively you can do `dub describe --cache=local` to put the 
packages in the current directory. You could then use `dub 
add-path .` or add `--cache=local` to all future calls to use 
those locally fetched packages.


Even better:
% mkdir cache
% cd cache
% dub describe --root=../ --cache=local

and then either
% dub build --root=../ --cache=local
or
% dub add-path .
% cd ../
% dub build

which keeps things nice and clean


Re: DUB: Only fetch and cache packages in dub.json without running build

2018-04-10 Thread John Colvin via Digitalmars-d

On Tuesday, 10 April 2018 at 15:31:41 UTC, John Colvin wrote:

On Tuesday, 10 April 2018 at 13:50:38 UTC, Clinton wrote:

Hi all,

I'm setting up a CircleCI config for my project. Right now I'm 
trying to cache dependencies before running builds. This way I 
can run "dub build --nodeps" immediately after the packages 
are cached to avoid extra network calls and speed it up.


I'm wondering if there's a way to isolate the part that 
downloads and caches all of the dependencies in dub.json 
without running the build.


Right now I have to run the build twice. First one, for the 
sake of downloading the dependencies and later for running if 
the cache exists. Having the build run the first time takes up 
a lot of time. I'm going for the "npm install" type of effect.


The reason the cache needs to be rebuilt each time is because 
CircleCI runs docker images. Once the deployment is finished, 
the image fs is destroyed so there's no way to hold onto the 
cache for future builds.


As far as I understand it, `dub describe` fetches everything. 
Then you can cache `~/.dub/packages/`.


Alternatively you can do `dub describe --cache=local` to put 
the packages in the current directory. You could then use `dub 
add-path .` or add `--cache=local` to all future calls to use 
those locally fetched packages.


Even better:
% mkdir cache
% cd cache
% dub describe --root=../ --cache=local

and then either
% dub build --root=../ --cache=local
or
% dub add-path .
% cd ../
% dub build

which keeps things nice and clean


As per Sönke's advice, you can replace `dub describe` with `dub 
upgrade --missing-only` to avoid generating the description.


Re: rvalues -> ref (yup... again!)

2018-03-26 Thread John Colvin via Digitalmars-d

On Monday, 26 March 2018 at 14:40:03 UTC, Atila Neves wrote:

On Friday, 23 March 2018 at 22:01:44 UTC, Manu wrote:

Forked from the x^^y thread...



There are too many replies on this thread, addressing all the 
comments would take forever and pollute the thread itself. So 
forgive me if I say something that was covered already by 
someone else.


AFAIK being able to bind rvalues to `ref const(T)`, only makes 
sense when calling C++ functions that take `const T&` 
(especially since that is common). I have not yet heard any 
other use for them. I'd be in favour of allowing it _only_ for 
`extern(C++)` functions. Otherwise use `auto ref` or have 
overloads for pass-by-value and pass-by-ref.
I too, once a recent immigrant from the lands of C++, used to 
keep writing `ref const(T)`. I just pass by value now.


C++ T&& (forwarding reference) -> D auto ref T
C++ T&& (Rvalue reference) -> D T
C++ const T& -> D T
C++ T& -> D ref T

If replacing const T& with T chafes, I understand. I used to 
feel that way too. It's _possible_ that would incur a penalty 
in copying/moving, but IME the cost is either 0, negligible, or 
negative (!).


I'm tearing my remaining stubs of hair out trying to understand 
why memory copies (not talking about copy constructors) are 
needed when passing an rvalue to a non-ref function: 
https://stackoverflow.com/questions/49474685/passing-rvalue-to-non-ref-parameter-why-cant-the-compiler-elide-the-copy


Re: rvalues -> ref (yup... again!)

2018-03-24 Thread John Colvin via Digitalmars-d

On Saturday, 24 March 2018 at 17:30:35 UTC, Manu wrote:
On 24 March 2018 at 04:57, John Colvin via Digitalmars-d 
<digitalmars-d@puremagic.com> wrote:

On Friday, 23 March 2018 at 22:01:44 UTC, Manu wrote:


Forked from the x^^y thread...

On 23 March 2018 at 12:16, Walter Bright via Digitalmars-d 
<digitalmars-d@puremagic.com> wrote:


On 3/23/2018 11:09 AM, Manu wrote:



[...]



Rvalue references are not trivial and can have major 
unintended consequences. They're a rather ugly feature in 
C++, with weirdities. I doubt D will ever have them.



Can you please explain these 'weirdities'?
What are said "major unintended consequences"?
Explain how the situation if implemented would be any 
different than

the workaround?

This seems even simpler than the pow thing to me.
Rewrite:
func(f());
as:
{ auto __t0 = f(); func(__t0); }



I understand what you want, but I'm struggling to understand 
why it's such a huge deal.


Because it makes this kind of D code that interacts with C++
objectively worse than C++, and there's no reason for it.
You can't say to someone who just frustrated-ly doubled their 
line

count by manually introducing a bunch of temporaries in a tiny
function that appears to do something so simple as 'call a 
function',
that "oh yeah, isn't it cool that you can't just call your 
functions

anymore! isn't D cool! we should switch to D right?"
It's embarrassing. I've been put in the position where I have 
to try
and 'explain' this feature quite some number of times... they 
usually
just give me 'the look'™; ya know, quietly wondering if I'm 
still
sane, and all I end up with is someone who's about 95% less 
convinced

that D is cool than they were 5 seconds beforehand.
What pisses me off is that's such a pointless thing to happen, 
because

this issue is so trivial!

In my experience, people are evaluating how D will materially 
impact
the exact same code they're already writing in C++. This is one 
of
those ways that they will be materially impacted, and it's 
almost
enough all on its own to cause people to dismiss the entire 
thing on

the spot.
Pretty much the best case at this phase is that the D code is 
exactly

the same as C++. If we can trim off a few parens here and there
(ufcs?), maybe remove some '::' operators (modules that don't 
suck),

that's a huge win.


The reason you want to pass by reference is for performance, 
to avoid copying the data at the call boundary.


So there are 2 cases: an lvalue needs to be passed, or an 
rvalue needs to be passed.


1. The address of the lvalue is passed.

2. The rvalue is copied to a local, then the address of that 
local is passed.


So in the rvalue case, you're not getting the performance 
benefit of passing by reference, because you have to copy to a 
local anyway.


What I would do in D currently to get the same performance and 
API:


void foo(float[32] v) { foo(v); }
void foo(ref float[32] v) { ... }

or

void foo()(auto ref float[32] v) { ... }


Can't be extern(C++), can't be virtual either (both is likely).
I said before; you're talking about Scott Meyers 'universal
references' as a language concept, and I'm just talking about 
calling

a function.


but I dont' get how or why. It's exactly D's solution to the 
problem.


It doesn't solve the problem... it doesn't even address the 
problem. You're talking about a totally different thing >_<




Auto ref allows the unnecessary copy to be avoided for lvalues 
and creates a temporary (as part of passing the value) for 
rvalues. It has downsides (virtual functions and extern(C++), but 
it does directly address the problem you're talking about, unless 
I have totally misunderstood you.


Here is a small proof of concept I made to demonstrate how easy 
it seems to be to use `auto ref` to call a C++ virtual const& 
function without incurring any more copies than would happen with 
the same calls from C++. I'm sure it could be improved a lot, but 
does the basic concept match what you would need?


// D source file:

/// mix this in to your extern(C++) class with a list of the 
functions where you

/// want to be able to pass rvalues to ref parameters.
auto rValueRefCalls(Funcs ...)()
{
string ret;
foreach (foo; Funcs)
ret ~= `extern(D) void ` ~ __traits(identifier, foo) ~ 
`(Args ...)(auto ref Args args)
if (__traits(compiles, (` ~ __traits(identifier, foo) ~ 
`)(args)))

{
()(args);
}`;

return ret;
}

extern(C++)
{
class A
{
void foo(const ref int v);
mixin(rValueRefCalls!foo);
}

A makeA();
}

void main()
{
int x = 3;
auto a = makeA();
a.foo(x);
a.foo(3);
}


// C++ source file:

#include

class A
{
public:
virtual void foo(const int& v)
{
printf("%d\n", v);
}
};

A *makeA()
{
return new A;
}



Re: rvalues -> ref (yup... again!)

2018-03-24 Thread John Colvin via Digitalmars-d

On Friday, 23 March 2018 at 22:01:44 UTC, Manu wrote:

Forked from the x^^y thread...

On 23 March 2018 at 12:16, Walter Bright via Digitalmars-d 
 wrote:

On 3/23/2018 11:09 AM, Manu wrote:


[...]


Rvalue references are not trivial and can have major 
unintended consequences. They're a rather ugly feature in C++, 
with weirdities. I doubt D will ever have them.


Can you please explain these 'weirdities'?
What are said "major unintended consequences"?
Explain how the situation if implemented would be any different 
than

the workaround?

This seems even simpler than the pow thing to me.
Rewrite:
func(f());
as:
{ auto __t0 = f(); func(__t0); }



I understand what you want, but I'm struggling to understand why 
it's such a huge deal.


The reason you want to pass by reference is for performance, to 
avoid copying the data at the call boundary.


So there are 2 cases: an lvalue needs to be passed, or an rvalue 
needs to be passed.


1. The address of the lvalue is passed.

2. The rvalue is copied to a local, then the address of that 
local is passed.


So in the rvalue case, you're not getting the performance benefit 
of passing by reference, because you have to copy to a local 
anyway.


What I would do in D currently to get the same performance and 
API:


void foo(float[32] v) { foo(v); }
void foo(ref float[32] v) { ... }

or

void foo()(auto ref float[32] v) { ... }

What is so totally unacceptable about those solutions? I 
personally like the second because it scales better to multiple 
parameters. I know you have said it's not relevant and annoying 
that people bring up auto ref, but I dont' get how or why. It's 
exactly D's solution to the problem.


There's a little more work to be done when thinking about 
extern(C++) and/or virtual functions, but most code for most 
people isn't made of virtual extern(C++) functions that take 
large value types can't accept the cost of copying a few lvalues.


Re: help cast

2018-03-19 Thread John Colvin via Digitalmars-d
On Monday, 19 March 2018 at 11:20:05 UTC, Steven Schveighoffer 
wrote:

Let me adjust your example a bit, and see if you still agree:

auto bytes = cast(ubyte[])[55_444, 289, 1_000_000, 846, 
123_456_789];


writeln(bytes); // [148, 33, 64, 78, 21]

I have used cast(ubyte[]) to get ubytes as well, but I normally 
would do this for values that actually *could be* ubytes. for 
values higher than ubytes, I would not have expected implicit 
truncation. It's especially confusing to someone who has seen 
when you cast an int[] to a ubyte[], and gets the bytes for 
that same data. When I use cast(ubyte[]), I took it to mean 
"pretend this is a ubyte[] literal", not "cast each element to 
ubyte".


I can also see this biting someone who has a long set of 
ubytes, and accidentally does one that is larger than 255.


-Steve


Raw `cast` is just nasty. It's overloaded and confusing. Wrapper 
template functions like `reinterpretBitsAs` can help alleviate 
the pain, e.g. `assert([1, 2, 
3].reinterpretBitsAs!(ubyte[]).length == 12);`.


I feel like C++ got it right (or just less wrong) with casts.


Re: DIP 1006 - Preliminary Review Round 1

2018-03-06 Thread John Colvin via Digitalmars-d

On Tuesday, 6 March 2018 at 02:05:58 UTC, Walter Bright wrote:

On 3/5/2018 2:30 PM, John Colvin wrote:
This just feels bad. Adding extra failsafes for my debug 
program shouldn't make my release program less safe.


Then use `enforce()`.


So, to clarify, adding asserts to my code makes my release builds 
violate @safe?


Re: DIP 1006 - Preliminary Review Round 1

2018-03-05 Thread John Colvin via Digitalmars-d

On Monday, 5 March 2018 at 10:30:12 UTC, Walter Bright wrote:
The idea behind removal of the runtime checks is as a 
performance optimization done on a debugged program. It's like 
turning on or off array bounds checking. Many leave asserts and 
array bounds checking on even in released code to ensure memory 
safety.


At a minimum, turning it off and on will illuminate just what 
the checks are costing you.


It's at the option of the programmer.


void safeCode1(int a, ref int[2] b) @safe
{
assert(a < 2);
b[a] = 0;
}

So, if I compile this with `-release -O`, the compiler is free to 
remove the bounds-check, which will cause a buffer overrun if `a 
> 1`. Ok.


void safeCode2(int a, ref int[2] b) @safe
{
b[a] = 0;
}

And here the compiler is *not* free to remove the bounds check.

This just feels bad. Adding extra failsafes for my debug program 
shouldn't make my release program less safe.


Re: PackedAliasSeq?

2018-02-24 Thread John Colvin via Digitalmars-d
On Thursday, 22 February 2018 at 19:26:54 UTC, Andrei 
Alexandrescu wrote:
After coding https://github.com/dlang/phobos/pull/6192 with 
AliasSeq, the experience has been quite pleasurable. However, 
in places the AliasSeq tends to expand too eagerly, leading to 
a need to "keep it together" e.g. when you need to pass two of 
those to a template.


I worked around the issue by nesting templates like this:

template Merge(T...)
{
template With(U...)
{
static if (T.length == 0)
alias With = U;
else static if (U.length == 0)
alias With = T;
else static if (T[0] < U[0]
 || T[0] == U[0] && T[1].stringof <= 
U[1].stringof)

alias With =
AliasSeq!(T[0], T[1], Merge!(T[2 .. $]).With!U);
   else
alias With =
AliasSeq!(U[0], U[1], Merge!T.With!(U[2 .. $]));
}
}

So instead of the unworkable Merge!(AliasSeq!(...), 
AliasSeq!(...)), one would write 
Merge!(AliasSeq!(...)).With!(AliasSeq!(...)).


The problem remains for other use cases, so I was thinking of 
adding to std.meta this simple artifact:


template PackedAliasSeq!(T...)
{
alias expand = AliasSeq!T;
}

That way, everything stays together and can be expanded on 
demand.



Andrei


Yes, I love this stuff, lots of possibilities.

E.g.

import std.traits : isInstanceOf;
import std.meta : allSatisfy, AliasSeq, staticMap, Alias;

template Pack(T ...)
{
alias expand = T;
enum length = expand.length;
}

enum isPack(alias T) = isInstanceOf!(Pack, T);

template Head(alias P)
if (isPack!P)
{
alias Head = Alias!(P.expand[0]);
}

template Tail(alias P)
if (isPack!P)
{
alias Tail = Pack!(P.expand[1 .. $]);
}

template staticZip(Seqs ...)
if (Seqs.length >= 2 && allSatisfy!(isPack, Seqs))
{
enum len = Seqs[0].length;
static foreach (Seq; Seqs[1 .. $])
static assert(Seq.length == len,
"All arguments to staticZip must have the same 
length");


static if (len == 0)
alias staticZip = AliasSeq!();
else
alias staticZip = AliasSeq!(Pack!(staticMap!(Head, Seqs)),
staticZip!(staticMap!(Tail, 
Seqs)));

}


Re: Workaround for https://issues.dlang.org/show_bug.cgi?id=18422?

2018-02-11 Thread John Colvin via Digitalmars-d
On Sunday, 11 February 2018 at 15:34:07 UTC, Andrei Alexandrescu 
wrote:
I'm trying to sketch a simple compile-time reflection system, 
and https://issues.dlang.org/show_bug.cgi?id=18422 is a blocker 
of the entire approach. My intent is to have a struct Module, 
which can be initialized with a module name; then:


struct Module
{
private string name;
Data[] data(); // all data declarations
Function[] functions();
Struct[] structs();
Class[] classes();
Union[] unions();
Enum[] enums();
}

Then each of those types carries the appropriate information. 
Notably, there are no templates involved, although all code is 
evaluated during compilation. Non-data information (types, 
qualifiers etc) is carried as strings. This allows for simple 
arrays to convey heterogeneous information such as "all 
functions in this module", even though their signatures are 
different.


This makes for a simple and easy to use system for 
introspecting things during compilation. Clearly in order to do 
that some of these compile-time strings must be mixed in, which 
is why https://issues.dlang.org/show_bug.cgi?id=18422 is so 
problematic.


Until we discuss a fix, are there any workarounds?


Thanks,

Andrei


I'm not 100% sure I follow what you need, but maybe one of these 
two will help:


`interface FunctionBase` and `class Function(string name) : 
FunctionBase`.


or

Use a templated constructor `this(string name)()`, so the fields 
are filled during ctfe using "template-time" information. This 
way the type stays the same.


Re: Channeling memory model experts...

2018-01-24 Thread John Colvin via Digitalmars-d
On Wednesday, 24 January 2018 at 18:37:54 UTC, Andrei 
Alexandrescu wrote:
... to review https://github.com/dlang/druntime/pull/2057/. 
Thanks! -- Andrei


Which memory model would that be? D's?


Re: LDC 1.7.0

2018-01-07 Thread John Colvin via Digitalmars-d-announce

On Saturday, 6 January 2018 at 16:25:46 UTC, German Diago wrote:
- want no gc? Ok, at least there is BetterC, so if I invest 
myself quite a bit on D (I am the kind of programmer that likes 
to squeeze power out of machines, so this always means that I 
will not consider VM languages), I will always have.


Also, it's perfectly possible to avoid most of the downsides of 
the GC (and keep some of the upsides) without worrying about 
BetterC. @nogc where you need it is great, BetterC is a much more 
extreme solution.


Re: Some Observations on the D Development Process

2018-01-05 Thread John Colvin via Digitalmars-d

On Friday, 5 January 2018 at 04:26:25 UTC, Walter Bright wrote:
I can't agree with the "just close older bugs and PRs." There's 
good stuff in them. Even if the PR is no good, it provides 
insight to someone working on a better fix. Closing it means 
nobody will ever be aware of it or look at it again.


Relying on the original author to revive it will not work.

It's similar with older bugs. They still have discussion on 
them that contributes valuable information and insight to 
anyone wishing to work on it. Closing them with no action means 
the information is all lost.


As for autotester resources, it should be easy enough to have 
it skip testing any PRs that have had no activity for XXX days.


I don't believe "Logan's Run" makes a good foundation for a 
functioning QA system.


+1

A perfect project would be able to make quick decisions on PRs, 
but that doesn't mean closing PRs makes a better project. It's a 
little bit cargo-culty.


Re: toChars Bug?

2017-12-12 Thread John Colvin via Digitalmars-d

On Tuesday, 12 December 2017 at 15:19:48 UTC, ketmar wrote:

p.s.: but no, i am wrong.

foo(-42);

this is perfectly valid for `foo (uint n)`, as D converts 
negative ints to uints without any warnings.


so no, overloads won't fit.


hmm yes, it seems it is not possible.


Re: toChars Bug?

2017-12-12 Thread John Colvin via Digitalmars-d

On Tuesday, 12 December 2017 at 12:49:32 UTC, ketmar wrote:
see documentation: 
http://dpldocs.info/experimental-docs/std.conv.toChars.html


"...Can be uint or ulong. If radix is 10, can also be int or 
long."


45 is int, not uint. so no radices except `10` will work.


I think it would be possible to alter toChars such that it had a 
set of overloads, such that value range propagation would allow 
an implicit conversion here.


Re: @ctfeonly

2017-12-08 Thread John Colvin via Digitalmars-d
On Thursday, 7 December 2017 at 01:21:11 UTC, Nicholas Wilson 
wrote:
I'd like to add an attribute to indicate that the annotated 
function is only available at compile time so that in cases 
where the operation is invalid at runtime (strings and 
concatenation on a GPU for instance) but the result is only 
used at compile time (for a mixin) the compiler is free to not 
codegen that function.


I can add this to LDC pretty easily, but does anyone else have 
a use for this (e.g. shrinking binary sizes for mixin heavy 
codebases) and would benefit having this as a standard thing?


How would such a thing interact with __traits(compiles, ...) and 
is-expressions?


Re: gdc is in

2017-10-07 Thread John Colvin via Digitalmars-d

On Saturday, 7 October 2017 at 16:46:44 UTC, Iain Buclaw wrote:
On 7 October 2017 at 15:00, jmh530 via Digitalmars-d 
 wrote:

On Saturday, 7 October 2017 at 10:24:38 UTC, Joakim wrote:

[...]



Also, maybe it will be easier to get people to help him if 
they know that it's up-to-date.


Why would that change anything?


Because language geeks are often motivated by the new and shiny 
and don't like to put effort in to things that don't feel like 
"the future".


Re: gdc is in

2017-10-06 Thread John Colvin via Digitalmars-d

On Friday, 6 October 2017 at 17:04:39 UTC, Iain Buclaw wrote:
On 6 October 2017 at 17:21, jmh530 via Digitalmars-d 
 wrote:

On Friday, 6 October 2017 at 15:04:25 UTC, Joakim wrote:



I assume you mean ddmd and static foreach, the mailing list 
post linked from my link implies it includes both.



I would think this would be bigger news...I mean LDC isn't 
even on 2.076 yet...



Really?  Well, maintenance should be rather small now that the 
patch / diff is relatively tiny for GDC.  Rebasing only against 
dmd/stable branch on a weekly basis or so should help things 
along also.


A lot of (most, even?) D users ignore GDC because it's been 
substantially behind the cutting edge for so long. Managing to 
catch up and become relevant to them is big news, if you want 
users.


To clarify: this includes Phobos, right?


Re: Proposal: Object/?? Destruction

2017-10-04 Thread John Colvin via Digitalmars-d

On Wednesday, 4 October 2017 at 10:03:56 UTC, aberba wrote:

 Upon reading this, It triggered an idea.


On Saturday, 30 September 2017 at 16:10:44 UTC, Jonathan 
Marler wrote:

https://wiki.dlang.org/DIP88

I'd like to see DIP88 (Named Parameters) revived.  Was this 
proposal rejected or is it just stale and needs a refresh?  
Named parameters can be implemented in a library, however, in 
my opinion they are useful enough to warrant a clean syntax 
with language support.  I'd be willing to refresh the DIP so 
long as I know the idea has not already been rejected.


DIP reminds me of object destruction.

/* extracts success & message from returned type. Could be 
tuple or structure, etc. May even eliminate use of tuples for 
multiple return

*/

auto {success, message} = callVoldermortFunction();

 This is concept is used in Kotlin. JavaScript es6 takes it 
even further (function parameters and arguments support object 
destruction)


People often call this "destructuring" or "unpacking" to avoid 
confusion with destructors.


Re: Should we add `a * b` for vectors?

2017-09-27 Thread John Colvin via Digitalmars-d
On Friday, 22 September 2017 at 17:11:56 UTC, Ilya Yaroshenko 
wrote:

Should we add `a * b` to ndslice for 1d vectors?
Discussion at https://github.com/libmir/mir-algorithm/issues/91


Unless it's always just simple element-wise, make it a different 
type. N-dimensional rectangular data structures are only 
sometimes matrices.


Also, if you did two different types I have concerns about code 
that mixed the two, it would become quite unclear which ones were 
matrix operations and which were element-wise.


Re: code.dlang.org is offline?

2017-09-22 Thread John Colvin via Digitalmars-d

On Friday, 22 September 2017 at 08:14:43 UTC, Szabo Bogdan wrote:

Hi,

Is there a reason why code.dlang.org is offline?

Thanks,
Bogdan


Works for me


Re: Specifying @nogc on structs seems to have no effect

2017-09-19 Thread John Colvin via Digitalmars-d

On Tuesday, 19 September 2017 at 13:11:03 UTC, Craig Black wrote:
I've recently tried coding in D again after some years.  One of 
my earlier concerns was the ability to code without the GC, 
which seemed difficult to pull off.  To be clear, I want my 
programs to be garbage collected, but I want to use the GC 
sparingly so that the mark and sweep collections will be fast.  
So I want guarantees that certain sections of code and certain 
structs will not require the GC in any way.


I realize that you can allocate on the non-GC heap using malloc 
and free and emplace, but I find it troubling that you still 
need to tell the GC to scan your allocation. What I would like 
is, for example, to be able to write a @nogc templated struct 
that guarantees that none of its members require GC scanning.  
Thus:


@nogc struct Array(T)
{
  ...
}

class GarbageCollectedClass
{
}

void main()
{
  Array!int intArray; // fine


}


@nogc has nothing to do with whether something needs scanning. It 
guarantees that code will never allocate with the GC or trigger a 
GC collection (because the only way to do that is to allocate or 
to call the functions in core.memory.GC, which are deliberately 
not marked @nogc).


Re: D std.regex is so slow

2017-09-19 Thread John Colvin via Digitalmars-d
On Tuesday, 19 September 2017 at 10:14:05 UTC, Dmitry Olshansky 
wrote:
On Tuesday, 19 September 2017 at 07:53:27 UTC, Daniel Kozak 
wrote:

https://github.com/mariomka/regex-benchmark#performance

Do you know why?

Here is a code:
https://github.com/mariomka/regex-benchmark/blob/master/d/benchmark.d

I have try it with ldc too, but is still much slower (10x) 
than PHP


Well I'd be interested in getting the data. The benchmark looks 
fine.


---
Dmitry Olshansky


As mentioned in the REAME: 
https://raw.githubusercontent.com/mariomka/regex-benchmark/master/input-text.txt


Re: Hong Kong dlang Meetup

2017-09-08 Thread John Colvin via Digitalmars-d-announce
On Monday, 4 September 2017 at 19:25:59 UTC, Jonathan M Davis 
wrote:
Several of us from the D community will be in Hong Kong on a 
business trip next week (me, John Colvin, Atila Neves, and Ilya 
Yaroshenko), and our client, Symmetry Investments[1], has 
offered to sponsor a dlang meetup. We haven't decided when 
exactly to meet up yet, but we're looking to meet up sometime 
during the week of the 11th - 15th (probably on Thursday or 
Friday evening) and figured that we should see if anyone here 
was interested in showing up and would thus have some stake in 
when during the week it happened.


The current plan is that the meetup will take place at 
Symmetry's main office in Chater House in Central Hong Kong.


- Jonathan M Davis

[1] http://symmetryinvestments.com/about-us/

Some open source dlang stuff whose developement was paid for by 
Symmetry: https://github.com/kaleidicassociates


Of note is https://github.com/kaleidicassociates/excel-d which 
Atila talked about at dconf this year.


We have a date and time: 
https://www.meetup.com//Dlang-Hong-Kong/events/243198527/?showDescription=true


Sorry to those who can't make it, we really wanted to make it 
after the Codeaholics meetup


Re: Hong Kong dlang Meetup

2017-09-06 Thread John Colvin via Digitalmars-d-announce
On Wednesday, 6 September 2017 at 00:48:07 UTC, Lionello Lunesu 
wrote:

Let's occupy codeaholics:
https://www.meetup.com/Codeaholics/events/242640432/


Good idea. I'll be there :)


Re: Templates, D way

2017-09-05 Thread John Colvin via Digitalmars-d
On Tuesday, 5 September 2017 at 12:41:45 UTC, Computermatronic 
wrote:

On Tuesday, 5 September 2017 at 12:20:14 UTC, crimaniak wrote:

[...]


I find it very strange that this works, as a non-mixin template 
should not be able to capture the context of where it was 
instantiated. If you take the alias template parameters out it 
behaves how it should (that is an error message saying this is 
not accessible).


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


Re: Templates, D way

2017-09-05 Thread John Colvin via Digitalmars-d

On Tuesday, 5 September 2017 at 11:08:57 UTC, Void-995 wrote:
Hi, everyone. I'm pretty new to D and trying my first steps in 
it. Currently I'm trying to port some code from C/C++ with 
pretty weird data structures and don't like idea of making 
boilerplate functions for accessing sub-lists in main binary 
structure (lets not talk about it's design, it's from legacy 
thing I want to deal with and I can't change the format itself 
or writing a lot of additional parsing code). With hour I spent 
on trying I've ended with what you may see below, but I wonder 
if there is more pleasant variant of re-writing that template 
as I haven't found anything better in either books or online 
documentation yet:


template DataList(const char[] listName, T, alias dataOffset, 
alias listLength)

{
const char[] DataList = format(q{
%s[] %s()
{
return (cast(%s *)(cast(byte *)() + %s))[0 .. %s];
}
	}, T.stringof, listName, T.stringof, dataOffset.stringof, 
listLength.stringof);

}

struct MyBinarySubStructAForA
{
int someIntegerFieldA;
float someFloatFieldA;
}

struct MyBinarySubStructBForA
{
int someIntegerFieldB;
float someFloatFieldB;
}

struct MyBinaryStructA
{
int firstSublistMembersCount;
int firstSublistMembersOffset;

int secondSublistMembersCount;
int secondSublistMembersOffset;

	@property mixin(DataList!("firstSublist", 
MyBinarySubStructAForA, firstSublistMembersCount, 
firstSublistMembersOffset));
	@property mixin(DataList!("secondSublist", 
MyBinarySubStructBForA, secondSublistMembersCount, 
secondSublistMembersOffset));

}

...

MyBinaryStructA *binaryData = cast(MyBinaryStructA 
*)fileData.ptr;


mixin template DataList(string listName, T, alias dataOffset, 
alias listLength)

{
mixin(
q{T[] } ~ listName ~ q{() @property
{
			return (cast(T*)(cast(ubyte*) + dataOffset))[0 .. 
listLength];

}}
);
}

struct MyBinarySubStructAForA
{
int someIntegerFieldA;
float someFloatFieldA;
}

struct MyBinarySubStructBForA
{
int someIntegerFieldB;
float someFloatFieldB;
}

struct MyBinaryStructA
{
int firstSublistMembersCount;
int firstSublistMembersOffset;

int secondSublistMembersCount;
int secondSublistMembersOffset;

	mixin DataList!("firstSublist", MyBinarySubStructAForA, 
firstSublistMembersCount, firstSublistMembersOffset);
	mixin DataList!("secondSublist", MyBinarySubStructBForA, 
secondSublistMembersCount, secondSublistMembersOffset);

}


Re: D as a Better C

2017-08-23 Thread John Colvin via Digitalmars-d-announce

On Wednesday, 23 August 2017 at 13:12:04 UTC, Mike Parker wrote:
To coincide with the improvements to -betterC in the upcoming 
DMD 2.076, Walter has published a new article on the D blog 
about what it is and why to use it. A fun read. And I'm 
personally happy to see the love this feature is getting. I 
have a project I'd like to use it with if I can ever make the 
time for it!


The blog:

https://dlang.org/blog/2017/08/23/d-as-a-better-c/

Reddit:
https://www.reddit.com/r/programming/comments/6viswu/d_as_a_better_c/


"D polymorphic classes will not, as they rely on the garbage 
collector."


They do? Don't have to allocate classes on the GC heap.


Re: threads, fibers and GPU kernels

2017-08-07 Thread John Colvin via Digitalmars-d

On Monday, 7 August 2017 at 08:57:35 UTC, Nicholas Wilson wrote:

On Monday, 7 August 2017 at 07:38:34 UTC, Suliman wrote:
Modern GPU have thousands of GPU kernels, it's far from CPU 
kernels, but it's interesting for me is there any chance that 
in future they be used in same maner as CPU kernels?


Do you mean threads? Not really, they are more like SIMD lanes 
that together are more analogous to a CPU thread. See John 
Colvin's 2015/2016 DConf talks.




As deadalnix reminded me after my 2016 talk, the wider picture of 
the GPU is SIMT, not SIMD, but from a computation point of view I 
find I don't need to conceptually separate the two so much. In my 
experience, most things that work well on GPU end up working very 
like SIMD on an OoO CPU when you do them right, even if they 
don't look like it in the code.


Re: Problem of undefined behaviour with overloaded methods and overloaded delegate's invokers

2017-08-01 Thread John Colvin via Digitalmars-d

On Tuesday, 1 August 2017 at 11:07:59 UTC, knex wrote:
I came across a strange thing and I am not sure if this is a 
bug or just an undefined behaviour of a compiler. Here is some 
sample code to present the case:


//

alias BoolFirst = void delegate(bool b, string s);
alias StringFirst = void delegate(string s, bool b);

class Caller {
void call(BoolFirst bs) { bs(true, "text"); }
void call(StringFirst sb) { sb("text", true); }
}

class Writer {
import std.stdio;
void write(bool b, string s) { writeln("bool+string:", b, 
"/", s); }
void write(string s, bool b) { writeln("string+bool:", s, 
"/", b); }

}

void main() {
new Caller().call( Writer().write);
}

//

As you can see, I have two classes, both having two overloaded 
methods. Writer has some dummy printing methods for bool and 
string, differing with the order of the arguments, while Caller 
takes one of these methods as a delegate and invokes it. In 
main() I create objects of these classes and call Caller's 
call() with Writer's write().


But - as far as I understand - this call is ambiguous, and 
compiler does not know what should be done here: calling 
call/write pair for bool+string or for string+bool parameters. 
Nevertheless the code compiles and the program runs the fist 
variant. The funny thing is that swapping write() methods in 
the source file causes calling the second one. But OK, suppose 
that this is and should be treated as an undefined behaviour. 
What is actually disturbing here, is that casting like 
c.call(cast(BoolFirst) ) compiles, although is not 
necessary, because not casting works the same way, but casting 
c.call(cast(StringFirst) ) - which should help here in 
calling string+bool variant - does not compile, and the 
compiler says that "Caller.call called with argument types 
(void delegate(string s, bool b)) matches both (...)", which is 
clearly true. Moreover, swapping write() methods again causes 
the exact opposite behaviour: cast(StringFirst) compiles, but 
is useless, and cast(BoolFirst) does not compile at all.


So, is this a bug, or am I just not getting something? In the 
first case, is there some kind of a workaround for the 
possibility of calling both variants (without changing the code 
of Caller and Writer classes)? In the last case, how should I 
do it properly?


I am using DMD32 D Compiler v2.075.0 on Linux.


looks like a bug to me. Please report at issues.dlang.org


Re: why no statements inside mixin teplates?

2017-07-27 Thread John Colvin via Digitalmars-d
On Friday, 12 May 2017 at 00:20:13 UTC, سليمان السهمي (Soulaïman 
Sahmi) wrote:
Is there a rational behind not allowing statements inside mixin 
templates? I know mixin does accept code containing statements, 
but using mixin is much uglier. so  I was wondering.


example use case:
//-
int compute(string)
{
return 1;
}

mixin template testBoilerPlate(alias arg, alias expected)
{
{
import std.format : format;
auto got = compute(arg);
assert(got == expected, "expected %s got 
%s".format(expected, got));

}
}

unittest
{
mixin testBoilerPlate("12345", 1);
mixin testBoilerPlate("00" ~ "0", 2 - 1);
}
//


If you can put up with the limitation of what can be done in a 
nested function then this convention works (choose whatever names 
you want, A and __ are just for example):


mixin template A()
{
auto __()
{
++a;
}
}

void main()
{
int a = 0;

mixin A!() __; __.__;

assert (a == 1);
}



Re: scope pointers in @safe code

2017-07-26 Thread John Colvin via Digitalmars-d

On Wednesday, 26 July 2017 at 08:20:42 UTC, Shachar Shemesh wrote:

void fn(scope int* var) @safe {
(*var)++;
}

void fn2() @safe {
int a;

fn();
}

The above program does not compile:
d.d(8): Error: cannot take address of local a in @safe function 
fn2


I propose that the scope keyword be activated to mean "I do not 
pass the pointer you gave me out of the function", which would 
make this code compile (as it should, as it is not doing 
anything unsafe).


Shachar


compile with -dip1000


Re: Boston D Meetup: Strawman Structs

2017-07-25 Thread John Colvin via Digitalmars-d-announce
On Sunday, 2 July 2017 at 10:35:49 UTC, Steven Schveighoffer 
wrote:
I'll have a short presentation on a weird trick I discovered 
while writing some MySQL serialization code. Hope you can 
attend!


https://www.eventbrite.com/e/d-lang-presentation-strawman-structs-tickets-35120523431

-Steve


Is there a written summary of the idea? Or is there a specific 
point in the video someone could point me to?


Re: proposed @noreturn attribute

2017-07-18 Thread John Colvin via Digitalmars-d

On Monday, 17 July 2017 at 23:01:40 UTC, Walter Bright wrote:

On 7/16/2017 5:41 AM, Timon Gehr wrote:

struct S{
T x;
Bottom everything;
}

turns the entire struct into an empty type. It is therefore 
most natural to say that Bottom.sizeof == ∞. (It's the only 
choice for which S.sizeof == Bottom.sizeof.)


Another way to think about it: If something of type A* 
converts to something of type B* without problems, then one 
would expect B.sizeof <= A.sizeof. This would imply that 
Bottom.sizeof >= size_t.max. (Because Bottom* converts to all 
other pointer types.)


One small issue is that one needs to avoid overflow for the 
size of a struct that has multiple fields where one of them is 
of type Bottom.




But if Bottom does not exist, then S doesn't exist either, and 
hence the < size relationship has no meaning.


(Reminds me of divide by 0 discussions in calculus class.)


Strictly speaking it just shouldn't have a sizeof, because sizeof 
is shorthand for "size of an instance of" (types don't really 
have sizes, how do I store the type "int" in memory?) and Bottom 
has no instances.


Infinity - or the next best applicable thing size_t.max - is a 
reasonable standin for an invalid value, except that people will 
do silly things like `auto paddedSpace =

 (ReturnType!foo).sizeof + 1;` and then you're in trouble.

Better to just not define it.

Is there some magic that can be done where all code that makes 
reference to an instance of Bottom just isn't compiled? I.e. if 
there happens to be a situation where a function returns Bottom 
then all code that touches that return type is just ignored?


Re: DCompute: GPGPU with Native D for OpenCL and CUDA

2017-07-18 Thread John Colvin via Digitalmars-d-announce

On Tuesday, 18 July 2017 at 00:49:11 UTC, Nicholas Wilson wrote:

On Monday, 17 July 2017 at 13:50:22 UTC, Mike Parker wrote:
Nicholas Wilson has put together a blog post on his progress 
with DCompute, expanding on his DConf talk. I have to admit 
that this is one of the D projects I'm most excited about, 
even though I'll probably never have a need to use it. I'd 
love to find an excuse to do so, though!


Blog:
https://dlang.org/blog/2017/07/17/dcompute-gpgpu-with-native-d-for-opencl-and-cuda/

Reddit:
https://www.reddit.com/r/programming/comments/6nt4ba/dcompute_gpgpu_with_native_d_for_opencl_and_cuda/


Thanks for that.

Oh and @JohnColvin do you like the solution for the lambdas?


I do, very nice :) You're essentially achieving what I set out to 
do and got stuck with, just much better.


Re: static foreach is now in github master

2017-07-17 Thread John Colvin via Digitalmars-d-announce
On Monday, 17 July 2017 at 18:14:35 UTC, Andrei Alexandrescu 
wrote:
For those who want to play with our new static foreach feature 
and are willing to take the steps to building their own dmd, 
the feature is now merged in master: 
https://github.com/dlang/dmd/pull/6760


Happy hacking!

Andrei


or for those using homebrew: `brew install dmd --HEAD`


Re: Idiomatic FFT(W) Wrapper

2017-07-13 Thread John Colvin via Digitalmars-d-learn

On Thursday, 13 July 2017 at 12:49:40 UTC, Per Nordlöw wrote:

Have anybody constructed an idiomatic D wrapper for FFTW?


No, sorry, although I have used the library quite a bit in D.


http://www.fftw.org/fftw3_doc/Tutorial.html#Tutorial

I'm specifically concerned about

- `RefCounted`-wrapping of the C structures `fftw_complex` and 
`fftw_plan`


Sounds useful perhaps for fftw_plan. fftw_complex is just 
`typedef double fftw_complex[2];` so I'm not sure what you're 
getting at there.


It's worth remembering that "wisdom" is separate from (and shared 
between) plans in fftw, so constructing and destroying plans can 
be very cheap and there's often no need to have multiple owners 
of a single plan.



- range semantics, lazy evaluation and caching of result in
  stream-based architectures; `fftw_plan`, `fftw_execute`


The discrete fourier transform is a global algorithm that can be 
lazy in input or output, but not both. I'm pretty sure the fast 
fourier transform algorithm for DFT cannot be lazy in either. Do 
you mean creating some sort of lazy short-time-fourier-transform 
(STFT or spectrogram or whatever other name people like)? Or are 
you thinking about 1-D transforms in multi-dimensional data 
(arguably the same thing actually)?



- slicing and scope


??

- seamless interoperability with Mir 
(https://github.com/libmir/mir)


This would definitely be nice to have

For most common use-cases I find fftw is dead simple to use with 
the C API though. So simple that I never even bother making 
bindings, I just declare what I need as I need it (which in a 
single application has never been more than about 10 
declarations).


Re: DIP 1010--Static foreach--Formal Review

2017-07-12 Thread John Colvin via Digitalmars-d
On Tuesday, 11 July 2017 at 23:50:26 UTC, Steven Schveighoffer 
wrote:

On 7/11/17 7:21 PM, H. S. Teoh via Digitalmars-d wrote:
On Tue, Jul 11, 2017 at 07:18:51PM -0400, Steven Schveighoffer 
via Digitalmars-d wrote:

[...]
3. The only controversial part I see is that `break` doesn't 
break
from the foreach loop. While I agree with the reasoning, and 
support
that concept, the truth is we currently have a "poor man's" 
static
foreach using a foreach over a tuple, and that DOES break 
from the

loop.


This is a false impression.  It actually does not break from 
the loop,
but inserts a break in the generated code, and continues to 
unroll the
rest of the loop.  It's only at codegen that the subsequent 
iterations

are detected as dead code and elided. See:


https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time#.22static.22_foreach_does_NOT_interpret_break_and_continue


Yes, I know that it still generates all the code, but the break 
is still interpreted as breaking out of the loop. Timon's 
proposal says it "does not interact with break", so I interpret 
that as meaning it should break out of whatever construct is 
surrounding the loop, not the loop itself.


Currently this:

foreach(j; 0 .. 2)
foreach(i; AliasSeq!(0, 1))
{
writeln(i);
static if(i == 0)
  break;
}

will print
0
0

Whereas with my understanding, this:

foreach(j; 0 .. 2)
static foreach(i; 0 .. 2)
{
writeln(i);
static if(i == 0)
   break;
}

would print
0

This seems too confusing.

-Steve


break inside a case inside a static foreach inside a switch is an 
interesting case for this sort of reasoning


Re: Why is phobos so wack?

2017-07-09 Thread John Colvin via Digitalmars-d

On Sunday, 9 July 2017 at 12:56:55 UTC, FoxyBrown wrote:

import string.

...
return str.join(" ");


gives

Error: template std.array.join cannot deduce function from 
argument types !()(string, string)


Well there's your mistake? There is no function `join` that takes 
(string, string). Everything after that is more detail that may 
or may not be useful, but reading the error message carefully, in 
order, is generally good enough. That said, it would be nice if 
the errors were less daunting somehow.


Re: proposed @noreturn attribute

2017-07-08 Thread John Colvin via Digitalmars-d
On Saturday, 8 July 2017 at 12:17:57 UTC, Andrei Alexandrescu 
wrote:

On 7/8/17 6:15 AM, Walter Bright wrote:
Has anyone a better idea? Does anyone want to write a DIP for 
this?


An attribute is fine. A more PL-minded possibility is to return 
a specific type:


struct None
{
@disable this();
@disable this(this);
@disable @property None init();
}

None ThisFunctionExits();

The compiler detects (without having anything hardwired about 
the particular type "None") that the type None is impossible to 
create and copy/move from a function, and therefore decrees the 
function will never return.



Andrei


I wonder if some lessons from Haskell's "bottom" type would be 
relevant here.


Re: Compilation times and idiomatic D code

2017-07-06 Thread John Colvin via Digitalmars-d

On Wednesday, 5 July 2017 at 20:32:08 UTC, Stefan Koch wrote:

On Wednesday, 5 July 2017 at 20:12:40 UTC, H. S. Teoh wrote:


I vaguely remember there was talk about compressing symbols 
when they get too long... is there any hope of seeing this 
realized in the near future?


Yes there is.
Rainer Schuetze is quite close to a solution. Which reduces the 
symbol-name bloat significantly.

See https://github.com/dlang/dmd/pull/5855


There is still a problem with the template system as a whole.
Which I am working on in my spare time.
And which will become my focus after newCTFE is done.


Please give consent for the D Foundation to clone you.


  1   2   3   4   5   6   7   8   9   10   >