Should "a is b" compile if a and b have unrelated classes?

2018-04-10 Thread Michael Coulombe via Digitalmars-d-learn
I had a bug in my code that was messing me up for a while, and it 
boiled down to an identity check between two Object references 
with unrelated static types, like below:


class A {}
class B {}
void main() {
A a = new A;
B b = new B;
if (a is b) {} // compiles
}

I was surprised that the type system failed me here. It's true 
that A and B could be upcast to Object and then comparisons would 
make sense type-wise, but the comparison should never pass (and 
the compiler should know it won't since they are in separate 
inheritance subtrees) unless the programmer is intentionally 
breaking the type system.


Is there reasoning for this? If not, should it be a warning or 
error, as it is for example when comparing two pointers to 
structs of different types?


Re: Simplest multithreading example

2017-08-31 Thread Michael Coulombe via Digitalmars-d-learn

On Friday, 1 September 2017 at 01:59:07 UTC, Brian wrote:
Hello, I am trying to get the most trivial example of 
multithreading working, but can't seem to figure it out.
I want to split a task across threads, and wait for all those 
tasks to finish before moving to the next line of code.


The following 2 attempts have failed :

-
Trial 1 :
-

auto I = std.range.iota(0,500);
int [] X; // output
foreach (i; parallel(I) )
X ~= i;
core.thread.thread_joinAll(); // Apparently no applicable here ?
writeln(X); // some random subset of indices


Trial 2 : (closer to Java)

class DerivedThread : Thread
{
int [] X;
int i;
this(int [] X, int i){
this.X = X;
this.i = i;
super();
}

private:
void run(){
X ~= i;
}
}

void main(){
auto I = std.range.iota(0,500);
int [] X; // output
Thread [] threads;
foreach (i; I )
threads ~= new DerivedThread( X,i);
foreach( thread; threads)
thread.start();
foreach( thread; threads)
thread.join(); // does not seem to do anything
core.thread.thread_joinAll(); // also not doing anything

writeln(X); // X contains nothing at all
}

How can I get the program to wait until all threads have 
finished before moving to the next line of code ?


Thank you !


Just like a sequential loop, when you do "foreach (i; parallel(I) 
) { ... }", execution will not continue past the foreach loop 
until all the tasks associated with each element of I have 
finished.


Your particular example of "X ~= i" in the body of the loop is 
not thread-safe, so if that is the code you really intend to run, 
you should protect X with a Mutex or something comparable.


Re: BinaryHeap crashes upon insertion if heapified with an array of length 1?

2017-04-09 Thread Michael Coulombe via Digitalmars-d-learn

On Sunday, 9 April 2017 at 00:36:00 UTC, TheGag96 wrote:
I'm trying to use a binary heap initialized with one element. 
However, this always seems to cause a range violation for some 
reason. This small example will do it:


import std.stdio, std.container;

void main() {
  auto pq = heapify([5]);
  pq.insert(8);
}

...And it produces this error: https://pastebin.com/dyLNRz2W

Oddly enough, if I heapify an array with any other length than 
1, I can insert as much as I want (that includes an empty 
array!). Is this a bug in Phobos or some odd expected behavior? 
Thanks guys!


This is a bug in the insert method. I created a bug report for 
you and submitted a pull request for a fix:


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


align(n) outside struct useless?

2017-02-20 Thread Michael Coulombe via Digitalmars-d-learn
I can't figure out how to set the alignment of a struct using 
align(n) on the outside of the struct. Only align on the fields 
(default or annotated) seems to work. I get the same results back 
to at least DMD 2.065... Is this a bug or am I using it wrong?


align(32) struct A { ubyte padding; }
pragma(msg, A.alignof); => 1

align(32) struct B { align(32) ubyte padding; }
pragma(msg, B.alignof); => 32

struct C { align(32) ubyte padding; }
pragma(msg, C.alignof); => 32

