Re: How do you get comfortable with Dlang.org's Forum?
On Saturday, 24 February 2018 at 19:30:52 UTC, Patrick Schluter wrote: On Saturday, 24 February 2018 at 18:46:50 UTC, Steven Schveighoffer wrote: On 2/24/18 7:00 AM, Patrick Schluter wrote: On Saturday, 24 February 2018 at 04:41:44 UTC, H. S. Teoh wrote: [...] Last week I saw a video showing how a forum was shutdown because it was alledgedly full of racists. The thread where there were "racist comments" was in fact one where the initial question was ok, the answers absolutely nice but then the troll changed the initial post to something sinister and all the positive answers looked like agreement to the racist slur of the first comment. It was then demonstrated that the troll was a journalist from a big mainstream media. If I find the article again I will give a link (it's in french though, might not interest that much). Wow, that's insane. I would be interested in seeing it. It's in the history of my work PC, may be I will find it on monday. I'm french, i'm interested to know what the hell you talked about. Google search gave nothing. Do you referred to the journalist who was harassed by people on a gamer forum ?
Re: implicit construction operator
On Monday, 26 February 2018 at 21:36:49 UTC, ketmar wrote: aliak wrote: It makes libraries *much* more intuitive and expressive (C++ just got it wrong by choosing the wrong default). If you allow library authors to opt in instead of opt out then it becomes a conscious decision for one. library authors can create overloads for various argument types. with `foo(T...) (T args)` it is possible to generate conversions with CTFE. so we *already* have such feature. Touche.
Re: implicit construction operator
On Monday, 26 February 2018 at 21:34:21 UTC, ketmar wrote: aliak wrote: And if that's also a no no, how about char -> int. Or int -> float? Is ok? no, it is not ok. it was a mistake. it is now too late to fix it, but we can avoid doing more of the same kind. Oops, yeah, ok, D char ... char -> int yeah mistake. int -> long even?
I have a patch to let lldb demangle D symbols ; help welcome to improve it
https://github.com/llvm-mirror/lldb/pull/3 + https://github.com/timotheecour/dtools/blob/master/dtools/lldbdplugin.d on OSX, it works great except when encountering large symbols which cause segfault when GC does a collection (triggered inside core.demangle.demangle); Help is welcome to improve that (or more generally to improve D support in lldb, which I started in https://github.com/llvm-mirror/lldb/pull/3) NOTE: lldb doesn't accept github PR's but easier to work with PR's for whoever wants to help on tha in the meantime
Re: implicit construction operator
On Mon, Feb 26, 2018 at 09:45:03PM +, TheFlyingFiddle via Digitalmars-d wrote: > On Monday, 26 February 2018 at 21:30:09 UTC, aliak wrote: > > On Monday, 26 February 2018 at 19:32:44 UTC, ketmar wrote: > > > WebFreak001 wrote: > > And if that's also a no no, how about char -> int. Or int -> float? > > Is ok? > > > > Maybe there're some valid arguments, to disallow it *completely* > > though? > > > > Cheers > > I would be very happy if char -> int and int -> float was not implicit. Yeah, implicit char -> int is totally evil, and should never have gotten into the language in the first place. To wit: void foo(dchar ch) { backup_files(); } void foo(byte b) { format_disk(); } foo('a'); // guess which one gets called. > This has happened to me enough times that i remember it: > > float a = some_int / some_other_int; //ops i don't think this was what I > wanted. > constrast > float a = some_int.to!float / some_other_int.to!float; //ugly but at-least > its clear. Actually, since operations involving float are "infectious", all you need is: float a = some_int.to!float / some_other_int; > Not really a big deal (and auto kind of ruins it) but it would make > stuff consistent between user types and built in ones. Not sure what you mean here. In a user type, if opBinary!"/" returns an int, then you still have the same problem. T -- He who laughs last thinks slowest.
Re: Go 2017 Survey Results
On Monday, 26 February 2018 at 21:04:20 UTC, Ali wrote: This link was posted today on hacker news (ycombinator) https://blog.golang.org/survey2017-results https://news.ycombinator.com/item?id=16468358 My biggest takes from this are 1) people are looking for python alternatives, probably more so than c alternatives 2) generic programming is important Or why I learned D.
Re: implicit construction operator
On Monday, 26 February 2018 at 21:30:09 UTC, aliak wrote: On Monday, 26 February 2018 at 19:32:44 UTC, ketmar wrote: WebFreak001 wrote: And if that's also a no no, how about char -> int. Or int -> float? Is ok? Maybe there're some valid arguments, to disallow it *completely* though? Cheers I would be very happy if char -> int and int -> float was not implicit. This has happened to me enough times that i remember it: float a = some_int / some_other_int; //ops i don't think this was what I wanted. constrast float a = some_int.to!float / some_other_int.to!float; //ugly but at-least its clear. Not really a big deal (and auto kind of ruins it) but it would make stuff consistent between user types and built in ones.
Re: Slow code, slow
H. S. Teoh wrote: On Mon, Feb 26, 2018 at 10:12:25PM +0200, ketmar via Digitalmars-d wrote: [...] but until that brave new world materializes, we have a smart/fast dilemma. alas. I'd like to contribute to the materialization of that brave new world. Rather than sit around and wait for it to happen. :-P i'd like to do it too, but dmd code to process templates knocks me out of my consciousness. alas.
Re: implicit construction operator
aliak wrote: It makes libraries *much* more intuitive and expressive (C++ just got it wrong by choosing the wrong default). If you allow library authors to opt in instead of opt out then it becomes a conscious decision for one. library authors can create overloads for various argument types. with `foo(T...) (T args)` it is possible to generate conversions with CTFE. so we *already* have such feature.
Re: Go 2017 Survey Results
On Mon, Feb 26, 2018 at 09:04:20PM +, Ali via Digitalmars-d wrote: [...] > 2) generic programming is important [...] It's something sorely lacking in Go, so it's not unsurprising it's a big item on the list. T -- BREAKFAST.COM halted...Cereal Port Not Responding. -- YHL
Re: Slow code, slow
On Mon, Feb 26, 2018 at 10:12:25PM +0200, ketmar via Digitalmars-d wrote: [...] > but until that brave new world materializes, we have a smart/fast > dilemma. alas. I'd like to contribute to the materialization of that brave new world. Rather than sit around and wait for it to happen. :-P T -- Your inconsistency is the only consistent thing about you! -- KD
Re: implicit construction operator
On Monday, 26 February 2018 at 19:32:44 UTC, ketmar wrote: WebFreak001 wrote: Now before you would have only been able to do this: --- Nullable!Foo a; foo(a, Nullable!int(5)); --- but now you should also be able to do: --- Nullable!Foo x = null; Nullable!Foo y = 5; foo(null, 5); please no. such unobvious type conversions goes out of control really fast. there is a reason why D doesn't have such thing, this is not an oversight, but a design decision. How if you don't mind me asking? Seems like many features can go out of control if used incorrectly, but that doesn't mean they're a bad idea. I can understand they're a slippery slope, but it seems some people think it's a completely bad idea. It makes libraries *much* more intuitive and expressive (C++ just got it wrong by choosing the wrong default). If you allow library authors to opt in instead of opt out then it becomes a conscious decision for one. But at the very least, shouldn't we put some thought in to allowing it for inherent sub-type relationships. Where an alias this is used, there's probably such a relationship. BigInt to int is another one. Algebraic types as mentioned falls under that category as well. And if that's also a no no, how about char -> int. Or int -> float? Is ok? Maybe there're some valid arguments, to disallow it *completely* though? Cheers
Re: implicit construction operator
aliak wrote: And if that's also a no no, how about char -> int. Or int -> float? Is ok? no, it is not ok. it was a mistake. it is now too late to fix it, but we can avoid doing more of the same kind.
Re: Go 2017 Survey Results
On Mon, 2018-02-26 at 21:04 +, Ali via Digitalmars-d wrote: > This link was posted today on hacker news (ycombinator) > https://blog.golang.org/survey2017-results > https://news.ycombinator.com/item?id=16468358 > > My biggest takes from this are > 1) people are looking for python alternatives, probably more so > than c alternatives People choosing to complete a Go-oriented survey are… > 2) generic programming is important > > As I understand the results of this survey, will be use to guide > Go's development > this is in my opinion very inclusive and transparent I can't imagine Go getting templates anytime soon. -- Russel. === Dr Russel Winder t: +44 20 7585 2200 41 Buckmaster Roadm: +44 7770 465 077 London SW11 1EN, UK w: www.russel.org.uk signature.asc Description: This is a digitally signed message part
Re: implicit construction operator
On Monday, 26 February 2018 at 19:25:06 UTC, WebFreak001 wrote: Now this would be really useful for Variant: --- struct Variant { this(U)(U value) @implicit { ... } } void bar(Variant x, Variant y) {} Variant[] myObjects = [1, 2, "abc", new Node()]; Variant a = 4; bar(4, "asdf"); --- This is possible in the language today using the implicit class construction feature of runtime variadic arrays: class VArray { Variant[] va; this(T...)(T ts) { foreach(t; ts) { va ~= Variant(t); } } } void test(VArray ta...) { foreach (v; ta.va) { writeln(v.type); } } void main() { test(1, "asdf", false); } What's your opinion on this? This is a very slippery slope to fall down. Even `alias this` is pushing the limit of what I think we should allow. That said, there is exactly 1 case where I really, really want some kind of implicit conversion: struct Success {} struct Error { string msg; } alias Result = Algebraic!(Success, Error); Result connectToHost(IPAddress host) { //do some stuff if (operationSucceeded) { return Success(); } else { return Error(statusMessage); } } This currently doesn't work, and you instead have to return Result(Success()) and Result(Error(statusMessage)). I would love to have some way of implicitly constructing an Algebraic from any of the possible underlying types. It would bring us very close (if not all the way) to having Algebraic work identically to sum types in other languages such as Rust, Swift, Haskell, etc. Having to explicitly wrapping the values in an Algebraic doesn't seem like a big deal, but it makes it really annoying to use it in everyday code.
Go 2017 Survey Results
This link was posted today on hacker news (ycombinator) https://blog.golang.org/survey2017-results https://news.ycombinator.com/item?id=16468358 My biggest takes from this are 1) people are looking for python alternatives, probably more so than c alternatives 2) generic programming is important As I understand the results of this survey, will be use to guide Go's development this is in my opinion very inclusive and transparent
Re: Slow code, slow
H. S. Teoh wrote: The problem is not the Phobos implementation. The problem is that the compiler's way of handling templates and CTFE needs to be improved. We seriously need to muster some manpower to help Stefan finish newCTFE, and then we need to take a serious look at improving the current implementation of templates. yeah, i'm not saying that phobos code is wrong. but being "not wrong" and being fast is not always the same. ;-) still, we can be either smart, or have fast compile times, but not both. T_T [...] I'll like to disagree. :-D There's got to be a way to do this that doesn't have to compromise either way. I mean, this is not like we're doing rocket science here, or solving an NP complete problem. It's a straightforward way of recognizing a particular code pattern and applying 1-to-1 mappings. The general case of completely arbitrary templates can still fallback to the current implementation. The point is to optimize for specific template usage patterns that are common and yields big speedups, but still leave the door open for weirder, but less common, template code. but until that brave new world materializes, we have a smart/fast dilemma. alas.
Re: Slow code, slow
On Mon, Feb 26, 2018 at 09:03:14PM +0200, ketmar via Digitalmars-d wrote: > H. S. Teoh wrote: [...] > > In my mind, even C's printf API is sucky, because it involves runtime > > parsing of what's usually a static string, over and over again. What we > > *really* want is for something like: > > > > writeln("blah %d bluh %s", i, s); > > > > to be translated into something like: > > > > stdout.putString("blah "); > > stdout.putInt(i); > > stdout.putString(" bluh "); > > stdout.putString(s); [...] > i once wrote such thing (for fun, using "Functional Programming With > Templates"). it was fun to do, and freakin' slow due to template > bloat. ;-) > but yes, it generates a string mixin, and in runtime there was no > format string parsing. The problem is not the Phobos implementation. The problem is that the compiler's way of handling templates and CTFE needs to be improved. We seriously need to muster some manpower to help Stefan finish newCTFE, and then we need to take a serious look at improving the current implementation of templates. > still, we can be either smart, or have fast compile times, but not > both. T_T [...] I'll like to disagree. :-D There's got to be a way to do this that doesn't have to compromise either way. I mean, this is not like we're doing rocket science here, or solving an NP complete problem. It's a straightforward way of recognizing a particular code pattern and applying 1-to-1 mappings. The general case of completely arbitrary templates can still fallback to the current implementation. The point is to optimize for specific template usage patterns that are common and yields big speedups, but still leave the door open for weirder, but less common, template code. T -- Fact is stranger than fiction.
Re: Can this be done? Defining type as in this Scala sample code
On Monday, 26 February 2018 at 15:43:54 UTC, Bienlein wrote: object Scratch extends App { // compiles: val list = List(1, 2.4, 5) val sum = list.sum println(sum) // does not compile: val list2 = List(1, 2.4, 5, "123") val sum2 = list2.sum println(sum2) } There's nothing in the language or standard library that supports this. However, it's perfectly possible to make something with those semantics: import std.variant; import std.stdio; struct List(T) { T[] values; alias values this; } auto list(T...)(T args) { import std.traits : CommonType; static if (is(CommonType!T == void)) List!Variant result; else List!(CommonType!T) result; result.length = T.length; foreach (i, e; args) { result[i] = e; } return result; } auto sum(T)(List!T lst) if (is(typeof(lst[0] + lst[0])) && !is(T == Variant)) { T result = 0; foreach (e; lst) { result += e; } return result; } unittest { auto list1 = list(1, 2.4, 5); auto sum1 = list1.sum; writeln(sum1); auto list2 = list(1, 2.4, 5, "123"); auto sum2 = list2.sum; writeln(sum2); } Since std.variant.Variant does operator overloads, we have to explicitly check if T == Variant in the sum function. For Variant, that's probably the correct choice. We could use Algebraic instead, but it also does operator overloads, even when no type in its arguments support them. Again, we could create our own - Algebraic and Variant are library types, after all. -- Simen
Re: implicit construction operator
WebFreak001 wrote: Now before you would have only been able to do this: --- Nullable!Foo a; foo(a, Nullable!int(5)); --- but now you should also be able to do: --- Nullable!Foo x = null; Nullable!Foo y = 5; foo(null, 5); please no. such unobvious type conversions goes out of control really fast. there is a reason why D doesn't have such thing, this is not an oversight, but a design decision.
implicit construction operator
hi, I had an idea from using some C# which I think would be really cool in D. Basically allow modifying implicit construction of a type. Right now we only have struct opAssign/constructor implicit conversion, but this addition would also add it to classes and make it even more convenient. Changes in code (example Nullable): --- struct Nullable(T) { this(typeof(null)) @implicit {} // <-- @implicit is new } void foo(Nullable!int a, Nullable!int b) {} --- Now before you would have only been able to do this: --- Nullable!Foo a; foo(a, Nullable!int(5)); --- but now you should also be able to do: --- Nullable!Foo x = null; Nullable!Foo y = 5; foo(null, 5); // while this would be nice, I am not sure how well this is possible right now: Nullable!int[] foo = [1, 2, 3, null, 5]; --- The array syntax might not be possible if it looks at consistency inside the array before attempting to cast it, but for function arguments and quicker This is especially making this case less of a pain to deal with: --- void sendMessage(string content, Nullable!Snowflake nonce = Nullable!Snowflake.init, Nullable!Embed embed = Nullable!Embed.init); Nullable!Embed embed = Embed.init; sendMessage("a", Nullable!Snowflake.init, embed) // -> void sendMessage(string content, Nullable!Snowflake nonce = null, Nullable!Embed embed = null); sendMessage("a", null, Embed.init); --- Now this would be really useful for Variant: --- struct Variant { this(U)(U value) @implicit { ... } } void bar(Variant x, Variant y) {} Variant[] myObjects = [1, 2, "abc", new Node()]; Variant a = 4; bar(4, "asdf"); --- Just a few examples where it could be used in phobos, especially when passing them function arguments: Variant, JSONValue, eventual XML node, Nullable, BigInt, Unique, scoped, NullableRef, Rebindable, AsciiString, Latin1String, etc and many more. Plus also many libraries will be able to make use of this like vibe.d Json, Bson or msgpack or dyaml etc etc etc. Additionally this will make many duplicate functions which are just there for emulating this behaviour disappear, std.regex could accept just regex as argument and strings will be implicitly cast to it, reducing template/overload usage and possibly also making it faster to import. What's your opinion on this? I think it is really useful to have when interoping with scripting languages or doing (de)serialization or for these attribute wrappers which are there because of no function attribute UDAs. I was looking into implementing this to dmd myself but the code on the implicit cast checks looks a bit hardcoded for the types that are in right now and not really suitable to implement this, but maybe someone with more knowledge about dmd internals can do this with ease. This is only a single direction T -> Wrapper and I think this would actually be enough, but it would maybe be possible to add @implicit to opCast in the future.
Re: Slow code, slow
H. S. Teoh wrote: On Mon, Feb 26, 2018 at 08:38:39PM +0200, ketmar via Digitalmars-d wrote: H. S. Teoh wrote: On Sat, Feb 24, 2018 at 09:43:35AM +, Stefan Koch via Digitalmars-d wrote: [...] This particular slowdown happens because there are somehow depdencies on std.format.format which is instantiated. Which has a ton of dependencies itself. Aha! That explains it. Thanks, Stefan, for the accurate diagnosis. :-) Now the next problem is: how to trim the fat off std.format ... p.s.: and ditch type safety. 'cause `foo(T...) (T args)` is a major slowdown -- it is a template. ;-) Actually, I think this is the classic example of why the compiler should improve the way it implements templates. In my mind, even C's printf API is sucky, because it involves runtime parsing of what's usually a static string, over and over again. What we *really* want is for something like: writeln("blah %d bluh %s", i, s); to be translated into something like: stdout.putString("blah "); stdout.putInt(i); stdout.putString(" bluh "); stdout.putString(s); I.e., there should not be Yet Another Template with Yet Another Ridiculously Long Argument List Type Encoded In The Mangled Name, along with needless marshalling of function arguments on the stack, branching to some other part of the code (potentially causing an instruction cache miss), tons of copy-pasta for calling the same old functions for outputting strings and formatting integers, and incurring Yet Another Branch Hazard when the function finally returns. And there should definitely be no silly runtime parsing of format strings and all of that useless dance. i once wrote such thing (for fun, using "Functional Programming With Templates"). it was fun to do, and freakin' slow due to template bloat. ;-) but yes, it generates a string mixin, and in runtime there was no format string parsing. still, we can be either smart, or have fast compile times, but not both. T_T p.s.: oops. just found that i cannot pass structs with dtors to `(...)` functions. not fun at all.
Re: Slow code, slow
On Mon, Feb 26, 2018 at 08:42:22PM +0200, ketmar via Digitalmars-d wrote: [...] > p.p.s.: or replace it with `void fmtlite (...) {}` thingy. this way we > can still have type safety, but get rid of templates. Given the huge amount of templates in your typical, average D code, I think it's a much more worthwhile effort to improve the way the compiler implements templates instead. :-D T -- Leather is waterproof. Ever see a cow with an umbrella?
Re: Slow code, slow
On Mon, Feb 26, 2018 at 08:38:39PM +0200, ketmar via Digitalmars-d wrote: > H. S. Teoh wrote: > > > On Sat, Feb 24, 2018 at 09:43:35AM +, Stefan Koch via Digitalmars-d > > wrote: > > [...] > > > This particular slowdown happens because there are somehow > > > depdencies on std.format.format which is instantiated. Which has > > > a ton of dependencies itself. > > > > Aha! That explains it. Thanks, Stefan, for the accurate diagnosis. :-) > > > > Now the next problem is: how to trim the fat off std.format ... > > p.s.: and ditch type safety. 'cause `foo(T...) (T args)` is a major > slowdown -- it is a template. ;-) Actually, I think this is the classic example of why the compiler should improve the way it implements templates. In my mind, even C's printf API is sucky, because it involves runtime parsing of what's usually a static string, over and over again. What we *really* want is for something like: writeln("blah %d bluh %s", i, s); to be translated into something like: stdout.putString("blah "); stdout.putInt(i); stdout.putString(" bluh "); stdout.putString(s); I.e., there should not be Yet Another Template with Yet Another Ridiculously Long Argument List Type Encoded In The Mangled Name, along with needless marshalling of function arguments on the stack, branching to some other part of the code (potentially causing an instruction cache miss), tons of copy-pasta for calling the same old functions for outputting strings and formatting integers, and incurring Yet Another Branch Hazard when the function finally returns. And there should definitely be no silly runtime parsing of format strings and all of that useless dance. The latest Phobos does support compile-time format strings, but all that does currently is to forward to the silly runtime parsing code (not to mention coming with its own baggage of additional templates to do the compile-time format string checking). Basically, the whole stupid function call should just be completely inlined and any external template function bodies thrown out the window, because chances are you'll never call format() again with exactly the same parameters somewhere else in the code. I haven't checked if ldc will actually do this level of inlining, but dmd certainly won't with its overly-conservative inliner. And besides, it's a stupid waste of compiler resources to have to generate all of that template code every single time format() is called, only to have the optimizer basically undo half of the work. There should be some way in the language to express format() in a way that doesn't involve tons of template bloat and wasted function body copy-pasta. T -- Meat: euphemism for dead animal. -- Flora
Re: Slow code, slow
H. S. Teoh wrote: On Sat, Feb 24, 2018 at 09:43:35AM +, Stefan Koch via Digitalmars-d wrote: [...] This particular slowdown happens because there are somehow depdencies on std.format.format which is instantiated. Which has a ton of dependencies itself. Aha! That explains it. Thanks, Stefan, for the accurate diagnosis. :-) Now the next problem is: how to trim the fat off std.format ... p.p.s.: or replace it with `void fmtlite (...) {}` thingy. this way we can still have type safety, but get rid of templates.
Re: Translating C "static arrays" into D?
On Mon, Feb 26, 2018 at 06:25:42PM +, Atila Neves via Digitalmars-d wrote: [...] > There's a common misconception in C that arrays and pointers are the > same thing - they're not. This comes about because of the dubious C > feature whereby arrays decay into pointers in function calls. Somewhat > related to this, a little known feature of C is pointers to arrays. In > your example, that's what y and z are. They have funky syntax and look > like function pointers, unless they're obscured with a typedef as in > your example. > > You can pass a double array of any size to x, or a pointer to double, > but y and z are constrained to be pointers to arrays of size 1. > Exemplified: > > typedef double mytype[1]; > void func1(mytype x); > void func2(mytype* x); > > int main() { > double arr1[1]; > double arr2[2]; > double* ptr; > > func1(arr1); // fine > func1(arr2); // fine > func1(ptr); // fine > > func2(&arr1); // fine > func2(&arr2); // oops - won't compile > } Ouch. After working with C for more than 20 years, this one still escaped me. :-( How I hate C array semantics... On Mon, Feb 26, 2018 at 01:33:58PM -0500, Steven Schveighoffer via Digitalmars-d wrote: [...] > If you declare mytype as: > > alias mytype = double[1]; > > Then you can use it pretty much anywhere. The only exception is when > it's the exact type of a parameter. In that case, use ref: > > extern(C) void someFunc(ref mytype x, mytype *y, mytype **z); [...] Nice, that's also the solution I eventually converged on. T -- Let's eat some disquits while we format the biskettes.
Re: Slow code, slow
H. S. Teoh wrote: On Sat, Feb 24, 2018 at 09:43:35AM +, Stefan Koch via Digitalmars-d wrote: [...] This particular slowdown happens because there are somehow depdencies on std.format.format which is instantiated. Which has a ton of dependencies itself. Aha! That explains it. Thanks, Stefan, for the accurate diagnosis. :-) Now the next problem is: how to trim the fat off std.format ... no wai. it is just Too General to be slim. what can be done, though, is `std.format.lite` module (or something), that supports only a very small subset of "big format" features, like simply printing numbers, arrays, and unconditionally calling `.toString` on structs/classes, and a very restricted set of formatting options. that should cover alot of use cases. 'cause most of the time people only need something like `%3d %s` and such.
Re: Slow code, slow
H. S. Teoh wrote: On Sat, Feb 24, 2018 at 09:43:35AM +, Stefan Koch via Digitalmars-d wrote: [...] This particular slowdown happens because there are somehow depdencies on std.format.format which is instantiated. Which has a ton of dependencies itself. Aha! That explains it. Thanks, Stefan, for the accurate diagnosis. :-) Now the next problem is: how to trim the fat off std.format ... p.s.: and ditch type safety. 'cause `foo(T...) (T args)` is a major slowdown -- it is a template. ;-)
Re: Translating C "static arrays" into D?
On 2/26/18 12:54 PM, H. S. Teoh wrote: What's the correct translation of the following C declarations into D? typedef double[1] mytype; void someFunc(mytype x, mytype *y, mytype **z); struct SomeStruct { mytype x; mytype *y; mytype **z; } I need this to interface with an external C library. Currently, I just wrapped the above as-is inside an extern(C) block. But I suspect it may be wrong, because: 1) In C, declaring a function parameter of type double[1] is, IIRC, the same thing as declaring it as double*. But in D, double[1] passes one double by value as a static array. So there may be an API mismatch here. If you declare mytype as: alias mytype = double[1]; Then you can use it pretty much anywhere. The only exception is when it's the exact type of a parameter. In that case, use ref: extern(C) void someFunc(ref mytype x, mytype *y, mytype **z); -Steve
Re: Translating C "static arrays" into D?
H. S. Teoh wrote: On Mon, Feb 26, 2018 at 08:07:11PM +0200, ketmar via Digitalmars-d wrote: [...] in C, arrays are *always* decaying to pointers. so void foo (int x[2]) is the same as void foo (int* x) `[2]` is purely informational. that is, in D it will be: alias mytype = double*; Actually, that doesn't work, because in the struct declaration it will be wrong: // C struct S { double[5] x; // actually occupies the space of 5 doubles } // D struct S { double* x; // occupies the space of 1 pointer (wrong) } yeah, sorry. somehow i completely missed structs.
Re: Translating C "static arrays" into D?
On Monday, 26 February 2018 at 17:54:12 UTC, H. S. Teoh wrote: What's the correct translation of the following C declarations into D? typedef double[1] mytype; This isn't valid C, but `typedef double mytype[1];` is. void someFunc(mytype x, mytype *y, mytype **z); struct SomeStruct { mytype x; mytype *y; mytype **z; } I need this to interface with an external C library. Currently, I just wrapped the above as-is inside an extern(C) block. But I suspect it may be wrong, because: 1) In C, declaring a function parameter of type double[1] is, IIRC, the same thing as declaring it as double*. But in D, double[1] passes one double by value as a static array. So there may be an API mismatch here. Yes, a `double[1]` parameter in C and `double*` are the same thing. However, that's not valid for the other two parameters (y and z). There's a common misconception in C that arrays and pointers are the same thing - they're not. This comes about because of the dubious C feature whereby arrays decay into pointers in function calls. Somewhat related to this, a little known feature of C is pointers to arrays. In your example, that's what y and z are. They have funky syntax and look like function pointers, unless they're obscured with a typedef as in your example. You can pass a double array of any size to x, or a pointer to double, but y and z are constrained to be pointers to arrays of size 1. Exemplified: typedef double mytype[1]; void func1(mytype x); void func2(mytype* x); int main() { double arr1[1]; double arr2[2]; double* ptr; func1(arr1); // fine func1(arr2); // fine func1(ptr); // fine func2(&arr1); // fine func2(&arr2); // oops - won't compile } 2) In C, declaring a *variable* or struct field as double[1] has essentially the same semantics as D's static arrrays. Meaning that I cannot just change the declaration of mytype in order to get the correct behaviour of function parameters. 3) I'm getting a segfault at runtime of some C++ code into D, that calls the library via this C API, and I suspect it's probably due to (1). The correct translation is: extern(C) void someFunc(double* x, double[1]* y, double[1]** z); Atila
Re: Slow code, slow
On Sat, Feb 24, 2018 at 09:43:35AM +, Stefan Koch via Digitalmars-d wrote: [...] > This particular slowdown happens because there are somehow depdencies > on std.format.format which is instantiated. > Which has a ton of dependencies itself. Aha! That explains it. Thanks, Stefan, for the accurate diagnosis. :-) Now the next problem is: how to trim the fat off std.format ... T -- What is Matter, what is Mind? Never Mind, it doesn't Matter.
Re: Translating C "static arrays" into D?
On Mon, Feb 26, 2018 at 08:07:11PM +0200, ketmar via Digitalmars-d wrote: [...] > in C, arrays are *always* decaying to pointers. so > > void foo (int x[2]) > > is the same as > > void foo (int* x) > > `[2]` is purely informational. > > that is, in D it will be: > > alias mytype = double*; Actually, that doesn't work, because in the struct declaration it will be wrong: // C struct S { double[5] x; // actually occupies the space of 5 doubles } // D struct S { double* x; // occupies the space of 1 pointer (wrong) } Furthermore, declaring it as `double*` breaks existing code ported from C: // Original C code: void foo(mytype x); mytype z; foo(z); // D code: void foo(double* x);// OK mytype z; // NG foo(z); // NG: passes uninitialized pointer // alternatively: double[1] z; foo(z); // NG: need to insert `&` to compile Eventually I figured out a (hackish) solution to make it work without silently breaking transliterated C code: declare all function parameters that take `mytype` as ref. This causes the D compiler to simulate the array -> pointer degradation semantics but still retain "static array" semantics in structs and variable declarations, without requiring a change in syntax. T -- Food and laptops don't mix.
Re: Translating C "static arrays" into D?
H. S. Teoh wrote: What's the correct translation of the following C declarations into D? typedef double[1] mytype; void someFunc(mytype x, mytype *y, mytype **z); struct SomeStruct { mytype x; mytype *y; mytype **z; } I need this to interface with an external C library. Currently, I just wrapped the above as-is inside an extern(C) block. But I suspect it may be wrong, because: 1) In C, declaring a function parameter of type double[1] is, IIRC, the same thing as declaring it as double*. But in D, double[1] passes one double by value as a static array. So there may be an API mismatch here. 2) In C, declaring a *variable* or struct field as double[1] has essentially the same semantics as D's static arrrays. Meaning that I cannot just change the declaration of mytype in order to get the correct behaviour of function parameters. 3) I'm getting a segfault at runtime of some C++ code into D, that calls the library via this C API, and I suspect it's probably due to (1). T in C, arrays are *always* decaying to pointers. so void foo (int x[2]) is the same as void foo (int* x) `[2]` is purely informational. that is, in D it will be: alias mytype = double*;
Re: Translating C "static arrays" into D?
On Mon, Feb 26, 2018 at 09:54:12AM -0800, H. S. Teoh via Digitalmars-d wrote: > What's the correct translation of the following C declarations into D? > > typedef double[1] mytype; Sorry, typo, should be: typedef double mytype[1]; > void someFunc(mytype x, mytype *y, mytype **z); > > struct SomeStruct { > mytype x; > mytype *y; > mytype **z; > } [...] T -- Real men don't take backups. They put their source on a public FTP-server and let the world mirror it. -- Linus Torvalds
Translating C "static arrays" into D?
What's the correct translation of the following C declarations into D? typedef double[1] mytype; void someFunc(mytype x, mytype *y, mytype **z); struct SomeStruct { mytype x; mytype *y; mytype **z; } I need this to interface with an external C library. Currently, I just wrapped the above as-is inside an extern(C) block. But I suspect it may be wrong, because: 1) In C, declaring a function parameter of type double[1] is, IIRC, the same thing as declaring it as double*. But in D, double[1] passes one double by value as a static array. So there may be an API mismatch here. 2) In C, declaring a *variable* or struct field as double[1] has essentially the same semantics as D's static arrrays. Meaning that I cannot just change the declaration of mytype in order to get the correct behaviour of function parameters. 3) I'm getting a segfault at runtime of some C++ code into D, that calls the library via this C API, and I suspect it's probably due to (1). T -- Amateurs built the Ark; professionals built the Titanic.
Re: Can this be done? Defining type as in this Scala sample code
you can do something like this (https://run.dlang.io/is/RYR5Dm): ``` import std.algorithm : sum; import std.range : only; import std.stdio : writeln; import std.typecons : tuple; void main() { { auto list = tuple(1, 2.4, 5); auto sum = list.expand.only.sum; writeln(sum); } { // do not compile /* auto list = tuple(1, 2.4, 5, "123"); auto sum = list.expand.only.sum; writeln(sum); */ } } ```
Re: Can this be done? Defining type as in this Scala sample code
On Monday, 26 February 2018 at 15:43:54 UTC, Bienlein wrote: Hello, just curious whether this is a Scala speciality or whether it could also be done in D. Here is some Scala code: object Scratch extends App { // compiles: val list = List(1, 2.4, 5) val sum = list.sum println(sum) // does not compile: val list2 = List(1, 2.4, 5, "123") val sum2 = list2.sum println(sum2) } In the code above list.sum compiles, because list only contains values that are of type Numeric. The sum method looks like this: def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus) So sum compiles if all values can be converted to Numeric which the compiler checks at compile time. For list2 this is not the case as "123" is a string and therefore not of type Numeric. Calling functions on list2 ist fine as long as no function is called that requires a conversion to Numeric for each element in the list such as in the case of sum. My question is now whether that kind of logic can also be defined in D. My knowledge of D is too limited to find out in reasonable time myself. Reason for my curiosity is that the Scala solution relies on implicit conversion at compile time which has its drawbacks (compilation times, colliding implicit conversions the compiler cannot detect, etc.). So I just wanted to see whether D does this in a clean way and I know that D allows for some type parameter constraints to be set. Thansk for any answers, Bienlein Probably more appropriate in the Learn forum. I don't really know much Scala, but it seems like val list2 = List(1, 2.4, 5, "123") would fail to compile because List requires the values to be of a common type and "123" is a string. By contrast, a tuple could hold all those elements, but then it might fail when calculating the sum. Even in D, it's a little tricky to take the sum of a Tuple. You may as well just do a for loop. So I suppose the question is can D do val list = List(1, 2.4, 5) val sum = list.sum Phobos has list containers in std.container. However, usually you would use an array for something like this unless you have a reason to use a list. The 1 and 5 ints are implicitly casted to doubles in both versions. //array version import std.algorithm : sum; import std.stdio : writeln; void main() { auto x = [1, 2.4, 5]; writeln(x.sum); } //list version import std.algorithm : sum; import std.stdio : writeln; import std.container : SList; void main() { auto x = SList!double(1, 2.4, 5); writeln(x[].sum); }
Can this be done? Defining type as in this Scala sample code
Hello, just curious whether this is a Scala speciality or whether it could also be done in D. Here is some Scala code: object Scratch extends App { // compiles: val list = List(1, 2.4, 5) val sum = list.sum println(sum) // does not compile: val list2 = List(1, 2.4, 5, "123") val sum2 = list2.sum println(sum2) } In the code above list.sum compiles, because list only contains values that are of type Numeric. The sum method looks like this: def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus) So sum compiles if all values can be converted to Numeric which the compiler checks at compile time. For list2 this is not the case as "123" is a string and therefore not of type Numeric. Calling functions on list2 ist fine as long as no function is called that requires a conversion to Numeric for each element in the list such as in the case of sum. My question is now whether that kind of logic can also be defined in D. My knowledge of D is too limited to find out in reasonable time myself. Reason for my curiosity is that the Scala solution relies on implicit conversion at compile time which has its drawbacks (compilation times, colliding implicit conversions the compiler cannot detect, etc.). So I just wanted to see whether D does this in a clean way and I know that D allows for some type parameter constraints to be set. Thansk for any answers, Bienlein
Re: PackedAliasSeq?
On Thursday, 22 February 2018 at 19:26:54 UTC, Andrei Alexandrescu wrote: template PackedAliasSeq!(T...) { alias expand = AliasSeq!T; } I started playing around with this a few days ago, and came up with another interesting abstraction - NamedPack: alias foo = NamedPack!("Type", int, "name", "foo"); assert(is(foo.Type == int)); assert(foo.name == "foo"); assert(foo.equals!(NamedPack!("Type", int, "name", "foo"))); And for good measure, a helper to define your own 'compile-time structs', for want of a better word: alias Field = DefinePack!("Type", Type, "name", string, "offset", int); alias field1 = Field!(int, "a", 0); assert(is(field1.Type == int)); assert(field1.name == "a"); assert(field1.offset == 0); assert(field1.equals!(NamedPack!("Type", int, "name", "a", "offset", 0))); One benefit over regular structs being of course that these will never end up in the binary. The more structured nature of this construct over the simple Pack template makes it useful where information would otherwise be encoded in the order of elements, as e.g. in pull #6192. Implementation and some more documentation: https://gist.github.com/Biotronic/8a2664c050f01aed5e0c45950509022b -- Simen