Re: A few notes on choosing between Go and D for a quick project
Walter Bright: On 3/13/2015 3:34 AM, bearophile wrote: Strict mode is a D2 with immutable+@safe+pure by default, Thank you Walter for giving me an actual answer :-) Note that you can get this largely by starting a module with the following: immutable @safe pure: immutable in my post was mostly referring to local variables, foreach variables and so on. something like a var keyword to denote mutable values, Transitive const may make this problematic. I don't understand, but perhaps you misunderstood me. I am talking about variables. In strict mode they are constant by default. This means in this code both x and y are immutable: auto x = 10; foreach (y; 0 .. 10) {} So in strict mode if you want them mutable you need a new keyword like var: var x = 10; foreach (var y; 0 .. 10) {} static full tracking of memory ownership, Makes the language significantly more complex. You are probably right. But it also gives good things back to a system language. In the last years I've seen that taking twice the time to write my code is a good deal if later I can avoid wasting stressful hours searching and fixing bugs. So now I am willing to pay a high price up front when I code to avoid some bugs later. I have friends that have taken a look at Rust and have dismissed it for being too much fussy and hard to get code to compile (despite probably with practice the Rust rules should become quite simpler to follow), but Rust looks like the right language for me and I'd like the same qualities in the language that I like more (D). So in the end I don't know what's the best solution for D. less implicit casts (because now we have the safe int(x) sytnax), I think D does very well with implicit casts. I am not sure of that. Implicit casts cause some troubles, you can see this if you program for a while in a language with no or with very little implicit casts like Haskell, and F#. In D we have some implicit casts also because the cast(int)x syntax is dangerous. But now we can write safe casts with the int(x) syntax, so there's less need of naked implicit casts. And I'd still like built-in tuple syntax in D. [... Just one more feature ...] is the road to hell. It's one more feature, and probably if D will last ten more years other features will be added to D. Built-in tuples have a mostly intuitive semantics, and they help de-clutter the code. So the language gets a little more complex, but the code becomes a little simpler. Bye, bearophile
Re: A few notes on choosing between Go and D for a quick project
Ola Fosheim Grøstad: Yes, but what is a strict mode. I agree with most of what is said about D and Go in the top post, but is there a market for yet another high level language that isn't high level enough? Strict mode is a D2 with immutable+@safe+pure by default, something like a var keyword to denote mutable values, no comma operator, static full tracking of memory ownership, less implicit casts (because now we have the safe int(x) sytnax), and few other small changes that make the language less bug prone and more strict. And I'd still like built-in tuple syntax in D. Bye, bearophile
Re: A few notes on choosing between Go and D for a quick project
Andrei Alexandrescu: That's a rather random collection - strict seems to be D without the stuff bearophile dislikes. -- Andrei I am OK with that definition. Is that your best critique to those suggestions? :-) Bye, bearophile
Compilation changes
Time ago Dmitry Olshansky gave me a nice script to compile dmd+Phobos from github, starting like this: My recipe on Windows, by Dmitry Olshansky: 0. Make sure there are no other DMD in the Windows path. 1. Get the latest DMD release zip you can find, unzip to some drive root(! otherwise get's trickier) 2. Delete all within src subfolder 3. Get a Git console in \dmd2\src, then the usual: ... Now I think it doesn't work any more, giving errors like this: make -fwin32.mak C=backend TK=tk ROOT=root HOST_DC= reldmd make -fwin32.mak C=backend TK=tk ROOT=root HOST_DC= OPT=-o DEBUG= LFLAGS=-L/delexe/la dmd.exe run idgen Error: 'run' not found --- errorlevel 1 --- errorlevel 1 So is Dmitry (or someone else) willing and able to tell me how to fix my compilation script and what to do? Thank you, bye, bearophile
Re: A few notes on choosing between Go and D for a quick project
Florin Mihaila: This note is getting too long, so if some of what I wrote needs more clarification, feel free to ask. I'm glad my humble notes are sparking discussion, and I hope D continues to grow. Constructive notes (as yours) are always welcome in this friendly community. Thank you for your help. Bye, bearophile
Re: A few notes on choosing between Go and D for a quick project
Andrei Alexandrescu: ## some or all of @safe, immutable, pure should be the default +1 I have a ER on @safe by default and Walter seems to agree. But I'd like more. A strict D mode? :-) # libraries, projects should be prominently listed and nurtured # single-idea advantage; D seems to embody too many ideas at once ## concurrency? ## networking? ## generics? ## interoperability with C and C++? ## focus on one! D can't be a single-purpose language. And it has more moving parts compared to Go. Bye, bearophile
Re: Int to float?
Ola Fosheim Grøstad: D claims to follow C, so using unions for type punning is ultimately implementation defined. I am not sure if D is the same as C regarding this. Bye, bearophile
Re: Parallel Merge Sort
Josh: swap(A, B) what exactly is this doing? You should learn to answer your own questions in many cases. Take a look at the source code of Phobos, you will see the swap() implementation inside std.algorithm. It swaps the content of two values. Here the values are the structs that contain the pointer+length of the dynamic arrays. Bye, bearophile
Re: Parallel Merge Sort
Ali Çehreli: I think there is bug in the algorithm: auto a = [90, 50, 33, 72, 35]; a.mergeSort; assert(a == [33, 50, 72, 90, 35]);// Incorrect ordering :( I translated that D code from C code of Wikipedia in few minutes, the probability of mistakes is high. Better to use some more reliable code then... Bye, bearophile
Re: RCArray is unsafe
Walter Bright: The complexity of a free list doesn't remotely compare to that of adding an ownership system. A sound complete ownership system is the only good enough solution for D. That's my opinion. Bye, bearophile
Re: is expression and type tuples
Jack Applegame: On Tuesday, 3 March 2015 at 17:49:24 UTC, bearophile wrote: That's 1 + n-1 :-) Could you please explain what does '1 + n-1' mean? This is your code: template Is(ARGS...) if(ARGS.length % 2 == 0) { enum N = ARGS.length/2; static if(N == 1) enum Is = is(ARGS[0] : ARGS[1]); else enum Is = is(ARGS[0] : ARGS[N]) Is!(ARGS[1..N], ARGS[N+1..$]); } The recursion scheme you are using is working on a single item (a single pair of items), and then calling the recursion on all other items but the first. If you look in std.traits you see examples of a different recursion that reduces compilation time: template isExpressionTuple(T ...) { static if (T.length = 2) enum bool isExpressionTuple = isExpressionTuple!(T[0 .. $/2]) isExpressionTuple!(T[$/2 .. $]); else static if (T.length == 1) enum bool isExpressionTuple = !is(T[0]) __traits(compiles, { auto ex = T[0]; }); else enum bool isExpressionTuple = true; // default } Bye, bearophile
Re: RCArray is unsafe
Walter Bright: How do you type an an array of pointers with different owners? Sound doesn't mean it should be able to do everything. It will be just an approximated model. It means it's going to forbid some valid code, just like every type system. You use some @system code to work around some of those limitations. And if the design is good, such islands of unsafety are located inside Phobos constructs that leak (http://en.wikipedia.org/wiki/Leaky_abstraction ) very little. Bye, bearophile
[rosettacode] std.container.DList problems
This code used to work in DMD 2.065: http://rosettacode.org/wiki/Strand_sort#D import std.stdio, std.container; DList!T strandSort(T)(DList!T list) { static DList!T merge(DList!T left, DList!T right) { DList!T result; while (!left.empty !right.empty) { if (left.front = right.front) { result.insertBack(left.front); left.removeFront(); } else { result.insertBack(right.front); right.removeFront(); } } result.insertBack(left[]); result.insertBack(right[]); return result; } DList!T result, sorted, leftover; while (!list.empty) { leftover.clear(); sorted.clear(); sorted.insertBack(list.front); list.removeFront(); foreach (item; list) { if (sorted.back = item) sorted.insertBack(item); else leftover.insertBack(item); } result = merge(sorted, result); list = leftover; } return result; } void main() { auto lst = DList!int([-2,0,-2,5,5,3,-1,-3,5,5,0,2,-4,4,2]); foreach (e; lst.strandSort) write(e, ); } Now it gives a runtime error like phobos\std\container\dlist.d(329): DList.front: List is empty. I think the cause is that list = leftover; has a different semantics. Is this a regression fit for Bugzilla? Bye, bearophile
Re: Implicit fall through not detected (Example from lex.html)
Andre: I am also not really happy with the actual behavor (w / wi switch needed) You shall always compile your D code with warnings active, unless you need them disabled for some real reason. Eventually the fall through warning will become a deprecation and then an error. It's meant to be an error, but in D we introduce errors slowly. Bye, bearophile
Re: is expression and type tuples
Jack Applegame: Seems like is expression doesn't support type tuples: pragma(msg, is(short : int)); // true enum Test(ARGS...) = is(ARGS[0..2] : ARGS[2..4]); pragma(msg, is(Test!(int, int, int, int))); // false pragma(msg, Test!(int, short, int, int)); // false Is it by design, or just not implemented? It's by design, perhaps because Walter didn't think of this case, or probably for compiler simplicity. But it should be not too much hard to implement it your code. Just use two is(), or use recursion (with splitting in two, and not 1 + n-1). Bye, bearophile
Re: is expression and type tuples
Jack Applegame: or use recursion (with splitting in two, and not 1 + n-1). Bye, bearophile I already have one: template Is(ARGS...) if(ARGS.length % 2 == 0) { enum N = ARGS.length/2; static if(N == 1) enum Is = is(ARGS[0] : ARGS[1]); else enum Is = is(ARGS[0] : ARGS[N]) Is!(ARGS[1..N], ARGS[N+1..$]); } That's 1 + n-1 :-) Bye, bearophile
Re: Parallel Merge Sort
Josh wrote: How can I make my parallel code more efficient. Currently, I am getting destroyed by the serial merge sort. http://pastebin.com/M0GKfTTX That serial merge sort I've written is little more than a toy. I suggest you to compare your parallel sort with a serial sort that allocates better. Perhaps later I'll add it. Here I have done a quick translation of some C code from Wikipedia, this is wasteful for memory (not tested much!): import std.stdio, std.algorithm; /// A has the items to sort, array B is a work array. void mergeSort(T)(T[] A) pure nothrow @safe out { assert(A.isSorted); } body { static void bottomUpMerge(T)(in T[] A, in size_t iLeft, in size_t iRight, in size_t iEnd, T[] B) pure nothrow @safe @nogc { size_t i0 = iLeft; size_t i1 = iRight; // While there are elements in the left or right runs. for (size_t j = iLeft; j iEnd; j++) { // If left run head exists and is = existing right run head. if (i0 iRight (i1 = iEnd || A[i0] = A[i1])) { B[j] = A[i0]; i0++; } else { B[j] = A[i1]; i1++; } } } immutable n = A.length; auto B = new T[n]; // Each 1-element run in A is already sorted. // Make successively longer sorted runs of length 2, 4, 8, 16... until whole array is sorted. for (size_t width = 1; width n; width = 2 * width) { // Array A is full of runs of length width. for (size_t i = 0; i n; i = i + 2 * width) { // Merge two runs: A[i:i+width-1] and A[i+width:i+2*width-1] to B[] // or copy A[i:n-1] to B[] ( if(i+width = n) ). bottomUpMerge(A, i, min(i + width, n), min(i + 2 * width, n), B); } // Now work array B is full of runs of length 2*width. swap(A, B); } } void main() { auto a = [3,1,2,5,4,8,6,7,2,9,1,4,3]; a.mergeSort; a.writeln; } Bye, bearophile
Re: Contradictory justification for status quo
Walter Bright: Actually, Kenji fearlessly deals with some of the hardest bugs in the compiler that require a deep understanding of how the compiler works and how it is supposed to work. He rarely does trivia. I regard Kenji's contributions as invaluable to the community. But my point was that probably there are even better things that Kenji can do in part of the time he works on D. Bye, bearophile
Re: DIP74: Reference Counted Class Objects
Jacob Carlborg: @arc class Foo { T1 opAddRef(); T2 opRelease(); } ... Alternative A gives a clear documentation it's a reference counted class without having to scan the methods. Assuming you want something like DIP74, this design design seems safer than the design proposed in DIP74. Bye, bearophile
Re: Contradictory justification for status quo
Andrei Alexandrescu: I'm following with interest the discussion My Reference Safety System (DIP???). Right now it looks like a lot of work - a long opener, subsequent refinements, good discussion. It also seems just that - there's work but there's no edge to it yet; right now a DIP along those ideas is more likely to be rejected than approved. But I certainly hope something good will come out of it. The second scope proposal looks simpler than the first: http://wiki.dlang.org/User:Schuetzm/scope2 Later in Rust they have added some lifetime inference to reduce the annotation burden in many cases. Bye, bearophile
Re: Contradictory justification for status quo
Zach the Mystic: You can see exactly how D works by looking at how Kenji spends his time. For a while he's only been fixing ICEs and other little bugs which he knows for certain will be accepted. I agree that probably there are often better ways to use Kenji time for the development of D. Bye, bearophile
Re: Contradictory justification for status quo
Andrei Alexandrescu: Safety is good to have, and the simple litmus test is if you slap @safe: at the top of all modules and you use no @trusted (or of course use it correctly), you should have memory safety, guaranteed. I have suggested to switch to @safe by default: https://issues.dlang.org/show_bug.cgi?id=13838 Bye, bearophile
Re: What am I doing wrong here - canFind with iota is not working
immutable float item = 0.174531f; r.canFind!q{ feqrel(cast()a, cast()b) = 21 }(item).writeln; } With a recent Phobos bug fix you can now write: r.canFind!q{ feqrel(a, b) = 21 }(item).writeln; Bye, bearophile
Re: What am I doing wrong here - canFind with iota is not working
Laeeth Isharc: Ie I think people diagnosed the problem, but what is the solution... A possible solution: void main() @safe { import std.stdio, std.range, std.algorithm, std.math; immutable float oneDegree = (PI / 180.0f); immutable float first = -(oneDegree * 10.0f); immutable float second = (oneDegree * 10.0f); immutable float step = 0.01f; immutable float[] r = iota(first, second, step).array; //r.writeln; immutable float item = 0.174531f; r.canFind!q{ feqrel(cast()a, cast()b) = 21 }(item).writeln; } Bye, bearophile
Re: DIP74: Reference Counted Class Objects
Andrei Alexandrescu: The compiler detects automatically and treats specially all classes and interfaces that define the following two methods: Defining only one of those methods needs to give a compile-time error. This lowering assumes left-to-right evaluation of function parameters. Is this currently enforced in all D compilers? This DIP allows defining reference counted class objects that are usable in @safe code. However, it does not enforce safety. And do you plan to later design what's needed to enforce their safety? Bye, bearophile
Re: Memory safety depends entirely on GC ?
Andrei Alexandrescu: using stack-allocated arrays in safe code is a rather niche use). I use stack-allocated arrays in supposedly safe code. And having a future D compiler that makes that kind of code actually safe is a good thing. Bye, bearophile
Re: Memory safety depends entirely on GC ?
Andrei Alexandrescu: It definitely is a good thing. The question is balancing its goodness against the costs of allowing it. It's not impossible you may get asked to change your code to use a struct instead of a fixed-sized array. I don't like the look of the annotations of DIP25. I'd like DIP25 removed from D language and replaced by a more principled solution. Sometimes a heavier solution can be simpler to understand (and it can be actually safe). Bye, bearophile
Re: Let's Play Code Golf
Steve Sobel: It can get down to 155 using ranges, but those imports really are killer. You usually don't want to design a language for code golfing (but several exist, like http://esolangs.org/wiki/GolfScript ). void main(){import std.algorithm,std.conv,std.range,std.stdio;foreach(n;stdin.byLine.drop(1))writefln(%.15f,iota(n.to!int).map!(-1.0)^^a/(2*a+1).sum);} You can remove one char: iota(n.to!int). n.to!int.iota. Bye, bearophile
Re: A Refcounted Array Type
Walter Bright: 5. bounds checking When you go past bounds of a built-in array you get an error located in the user code, while if you put a pre-condition in your Array struct to detect the same errors, you get a run-time error message located in that pre-condition instead. I'd like some way to solve this small problem of giving more correctly located error messages. In Contract programming lingo it's a problem of blame management (I'd also like a way to detect some compile-time out-of-bound errors for user-defined collections, but you said this is not worth the effort). Bye, bearophile
Re: DDMD just went green on all platforms for the first time
Benjamin Thaut: Are there any performance comparisons? E.g. how long das DDMD take to compile phobos vs regular DMD? Yes, there are several performance comparisons I'm curious about, like binary size, compilation speed, compilation speed of the compiler, max memory to compile Phobos without unittests, and few more basic data points. Bye, bearophile
Re: UFCS on template alias ?
Baz: Is this a normal behaviour ? Try to move the definition of poly to module-level scope. This is a design decision to avoid other troubles. Bye, bearophile
Re: D : dmd vs gdc : which one to choose?
Mayuresh Kathe: Should I choose DMD or go with GDC? It's a good idea to use all available compilers. LDC and DMD are both useful. Every one of them has advantages and disadvantages. Bye, bearophile
Re: let (x,y) = ...
Kagamin: Doesn't let normally declare a new variable? You are right, yours is a valid point... So tie could be a better name after all. Bye, bearophile
Re: let (x,y) = ...
Ola Fosheim Grøstad: Maybe change the name to tie: http://www.cplusplus.com/reference/tuple/tie/ ? I prefer let, it's much more traditional and descriptive. C++ standard library is often a bad example to follow... Bye, bearophile
Re: let (x,y) = ...
Mengu: that's a great example to show d's strength. thank you. It's also a great way to show what's missing in D syntax. Bye, bearophile
Re: let (x,y) = ...
Kagamin: Or even more obvious (VBA,TSQL): set (x,y,z) = [1,2,3]; I prefer to use set as in Python, to define sets: s = set([1, 2, 3]) 2 in s True Bye, bearophile
Re: Mimicking C++'s indexing behavior in D associative arrays
Rikki Cattermole: Foo*[string] bar; Foo v = *bar.grab(mykey); Is this the setdefault of Python dicts? If this need is strong a new function could be added to Phobos (or even druntime if you want to reduce the number of hash computations). Bye, bearophile
Re: contiguous ranges
Andrei Alexandrescu: for an array r, is r.retro contiguous or not? Is the most useful contiguous range forward? So can you name it ForwardContiguousRange? Bye, bearophile
Re: Consistency
John Colvin: I'm quite a fan of python's // operator for integer division, especially when combined with python 3's choice to make / always mean floating point division (i.e. 3/2 == float(3)/2, 3//2 == 1). It recognises that integer division is a weird thing and separates it from the much less weird floating point division. The C/D division operator semantics is a bug-prone design mistake, and this design was fixed in Python3 despite this has broken lot of Python2 code. It's a pitfall that a modern language must avoid (I don't know how Rust handles divisions, I hope they have removed this problem). Bye, bearophile
Re: Consistency
Daniel Murphy: No, they were still O(n) worst case, for a single bucket with a degenerate binary tree. I see. I was unable to hit this degenerate case in my testing code, but I guess that was possible. Thank you. Bye, bearophile
Re: what is the offical way to handle multiple list in map() ?
Baz: is this the official way ? It seems a way to perform nested mapping in D. --- auto fruits = [apple, banana, orange][]; auto vegies = [grass, salad][]; Those trailing [] are unneded. auto youreallygonna = map!( `map!(a = eat ~ a)(a)` )([fruits, vegies]); Better to use another lambda inside, instead of that string. Bye, bearophile
Re: contiguous ranges
Vlad Levenfeld: a ContiguousRange would be any RandomAccessRange which has a member called ptr which supports a dereferencing operator * that yields an ElementType!R. This notion is useful for functions which might otherwise perform an element-by-element transfer to an OutputRange via put, instead perform an optimized batch transfer directly to a ContiguousRange via ptr. Increasing the number of basic ranges will lead to a little more complexity, but this seems a nice idea. Bye, bearophile
Re: Consistency
John Colvin: tup1.expand.only.countUntil(2).writeln; Admittedly, it's a little longer than expected :) A little shorter: tup1[].only.countUntil(2).writeln; Bye, bearophile
Re: ranges reading garbage
John Colvin: prints things like [0, 4, 5, 1, 1, 1459971595, 1459971596, 2, 2, 1459971596, 1459971597, 3, 4, 8, 9, 5, 5, 4441427819, 4441427820, 6, 6, 4441427820, 4441427821, 7] but the output isn't consistent, the big numbers change on each run. Try to replace the only() with: [y, y+ys.length, y+ys.length+1, y+1] Like this: import std.range, std.algorithm, std.stdio; void foo(in float[] data, in float[] xs, in float[] ys) @safe { iota(0, data.length, ys.length) .map!(xBase = iota(xBase, xBase + ys.length - 1) .map!(y = [y, y+ys.length, y+ys.length+1, y+1]) .joiner) .joiner .writeln; } void main() { foo([1,2,3,4,5,6,7,8], [0.1,0.2], [10,20,30,40]); } In Rust the compiler enforces that all stack-allocated data doesn't come from dead stack frames. In D you have to be careful to avoid doing it. In future this kind of bugs will be hopefully avoided by a better tracking of the memory. I am not sure if http://wiki.dlang.org/DIP69 is able to avoid this bug, if it can't, then DIP69 needs to be improved. Bye, bearophile
Re: Consistency
Xinok: In that respect, it only makes sense for dictionaries Values as in Python are much more useful for arrays :-) Meta: D is better off than Python in this case, I've never subscribed with point of view :-) Bye, bearophile
Re: Consistency
Meta: Oh, whoops. I mixed up average-case complexity with worst-case. Although, isn't lookup O(n) in the worst case for hash tables? D associative arrays used to be O(1) amortized and O(n ln n) in worst case. Now they are O(1) amortized and O(n) worst case. And for an adversary it's not too much hard to find and hit that O(n) case. Bye, bearophile
Re: ranges reading garbage
FG: Odd... Still something is wrong. It prints: [0, 4, 5, 1, 1, 5, 6, 2, 2, 6, 7, 3, 4, 8, 9, 5, 5, 5, 6, 6, 6, 6, 7, 7] instead of this: [0, 4, 5, 1, 1, 5, 6, 2, 2, 6, 7, 3, 4, 8, 9, 5, 5, 9, 10, 6, 6, 10, 11, 7] This is less lazy and gives another result: import std.range, std.algorithm, std.stdio; void foo(in float[] data, in float[] xs, in float[] ys) @safe { iota(0, data.length, ys.length) .map!(xBase = iota(xBase, xBase + ys.length - 1) .map!(y = [y, y+ys.length, y+ys.length+1, y+1]) .join) .join .writeln; } void main() { foo([1,2,3,4,5,6,7,8], [0.1,0.2], [10,20,30,40]); } What a fun program :-) Bye, bearophile
Re: Data-Flow (Escape) Analysis to Aid in Avoiding GC
Per Nordlöw: Then how does the GC know when to release when there are multiple references? The mark phase counts what's reachable and what can't be reached. If an object has one pointer to it, or one hundred pointers, it is not removed. If nothing points to it, it is removed. I suggest you to read how a marksweep GC works, or better to implement a bare-bones marksweep GC in C language yourself for Lisp-like cons cells, you only need 100 lines of code or so to do it. Bye, bearophile
Re: Number of Bits Needed to Represent a Zero-Offset Integer
H. S. Teoh: Maybe that could be the basis of a better name? Right. Bye, bearophile
Re: Number of Bits Needed to Represent a Zero-Offset Integer
H. S. Teoh: So it could be called ilog2? Perhaps floorIlog2? Isn't ilog2 a different function? Bye, bearophile
Re: What is the Correct way to Malloc in @nogc section?
Foo: I'm regret that I tried to help, I will delete this repo as far as possible. :) Language communities aren't perfect, but the success of a language comes from the help of many little hands :) Perhaps Rust will win over D in the end, but there's no reason to throw away your work just for a comment... be tolerant and be good. Bye, bearophile
Re: Number of Bits Needed to Represent a Zero-Offset Integer
Dominikus Dittes Scherkl: I would recommend to use something like this: /// returns the number of the highest set bit +1 in the given value or 0 if no bit is set size_t bitlen(T)(const(T) a) pure @safe @nogc nothrow if(isUnsigned!T) { static if(T.sizeof = size_t.sizeof) // doesn't work for ulong on 32bit sys { return x ? core.bitop.bsr(x)+1 : 0; } else static if(T.sizeof == 8) // ulong if size_t == uint { return x ? x32 ? core.bitop.bsr(x)+33 : core.bitop.bsr(x)+1 : 0; } } Is this good to be added to Phobos? Perhaps with a more descriptive name? Bye, bearophile
Re: Data-Flow (Escape) Analysis to Aid in Avoiding GC
Tobias Pankrath: Why should splitter.front allocate? I think that front was able to throw Unicode exceptions, that require the GC. But I think later they have become asserts, that don't require the GC. Bye, bearophile
Re: This Week in D: Issue #4
It it a good idea to keep a weekly rhythm? Perhaps one issue every two, three or even four weeks is better at this stage of the D life. Bye, bearophile
Re: How to write similar code D?
FG: auto query = iota(2, 2 + 10) .map!(c = [Length: 2 * c, Height: c * c - 1, Hypotenuse: c * c + 1]) .map!(x = format(%4d%4d%4d, x[Height], Unlike other languages like JavaScript, the D front-end is very weak in optimizing well such kind of code... I think D compilers handle built-in associative arrays in a very straight way. Bye, bearophile
Re: cannot deduce function from argument types issue.
ted: Could someone enlighten me ? This works: import std.range: ElementType, isInputRange; ElementType!R testFunc(R, T)(R range, T foo) if (is(ElementType!R == T)) { static assert(isInputRange!R); typeof(return) retVal = foo ^^ 2; // More DRY. return retVal; } void main() { auto values = [0.0, 3.0, -1.0, 5.0]; auto result = testFunc(values, 8.8); } The D compiler seems unable to compute ElementType!R in the function signature. If I am right, then this seems worth an enhancement request. Bye, bearophile
Re: cannot deduce function from argument types issue.
Ali Çehreli: If think it is a little too much to ask from the template system of D. I remember hitting a similar problem with code like this bar() function: // OK void foo(size_t N1, size_t N2)(int[N1] a, int[N2] b) if (N2 == N1 ^^ 2) {} // Not OK void bar(size_t N)(int[N] a, int[N ^ 2] b) {} void main() { int[2] a = [1, 2]; int[4] b = [1, 2, 3, 4]; foo(a, b); bar(a, b); } So perhaps my suggestion to file an enhancement request is not a good idea... Bye, bearophile
Re: cannot deduce function from argument types issue.
void bar(size_t N)(int[N] a, int[N ^ 2] b) {} I meant: void bar(size_t N)(int[N] a, int[N ^^ 2] b) {}
Re: Classes and @disable this()
I think this can be filed in Bugzilla as diagnostic enhancement: class Foo { @disable this(); this(int i) {} } void main() {} https://issues.dlang.org/show_bug.cgi?id=14163 Bye, bearophile
Re: cannot deduce function from argument types issue.
ted: ... where you say 'More DRY' above, are you referring to I was referring to both, but mostly to the typeof. It's more DRY (http://en.wikipedia.org/wiki/Don%27t_repeat_yourself ). You are stating only once the type of the return variable. This is less bug-prone. Bye, bearophile
Re: To write such an expressive code D
Dennis Ritchie: Please help. This starts to look like homework :-) Bye, bearophile
Re: Compilation with dub + dmd: out of memory
Vlasov Roman: I have the quite computer with 2 GB RAM. At compilation with dub and dmd of small project this pair eating about 1.4~1.5 GB RAM. I solve this probleb by connecting swap partition, but it calls some freezes + it take ~10% of swap, and after compilation swap not released. At switching off swap as result we get ~200 MB of dead data in RAM, which can be released by rebooting. How i can resolve it? Look for CTFE code, perhaps some of it is excessive. You can convert some of it to run-time in a module-level static this(). Bye, bearophile
Re: To write such an expressive code D
Dennis Ritchie: Output: 0 xor 0 xor 0 = 0 0 xor 0 xor 1 = 1 0 xor 1 xor 0 = 1 0 xor 1 xor 1 = 0 1 xor 0 xor 0 = 1 1 xor 0 xor 1 = 0 1 xor 1 xor 0 = 0 1 xor 1 xor 1 = 1 This man again took advantage of the fact that in D there is no such operation - (analog switch). A natural solution in D: void main() { import std.stdio; foreach (immutable a; 0 .. 2) foreach (immutable b; 0 .. 2) foreach (immutable c; 0 .. 2) writefln(%d xor %d xor %d = %d, a, b, c, (a + b + c) % 2); } Alternative solution closer to the F# code: import std.stdio, std.algorithm, std.typecons; int f(T)(T t) if (isTuple!T) { return t.predSwitch( tuple(0, 0, 0), 0, tuple(0, 1, 1), 0, tuple(1, 0, 1), 0, tuple(1, 1, 0), 0, /*else*/ 1); } void main() { foreach (immutable a; 0 .. 2) foreach (immutable b; 0 .. 2) foreach (immutable c; 0 .. 2) writefln(%d xor %d xor %d = %d, a, b, c, tuple(a, b, c).f); } Bye, bearophile
Re: How to write similar code D?
Dennis Ritchie: Tell me, please, how to write similar С# code D: This is more or less exactly the same: void main() { import std.stdio, std.range, std.algorithm, std.typecons, std.format; auto query = iota(2, 12) .map!(c = Tuple!(int,length, int,height, int,hypotenuse) (2 * c, c ^^ 2 - 1, c ^^ 2 + 1)) .map!(x = %3d%4d%4d.format(x.height, x.hypotenuse, x.length)); foreach (immutable x; query) x.writeln; } But often you write something more like this in D using the latest version of the compiler: void main() { import std.stdio, std.range, std.algorithm, std.typecons; iota(2, 12) .map!(c = tuple(c ^^ 2 - 1, c ^^ 2 + 1, 2 * c)) .each!(x = writefln(%3d%4d%4d, x[])); } Bye, bearophile
Re: A safer interface for core.stdc
H. S. Teoh: Come to think of it, is there any point in making malloc @safe/@trusted at all? I am not asking for a @trusted function. I'd like a @system template wrapper for malloc/calloc/free that is safer than the C functions (safer because it's type-aware). Bye, bearophile
Re: Classes and @disable this()
fra: However making it a compiler error would be far, far better I think this can be filed in Bugzilla as diagnostic enhancement: class Foo { @disable this(); this(int i) {} } void main() {} Bye, bearophile
Re: Template constructor in a non-template struct.
ChrisG: I don't really understand how I'd differentiate a constructor template from a class/struct template. One solution is to use a template struct (struct/class names start with an upper case in D, while typed enum members usually start with a lower case): enum E { option1, option2 } struct Boring(E Opt = E.option1) { this(int arg1, int arg2) {} } void main() { auto a = Boring!(E.option2)(1, 2); } If you want to instantiate the constructor template without type inference, then this seems to work, but it's not idiomatic D: enum E { option1, option2 } struct Boring { this(E Opt = E.option1)(int arg1, int arg2) {} } void main() { auto a = Boring().__ctor!(E.option2)(1, 2); } Bye, bearophile
Re: primitive type variables not nullable ?
Tobias Pankrath: Check for null with (x is null) not via printing to stdout. In most cases instead of checking dynamic arrays for null, it's better to use std.array.empty. Bye, bearophile
Re: A safer interface for core.stdc
Andrei Alexandrescu: Such wrappers would allow safe code to use more C stdlib primitives. I'd also like a safer templated wrapper for calloc() and malloc() and similar. Bye, bearophile
Re: Another idiom I wish were gone from phobos/druntime
Ola Fosheim Grøstad: Ada with SPARK 2014 makes D look like it is stuck in the 80s: 4.2. Subprogram Contracts 4.2.1. Preconditions 4.2.2. Postconditions 4.2.3. Contract Cases 4.2.4. Data Dependencies 4.2.5. Flow Dependencies 4.2.6. State Abstraction and Contracts 4.2.6.1. State Abstraction and Dependencies 4.2.6.2. State Abstraction and Functional Contracts 4.3. Package Contracts 4.3.1. State Abstraction 4.3.2. Package Initialization 4.3.3. Package Initial Condition 4.3.4. Interfaces to the Physical World 4.3.4.1. Volatile Variables 4.3.4.2. Flavors of Volatile Variables 4.3.4.3. External State Abstraction 4.4. Type Contracts 4.4.1. Scalar Ranges 4.4.2. Static Predicates 4.4.3. Record Discriminants 4.4.4. Default Initial Condition 4.5. Specification Features 4.5.1. Attribute Old 4.5.1.1. In a Postcondition 4.5.1.2. In Contract Cases 4.5.1.3. In a Potentially Unevaluated Expression 4.5.2. Attribute Result 4.5.3. Attribute Loop_Entry 4.5.4. Attribute Update 4.5.5. Conditional Expressions 4.5.6. Quantified Expressions 4.5.7. Expression Functions 4.5.8. Ghost Code 4.5.8.1. Ghost Functions 4.5.8.2. Ghost Variables Case 1: Keeping Intermediate Values Case 2: Keeping Memory of Previous State Case 3: Logging Previous Events 4.5.8.3. Ghost Types 4.5.8.4. Ghost Procedures 4.5.8.5. Ghost Packages 4.5.8.6. Imported Ghost Subprograms 4.6. Assertion Pragmas 4.6.1. Pragma Assert 4.6.2. Loop Invariants 4.6.3. Loop Variants 4.6.4. Pragma Assume 4.6.5. Pragma Assert_And_Cut That seems a bit too much for the average human to handle :-) Sometimes features help, but that list seems excessive for a language that is not meant for high integrity systems as D. Bye, bearophile
Some notes on Rust
In the best language blog: http://lambda-the-ultimate.org/node/5113 The discussion is long. They discuss if a good GC can be written in the language itself, about actual security, what a GC can and can't do, and more. Bye, bearophile
Re: Do you have a better way to remove element from a array?
Tobias Pankrath: Works as designed: http://dlang.org/phobos/std_algorithm.html#.remove Unfortunately it's one of the worst designed functions of Phobos: https://issues.dlang.org/show_bug.cgi?id=10959 Bye, bearophile
Re: how can I get a reference of array?
zhmt: Will arr.ptr change in the future? As the array add more members , it need more memroy, then remalloc may be called, the pointer maybe change, then the stored pointer will be invalid. Will this happen? Yes, it can happen. Bye, bearophile
Re: Do you have a better way to remove element from a array?
bachmeier: It seems your argument is that remove is poorly designed because it's not destructive. Or am I missing your argument? It has to be a void function (or perhaps bettter it can return true/false if it has removed the item, so it becomes @nogc and nothrow). And it has to remove the first item equal to the given one. You can then add a second function that removes at a given index (like removeAt). Bye, bearophile
Re: Another idiom I wish were gone from phobos/druntime
Andrei Alexandrescu: auto opSlice(size_t low, size_t high) in { assert(low = high); } body { import std.range : take; return this[low .. $].take(high - low); } which of course trivially boils down to: auto opSlice(size_t low, size_t high) { assert(low = high); import std.range : take; return this[low .. $].take(high - low); } What advantage could possibly be in transforming a 5-liner into a 9-liner? Contracts can be read by tools, and they are part of the function signature. Contracts should be encouraged and increased, not discouraged. Bye, bearophile
Re: FYI - DIP25 is approved for 2.067
Andrei Alexandrescu: http://wiki.dlang.org/DIP25 I'd like a more comprehensive and flexible solution to the problem of static memory ownership. Bye, bearophile
Re: Another idiom I wish were gone from phobos/druntime
Zach the Mystic: I have an idea. Treat all assert statements which come before the first non-assert statement as part of the 'in' contract. I'm not saying the compiler has to generate a whole 'in' function, but these asserts can be internally tagged to behave *as if* in an 'in' contract. That solves the tooling problem and the too-much-code problem, no? Bad idea. We had DbC, let's start using it. Bye, bearophile
Re: Conway's game of life
Paul: Regarding the immutable loop variable, I've conditioned myself never to interfere with loop control values But adding immutable you don't risk modifying the variable by mistake. It's another design mistake of D. Variables (like foreach loop indexes) must be immutable by default because otherwise programmers often don't bother making them immutable. It's a lost war. Bye, bearophile
Re: Conway's game of life
Paul: enum WORLDSIZE = 20; enum INITIALPOP = 70; //experimental enum DEAD = 0; enum ALIVE = 1; D enums don't need to be ALL UPPERCASE :-) int world[WORLDSIZE][WORLDSIZE]; Don't forget to compile with warnings active (it's a design error of the D compiler to have them disabled by default). foreach(i; 0..INITIALPOP){ It's less bug-prone to make that index immutable: foreach(immutable i; 0 .. initialPop) { Bye, bearophile
Re: how convert the range to slice ?
Nordlöw: Is started digging a bit... The magic happens at line 103 in cast.c. How do I most conveniently figure out which members (functions) a type (e-type) has? I figured I could check for typical InputRange members and issue a hint about using .array if e-type has them. It's probably better to ask such questions on GitHub (and to open an enhancement request in Bugzilla). Bye, bearophile
Re: Conway's game of life
gedaiu: https://github.com/gedaiu/Game-Of-Life-D A bare-bones implementation: http://rosettacode.org/wiki/Conway%27s_Game_of_Life#Faster_Version The quality of the D GC is not important for a simple Life implementation, you just need two arrays. Bye, bearophile
Re: std.algorithm sort() and reverse() confusion
Jonathan M Davis: arr.reverse.map!sqrt Yes, but arguably, chaining calls in this case is bad, We have discussed this some time... and I'd like reverse() to return the original array (like the deprecated array .reverse property). It's not a perfect design, but allowing UFCS chains is quite important. Bye, bearophile
Re: Arrays, garbage collection
Andrei Alexandrescu: No, we need to define a function for that - please file an enhancement request, thanks. -- Andrei No, the enhancement is in Bugzilla since lot of time. But it's for a built-in syntax. A function name is too much long, and when the inlining is switched off it makes the code bad. Thanks. Bye, bearophile
Re: Arrays, garbage collection
deadalnix: - added optimization to promote them on heap. Thing like int[2] = [1, 2] can trivially avoid GC allocation. See my usage examples (think of the examples as not having the s suffix): void main() { // Some imports here. foo([[1, 2]s, [3, 4]]s); auto t1 = tuple([1, 2]s, red); auto aa1 = [key: [1, 2]s]; auto pairs = 10.iota.map!(i = [i, i + 10]s); } A smart system can promote only the first one to value array. The compiler has to leave the other cases to the judgement of the programmer. - added some support for ownership/lifetime. This will allow the compiler to promote even more on heap. This is what I too have said in my original post. For those features to work well you need first a good static management of memory ownership. If don't expect the new syntax to be that useful if these point are addressed. If I'm turn out to be wrong, we can reconsider at that point. I can show code similar to the examples above where the []s syntax is useful. And using a function as Andrei suggests is not a good idea: foo(staticArray(staticArray(1, 2), staticArray(3, 4))); I don't think lot of people is going to write code like that. And if you are about to suggest this: alias S = staticArray; Well, do you like to see aliases in your code? Bye, bearophile
Re: Arrays, garbage collection
Daniel Kozák: No, it makes more bugs possible // this is compile error so its ok int[MUST_HAVE_FIVE_ITEMS] a=[1,2,3,5]; // Error: mismatched array lengths, 5 and 4 Have you tried to compile my code? It doesn't give an error. Bye, bearophile
Re: Deducing a template retrun parameter type based on an assignment?
Jeremy DeHaan: I figured that it would be smart enough to deduce the parameter type based on the type that it was trying to be assigned to. For that you need languages like Haskell/Rust. D type inference doesn't work from the type something is assigned to. Bye, bearophile
From C#7 and Haskell
Design Notes for C#7: https://github.com/dotnet/roslyn/issues/98 Perhaps they will enhance C# switch (plus an optional special method) to support a form of pattern matching. I'd like something related in D, someday. - - - - - - - Haskell in the large (PDF): http://code.haskell.org/~dons/talks/dons-google-2015-01-27.pdf It's perhaps the first time I see Haskell used for a large program and system. New things: - Data mining: In-language relational algebra data structures and API. - Memoization: In-language data flow graph library with memoization support. Native relational algebra data type. - An awful lot of data mining and analysis is best done with relational algebra. - Not just in the database. Bye, bearophile
Re: Check if type is from specific template?
Tofu Ninja: Basically what the title says, how do I check if a type T is an instantiation of a specific template? If you have an updated Phobos std.traits.isInstanceOf could be what you look for. Bye, bearophile
Arrays, garbage collection
The D type inference for array literals is now more flexible: void main() { auto[$][$] m1 = [[1, 2], [3, 4], [5, 6]]; pragma(msg, typeof(m1)); // int[2][3] const auto[string] aa1 = [red: 1, blue: 2]; pragma(msg, typeof(aa1)); // const(int)[string] } It helps avoid bugs like: int[5] a = [1,2,4,5]; void main() {} And it makes the usage of value arrays (fixed size arrays) more handy. We need to minimize the work that the garbage collector has to do. Value arrays help in this. So making value arrays more handy and natural to use is good (regardless how the current Phobos hates them). - - - - - - - - - What's missing is a handy and compiler-efficient syntax to create value array literals. Some persons have proposed the []s syntax: void main() { // Some imports here. foo([[1, 2]s, [3, 4]]s); auto t1 = tuple([1, 2]s, red); auto aa1 = [key: [1, 2]s]; auto pairs = 10.iota.map!(i = [i, i + 10]s); } To do those same things without the []s syntax you have to write longer code. - - - - - - - - - Another missing handy feature regards dynamic/associative arrays (this syntax is currently accepted): void main() { scope int[] a = [1, 2]; scope int[int] aa = [1: 2]; } A good management of memory ownership is needed to make scope dynamic/associative arrays fully safe. They should be more efficient for the GC because they can be deallocated safely when the scope ends, without no need for the GC to track their usage (if they contain references to objects that contain other references, then the GC has to track and manage those other references). - - - - - - - - - Sometimes I have suggested that it's useful to have in Phobos a kind of variable-length value arrays that are handled in a special way by the compiler when they are allocated in a stack frame, usable in @nogc functions (so it's a hybrid Phobos/D feature). This should give the advantages of C99 Variable Length Arrays without most of their disadvantages and complexities (the main disadvantage that's left is the risk of stack overflow. Currently on Windows D doesn't give a nice error message when the stack overflows, as it used to do). - - - - - - - - - With those features, with a good static management of memory ownership, D can become safer and reduce the work for the GC. I think only a limited percentage of arrays need to be fully handled by the GC. Bye, bearophile
Re: accept @pure @nothrow @return attributes
Ola Fosheim Grøstad: [0.1*x for x in range(10)] map(operator.mul,range(10),[0.1]*10) numpy.arange(0.,0.95,0.1) numpy.linspace(0,0.9,num=10) list(itertools.islice(itertools.count(0.0, 0.1), 10)) The first one (the list comp) is Pythonic, and it's obviously the obvious one :-) If you want/need to use numpy, the fourth is good. No problems :-) Bye, bearophile
Re: accept @pure @nothrow @return attributes
Dicebot: Yes, but it didn't also fix anything, only introduced more ways to do the same thing - without any plans for some consistent model. One of the rules of the Python Zen: There should be one-- and preferably only one --obvious way to do it. The word obvious is important, because usually there are multiple ways to do something, but only one of them should be obvious in Python :-) Bye, bearophile
Re: Concern about the ref return argument and scope
Walter Bright: Of course, there is a bit of leap of faith in the least disruption thing, only some experience with the feature will tell for sure. It's very OK to experiment. deadalnix could be right: a more general solution could be easer to learn and use for the programmers than the -dip25 -dip69 solution. Bye, bearophile
Re: how convert the range to slice ?
Chris Williams: Range is not castable to array. See std.array.array to generate an array from a Range. Currently this program: void main() { import std.range; int[] a = iota(10); } Gives an error like: test.d(3,19): Error: cannot implicitly convert expression (iota(10)) of type Result to int[] For the error message to be like yours, the compiler has to recognize a Range, this could be possible because foreach() already does that. I think you can try to open a diagnostic enhancement request. In D there are already examples of hardcoded error messages targeting newbies: void main() { int x; writeln(a); printf(%d\n, x); } Gives: test.d(3,5): Error: 'writeln' is not defined, perhaps you need to import std.stdio; ? test.d(4,5): Error: 'printf' is not defined, perhaps you need to import core.stdc.stdio; ? Bye, bearophile
Re: how convert the range to slice ?
Nordlöw: Is there any chance we could add logic to dmd+phobos that hints user about this? It's such a fundamental part of D+Phobos that newbies are forced to learn this quickly. On the other hand an informative error message could be useful... What error message do you suggest? Bye, bearophile
Re: I left my program open for 9 hours and it used up 700mb of ram, could someone review it?
Gan: Is there some special stuff I gotta do extra with structs? Do they need manually allocated and released? Most of your usages of tiny structs should be by value. So just keep in mind they are values. Even when you iterate with a foreach on a mutable array of them :-) On a second question, do I ever need to manually release objects I create with new? Usually not. How much advanced do you want to be? :-) Bye, bearophile
Re: Array List object?
Gan: //Initializing the array tiles = new SBTile[](0); This is often useless. //Clearing the array tiles = []; This doesn't clear the array, it rebinds it to a null pointer. Bye, bearophile
Re: Array List object?
And it's named dynamic array, instead of Array List object, it's not a class instance. Bye, bearophile
Re: Virtual functions and inheritance
Baz: doesn't work. And similarly to the the orginal post: I suggest to read some D documentation first, and program later. Bye, bearophile
Re: Classical bug
Vladimir Panteleev: But the check seems very simple, and is easily circumvented. This compiles: byte[] func() { byte[1024] buffer; auto p = buffer[0..3]; return p; } I guess such bugs will be detected (in safe code only!) after the implementation of: http://wiki.dlang.org/DIP69 Currently we are implementing a kind of pre-phase: http://wiki.dlang.org/DIP25 And here I have asked for @safe to become the default (Walter seems not against this idea): https://d.puremagic.com/issues/show_bug.cgi?id=13838 Bye, bearophile
Re: I left my program open for 9 hours and it used up 700mb of ram, could someone review it?
Gan: How can I make it use less CPU/RAM? Most tiny classes probably should be structs. More generally, use a struct every time you don't need a class. You can start with those two: struct SBRange { double left = 0.0, right = 0.0, top = 0.0, bottom = 0.0; } struct Point(T) { T x, y; } This probably isn't enough to solve your problems, but it's a start. Bye, bearophile