Re: Deep nesting vs early returns
H. S. Teoh wrote: > I've had to work with code that had multiply-nested #define macros > involving `do {} while(0)`, and have hated every minute of it. Yes it's ugly but it's also the only way to define a multi-statement macro that can be used like a function. --- Tobias
Re: Dicebot on leaving D: It is anarchy driven development in all its glory.
H. S. Teoh wrote: > On Tue, Aug 28, 2018 at 10:20:06AM -0700, Manu via Digitalmars-d wrote: > [...] > Actually, I think C++ const is not very useful, because it guarantees > nothing. At the most, it's just a sanity checker to make sure the > programmer didn't accidentally do something dumb. But given an opaque > C++ function that takes const parameters, there is ZERO guarantee that > it doesn't actually modify stuff behind your back, and do so legally > (per spec). No, casting away const on pointers and references is only legal if the object pointed to is actually mutable (not const). Everything else is UB. Casting away const of a function parameter that is not under your control will sooner or later lead to UB. Tobi
Re: Parenthesis around if/for/while condition is not necessary
aedt wrote: > Modern languages have already > dropped this requirement (i.e. Rust, Nim) and I don't see any > reason not to do so. AFAIK the if and else branches in Rust always have to be enclosed in curly braces because of this. I don't remember the exact ambiguity though.
Re: Sealed classes - would you want them in D?
KingJoffreywrote: > actually, private is default in Rust. > > public is default in D. > > also, in Rust, private is private within the module, *and* its > descendants. > > I don't believe that is the case in D (someone correct me if I'm > wrong) The point is, that the module is the abstraction boundary.
Re: Sealed classes - would you want them in D?
Tobias Müllerwrote: > KingJoffrey wrote: >> actually, private is default in Rust. >> >> public is default in D. >> >> also, in Rust, private is private within the module, *and* its >> descendants. >> >> I don't believe that is the case in D (someone correct me if I'm >> wrong) > > The point is, that the module is the abstraction boundary. > > s/abstraction/encapsulation/
Re: Sealed classes - would you want them in D?
KingJoffreywrote: > The problem is not so much D, but that C++/Java/C# programmers, > and many from other languages (Go, Rust) will expect private > to mean private...not private..depending on Well, that's not entirely true. Visibility in Rust is similar to D. There's no one true language semantics that holds for all languages. That's the point of having different languages.
Re: Annoyance with new integer promotion deprecations
Nick Sabalausky (Abscissa)wrote: > On 02/19/2018 03:52 AM, Manu wrote: >> On 18 Feb. 2018 10:25 pm, "Walter Bright via Digitalmars-d" < >> digitalmars-d@puremagic.com> wrote: >> >> On 2/18/2018 7:52 PM, Nick Sabalausky (Abscissa) wrote: >> >>> Well, it's also the world's most inconsistant and statndards-disregarding. >>> We're talking 1990's MS-level behavior here. It's *always* causing trouble >>> for something or another. >>> >> >> And the great thing about NNTP is that the user gets to choose the client. >> Not the server. If you don't like the way your client behaves, use another >> one. >> >> >> Except in this case it's you that doesn't like the way my mail client >> behaves. >> > > Because your mail client is BROKEN. > >> I don't want to install software, I'll continue using Gmail, undoubtedly >> the world's most popular mail client... > > Then petition *Google* to fix their shitty fucking software. You've > already been told it has fuck all to do with NNTP. > > Seriously, why the fuck would ANYONE think that by relying on Google > software they're somehow NOT being dragged along by the ear on Google's > every whim and misstep. Christ, we've already been through all this SAME > EXACT shit in the 90's with Microsoft, let's try actually *learning* > from it and move on. It's no wonder that D has so few contributors if they are actively scared away. If you want more people to contribute, make it as easy for them as possible. I really don't understand why this cannot be solved on the server. Replying to all adresses in the Reply-To: header isn't what I would call broken anyway. Is he even using NNTP? Or maybe the mailing list Interface?
Re: Introducing Nullable Reference Types in C#. Is there hope for D, too?
Timon Gehrwrote: >> I wish there was a null >> for int types. > > AFAIU, C# will now have 'int?'. C# had 'int?' (nullable value types) for ages. The new thing is explicitly nullable classes (reference types). I'm really looking forward to use those.
Re: proposed @noreturn attribute
Timon Gehrwrote: > [...] > What I am saying is: in a language with a bottom type, we can create a > function: > > T f(T)(Bottom b){ > return b; // assuming b converts to all types implicitly. > } > > Within the function body, b is a value of type Bottom. > We use a value of type Bottom to create a value of any type we want. As I understand it, you can create *variables* of type Bottom but not *values*. b is a variable, not a value, you cannot actually call that function at runtime.
Re: Checked vs unchecked exceptions
Moritz Maxeinerwrote: > [...] > Or, more succinct: You must either manually write things down the > compiler could find out in a fraction of the time via static > analysis, or cheat the system; both cases are bad code. It's not at all bad code to write things down that the compiler could infer, quite the opposite. Writing it down signals _intent_ and the compiler can check if the implementation is matching the specification which gives you additional security. Additionally it allowes the compiler to do the checks locally which is much easier. Function signatures are interfaces which should be self-contained IMO, i.e. it should not be necessary to examine the function body. That's what signatures are for. At very least for public interfaces. I honestly don't understand how people that care a great deal about expressive type systems can be so opposed to checked exceptions. After all they wouldn't use 'object' for everything either. Tobi
Re: memcpy() comparison: C, Rust, and D
Walter Brightwrote: > On 2/1/2017 9:28 AM, Michael Howell wrote: >> unsafe fn copy_nonoverlapping_ref(src: , dest: T, len: usize) { >> std::ptr::copy_nonoverlapping(src, dest, len) >> } >> >> Again, it doesn't guarantee no side effects, it may guarantee that src isn't >> mutated, it does guarantee that they aren't stored away somewhere, and it >> guarantees that src and dest don't overlap. > > What part of the signature guarantees non-overlap? Mutable references cannot overlap in Rust, at least in safe code. The exact guarantees in unsafe code are not yet clear and currently being fleshed out. OTOH using unsafe code in Rust is quite rare.
Re: memcpy() comparison: C, Rust, and D
Walter Brightwrote: > On 2/1/2017 9:22 AM, Tobias Müller wrote: >> You wouldn't use memcpy but just assign the slices. > > I clearly made a mistake in this example. I wanted to show how a compiler > learns > things from the declaration by using a very familiar declaration. But it > keeps > getting diverted into what people (and some compilers) "know" about memcpy > that > is not in the declaration. I also showed you how memcpy could look like in Rust, I think it's only fair to also point out that this would be fairly unidiomatic. Apart from that, the entire point of building a safe wrapper around an unsafe FFI function is to exploit additional knowledge that is not present in the C declaration, but only in documentation. It's not relevant if that wrapper is built into the language or a library function. After all, to write the D declaration you also had to exploit that knowledge once.
Re: memcpy() comparison: C, Rust, and D
Tobias Müllerwrote: > Walter Bright > But if you still wanted a memcpy it would probably look like this: > > fn memcpy<'a, T>(dest: &'a mut [T], src: &[T]) -> &'a mut [T] No, sorry: fn memcpy<'a, T: Copy>(dest: &'a mut [T], src: &[T]) -> &'a mut [T] And mutable references can never alias, you have the same guarantees as with _restrict, statically checked even at the call site.
Re: memcpy() comparison: C, Rust, and D
Walter Brightwrote: > I'm not very familiar with Rust. Can you post what a Rust declaration for > memcpy > would look like with all the guarantees? You wouldn't use memcpy but just assign the slices. Assignment is always just memcpy in Rust because of move-semantics: a[m1..n1] = b[m2..n2]; It will panic if sizes don't match. But if you still wanted a memcpy it would probably look like this: fn memcpy<'a, T>(dest: &'a mut [T], src: &[T]) -> &'a mut [T]
Re: memcpy() comparison: C, Rust, and D
Walter Brightwrote: > Rust says https://doc.rust-lang.org/1.14.0/libc/fn.memcpy.html: > > pub unsafe extern fn memcpy(dest: *mut c_void, > src: *const c_void, > n: size_t) > -> *mut c_void > > > [...] > The Rust declaration does not give us 1, 2 or 4 (because it is marked as > unsafe). If it was safe, the declaration does not give us 2. Using an FFI function to compare D vs Rust doesn't tell you much. Foreign functions are usually not used directly in Rust, they are used to build safe wrappers that will give you *all* possible guarantees, including type safety. As a consequence it's not necessary to augment the C declaration with additional information. Marking the function as safe would be wrong in Rust, because dereferencing raw pointers is unsafe. Raw pointers are not necessarily valid, even in safe code. You need references for that guarantee. But again, raw pointers are usually only used for FFI and to build safe abstractions. Tobi
Re: ycombinator"In my Christmas wishlist is a language ..."
Ilya Yaroshenkowrote: > This is small but pleasant proof that D can be a backend language > for high performance software. Go and Rust developers will be > happy to use D under the hood of Go/Rust API if we can propose > the best libraries. They do not against D! The only things we > need to be in touch with the rest of world is to write a good > libraries and provide betterC interface to interact with other > languages :-) TBH I think it's not realistic that Rust and Go developers will adopt D for high performance under the hood, unlike more dynamic languages like Python or Ruby. Go and Rust languages target a similar audience and are not inherently slower than D. Existing good quality libraries like Mir GLAS have certainly a good chance of being adopted. But going through FFI is not without costs (both for library writers and users) and if there are similar libraries in the native language I honestly don't see much chances for libraries written in D, unless they are really much better.
Re: From r/linux: Which language should i use/learn ?
Chris Wrightwrote: > Okay, and D gives me sufficient tools to not leak database connections > under typical workflows. So does C#. So does Python. So does Java, these > days. The last time it's been even vaguely annoying for me was with > nodejs, thanks to callback hell, and even then it was only an annoyance. TBH, IDisposable/AutoClosable is just a PITA. It's like going back to manual memory management and doesn't work at all for shared ownership. > The only type of resource I have to deal with that isn't a database > connection or memory is a socket. They don't go out of scope before > they're closed. Ever. So that automatic resource cleanup stuff doesn't > even help there. Another kind is wrapping non-threadsafe FFI object structures, which are actually also memory. Because of finalizers running in a different thread, you cannot just rely on the GC but have to make everything either synchronized or IDisposable (or a combination thereof). It's not impossible but requires some serious thought and overhead. > My handling of non-memory resources that require any sort of cleanup > takes up like 3% of my code, constrained to two files. (I measured.) So > it's going to be right quick for me to isolate any problems. The problem is not where the code is written but where it is used (transitively). Tools like IDisposable are contagious and infect everything that's using it.
Re: ADL
ZombineDevwrote: > So what? C#'s generics are less flexible than C++ and D templates. > The point is that C#'s lookup does not consider only the > implemented interfaces, but also falls back to extensions > methods. If C# had ADL, > the compiler would also look for extension methods in the > namespace > of the type (in non-generic methods, when the type is "known"), > although the user of the type may not have imported the namespace. ADL wouldn't change anything if you don't cast to a specific type, and if you do, that part of the code is not generic anymore. >>> Sum is implemented in that stupid way, because unlike C++, in >>> C# operators need to be implemented as static methods, so you >>> can't abstract them with an interface. If they were instance >>> methods, you could implement them outside of the class as >>> extension methods and there would be no need to write a >>> distinct method for each type. Here's an example: >>> http://rextester.com/PQFPC46087 >>> The only thing missing is syntax sugar to forward the '+' >>> operator to 'Add' in my example. >> >> With runtime reflection you can do almost anything... That's >> circumventing the type system and doesn't disprove anything. > > There's no circumventing the type system. `typeof(obj)` is barely > even reflection. You can do this with regular cast or using the > `is` expression (http://rextester.com/CXGNK69048). I used > `typeof` just because it could yield better performance. Typecasting *is* circumventing the type system.
Re: ADL
Andrei Alexandrescuwrote: > On 9/3/16 7:08 PM, Tobias M wrote: >> On Saturday, 3 September 2016 at 16:33:07 UTC, Andrei Alexandrescu wrote: >>> I see. This is a matter orthogonal to DbI - introspection should be >>> able to figure out whether a member can be found, or a nonmember if >>> the design asks for it. I wouldn't like "tricking" DbI into thinking a >>> member is there when there isn't. -- Andrei >> >> The problem I see with DbI is rather that the user of a function thinks >> that an optional constraint is satisfied, while in reality it isn't, due >> to a non-obvious lookup/visibility problem. > > At some point there's a need to RTFM. -- Andrei Is there one for DbI? (Sincere question)
Re: ADL
Tobias Mwrote: > On Saturday, 3 September 2016 at 16:32:16 UTC, ZombineDev wrote: >> Sum is implemented in that stupid way, because unlike C++, in >> C# operators need to be implemented as static methods, so you >> can't abstract them with an interface. If they were instance >> methods, you could implement them outside of the class as >> extension methods and there would be no need to write a >> distinct method for each type. Here's an example: >> http://rextester.com/PQFPC46087 >> The only thing missing is syntax sugar to forward the '+' >> operator to 'Add' in my example. > > With runtime reflection you can do almost anything... That's > circumventing the type system and doesn't disprove anything. > I mean, it even "works" for types that cannot be added at all, by > just returning a default value... It's not runtime reflection, sorry about that. But Add claims to be generic but it's actually just a list of special cases. It compiles for all types but only works for some. And even worse, for types that actually do support addition but are not in the list it silently does the wrong thing. You cannot do the same in a truly generic way.
Re: ADL
On Friday, 2 September 2016 at 23:51:35 UTC, Manu wrote: This pattern seems to bite me every direction I turn when trying to write range or algorithm style code. C++ has ADL, and ADL works. I've never thought about this problem in C++, or had any problems with ADL. IMO the root of this problem is that templates are *duck typed*. All those problems wouldn't even exist with concepts/traits/typeclasses (done right). ADL is only an ugly hack. And with "Design by Introspection" it only gets worse: If an optional operation exists, but is not found because of unexpected problems like these, it still compiles but you only get limited functionality or bad performance.
Re: The Case Against Autodecode
On Sunday, 29 May 2016 at 11:25:11 UTC, Chris wrote: Unicode graphemes are not always the same as graphemes in natural (written) languages. If <é> is composed in Unicode, it is still one grapheme in a written language, not two distinct characters. However, in natural languages two characters can be one grapheme, as in English , it represents the sound in `shower, shop, fish`. In German the same sound is represented by three characters as in `Schaf` ("sheep"). A bit nit-picky but we should make clear that we talk about "Unicode graphemes" that map to single characters on the written page. But is that at all possible across all languages? To avoid confusion and misunderstandings we should agree on the terminology first. No, this is well established terminology, you are confusing several things here: - A grapheme is a "character" as written on the page - A phoneme is a spoken "character" - A codepoint is the fundamental "unit" of unicode Graphemes are built from one or more codepoints. Phonemes are a different topic and not really covered by the unicode standard AFAIK. Except for the IPA notation, but these are again graphemes that represent phonemes.
Re: Always false float comparisons
On Friday, 20 May 2016 at 22:22:57 UTC, Walter Bright wrote: On 5/20/2016 5:36 AM, Tobias M wrote: Still an authority, though. If we're going to use the fallacy of appeal to authority, may I present Kahan who concurrently designed the IEEE 754 spec and the x87. Actually cited this *because* of you mentioning Kahan several times. And because you said "The people who design these things are not fools, and there are good reasons for the way things are." Obviously, the designer of x87 and IEEE 754 (which both explicitly allow such "magic" behind the back of the programmer) thinks this is a good thing. But after reading the book, I tend to agree with Gustafson. In the book this is elaborated more in detail, I just cited the conclusion.
Re: Always false float comparisons
On Friday, 20 May 2016 at 06:12:44 UTC, Walter Bright wrote: On 5/19/2016 1:26 PM, Timon Gehr wrote: Those two lines producing different results is unexpected, because you are explicitly saying that y is a double, and the first line also does implicit rounding (probably -- on all compilers and targets that will be relevant in the near future -- to double). > [...] It's obviously bad language design on multiple levels. Floating point semantics simply are not that simple, on any compiler, language or hardware. I recommend reading what the C/C++ Standards say about it, and look at the plethora of compiler switches for VC++/g++/clang++. The people who design these things are not fools, and there are good reasons for the way things are. Sorry, I don't agree. Let me cite Prof. John L Gustafson from his Book "The End of Error" (it's worth reading): --- The lesson taught by all these attempts at clever hidden scratchpad work is that computer users want *consistent* answers, and want to be *permitted the trade-of between speed and accuracy* depending on the situation. There is a subtle arrogance in any computer system that takes the position "You asked for a quick, cheap, approximate calculation, but I know what is good for you and will instead do a better job even if it takes more time and storage and energy and gives you a different answer. You're welcome." ---
Re: How my little brother try D
Jesse Phillipswrote: > Oh this was the other thing I was looking for: > > http://stackoverflow.com/a/23231073/34435 > > C#'s move doesn't work across network. That's wrong AFAIK. Tobi
Re: Females in the community.
Walter Brightwrote: > On 3/25/2016 5:36 PM, Bruno Medeiros wrote: >> What NNTP client do you use on your phone? > > I know there's at least one available on the iphone, and of course you'd have > the option to use the DFeed web interface. > > https://itunes.apple.com/us/app/newstap-usenet-newsreader/id292410356 Yes, exactly that one. Probably the most used app on my phone.
Re: Females in the community.
Bruno Medeiroswrote: > On 24/03/2016 09:16, Walter Bright wrote: >> We're doing just fine with NNTP and Vladimir's forum software. > > And this is one of the reasons why I've essentially moved from D to > Rust. Yes, the forum software. It's the exact opposite for me. I like Rust the language better than D but the forum is much easier to follow than Discourse. Discourse is using far to much resources/bandwidth. It's a PITA on my (quite old) phone. For the D forum I've a nice NNTP client that works like a charm. Tobi
Re: std.xml2 (collecting features)
Adam D. Ruppewrote: > On Wednesday, 2 March 2016 at 06:59:49 UTC, Tobias Müller wrote: >> What's the usecase of DOM outside of browser >> interoperability/scripting? The API isn't particularly nice, >> especially in languages with a rich type system. > > I find my extended dom to be very nice, especially thanks to D's > type system. I use it for a lot of things: using web apis, html > scraping, config file stuff, working on my own documents, and > even as my web template system. > > Basically, dom.d made xml cool to me. Sure, some kind of DOM is certainly useful. But the standard XML-DOM isn't particularly nice. What's the point of a linked list style interface when you have ranges in the language?
Re: std.xml2 (collecting features)
Dejan Lekicwrote: > If you really want to be serious about the XML package, then I > humbly believe implementing the commonly-known DOM interfaces is > a must. Luckily there is IDL available for it: > https://www.w3.org/TR/DOM-Level-2-Core/idl/dom.idl . Also, > speaking about DOM, all levels need to be supported! > > Also, I would recommend borrowing the Tango's XML pull parser as > it is blazingly fast. > > Finally, perhaps integration with signal/slot module should > perhaps be considered as well. > What's the usecase of DOM outside of browser interoperability/scripting? The API isn't particularly nice, especially in languages with a rich type system.
Re: [OT] Some neat ideas from the Kotlin language
rsw0xwrote: > On Saturday, 20 February 2016 at 09:40:40 UTC, Tobias Müller > wrote: >> Yuxuan Shui wrote: >>> [...] >> >> In Rust that would be: >> >> let var : Option = ...; >> if let Some(var) = var { >> // You can use var here >> } >> >> It works for every enum (= tagged union), not just Option >> >> Swift also has "if let". >> >> It's not much more verbose but more explicit. >> Changing the type of a variable based on static analysis is >> just advanced >> obfuscation. It hurts readability and the gain is questionable. >> At least it >> only works for nullable types. >> >> Tobi > > D has this too, but only for nullable types afaik. > > if(byte* ptr = someFunc()){ > //... > } > > That's not quite the same as there are no non-nullable pointers in D. There's no guarantee from the type system that the byte* is not null and there are no compiler checks involved. It's a simple runtime check. OTOH in the examples in Kotlin/Rust the variable 'var' changes its type from 'int?' to plain 'int'. In Kotlin this is done with static analysis, in Rust with rebinding of the name. Tobi
Re: [OT] Some neat ideas from the Kotlin language
Yuxuan Shuiwrote: > Just come across Kotlin today, and found some interesting ideas > skimming through its tutorial: > > 1) Null check > > Kotlin has Optional types, suffixed with a '?'. Like 'Int?', same > as in Swift. But instead of explicitly unwrapping them (e.g. var! > in Swift, or var.unwrap() in Rust), Kotlin let you do this: > > > var: Int? > if (var != null) > //You can use var here In Rust that would be: let var : Option = ...; if let Some(var) = var { // You can use var here } It works for every enum (= tagged union), not just Option Swift also has "if let". It's not much more verbose but more explicit. Changing the type of a variable based on static analysis is just advanced obfuscation. It hurts readability and the gain is questionable. At least it only works for nullable types. Tobi
Re: TIOBE February 2016.... 15 ?!
Ola Fosheim Grøstadwrote: > On Wednesday, 3 February 2016 at 07:06:47 UTC, cym13 wrote: >> It's all true, D rose up 6 positions: >> http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html >> >> I don't quite know what the leading factor for that change was >> but it sure will be great for its image. > > I don't think anyone takes Tiobe seriously. Here is the search > trend for "dlang", "golang", "swift ios" and "rust (programming > langauge)": > > https://www.google.com/trends/explore#q=dlang%2C%20golang%2C%20swift%20ios%2C%20%2Fm%2F0dsbpg6=q=Etc%2FGMT-1 > > golang and swift are soaring, rust is gaining ground and dlang is > stable. > > Tiobe is measuring search _results_, not queries. Tobi
Re: C++17
H. S. Teoh via Digitalmars-dwrote: > [long rant] If you want to attract new programmers you should stop constantly bashing other programming languages on the public forums. This is one thing that Rust got right. Tobi
Re: C++17
H. S. Teoh via Digitalmars-dwrote: > This reminds me of the time when I wanted to make a "trivial" change to > an old C++ project of mine. This was after I had become acquianted with > D, and gotten used to built-in AA's. I noticed that C++14 finally > officially had hashtables in the standard library (which is worth a rant > in itself -- who has ever heard of a modern programming language that > has no standard hashtable implementation until how many decades > after?!), and was eager to finally try it out in my code. It would be a > simple task, I thought; simply plop in the new standard hashtable at a > strategic point in the code to serve as a cache, and performance should > improve. Right? Right?? > > Many hours later, I was tearing my hair out trying to resolve stupid > issues like: > > 1) You cannot instantitate a hashtable template without also specifying >a hash function. WAT?! No built-in hash function??! Well, yes there >is, except... Wrong. There's std::hash. It's a struct, not a function though. > 2) The standard hashtables have no standard hash function for structs. >You have to write your own. WAT??! Usually, you just specialize std::hash for your type. How often do you write custom structs/classes (it's the same in C++) to be used _by value_ as key in a hash table anyway? > 3) After you have a hash function, you have to create the hashtable with >an explicitly-attached hash function Wrong. > -- it's not a template parameter, Wrong again. It is a template parameter and it defaults to std::hash. >it has to be a function object passed to the hashtable's >ctor. With default argument std::hash(). >Which means passing around the hash function everywhere all >over the code, wherever there's the need to create a hashtable. Wrong. You just specialize std::hash and be done. >Arghh... Yes. > I'm pretty sure with a "little" more effort I could have made it work... > but seriously, that was several *hours* compared to the 2 seconds it > takes in D to add an AA to your code. > > You people who think there's still enough reasons to stick to C++ crack > me up. Do you have any idea what on earth you're talking about?! Well apparently you don't. Tobi
Re: extern(C++, ns)
Walter Brightwrote: > Oh what the hell. I'll answer it one last time: > > 1. C++ has namespaces. They went and invented a whole 'nother thing called > modules. Evidently not even they think that modules and namespaces are the > same > thing. D has modules, C++ has namespace. Why do you introduce yet another concept? You call it named scope but for consumers it behaves like a module... > 2. Multiple modules cannot have the same name in D. C++ practice is to litter > code with namespaces using the same name. It doesn't help if they are just imported as modules in disguise. > 3. Modules have ModuleInfos, static constructors/destructors, etc. These do > not > make obvious sense for namespaces. > > 4. Modules and files have a 1:1 correspondence. This does not work for > namespaces. > > 5. "extern (C++) module std" ? Ugh. Nobody has ever suggested this. mod and extern should be completely separate. > 6. Modules do not nest. Namespaces nest. > > 7. Module semantics are independent of where they are imported. Not so for > namespaces. > > I.e. if modules were bludgeoned into being namespaces, there would be such a > list of special cases and confusions and exceptions and awkward crap you'd be > far, far better off having namespace as a SEPARATE feature, because that's > what > they'd wind up being anyway, even if they were named "modules". mod should not imply a C++ namespace and extern(C++, ns) should not introduce a named scope. This gives you maximal flexibility with minimal complexity. You could import symbols from different namespaces to the same module and you could import symbols from the same namespace to different modules. Modules and namespaces would be completely independent. I'd even count all those points above as arguments _against_ the current design. Tobi
Re: dmd codegen improvements
Iain Buclaw via Digitalmars-dwrote: > On 5 Sep 2015 11:25 pm, "Walter Bright via Digitalmars-d" < > digitalmars-d@puremagic.com> wrote: >> >> On 9/5/2015 5:54 AM, Adam D. Ruppe wrote: >>> >>> On Saturday, 5 September 2015 at 08:15:06 UTC, Walter Bright wrote: And your post did it too. If you're using the Thunderbird news reader, typing Cntl-U will show > the full source of the message. >>> >>> >>> This is perfectly normal for emails and such. They are > multipart/alternative >>> MIME messages which pack different versions of the same message together > and >>> your client picks its preferred one to show you. >>> >>> It is kinda useless because the html version adds zero value, but the > text >>> version is still there to so your client should just ignore it. >> >> >> I know, and my client does, but given the size of the n.g. message > database, doubling its size for no added value makes it slower. > > There's no way to change the Gmail client behaviour. And I'm assuming that > it isn't a recent feature either. Considering the messy quoting in your posts I'd actually prefer HTML messages.
Re: DIP74 - where is at?
Manu via Digitalmars-dwrote: > Nothing here explains to me how it is that the compiler can do without > RC primitives that the compiler knows it is allowed to > optimise/schedule as it likes? > How does it look in rust that it is able to optimise calls to inc/dec > primitives? > > You also make the points that I expect to bank on in D; we are > thread-local by default (big advantage!), nothrow is pervasive (big > advantage!), but the language still doesn't know the primitives that > it can use to optimise. > > The ownership proposal solving the problem isn't entirely correct. > Sure, borrowed pointers imply RC elision, and it's particularly useful > for writing API's that are allocation/ownership agnostic, but it > doesn't solve the problem as you suggest. Once a pointer is borrowed, > it can't be assigned to another RC pointer anymore. If you must use > borrowing to implement RC elision across calls, then you lose the > ability to give someone else a reference down the call-tree. > Passing an RC object proper to a function also elides RC fiddling, but > the compiler can't distinguish between RC fiddling and copying logic > unless the RC primitives are explicit. I find that this is a very > common case. The key is, that RC in Rust is a move-by-default type. That means if you are passing RCs around, you are actually passing ownership. Only if you explicitly call 'clone', ownership is split up. That means in the default case, no inc/dec is necessary. Even more important, RC isn't used very often. True shared ownership is actually quite rare. References (borrowed pointers) and 'Box'es (unique pointers) are much more common. shared_ptr is much overused in C++ IMO. Tobi
Re: Implementing typestate
Ola Fosheim Grøstadwrote: > On Tuesday, 15 September 2015 at 20:34:43 UTC, Tobias Müller wrote: >>> There's a Blog post somewhere but I can't find it atm. >> >> Ok found it: > http://pcwalton.github.io/blog/2012/12/26/typestate-is-dead/ > > But that is for runtime detection, not compile time? Not as far as I understand it. The marker is a type, not a value. And it's used as template param. But you need non-copyable move-only types for it to work. In D it would probably look like: File!Open file = open(...); File!Closed file = close(file); Tobi
Re: Implementing typestate
Tobias Müllerwrote: > I think they settled for a simpler library solution using a marker type (I > think it was called Phantom type) as template parameter and then using > local shadowing to emulate mutable type state. Multiple variables with same > name but different (marker) type. > There's a Blog post somewhere but I can't find it atm. Ok found it: http://pcwalton.github.io/blog/2012/12/26/typestate-is-dead/ Tobi
Re: Implementing typestate
Ola Fosheim Grøstadwrote: > On Tuesday, 15 September 2015 at 20:01:16 UTC, Meta wrote: >> [...] >> If I remember correctly Rust *did* have a typestate system very > early >> on but it was done away with in favour of the borrow > checker. > > Yeah, I've seen the Rust creator write about how they started out with > all whistles and bells with the intent of having a full blow effect > system. Then realized that they had to make things simpler and focus on > memory management because that was the most critical feature. Probably a > wise strategy to go for simplicity and hit version 1.0 sooner. I think they settled for a simpler library solution using a marker type (I think it was called Phantom type) as template parameter and then using local shadowing to emulate mutable type state. Multiple variables with same name but different (marker) type. There's a Blog post somewhere but I can't find it atm. Maybe that's also possible for D? Tobi
Re: [OT] Sharp Regrets: Top 10 Worst C# Features
Chris wend...@tcd.ie wrote: [...] As if most people were too stpid to grasp the concept that `x++` is the same as `x += 1` (which is intellectually as 'challenging' as `x++`, by the way). Because it's not. ++x is the same as x+=1, not x++. Tobi
Re: Rant after trying Rust a bit
Jonathan M Davis jmdavisp...@gmx.com wrote: trait C : A,B { } How is that any different from interfaces? You can do exactly the same thing with them. implT: A+B C for T { } ^^^ That's the important line. You can define *and implement* the trait C for *all types that already implement A and B*. That's definitely not possible with interfaces. The difference between traits and interfaces is, that trait implementation is separate from the type definition. fn myFunction(c: C) {...} [...] But as soon as you have to create a new one that combines two or more interfaces/traits/concepts, then that doesn't scale. interfaces force that. I wouldn't expect traits or concepts to, because they're compile-time constructs, but that would depend on how the language defines them. It might make sense to create combined traits/concepts for the cases where the operations in question are often going to be required together, but in general, it's going to scale far better to require them separately rather than require a combined trait/concept. Otherwise, you get a combinatorial explosion of traits/concepts as you combine them to create new traits/concepts - either that, or you code doesn't end up being very generic, because it's frequently using traits/concepts that require more operations than it actually uses, meaning that it will work with fewer types than it would otherwise. Because you can implement the combined trait directly for all separate subtraits, you can define that new trait just for the use of one function. Tobi
Re: Rant after trying Rust a bit
Jonathan M Davis jmdavisp...@gmx.com wrote: On a related note, while I'd noticed it on some level, I don't think that it had ever clicked for me how restrictive interfaces are before this discussion. The simple fact that you can't ask for two of them at once really reduces how reusable your code can be. So, templatizing those checks rather than using interfaces is huge. And DbI is an extension of that. There's likely a lot of unplumbed depth there. One big improvement of traits over interfaces is, that you can implement traits for types after they are defined, even for types that you didn't define yourself. So in Rust, if your function needs two unrelated interfaces (trait objects == dynamic polymorphism) A and B, you can easily define a new trait C that depends on A and B and implement C for all types that also implement A and B: trait A {...} trait B {...} trait C : A,B { } implT: A+B C for T { } fn myFunction(c: C) {...} For generics you don't even need that: fn myFunctionT: A+B(t: T) {...} Tobi
Re: Read text file fast, how?
Martin Nowak code+news.digitalm...@dawg.eu wrote: On 07/26/2015 09:04 PM, Jesse Phillips wrote: It would be better to compare with LDC or GDC to match the same backend as C++. That is a little harder since they don't have 2.068 yet. Reading a file is IO and memcpy limited, has nothing to do with compiler optimizations. Clearly we must be doing some unnecessary copying or allocating. Or too much syscalls because of non-optimal buffering? Tobi
Re: Rant after trying Rust a bit
Walter Bright newshou...@digitalmars.com wrote: On 7/26/2015 3:44 PM, deadalnix wrote: or template code (which will blow up at instanciation time, or worse, do random shit). Um, all Rust traits do is test for a method signature match, so it compiles. It is NOT a defense against a random method that just happens to match and does some other unrelated random shit. Rust traits have to be implemented *explicitly*. It's not just an implicit test for a matching signature. For example, the '+' operator. Rust traits sez gee, there's a + operator, it's good to go. Ship it! Meanwhile, you thought the function was summing some data, when it actually is creating a giant string, or whatever idiot thing someone decided to use '+' for. + operator is somewhat special because it can only be implemented via trait. That doesn't apply for normal methods. Rust still has not obviated the necessity for unit tests, nor is Rust remotely able to guarantee your code doesn't do random shit if it compiles. An example: Rust std lib defines two traits, PartialOrd and Ord. Ord depends on PartialOrd but doesn't provide any new methods. And it's clearly documented when to implement Ord and when PartialOrd. So sure, someone could decide to deliberately ignore that, but then I just don't care anymore. Tobi
Re: Rant after trying Rust a bit
Alix Pexton alix.dot.pex...@gmail.dot.com wrote: On 25/07/2015 9:48 PM, Walter Bright wrote: Unfortunately, Bruce Eckel's seminal article on it http://www.mindview.net/Etc/Discussions/CheckedExceptions has disappeared. Eckel is not a Java code monkey, he wrote the book Thinking In Java http://www.amazon.com/gp/product/0131002872/ https://web.archive.org/web/20150515072240/http://www.mindview.net/Etc/Discussions/CheckedExceptions This is article not convincing at all. His argument is basically Most programmers are sloppy and tend to catch and ignore checked exceptions. The same programmers that do this will just catch all RuntimeExceptions at top level, write a log entry and proceed. That's actually not much better and certainly not correct error handling. Tobi
Re: Rant after trying Rust a bit
Walter Bright newshou...@digitalmars.com wrote: It's also clear that traits work very well in the small, i.e. in specifications of the feature, presentation slide decks, tutorials, etc. Just like Exception Specifications did. It's the complex hierarchies where it fell apart. I'm not convinced at all that checked exceptions (as implemented in Java, not C++) don't work. My suspicion is that the usual Java code monkey is just too sloppy to care and thus sees it more as a nuisance rather than the help that it is. I think Rust attracts a different kind of programmer than Java. Tobi
Re: Rant after trying Rust a bit
Walter Bright newshou...@digitalmars.com wrote: On 7/23/2015 10:49 PM, Tobias Müller wrote: Walter Bright newshou...@digitalmars.com wrote: I know a lot of the programming community is sold on exclusive constraints (C++ concepts, Rust traits) rather than inclusive ones (D constraints). What I don't see is a lot of experience actually using them long term. They may not turn out so well, like ES. Haskell has type classes since ~1990. Haskell is sometimes described as a bondage-and-discipline language. Google it if you don't believe me :-) Such languages have their place and adherents, but I don't think D is directed that way. I just wanted to point out that there *is* long time experience. What you're thinking about haskell is besides the point. Tobi
Re: Rant after trying Rust a bit
Walter Bright newshou...@digitalmars.com wrote: On 7/24/2015 8:43 PM, Tofu Ninja wrote: there is just a type at the top of the tree that implements them all The one type that encompasses everything defeats the whole point of type checking, traits, concepts, etc. That's exactly my feeling with dynamic casts / QueryInterface... Pass 'object' everywhere and then cast it to the desired interface in demand. Tobi
Re: Rant after trying Rust a bit
Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Once we agree on that, we figure that concepts help nobody. You keep saying that, but I cannot find an explanation. Care to elaborate or give me a pointer? Tobi
Re: Rant after trying Rust a bit
Walter Bright newshou...@digitalmars.com wrote: On 7/23/2015 12:50 PM, Tobias Müller wrote: TBH I'm very surprised about that argument, because boolean conditions with version() were dimissed for exactly that reason. I knew someone would bring that up :-) No, I do not believe it is the same thing. For one thing, you cannot test the various versions on one system. On any one system, you have to take on faith that you didn't break the version blocks on other systems. This is quite unlike D's template constraints, where all the combinations can be tested reliably with a unittest{} block. How is this related to testability? Using boolean conditions does not introduce any new code paths compared to helper versions/ helper traits. Testability is exactly the same. My point was that you argued with cleaner design in the case of versions. *I agree with that*, and I think the same is true for traits. Even if you're right and testability is better, that doesn't contradict the point that I'm trying to make. Tobi
Re: Rant after trying Rust a bit
Walter Bright newshou...@digitalmars.com wrote: On 7/23/2015 10:39 PM, Tobias Müller wrote: You may aus well ask How do interfaces in OO programming deal with this?. It's a good question. And the answer is, the top level function does not list every interface used by the call tree. Nested function calls test at runtime if a particular interface is supported by an object, using dynamic casting or QueryInterface() calls. It's fundamentally different from traits and concepts. IMO dynamic casting or QueryInterface() is a sign of bad design. But then again, I also like exception specifications, at least the way Java does it. In C++ they're pointless, that true. Tobi
Re: Rant after trying Rust a bit
Walter Bright newshou...@digitalmars.com wrote: BTW, you might want to remove the UTF-8 characters from your user name. Evidently, NNTP doesn't do well with them. I don't think NNTP has any problems with that. My newsreader displays it just fine. Tobi
Re: Rant after trying Rust a bit
Walter Bright newshou...@digitalmars.com wrote: They write it something like: void foo(hasPrefix t) { t.prefix(); s = cast(hasSuffix)t; if (s) bar(s); else RuntimeError(message); } That's horrible! Tobi
Re: Rant after trying Rust a bit
Walter Bright newshou...@digitalmars.com wrote: On 7/23/2015 3:12 PM, Dicebot wrote: On Thursday, 23 July 2015 at 22:10:11 UTC, H. S. Teoh wrote: OK, I jumped into the middle of this discussion so probably I'm speaking totally out of context... This is exactly one major advantage of Rust traits I have been trying to explain, thanks for putting it up in much more understandable way :) Consider the following: int foo(T: hasPrefix)(T t) { t.prefix();// ok bar(t);// error, hasColor was not specified for T } void bar(T: hasColor)(T t) { t.color(); } Now consider a deeply nested chain of function calls like this. At the bottom, one adds a call to 'color', and now every function in the chain has to add 'hasColor' even though it has nothing to do with the logic in that function. This is the pit that Exception Specifications fell into. I can see these possibilities: 1. Require adding the constraint annotations all the way up the call tree. I believe that this will not only become highly annoying, it might make generic code impractical to write (consider if bar was passed as an alias). 2. Do the checking only for 1 level, i.e. don't consider what bar() requires. This winds up just pulling the teeth of the point of the constraint annotations. 3. Do inference of the constraints. I think that is indistinguishable from not having annotations as being exclusive. Anyone know how Rust traits and C++ concepts deal with this? You may aus well ask How do interfaces in OO programming deal with this?. Frankly, I've never had an issue with that. Or it's a hint for design problems. Traits (and interfaces) are mostly not that fine grained, i.e. you don't have a trait/interface for every method. They should ideally define an abstraction/entity with a semantic meaning. If your constraint hasColor(x) just means x has method color(), and then implement it for every class that has this method, you can just as well omit constraints and use duck typing. Tobi
Re: Rant after trying Rust a bit
Walter Bright newshou...@digitalmars.com wrote: I know a lot of the programming community is sold on exclusive constraints (C++ concepts, Rust traits) rather than inclusive ones (D constraints). What I don't see is a lot of experience actually using them long term. They may not turn out so well, like ES. Haskell has type classes since ~1990. Tobi
Re: Rant after trying Rust a bit
Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 7/23/15 5:07 AM, Walter Bright wrote: Turns out many constraints in Phobos are of the form (A || B), not just (A B). Agreed. And that's just scratching the surface. Serious question: how do you express in Rust that a type implements one trait or another, then figure out statically which? You define a new trait and implement it differently for A and B. That leads to a cleaner design IMO because you have to think about the right abstraction for that trait. TBH I'm very surprised about that argument, because boolean conditions with version() were dimissed for exactly that reason. Tobi
Re: Rant after trying Rust a bit
jmh530 john.michael.h...@gmail.com wrote: I feel like it's hard to separate borrowing from Rust's variety of pointers ( is borrowed pointer, ~ is for unique pointer, @ is for managed pointer). That's actually very outdated information. Two of the four pointer types (,@,~ and *) were ditched in favor of library solutions. *T: Raw pointers are still the same T: is now called reference, not borrowed pointer ~T: Is now BoxT @T: Is now RcT (and possibly GcT although a GC was never implemented) Tobi
Re: Future(s) for D.
Nick Sabalausky seewebsitetocontac...@semitwist.com wrote: On 06/20/2015 12:34 PM, ketmar wrote: On Sat, 20 Jun 2015 12:23:59 -0400, Nick Sabalausky wrote: let's compare numbers for php, java, ruby, js -- and D. most companies will not bet on language for which a pool of hireable developers is small. and it's understandable: two developers quit, and the project is dead, doomed to complete rewrite in another language. sheesh! Well, not really. I mean, managers and HR all *believe* that to be so. But that's because pretty much all non-programmers, even ones in the software dev industry who really should know better, are stuck in this bizarre idea that programming skills are somehow non-transferable between languages. Which is obviously total bullcrap, but try explaining that to self-assured HR folk and other pointy-hairs. Hell, my first introduction to JS, ASP (yea, it was a long time ago) and web-dev in general was on-the-job as a fresh hire, and I was up to speed in like a week or so, if even that. The one thing relevant here that has *never* left my mind: http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html Favorite part: The recruiters-who-use-grep, by the way, are ridiculed here, and for good reason. I have never met anyone who can do Scheme, Haskell, and C pointers who can't pick up Java in two days, and create better Java code than people with five years of experience in Java, but try explaining that to the average HR drone. So true. But do you also think that the average java code monkey will pick up D equally fast? For many programmers, programming is just a job, not more. They don't program in their spare time and are not really interested in programming languages as you are. Java is a very simple language. That means if you're a power user, you will be limited by that, but as an average programmer this means you can understand code written by others. D on the other hand is a quite complex language. You can write nice and concise code in D, but that doesn't mean that the language is simple.
Re: Slice patterns in Nightly Rust
Nicholas Wilson iamthewilsona...@hotmail.com wrote: On Sunday, 21 June 2015 at 03:23:18 UTC, Dennis Ritchie wrote: Recently published documentation Nightly Rust. I saw this: https://doc.rust-lang.org/nightly/book/slice-patterns.html What do you think about this: a terrible thing or a cool feature? fn is_symmetric(list: [u32]) - bool { match list { [] | [_] = true, [x, inside.., y] if x == y = is_symmetric(inside), _ = false } } [...] Also implicit declaration of variables. Urgh. Patterns are the way that variables are declared in Rust, there's nothing implicit about that. let pattern = expr; match expr { pattern = expr, pattern = expr, } fn myfunction(pattern, pattern) And AFAIK those are the only places where patterns appear and where variables are declared. Tobi
Re: Asked on Reddit: Which of Rust, D, Go, Nim, and Crystal is the strongest and why?
Dave whate...@whatever.com wrote: On Thursday, 11 June 2015 at 20:06:45 UTC, Kagamin wrote: On Thursday, 11 June 2015 at 18:17:01 UTC, Dave wrote: Disagree. Traditionally also handled by throwing exceptions. C# throws a Format exception if a parse fails. https://msdn.microsoft.com/en-us/library/f02979c7%28v=vs.110%29.aspx https://msdn.microsoft.com/en-us/library/bb299639%28v=vs.110%29.aspx Forgot the one named Parse... https://msdn.microsoft.com/en-us/library/b3h1hf19(v=vs.110).aspx Microsoft does lets you opt out (as I suggested). The default function, the one actually named Parse (Int32.Parse), throws an exception by default. Originally (.Net 1) there was only 'Parse', 'TryParse' came in .Net 2, I guess they had to admit that exceptions are not always practical.
Re: [OT] Modules dropped out of C++17
Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 6/9/15 12:58 AM, Kagamin wrote: Same as with @safe @nogc @nothrow @pure. No, these are attributes that change the function's type; constexpr does not. Why is that better?
Re: [OT] Modules dropped out of C++17
Kagamin s...@here.lot wrote: On Tuesday, 9 June 2015 at 10:48:22 UTC, Marc Schütz wrote: static assert() is your friend in this case The point is that in D you don't need to express ctfe guarantee at all. It just works. In other words you have no guarantee. If you want the guarantee you have to ensure it via static assert or unittest and you have to document it. The constexpr attribute covers both at once. And if you don't give that guarantee, well then it may just work. Or not. Or just stop working at some point in the future.
Re: [OT] Modules dropped out of C++17
ponce cont...@gam3sfrommars.fr wrote: C++'s constexpr looks broken because everything must be marked constexpre, which defeats the purpose of having compile-time code looking like runtime code. But I never had the pleasure to use it. constexpr functions are just as well runtime functions. They are only annotated that they are usable in a constant expression. I don't think it's fair to call that broken regarding all the attributes that D functions can take... Tobi
Re: [dlang website] Up Arrow in library
Chris wend...@tcd.ie wrote: On Monday, 18 May 2015 at 19:22:09 UTC, Walter Bright wrote: On 5/18/2015 2:18 AM, Chris wrote: A small suggestion for the library layout (phobos etc) on dlang.org: An up arrow like on duckduckgo would be cool, i.e. as soon as you scroll down an up arrow appears that brings you back to the top, if you click on it. This would be very convenient when browsing through the library. Would it be hard to add this feature? If needs be, I could write a JS function for that. Pressing the [Home] key does that. And what do you use on touch screen devices? The up arrow (on duckduckgo for example) is very convenient. It's one of those little things that are not _strictly_ necessary but often come in handy. On iOS (Safari) just tap on the status bar at the top, where the time and battery status is displayed.
Re: A reason to choose D over Go
weaselcat weasel...@gmail.com wrote: On Sunday, 22 March 2015 at 01:24:10 UTC, Martin Nowak wrote: On Saturday, 21 March 2015 at 23:49:26 UTC, Atila Neves wrote: I actually think that there are two large categories of programmers: those like writing the same loops over and over again and those who use algorithms. I agree, at some point I learned that there is a huge cultural distinction between C and C++ programmers. yes, the other main distinction are the people who correctly put the * next to the type because it's part of the type, or the wrong people who put it next to the variable name because they're heathens One could argue that in the declaration: int *a; the type of *a is int. So it's not a pointer type but a dereference operator. That actually similar to how patterns work in modern programming languages. Tobi
Re: @trust is an encapsulation method, not an escape
Ola Fosheim Grøstad ola.fosheim.grostad+dl...@gmail.com wrote: On Friday, 6 February 2015 at 13:28:59 UTC, Steven Schveighoffer wrote: The bottom line of my reasoning is that code changes over time, by different people. Context is forgotten. It's much better to have the compiler verify you know what you are doing when working with @trusted than it is to just allow anyone to inject code anywhere. Actually, I think this argument goes against what you are arguing for. Anything within a @trusted section has a big warning sign attached to it that says cannot modify this without detailed review. But the compiler cannot verify that a @safe function with local @trusted blocks are actually safe, so it only buys you a false sense of security. I'd go even further: The compiler could even make optimizations in @safe code based on the assumption that all @trusted function calls expose a safe interface. I suspect this will lead to undefined behavior and very subtle bugs.
Re: Why exceptions for error handling is so important
H. S. Teoh via Digitalmars-d digitalmars-d@puremagic.com wrote: On Mon, Jan 12, 2015 at 06:06:19PM +, Tobias Müller via Digitalmars-d wrote: C#'s Dictionary has TryGetValue that returns a bool in addition to the normal indexing operator [] that throws, exactly for that reason. And this is no exception (no pun intended), there are several cases like that in C#. IMO there's something wrong if you have to resort to such code duplification. And what exactly should operator[] return if a key wasn't found? The only sane way is to have the user specify a default value if the key wasn't found, since not all types have a null value (and besides, what if null is a valid value in the dictionary?). IOW something like TryGetValue that takes multiple arguments instead of operator[]. Just stick with one. Some kind of OptionalT would be a good fit. You really should be using operator[] only when the key is expected to exist. If during normal operations there's a 50% chance the key doesn't already exist, you shouldn't be using []. I know that and this is exactly the point. You have two methods that do almost exactly the same just with different error handling and you have to choose based on what the caller considers an error. It's often the case that only the caller can decide what is an error and what not. The designer of an API has to predict all those cases and provide different methods for each case. The problem with exceptions is, that the *callee* has to decide, not the caller.
Re: Why exceptions for error handling is so important
H. S. Teoh via Digitalmars-d digitalmars-d@puremagic.com wrote: On Mon, Jan 12, 2015 at 05:22:26PM +, Adam D. Ruppe via Digitalmars-d wrote: I still wouldn't use them for ordinary flow as a general rule though, but I think they work well for cases where you ask a function to do something and it just can't. Yeah, exceptions are supposed to be ... well, *exceptions*, rather than the norm. :-) If you're using exceptions to do flow control, you're doing something wrong. But what's exceptional for you is normal for me. C#'s Dictionary has TryGetValue that returns a bool in addition to the normal indexing operator [] that throws, exactly for that reason. And this is no exception (no pun intended), there are several cases like that in C#. IMO there's something wrong if you have to resort to such code duplification.
Re: Why exceptions for error handling is so important
Walter Bright newshou...@digitalmars.com wrote: On 1/11/2015 11:09 PM, Tobias Müller wrote: - Error codes are automatically ignored - Exceptions are automatically propagated IMO both are not ideal and lead to sloppy programming. Ignoring errors is of course worse than aborting where you could have handled the error. Rust-style packed errors are nice because you are forced to think about the correct handling. I don't think this is an answer to my point. I thought that your question was a rhetorical one and I agree to a certain degree. You can still have automatic cleanup though. Rust has RAII. The point is that I think that trading some prettyness for explicitness is a good thing in that case. But then again I also like checked exceptions (java) that seem to be disliked by most. It a similar tradeoff.
Re: Why exceptions for error handling is so important
weaselcat weasel...@gmail.com wrote: On Monday, 12 January 2015 at 07:09:54 UTC, Tobias Müller wrote: - Error codes are automatically ignored - Exceptions are automatically propagated IMO both are not ideal and lead to sloppy programming. Ignoring errors is of course worse than aborting where you could have handled the error. Rust-style packed errors are nice because you are forced to think about the correct handling. There's nothing stopping you from just throwing errors out in Rust(last I used it anyways) via empty match statements and/or unwrap. But you have to do so explicitly. You cannot just remove every possibility to ignore errors, because sometimes it is justified. BTW: 'unwrap' panics if it contains an error. But that's not really important here.
Re: Why exceptions for error handling is so important
Walter Bright newshou...@digitalmars.com wrote: On 1/11/2015 5:06 AM, Dicebot wrote: What is your opinion of approach advertised by various functional languages and now also Rust? Where you return error code packed with actual data and can't access data without visiting error code too, compiler simply won't allow it. It's a great question. I have a lot of experience with error codes, and with exceptions. I have zero with the packed scheme, though that doesn't stop me from having an opinion :-) Perhaps I misunderstand, but given A calls B calls C, A = B = C and C detects an error, and A knows what to do with the error. B then becomes burdened with checking for the error, invoking some sort of cleanup code, and then propagating it. Wouldn't this be uglifying B's source code? With exceptions, C throws, A catches, and B's cleanup happens automatically. This matters very much for pipeline style programming (i.e. ranges and algorithms). - Error codes are automatically ignored - Exceptions are automatically propagated IMO both are not ideal and lead to sloppy programming. Ignoring errors is of course worse than aborting where you could have handled the error. Rust-style packed errors are nice because you are forced to think about the correct handling.
Re: Improving ddoc
Joseph Rushton Wakeling via Digitalmars-d digitalmars-d@puremagic.com wrote: Three things I'm not sure about: (i) does it allow definitions of custom macros as with Ddoc (although I'm not sure how necessary that is in practice); (ii) I have a nasty feeling its @keyword markup syntax (e.g. @return @param etc.) might not play nice with D code examples; (iii) I suspect we'd have to do some integration work getting D support into Doxygen in order to enjoy the best of all its features. AFAIK @keyword is javadoc style (but supported by doxygen) and original doxygen style uses \keyword.
Re: DIP69 - Implement scope for escape proof references
Walter Bright newshou...@digitalmars.com wrote: [...] and ref's can still be null in C++! AFAIK only if you dereference a NULL pointer, which is UB. So not really. [...] Tobi
Re: toString refactor in druntime
Walter Bright newshou...@digitalmars.com wrote: [snip] Have you ever looked at the C openssl.lib? The .h files with it are loaded with metaprogramming done with C macros. Yet I've never heard anyone complain about it. Those macros are a very common common complaint in my experience. C .h files for DLLs are typically stuffed with C macros. [snip] The defense presents openssl as Exhibit A! Presenting OpenSSL as a case for good interface design is a crime by itself! Tobi
Re: Program logic bugs vs input/environmental errors
Walter Bright newshou...@digitalmars.com wrote: On 10/4/2014 3:30 AM, Steven Schveighoffer wrote: On 10/4/14 4:47 AM, Walter Bright wrote: On 9/29/2014 8:13 AM, Steven Schveighoffer wrote: I can think of cases where it's programmer error, and cases where it's user error. More carefully design the interfaces if programmer error and input error are conflated. You mean more carefully design File's ctor? How so? You can start with deciding if random binary data passed as a file name is legal input to the ctor or not. I think it helps to see contracts as an informal extension to the type system. Ideally, the function signature would not allow invalid input at all. In practice, that's not always possible and contracts are a less formal way to specify the function signature. But conceptually they are still part of the signature. And of course (as with normal contract-less functions) you are always allowed to provide convenience functions with extended input validation. Those should then be based on the strict version. For example take a constructor for an XML document class. It could take the (unvalidated) file path as string parameter. Or a file (validated that it exists) object. Or a stream (validated that it exists and is already opened). You can provide all three for convenience, but I think it's still good design to provide three _different_ functions. Contracts are not a magical tool to provide you all three variants in one function depending somehow on the needs of the caller. Tobi
Re: Program logic bugs vs input/environmental errors
Paolo Invernizzi paolo.invernizzi@no.address wrote: And guess it, here the buildings made by ancient romans are still up and running, while we have schools building made in the '90 that come down at every earthquake... All the bad buildings from the ancient romans already came down while the last 2000 years. The best 1% survived. Tobi
Re: [Semi OT] Language for Game Development talk
Walter Bright newshou...@digitalmars.com wrote: On 9/26/2014 8:21 AM, Manu via Digitalmars-d wrote: I've never used an exception before. I can't imagine a reason I would ever want to. Nothrow is your friend, then! BTW, you need exceptions if there appears in your code things like: if (errorHappened) goto LcleanupCode; No you need destructors/RAII/finally. And all those work equally with without exceptions (early return). Tobi
Re: Which patches/mods exists for current versions of the DMD parser?
Ola Fosheim Grøstad ola.fosheim.grostad+dl...@gmail.com wrote: This is my take on this: I don't think a fork is a bad thing, and I think BSD/MIT style licensing increase the probability of a fork down the road compared to GPL. The payoff for forking is simply higher with a liberal license. I think you are confusing the language with the compiler. The license gives you the right to take the compiler sources and do basically anything with it. But if that modified compiler compiles a different language than the official 'D', that does not automatically mean that you have the right to call that language fork 'D' and publish it on the D forum. I don't say that it's forbidden, it's just not covered by the compiler license. Tobi
Re: [OT] Microsoft filled patent applications for scoped and immutable types
Russel Winder via Digitalmars-d digitalmars-d@puremagic.com wrote: First to file not first to invent – by the corporations for the corporations. This should tell you everything you need to know about technological innovation in the USA. I think you misunderstood the first to file rule. In a strict first to file system (like in the EU), any early disclosure counts as prior art. First to file is only between two competing patent applications of an undisclosed invention. USA is a bit less strict and grants a grace period after disclosure.
Re: checkedint call removal
Walter Bright newshou...@digitalmars.com wrote: On 7/30/2014 10:16 PM, bearophile wrote: But you have redefined assert to mean a mix of assume and assert. I haven't redefined anything. It's always been that way. It's used that way in C/C++ (see your Microsoft C++ link). Actually I cannot find anything in (the latest draft of) the C standard that would allow that. There's no mention of undefined behavior if an assertion is not met with NDEBUG defined. It's clearly defined what the macro should expnd to in that case. Quote (Source: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf): --- The header assert.h defines the assert and static_assert macros and refers to another macro, NDEBUG which is not defined by assert.h. If NDEBUG is defined as a macro name at the point in the source file where assert.h is included, the assert macro is defined simply as #define assert(ignore) ((void)0) The assert macro is redefined according to the current state of NDEBUG each time that assert.h is included. --- And: --- The assert macro puts diagnostic tests into programs; it expands to a void expression. When it is executed, if expression (which shall have a scalar type) is false (that is, compares equal to 0), the assert macro writes information about the particular call that failed (including the text of the argument, the name of the source file, the source line number, and the name of the enclosing function — the latter are respectively the values of the preprocessing macros __FILE__ and __LINE__ and of the identifier __func__) on the standard error stream in an implementation-defined format.191) It then calls the abort function. --- Tobi
Re: assume, assert, enforce, @safe
Walter Bright newshou...@digitalmars.com wrote: 2. The compiler can make use of assert expressions to improve optimization, even in -release mode. I can see the benefits of that, but I consider it very dangerous. It similar to undefined behavior in C/C++. There the 'assume/assert' is implicit not explicit, but it's still the same effect. If the assume/assert is hidden somewhere in a function you basically introduce new traps for UB. Initially I was strong proponent of such optimizations: (a + a)/2 can be optimized to just a for signed integers, that's nice, the classic example. This inserts an implicit assume(a INT_MAX/2). My opinion suddenly changed when I realized that such assumptions (explicit or implicit) can also propagate up/backwards and leak into a bigger context. A wrong assumption can introduce bugs in seemingly unrelated parts of the program that would actually be correct on their own. With relatively 'dumb' compilers, this is not a big problem, but optimizers are more and more clever and will take profit of such assumptions if they can. Tobi
Re: checkedint call removal
Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 7/30/14, 7:55 AM, Tofu Ninja wrote: On Wednesday, 30 July 2014 at 14:51:34 UTC, Andrei Alexandrescu wrote: Also, it's unclear to me what the optimizer would be supposed to do if an assumption turns out to be false. Bad... bad... things... So then I see nothing that assume can do that assert can't. -- Andrei The point is that optimizations based on asserts can have a big impact because they are leaky. By having both, a dangerous assume and a mre harmless assert (that terminates in debug and does nothing in release), the programmer can use assert a lot without many consequences if there's an error. Only if optimizations are really necessary he can use assume, but he can use it with care. It's not that assert is not powerful enough. It too dangerous to be used frequently. Tobi
Re: checkedint call removal
Walter Bright newshou...@digitalmars.com wrote: On 7/30/2014 3:53 PM, Artur Skawina via Digitalmars-d wrote: No, with the assert definition you're proposing, it won't. It would be allowed to optimize away the bounds check. And this is just one of many problems with the assert==assume approach. Please explain how assume would behave any differently. It wouldn't and that's the point. If you have (a more harmless) assert _and_ assume you can still use assert, which would then _not_ allow those optimization. Tobi
Re: opCmp and opEquals woes
Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: It creates very awkward relationships between the suite of operators which is likely to break down in many logical constructs. Doesn't seem that drastic to me. I don't understand; your example is the perfect example of why opCmp==0 should be the default opEquals, but somehow it's an argument against? I have no idea how to reason about this topic.. You yourself seemed to reach for an operator ===. In fact those comparisons you think should exist already exist: what you claim == should be is really !(a b) !(b a) or !opCmp(a, b); and what you think === should be is really ==. I come from a place where ,=,==,!=,=, are a suite, and it is reasonable to assume they all work the same. I think that place is not a good place. That's not a reasonable assumption. Is that not the default presumption of modern programmers? No. Is it really so unlikely that people would make the mistake of assuming they are related? Yes. I also strongly disagree with that. opCmp and opEquals should be separate because only one of them may make sense for a type. But if both make sense they should agree. Of course there exist many possible sorting orders for a type, but the standard comparison operators should always be the natural ones. For other orders you have predicate based sorting. As I understand it, that's also Walters argument why breaking code is ok in that case, because if they don't agree, the code was already buggy in the first place. At very least *I* would be surprised inconsistent comparison operators. And if I wasn't, I still wouldn't implement it like that because I'm sure that someone at some time will be confused by it. Tobi
Re: Integer overflow and underflow semantics?
Marc Schütz schue...@gmx.net wrote: On Sunday, 20 July 2014 at 11:09:45 UTC, Tobias Müller wrote: Marc Schütz schue...@gmx.net wrote: On Saturday, 19 July 2014 at 19:49:24 UTC, Ola Fosheim Grøstad wrote: On Saturday, 19 July 2014 at 08:34:39 UTC, Kagamin wrote: Can't it simply generate code as is? Seems wasteful to spend compilation time on this. Not if you want fast code, consider a template with: if (a.length+M b.length+N) {} then you alias b = a in the template instantiation: if(a.length+M a.length+N){} you want this reduced to: if (MN){ } which can be resolved at compile time. Yes, but that is the optimizer's job. The front-end doesn't need to spend time on it, if the back-end then anyway does the same optimization again. I don't think anyone has said that the frontend does that. I do ;-) This is how I interpret Kagamin's post. Hm I interpreted it the other way round, it's wasteful to spend time for such optimizations, just. But my english is probably not as good as yours. Tobi
Re: Software Assurance Reference Dataset
Andrew Godfrey x...@y.com wrote: 1) A function annotation that means I will call myself recursively, and when I do, I expect the tail recursion optimization. I have seen code which allocates something big on the stack and depends on the optimization. So this intent should be expressible. Wouldn't it be more useful to have a modified/annotated return statement for that? Tail-recursiveness is an implementation detail, for the user of the function it's not really interesting. Except for the fact that it has bounded stack size which is a useful property by itself and not only for tailrecursive functions. Tobi
Re: Integer overflow and underflow semantics?
Marc Schütz schue...@gmx.net wrote: On Saturday, 19 July 2014 at 19:49:24 UTC, Ola Fosheim Grøstad wrote: On Saturday, 19 July 2014 at 08:34:39 UTC, Kagamin wrote: Can't it simply generate code as is? Seems wasteful to spend compilation time on this. Not if you want fast code, consider a template with: if (a.length+M b.length+N) {} then you alias b = a in the template instantiation: if(a.length+M a.length+N){} you want this reduced to: if (MN){ } which can be resolved at compile time. Yes, but that is the optimizer's job. The front-end doesn't need to spend time on it, if the back-end then anyway does the same optimization again. I don't think anyone has said that the frontend does that. But the language semantics forbid such optimizations if overflow is defined as wrapping. If the optimizer respects that is a different chapter, as the experiment with GDC shows. Tobi
Re: LinkedIn Article to be: Why you need to start moving off C/C++ to D, now.
deadalnix deadal...@gmail.com wrote: On Thursday, 17 July 2014 at 19:58:32 UTC, Tobias Müller wrote: IMO manual memory management is quite easy. In 99% of all cases ownership is clear to trivial. But maybe this is just because I usually write C++ and ownership is crucial in C++. Maybe it's more difficult if your accustomed to a GC. Tobi Except that you and I both do a shitton of stupid mistakes when coding all the time. And if you think you don't, you probably do a lot more than I (as being blind to one's own weakness usually don't help improving). I'm well aware of that, otherwise I wouldn't be reading here (and on rust mailing list). I don't want to advertise completely manual memory management, don't get me wrong. But most of the time GC and RC are just overkill because ownership is clear. As a result, even when hat needs to be done is obvious (which it is quite often when it come to memory allocations) mistake will creep in. My point was not that errors cannot happen but more that as you say it hat needs to be done is obvious in most cases. Memory allocation mistake are special. They lead to memory leak (which won't show up in tests, With deterministic memory management they do. Just scan the heap before and after the tests (or a bunch of tests). but only after tue program is long running, which lead to long and annoying debuging experience where you try to analyze the heap and find how the hell you ended up allocating all of this) In my experience memory leaks are seldom a problem. They are easily detected, found and fixed. More difficult to find are false memory leaks, memory that is not needed but still referenced. But those also happen with automatic memory management. or worse, undefined behavior (which typically will cause crashes in unrelated part of the code, leading to even more confusing debuging sessions). Memory corruption is a different beast, those bugs are really hard. But (again IME) memory management is most often not the cause of those. Multithreading issues are much more prominent. As such, automatic memory management has value in itself. It is a safe default. That's for sure. But GC/RC are overkill in most cases. Static verification of ownership is often enough. I understand that manual memory management is often needed, and that is why we need way to escape that and manually manage. And with a little bit of care/encapsulation also quite safe. But again, I don't want to advertise manual memory management, but I just don't agree with the premise that ownership relations are so complex that deallocation becomes unpredictable. Tobi
Re: LinkedIn Article to be: Why you need to start moving off C/C++ to D, now.
Araq rump...@web.de wrote: The paper focusses on RC vs tracing. My point is tracing vs copying is another tradeoff. Here is a marksweep algorithm: - Trace live objects. - For each dead object: Deallocate. Here is a copying GC: - Trace and copy live objects. - There is no deallocation step. The old region is free for further usage. It's more like: - Allocate a new memory region as big as the current one. - Trace live objects and copy them to the new region. - Deallocate old region. Not only are you deallocating in each step, you are also allocating. This only pays off if you use very small and short-living objects such that the deallocation of the whole region is much faster than the deallocation of the (dead) individual objects and you only have to copy a small fraction of the objects. Also be aware that you can only use half of the available (virtual) memory. And if physical memory is low, you have constant swapping due to the copying. Tobi
Re: LinkedIn Article to be: Why you need to start moving off C/C++ to D, now.
Araq rump...@web.de wrote: On Thursday, 17 July 2014 at 15:38:44 UTC, Tobias Müller wrote: Araq rump...@web.de wrote: The paper focusses on RC vs tracing. My point is tracing vs copying is another tradeoff. Here is a marksweep algorithm: - Trace live objects. - For each dead object: Deallocate. Here is a copying GC: - Trace and copy live objects. - There is no deallocation step. The old region is free for further usage. It's more like: ... Your description is still naive and as such your post is more misleading than helpful. My description is naive to get the basic point across, I have no idea what the point of your post is. Since you snipped everything, my points are: 1. There is no deallocation is just plain wrong. 2. The cost of complex object graphs vs simple objects lies in the mark, not in the sweep. mark-copy has no advantage vs. mark sweep in that respect. Same cost applies for RC. 3. The real difference between mark-sweep and mark-copy lies in number of dead objects vs number of live objects. 4. Your comparison with a region allocator is moot, because _really_ just bulk-deallocate, without a mark step. Tobi
Re: LinkedIn Article to be: Why you need to start moving off C/C++ to D, now.
Paulo Pinto pj...@progtools.org wrote: On Tuesday, 15 July 2014 at 21:11:24 UTC, John Colvin wrote: I've been wondering about this. Could the following argument be true? Situations where automatic memory management are necessary are, by definition, the situations where one cannot easily reason about where memory freeing can occur. My experience is completely different: 1. Shared ownership is rarely necessary. 2. Where is is necessary, deallocation often happens at the same (or a few similar) _code_ location, just the actual _object_ that triggers deallocation is different at runtime. Therefore, no automatic memory management system can be considered practically predictable, unless you didn't* need it in the first place. *strictly speaking Which happens all the time in any codebase written by more than one developer. Developer attrition and third party libraries help to the entropy of memory leak bugs. Personally, I don't believe anyone is able to reason properly about manual memory management, unless they wrote 100% of their code, and don't work in more than one codebase. IMO manual memory management is quite easy. In 99% of all cases ownership is clear to trivial. But maybe this is just because I usually write C++ and ownership is crucial in C++. Maybe it's more difficult if your accustomed to a GC. Tobi
Re: LinkedIn Article to be: Why you need to start moving off C/C++ to D, now.
deadalnix deadal...@gmail.com wrote: On Thursday, 17 July 2014 at 19:19:40 UTC, Tobias Müller wrote: 1. There is no deallocation is just plain wrong. It is actually fairly common to not deallocate and reuse the pool for later allocations. If by deallocation you mean returning the memory to the OS, then yes. But the same holds for 'free' in C. Marking a memory region as free for reuse _is_ deallocation IMO. I guess it's a terminology thing. Also, it doesn't matter as the complexity of deallocation doesn't depend on the size of the block deallocated. In the case of a copying collector, the deallocation won't even show up in benchmark as tracing and copying will dominate CPU time by a LOT ! Yes that's what I said, bulk deallocation is cheap. Got snipped away unfortunately. Tobi
Re: DIP61: Add namespaces to D
Walter Bright newshou...@digitalmars.com wrote: On 4/26/2014 12:27 PM, Daniel Murphy wrote: We already have a feature to manage conflicts and organisation in D code - modules! True. But what D doesn't have is a global namespace. I don't propose one for D, but C++ symbols may appear in the C++ global namespace, or in a C++ namespace. So using D modules to represent C++ namespaces has a problem. But C++ namespaces and D modules don't have to match at all. You can import any C++ function from an arbitrary namespace into any D module, just as you like. Also, I guess there is a reason, why D doesn't have a global module. Tobi
Re: DIP61: Add namespaces to D
Walter Bright newshou...@digitalmars.com wrote: On 4/26/2014 4:01 AM, Mike wrote: pragma(cpp_namespace, A.B) extern(C++) void f() {} This implies that it only affects the name mangling. There needs to be a scope created, too. I think that's the crucial point here. Most people that disagree with your proposal disagree exactly with that. Scope should be created by modules and only modules. Tobi