align(32) struct D { int padding; }
pragma(msg, D.alignof); => 4


Re: usage of ref foreach with variadic functions fails with "cannot be ref"

2017-02-11 Thread Michael Coulombe via Digitalmars-d-learn

On Saturday, 11 February 2017 at 15:02:11 UTC, error wrote:
On Saturday, 11 February 2017 at 14:43:18 UTC, rikki cattermole 
wrote:

Try:

foreach(i, v; vars) {
vars[i] = ...;
}


Perfect! Thanks so much - I wish that hint was in the 
documentation for variadic functions, although I guess it 
suggests an inefficiency in the compiler - since there would be 
an additional copy of vars[i] created in v.


Do you have a complete code example that gives your error? I 
can't reproduce it (DMD v2.073.0):


int foo(T...)(T vars) {
int i = 0;
foreach(ref v ; vars) {
v = 5;
i += v;
}
return i;
}
void bar(T...)(ref T vars) {
foreach(ref v ; vars) {
v = 3;
}
}
void main() {
import std.stdio;
int x = 7;
bar(x);
writeln(foo(4,x,8.2)); // 15, no errors
}


Re: Mallocator and 'shared'

2017-02-10 Thread Michael Coulombe via Digitalmars-d-learn

On Friday, 10 February 2017 at 23:57:18 UTC, bitwise wrote:

https://github.com/dlang/phobos/blob/cd7846eb96ea7d2fa65ccb04b4ca5d5b0d1d4a63/std/experimental/allocator/mallocator.d#L63-L65

Looking at Mallocator, the use of 'shared' doesn't seem correct 
to me.


The logic stated in the comment above is that 'malloc' is 
thread safe, and therefore all methods of Mallocator can be 
qualified with 'shared'.


I thought that qualifying a method as 'shared' meant that it 
_can_ touch shared memory, and is therefore _not_ thread safe.



The following program produces this error:
"Error: shared method Mallocator.allocate is not callable using 
a non-shared object"


import std.experimental.allocator.mallocator;

int main(string[] argv) {
Mallocator m;
m.allocate(64);
return 0;
}

And the above error is because it would be un(thread)safe to 
call those methods from a non-shared context, due to the fact 
that they may access shared memory.


Am I wrong here?


A shared method means that it can only be called on a shared 
instance of the struct/class, which will have shared fields. A 
shared method should be logically thread-safe, but that cannot be 
guaranteed by the compiler. A non-shared method can touch shared 
memory, and thus should be thread-safe if it does, but can only 
be called on a non-shared instance with possibly non-shared 
fields.


shared/non-shared methods don't mix because you generally need to 
use different, less-efficient instructions and algorithms to be 
thread-safe and scalable in a shared method. In the case of 
Mallocator, there are no fields so as far as I can tell the 
attribute doesn't do much except for documentation and for 
storing references to it in other shared structs/objects.


Re: Quine using strings?

2017-01-15 Thread Michael Coulombe via Digitalmars-d-learn

A quine I came up with a while ago, using q{} string notation:

enum s = q{enum s = q{%s};
void main() {
import std.stdio;
writefln(s,s);
}};
void main() {
import std.stdio;
writefln(s,s);
}


Re: Reflection: Order of fields guaranteed?

2016-10-22 Thread Michael Coulombe via Digitalmars-d-learn

On Friday, 21 October 2016 at 01:51:44 UTC, Stefan Koch wrote:
On Friday, 21 October 2016 at 01:34:44 UTC, Nick Sabalausky 
wrote:
When using reflection to obtain the fields of a class/struct, 
is there any guarantee that the order is the same as the order 
the fields are defined?


Yes they should always come in lexical order.


For classes, the spec disagrees, even though it might be true 
using current compilers.


https://dlang.org/spec/class.html#fields

"The D compiler is free to rearrange the order of fields in a 
class to optimally pack them in an implementation-defined manner. 
... Explicit control of field layout is provided by struct/union 
types, not classes."


Retreive method given object, name and arguments

2016-08-11 Thread Michael Coulombe via Digitalmars-d-learn
Is there a way to implement "getSymbolOfCall" and 
"getDelegateOfCall" such that doit is functionally equivalent to 
calling the method directly?


auto doit(C, string methodName, Args...)(C c, Args args) {
alias methodSymbol = getSymbolOfCall!(c, methodName, Args);
pragma(msg, hasUDA!(methodSymbol, "my attr"));
auto dg = getDelegateOfCall!(c, methodName, Args);
return dg(args);
}

They should deal with getting the right overload, opDispatch-ing, 
and deducing template arguments from the real argument list to 
get a concrete delegate pointer. methodSymbol should give access 
to compile-time introspection like full signature and UDAs.


The ability to do this for non-member functions would be cool 
too, but is beyond my use case.


Re: SortedRange.lowerBound from FrontTransversal

2016-08-07 Thread Michael Coulombe via Digitalmars-d-learn

On Monday, 8 August 2016 at 00:57:41 UTC, Michael Coulombe wrote:

...


And looking at the source, the reason it fails when using 
TransverseOptions.assumeNotJagged is that it does not implement 
length or $.


I made this into an enhancement request: 
https://issues.dlang.org/show_bug.cgi?id=16363


Re: SortedRange.lowerBound from FrontTransversal

2016-08-07 Thread Michael Coulombe via Digitalmars-d-learn

On Saturday, 6 August 2016 at 23:00:42 UTC, Alex wrote:

Hi all... a technical question from my side...
why the last line of the following gives the error?

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

void main()
{
size_t[][] darr;
darr.length = 2;
darr[0] = [0, 1, 2, 3];
darr[1] = [4, 5, 6];
auto fT = frontTransversal(darr);
assert(equal(fT, [ 0, 4 ][]));

auto heads = assumeSorted!"a <= b"(fT);
writeln(heads.lowerBound(3)); //!(SearchPolicy.gallop)
}

The error is:
Error: template 
std.range.SortedRange!(FrontTransversal!(ulong[][], 
cast(TransverseOptions)0), "a <= b").SortedRange.lowerBound 
cannot deduce function from argument types !()(int), candidates 
are:
package.d(7807,10): 
std.range.SortedRange!(FrontTransversal!(ulong[][], 
cast(TransverseOptions)0), "a <= 
b").SortedRange.lowerBound(SearchPolicy sp = 
SearchPolicy.binarySearch, V)(V value) if 
(isTwoWayCompatible!(predFun, ElementType!Range, V) && 
hasSlicing!Range)


I tried also with "assumeNotJagged" for the FrontTransversal, 
it didn't worked either, beyond the fact, that assumeNotJagged 
is not of interest for me...


Unfortunately, frontTraversal is not giving you a random access 
range, only a bidirectional range, which means it does not 
support indexing or slicing. It appears that the TraversalOptions 
doesn't cover the case where each range is "long enough" to be 
indexed but not equal length.


static assert(isBidirectionalRange!(typeof(fT))); // succeeds
static assert(isRandomAccessRange!(typeof(fT)));  // fails
static assert(__traits(compiles, fT[0])); // fails
static assert(__traits(compiles, fT[0 .. 2]));// fails

In the mean time, you can use this simple alternative:

auto fT = darr.map!front; // for arrays
auto fT = darr.map!"a.front"; // for any range


Re: Static ternary if

2016-07-25 Thread Michael Coulombe via Digitalmars-d-learn

On Monday, 25 July 2016 at 22:57:05 UTC, Gorge Jingale wrote:

On Monday, 25 July 2016 at 22:27:11 UTC, Cauterite wrote:

On Monday, 25 July 2016 at 02:15:12 UTC, Gorge Jingale wrote:

Is there a static ternary if?

(A == B) ? C : D;

for compile type that works like static if.


You can pretty easily make your own;

  template staticIf(bool cond, alias a, alias b) {
static if (cond) {
  alias staticIf = a;
} else {
  alias staticIf = b;
};
  };

The drawback is that there's no 'short-circuiting'; a and b 
are both evaluated.


Cool, that would work. I don't think the lazy evaluation is a 
problem at compile time? Just makes for longer times, but 
should be pretty minuscule.


If that's ok, then try out std.traits.Select or std.traits.select:
https://dlang.org/phobos/std_traits.html#Select


Re: Variadic Tuple of Structs with Mixed Types

2016-07-15 Thread Michael Coulombe via Digitalmars-d-learn

On Friday, 15 July 2016 at 17:00:09 UTC, jmh530 wrote:
I was working with the lightweight wrapper and it seemed to 
work for simple stuff, but then I started getting a bunch of 
errors when I tried to integrate it in to my project.


Below is the stripped down version of what I've been working 
with. I think the problem is that I can't get the fillAliasSeq 
template to work with aliases. If I change Foo to just take 
types and pass something like int or float, then it works fine.


Note, I originally had fillAliasSeq as a nested template within 
bar, but this was causing errors similar to what is brought up 
in this thread

http://forum.dlang.org/post/mailman.578.1343005779.31962.digitalmars-d-le...@puremagic.com


Your issue is this line:

alias boxAR(A) = Box!(A, R);

This means that A must be a type, but you are trying to 
instantiate it with lambdas. If you switch to:


alias boxAR(alias A) = Box!(A, R);

But now you are back to the "local '__lambda1' as parameter to 
non-global template" error.


Have you considered recursive solutions?

template fillAliasSeq(R, f...)
{
import std.meta : AliasSeq;

static if (f.length == 0) {
alias fillAliasSeq = AliasSeq!();
}
else {
	alias fillAliasSeq = AliasSeq!(Foo!(f[0], R), 
fillAliasSeq!(R, f[1..$]));

}
}


Re: Typesafe variadic functions requiring at least one argument

2016-07-07 Thread Michael Coulombe via Digitalmars-d-learn

On Wednesday, 6 July 2016 at 19:50:11 UTC, pineapple wrote:
I'd like to do something like this but it doesn't seem to be 
legal -


void test(int[] ints...) if(ints.length){
// stuff
}

Not being able to specify this interferes with how I'd like to 
define my method overloads. What's the best way to achieve what 
I'm looking for?


Is this close enough?

void test(int first, int[] rest...) {
auto ints = only(first).chain(rest);
// stuff
}
void main() {
//test(); // fails to compile
test(1);
test(1,2,3);
}


Re: Print a triangle

2016-04-29 Thread Michael Coulombe via Digitalmars-d-learn

On Friday, 29 April 2016 at 12:01:19 UTC, Joel wrote:
On Friday, 29 April 2016 at 11:31:51 UTC, rikki cattermole 
wrote:

Not entirely the goal I'm guessing output wise, but this works.

import std.range : repeat;
foreach(line; 1 .. 11) {
writeln('#'.repeat(line));
}


That is shorter than my foreach version, but I want one that 
doesn't use foreach in it at all.


Try this:

iota(1,11).each!(a => writeln("#".replicate(a)))


Re: Shortest way to allocate an array and initialize it with a specific value.

2015-06-10 Thread Michael Coulombe via Digitalmars-d-learn

On Wednesday, 10 June 2015 at 20:22:18 UTC, Adel Mamin wrote:

ubyte[5] a = 0xAA; // Fine. Five 0xAA bytes.
auto a2 = new ubyte[5]; // Fine. Five 0 bytes.
Now, let's say, I want to allocate an array of a size, derived 
at run time, and initialize it to some non-zero value at the 
same time. What would be the shortest way of doing it?


Probably:

auto a2 = value.repeat(size).array;