digitalmars.D - Interested in D, spec confuses me.
- Bambi (41/41) Feb 02 2016 I have to disclaim that I am not a very good programmer, and I am
- Jacob Carlborg (45/69) Feb 02 2016 "const" is like a read-only view of data.
- jmh530 (2/3) Feb 02 2016 Does it make sense to add any of this to the spec?
- Daniel Kozak via Digitalmars-d (3/7) Feb 02 2016 Everything is there already
- jmh530 (3/4) Feb 02 2016 Sure, but - as this post illustrates - there are clearly sections
- Jacob Carlborg (9/11) Feb 02 2016 I think the spec on "extern" [1][2] is pretty clear. I think the
- Era Scarecrow (6/9) Feb 02 2016 It's sorta why i don't refer to the spec to see how the language
- anonymous (12/16) Feb 02 2016 "immutable" is not a homonym here. It means the same thing ("cannot ever...
- Bambi (11/22) Feb 02 2016 Making the return value immutable is a very different thing from
- Steven Schveighoffer (13/35) Feb 02 2016 Technically, it doesn't *make* it immutable, it is just an overload that...
- anonymous (12/17) Feb 02 2016 Sure it's a different thing, but the meaning of "immutable" is the same.
- H. S. Teoh via Digitalmars-d (7/14) Feb 02 2016 Another way to think about it, is that the "immutable" on the function
- IceCreamEater (4/17) Feb 02 2016 I thought immutable was added to the language as a better
- Chris Wright (12/32) Feb 02 2016 D1 const (and up to about D2.007) was, if I recall, strictly for compile...
- H. S. Teoh via Digitalmars-d (65/86) Feb 02 2016 You're misunderstanding D's type system. Immutable is not a "better
- bubbasaur (20/29) Feb 02 2016 Ok, but what would differ using immutable instead of const in
- =?UTF-8?Q?Ali_=c3=87ehreli?= (17/28) Feb 02 2016 I cannot trust that a member of 'd' will not be modified later on. So, I...
- bubbasaur (4/8) Feb 02 2016 Well this explanation on the matter was simple, solid and
- Dicebot (6/24) Feb 02 2016 Casting immutable and violating it is undefined behavior and once you do
- bubbasaur (11/18) Feb 02 2016 Well if anything bad happen it will mess with dpaste. :)
- =?UTF-8?Q?Ali_=c3=87ehreli?= (6/8) Feb 02 2016 That table has a bunch of check marks, which happens to be a Unicode
- Jack Stouffer (5/9) Feb 02 2016 Works for me. Something isn't loading properly for you. If you
- bubbasaur (7/11) Feb 02 2016 I just have Ublock Origin here, I tried dev-tools on chrome and
- =?UTF-8?Q?Ali_=c3=87ehreli?= (3/12) Feb 02 2016 Yay! Now assume that those empty boxes are check marks. :)
- Kagamin (2/5) Feb 03 2016 DMD performs some immutable optimizations and people noticed it.
- Chris Wright (10/13) Feb 02 2016 const opens up optimizations at the call site, so it's useful. immutable...
- Steven Schveighoffer (8/19) Feb 03 2016 This isn't exactly right. If I call a function with "hello", I'd want it...
- Chris Wright (10/29) Feb 03 2016 In the general case, yes.
- Bambi (14/75) Feb 03 2016 In C90+, const can apply to both values and pointers to those
- Kagamin (6/9) Feb 03 2016 Immutablity provides stronger guarantee that allows more
- Bambi (7/12) Feb 03 2016 In C, you can only make pointers to const data a const pointer.
- Kagamin (6/8) Feb 03 2016 const data in C can be immutable, but also can be mutable and
- Era Scarecrow (11/19) Feb 04 2016 I tend to take away the meanings in D:
- Kagamin (5/5) Feb 03 2016 Another nice property of immutable data is that it can be safely
- H. S. Teoh via Digitalmars-d (31/49) Feb 02 2016 [...]
- Kagamin (19/27) Feb 03 2016 The idea was to ease porting C code to D, so many things work the
I have to disclaim that I am not a very good programmer, and I am doing this on a hobby level. I'm reading through the spec because D seems to be a very without the syntactical mess of C++. A few things confuse me a lot. 1. const isn't constant To my mind, a const is a value that cannot change from the moment it is defined. But D allows for modification of const values through non-const references and pointers, and does not promise to optimize const by placing it in read only memory or similar. Instead, it provides immutable, which does promise an constant value throughout the lifetime of the value. I'm not sure why this distinction was created, or what const is supposed to accomplish here. It's just very confusing to have two keywords that intuitively do the same thing but don't really. Applying these keywords to methods would seem to make the data of the parent object immutable to only the function. Which might be useful but isn't immediately obvious from the written form. The example snippet ' immutable(int[]) bar() immutable {} ' brings back bad memories of redundant declarations of the style ' Object object = new Object(); '. And homonyms in programming languages seem like a bad idea in general. 2. when is an extern an extern? The wiki page on interfacing with C states that C globals require an extra extern. The extern definition in the spec clarifies that extern(C) alone will copy the global into the current module, but that extern extern(C) will read it right from the C code. Or maybe it means to say that using extern(C) alone will only specify a different calling convention for the variable you are declaring. It's honestly not clear. Homonym problem again. 3. typeof is an operator, sizeof is a property ...but not really :^). It seems like these are similar, they give compile time information about the object you pass them, but one is implemented as a function-looking operator in the classic C style while another is trying to mimic member access. It lacks consistency. And confuses as to what is a member and what isn't. Let the period operator be reserved for real member access and other operators be their own thing. That's all for now. I don't really understand these choices. They seem to only confuse rather than clarify.
Feb 02 2016
On 2016-02-02 15:36, Bambi wrote:1. const isn't constant To my mind, a const is a value that cannot change from the moment it is defined. But D allows for modification of const values through non-const references and pointers, and does not promise to optimize const by placing it in read only memory or similar. Instead, it provides immutable, which does promise an constant value throughout the lifetime of the value. I'm not sure why this distinction was created, or what const is supposed to accomplish here. It's just very confusing to have two keywords that intuitively do the same thing but don't really. Applying these keywords to methods would seem to make the data of the parent object immutable to only the function. Which might be useful but isn't immediately obvious from the written form."const" is like a read-only view of data. int a = 3; const(int*) b = &a; assert(*b == 3); a = 4; assert(*b == 4); *b = 5; // Error: cannot modify const expression *b "const" also acts like a super set of immutable and mutable data: const(int*) a = new int; immutable(int)* b = new int; int* c = new int; foo(a); foo(b); foo(c); void foo(const(int*) a) {} That would mean that "foo" will not change "a" regardless of if the original data is immutable, const or mutable.The example snippet ' immutable(int[]) bar() immutable {} ' brings back bad memories of redundant declarations of the style ' Object object = new Object(); '. And homonyms in programming languages seem like a bad idea in general.The first immutable means that "bar" returns an immutable array of ints. The second immutable means that "bar" cannot modify the "this" reference: class Foo { int a = 3; void bar() immutable { a = 4; // Error: cannot modify immutable expression this.a } }2. when is an extern an extern? The wiki page on interfacing with C states that C globals require an extra extern. The extern definition in the spec clarifies that extern(C) alone will copy the global into the current module, but that extern extern(C) will read it right from the C code. Or maybe it means to say that using extern(C) alone will only specify a different calling convention for the variable you are declaring. It's honestly not clear. Homonym problem again."extern(C)" means C linkage and calling conventions. "extern" means that a symbol is defined in another object file. extern (C) int foo; Compiling that and running the "nm" command to print the symbols will list "foo": 00000000000000d0 S _foo Adding "extern" and doing the same: extern(C) extern int foo; Will result in this output: U _foo That means "foo" is undefined. That is, the linker needs to find that symbol in some other library. If you create bindings to a C library, you would use "extern(C) extern". If you create a library in D that some C code should access you would use "extern(C)"., -- /Jacob Carlborg
Feb 02 2016
On Tuesday, 2 February 2016 at 15:21:29 UTC, Jacob Carlborg wrote:[snip]Does it make sense to add any of this to the spec?
Feb 02 2016
Everything is there already Dne 2. 2. 2016 17:15 napsal u=C5=BEivatel "jmh530 via Digitalmars-d" < digitalmars-d puremagic.com>:On Tuesday, 2 February 2016 at 15:21:29 UTC, Jacob Carlborg wrote:[snip]Does it make sense to add any of this to the spec?
Feb 02 2016
On Tuesday, 2 February 2016 at 16:23:01 UTC, Daniel Kozak wrote:Everything is there alreadySure, but - as this post illustrates - there are clearly sections of the spec that could have their explanations improved.
Feb 02 2016
On 2016-02-02 17:41, jmh530 wrote:Sure, but - as this post illustrates - there are clearly sections of the spec that could have their explanations improved.I think the spec on "extern" [1][2] is pretty clear. I think the explanation of "const" and "immutable" [3] is clear as well. All of the sections have examples as well. [1] http://dlang.org/spec/declaration.html#extern [2] http://dlang.org/spec/attribute.html#linkage [3] http://dlang.org/spec/const3.html -- /Jacob Carlborg
Feb 02 2016
On Tuesday, 2 February 2016 at 16:41:54 UTC, jmh530 wrote:Sure, but - as this post illustrates - there are clearly sections of the spec that could have their explanations improved.It's sorta why i don't refer to the spec to see how the language currently works, and instead refer to the D book that's the baseline for the D2 standard; even if it's incredibly out of date. Too much of the spec from when i glanced at it felt like i was reading a lexx/yacc definition, which is a total turn-off.
Feb 02 2016
On 02.02.2016 15:36, Bambi wrote:The example snippet ' immutable(int[]) bar() immutable {} ' brings back bad memories of redundant declarations of the style ' Object object = new Object(); '. And homonyms in programming languages seem like a bad idea in general."immutable" is not a homonym here. It means the same thing ("cannot ever change"). And it's not redundant either, as the two instances apply to different targets. It's clear what the first "immutable" ties to: It qualifies the return type. The second one is less clear: It qualifies the type of the object, meaning the method can only be called on an immutable object. Leaving either of them out changes the meaning of the signature: `int[] bar() immutable {}` - Return type is mutable now. `immutable(int[]) bar() {}` - Object type is mutable now. I.e., this method can be called on a mutable object, and it cannot be called on an immutable object.
Feb 02 2016
On Tuesday, 2 February 2016 at 15:48:02 UTC, anonymous wrote:"immutable" is not a homonym here. It means the same thing ("cannot ever change"). And it's not redundant either, as the two instances apply to different targets. It's clear what the first "immutable" ties to: It qualifies the return type. The second one is less clear: It qualifies the type of the object, meaning the method can only be called on an immutable object. Leaving either of them out changes the meaning of the signature: `int[] bar() immutable {}` - Return type is mutable now. `immutable(int[]) bar() {}` - Object type is mutable now. I.e., this method can be called on a mutable object, and it cannot be called on an immutable object.Making the return value immutable is a very different thing from making every value of the object immutable to the method alone. These are different meanings. It reads like a redundancy but has different meanings. This isn't good in my eyes. Also it's not so much an issue of clarification - well, the extern one is, I genuinely didn't understand what the documentation meant - but it is an issue of the design choices not making much sense to me. These just stand out to me as unnecessarily confusing and obscure in an otherwise nice and clear language.
Feb 02 2016
On 2/2/16 2:50 PM, Bambi wrote:On Tuesday, 2 February 2016 at 15:48:02 UTC, anonymous wrote:Technically, it doesn't *make* it immutable, it is just an overload that accepts an immutable object. I like to think of a method like this: immutable(int)[] bar() immutable as a function that looks like this: immutable(int)[] bar(immutable(Object) this) If you tried to call this method on a mutable object, and there wasn't a mutable overload (i.e. without an attribute), the call would fail."immutable" is not a homonym here. It means the same thing ("cannot ever change"). And it's not redundant either, as the two instances apply to different targets. It's clear what the first "immutable" ties to: It qualifies the return type. The second one is less clear: It qualifies the type of the object, meaning the method can only be called on an immutable object. Leaving either of them out changes the meaning of the signature: `int[] bar() immutable {}` - Return type is mutable now. `immutable(int[]) bar() {}` - Object type is mutable now. I.e., this method can be called on a mutable object, and it cannot be called on an immutable object.Making the return value immutable is a very different thing from making every value of the object immutable to the method alone. These are different meanings. It reads like a redundancy but has different meanings. This isn't good in my eyes.Also it's not so much an issue of clarification - well, the extern one is, I genuinely didn't understand what the documentation meant - but it is an issue of the design choices not making much sense to me. These just stand out to me as unnecessarily confusing and obscure in an otherwise nice and clear language.A lot of things in D come from C++. This is how C++ specifies const methods. The purpose is to be familiar to C++ developers, and to make porting easier. This means it can look confusing as not all C/C++ decisions were the best. However, this one I happen to like -- I can't think of a better way. -Steve
Feb 02 2016
On 02.02.2016 20:50, Bambi wrote:Making the return value immutable is a very different thing from making every value of the object immutable to the method alone.Sure it's a different thing, but the meaning of "immutable" is the same. By the way, it's not that the object's fields are made immutable for the method, but the method can only be called on immutable objects.These are different meanings. It reads like a redundancy but has different meanings. This isn't good in my eyes.I don't see how it reads like a redundancy. Surely, you don't expect a redundancy in this: void f(immutable int[] a, immutable int[] b); The other signature is no different. Two occurrences of "immutable", applying to two different things. I agree that it can be unclear to newbies what exactly is immutable when a method is marked immutable, but the meaning of the keyword is the same as elsewhere. Using another word there would be more confusing.
Feb 02 2016
On Tue, Feb 02, 2016 at 09:13:41PM +0100, anonymous via Digitalmars-d wrote: [...]The other signature is no different. Two occurrences of "immutable", applying to two different things. I agree that it can be unclear to newbies what exactly is immutable when a method is marked immutable, but the meaning of the keyword is the same as elsewhere. Using another word there would be more confusing.Another way to think about it, is that the "immutable" on the function means that the implicit `this` reference to the object is immutable. T -- "How are you doing?" "Doing what?"
Feb 02 2016
On Tuesday, 2 February 2016 at 20:17:20 UTC, H. S. Teoh wrote:On Tue, Feb 02, 2016 at 09:13:41PM +0100, anonymous via Digitalmars-d wrote: [...]I thought immutable was added to the language as a better guarantee to 'const'. Which really tells me const wasn't cutting it and wasn't a proper guarantee.The other signature is no different. Two occurrences of "immutable", applying to two different things. I agree that it can be unclear to newbies what exactly is immutable when a method is marked immutable, but the meaning of the keyword is the same as elsewhere. Using another word there would be more confusing.Another way to think about it, is that the "immutable" on the function means that the implicit `this` reference to the object is immutable. T
Feb 02 2016
On Tue, 02 Feb 2016 21:35:13 +0000, IceCreamEater wrote:On Tuesday, 2 February 2016 at 20:17:20 UTC, H. S. Teoh wrote:D1 const (and up to about D2.007) was, if I recall, strictly for compile- time constants. When designing immutable, Bartosz and Walter realized that many functions don't care whether their parameters are mutable by anyone or not. For instance, the 'find' function in std.array -- it's not mutating the array, but it should be usable on mutable arrays. So we got const, where all values implicitly cast to const. Functions promise not to modify anything marked const, so it's always safe to submit immutable values. They don't get access to potential optimizations available with immutable objects, which means they're safe for mutable values.On Tue, Feb 02, 2016 at 09:13:41PM +0100, anonymous via Digitalmars-d wrote: [...]I thought immutable was added to the language as a better guarantee to 'const'. Which really tells me const wasn't cutting it and wasn't a proper guarantee.The other signature is no different. Two occurrences of "immutable", applying to two different things. I agree that it can be unclear to newbies what exactly is immutable when a method is marked immutable, but the meaning of the keyword is the same as elsewhere. Using another word there would be more confusing.Another way to think about it, is that the "immutable" on the function means that the implicit `this` reference to the object is immutable. T
Feb 02 2016
On Tue, Feb 02, 2016 at 09:35:13PM +0000, IceCreamEater via Digitalmars-d wrote:On Tuesday, 2 February 2016 at 20:17:20 UTC, H. S. Teoh wrote:You're misunderstanding D's type system. Immutable is not a "better const", as though const is somehow defective. Perhaps the following diagram may help to clear things up: const / \ (mutable) immutable What this means is that both mutable and immutable are implicitly convertible to const. Or, to put it another way, const is a kind of "wildcard" that can point to underlying data that's either mutable or immutable. Mutable data is, well, mutable -- anybody who can get to it, can modify it. Immutable means *nobody* can modify it once it's initialized. Why const, then? Const is useful for when a function doesn't care whether the underlying data is mutable or not, because it doesn't need to change the data. Const provides guarantees to the caller that the function won't touch the data -- even if the data is actually mutable in the caller's context. It's a "no-mutation view" on data that's possibly mutable by a third party. Furthermore, since const provides actual guarantees that the called function isn't going to touch the data, this opens up optimization opportunities for the compiler. E.g., it can assume that any part(s) of the data that are held in registers will remain valid after the function call (provided said registers aren't touched by the function), so it doesn't need to issue another load after the function returns. As a contrived example, say you have code like this: struct Data { int x; } int func1(Data* d) { ... } int func2(const(Data)* d) { ... } ... void main() { Data d; int value1 = d.x*func1(&d) + d.x; int value2 = d.x*func2(&d) + d.x; d.x++; } When evaluating value1, the compiler may have issued a load for the first occurrence of d.x, then it calls func1. But since func1 may modify d.x, the second d.x needs another load in order to ensure the correct value is used. When evaluating value2, however, since func2 takes a const pointer to the Data, the compiler knows the value of d.x cannot possibly change across that function call, so it can safely reuse the value of d.x that was previously loaded. It may also go further and refactor the expression as d.x*(func2(&d) + 1), because the const guarantees that func2 can't mutate d.x behind our backs and invalidate the result. Such a refactoring is invalid with func1, because there is no guarantee that d.x will have the same value after func1 returns. Now, the same argument applies if immutable was used in place of const. However, the last line in main() illustrates why we need const rather than immutable in this case: we actually *want* to modify d.x in main(). We just don't want func2 to touch anything. So we can't use immutable -- since immutable means *nobody* can touch the data. So, const provides both the guarantee that func2 won't touch the data, thus allowing the aforementioned optimization, and also continues to let main() mutate the data at its leisure. As an added benefit, you can also call func2 with immutable Data: you know it's safe, because even though func2 doesn't require immutability, it also guarantees that it won't touch the data. So you don't need to write two copies of func2, one to work with mutable data and one to work with immutable data. This is why both mutable and immutable can implicitly cast to const. T -- He who does not appreciate the beauty of language is not worthy to bemoan its flaws.On Tue, Feb 02, 2016 at 09:13:41PM +0100, anonymous via Digitalmars-d wrote: [...]I thought immutable was added to the language as a better guarantee to 'const'. Which really tells me const wasn't cutting it and wasn't a proper guarantee.The other signature is no different. Two occurrences of "immutable", applying to two different things. I agree that it can be unclear to newbies what exactly is immutable when a method is marked immutable, but the meaning of the keyword is the same as elsewhere. Using another word there would be more confusing.Another way to think about it, is that the "immutable" on the function means that the implicit `this` reference to the object is immutable. T
Feb 02 2016
On Tuesday, 2 February 2016 at 23:41:07 UTC, H. S. Teoh wrote:Now, the same argument applies if immutable was used in place of const. However, the last line in main() illustrates why we need const rather than immutable in this case: we actually *want* to modify d.x in main(). We just don't want func2 to touch anything. So we can't use immutable -- since immutable means *nobody* can touch the data. So, const provides both the guarantee that func2 won't touch the data, thus allowing the aforementioned optimization, and also continues to let main() mutate the data at its leisure.Ok, but what would differ using immutable instead of const in your example (AS ARGUMENTS)? See: import std.stdio; struct Data { int x; } auto func1(Data* d) { return d.x; } auto func2(const(Data)* d) { return d.x; } auto func3(immutable(Data)* d) { return d.x; } void main() { Data d; auto value1 = d.x*func1(&d) + d.x; auto value2 = d.x*func2(&d) + d.x; auto value3 = d.x*func3(cast(immutable)&d) + d.x; d.x++; writeln(d.x++); } Functions 2 and 3 are acting in the same way and different from what you said I can change the d.x in main. Bubba.
Feb 02 2016
On 02/02/2016 04:31 PM, bubbasaur wrote:Ok, but what would differ using immutable instead of const in your example (AS ARGUMENTS)? See: import std.stdio; struct Data { int x; } auto func1(Data* d) { return d.x; } auto func2(const(Data)* d) { return d.x; }I cannot trust that a member of 'd' will not be modified later on. So, I cannot store 'd' as is. If I want to make use of its current state later, I must make a copy of it (which may have its own member-with-inderection issues). In short, the promise of "I will not change members of 'd'" is not related to what can happen to that date by other parts of the code.auto func3(immutable(Data)* d) { return d.x; }There, I know that 'd' will not change state. I can store it somewhere for later use; no need to copy. I can even pass it to a thread without needing a lock.auto value2 = d.x*func2(&d) + d.x; auto value3 = d.x*func3(cast(immutable)&d) + d.x;That's not very nice because we've just fooled func3(). :) Although it required immutable data, we've given it mutable data. The programmer is on his or her own at that point. We hope the program will work correctly. :)Functions 2 and 3 are acting in the same wayI like this explanation: - A const parameter is a promise by the callee to not modify - An immutable parameter is a requirement for the caller to never modify Ali
Feb 02 2016
On Wednesday, 3 February 2016 at 00:41:31 UTC, Ali Çehreli wrote:I like this explanation: - A const parameter is a promise by the callee to not modify - An immutable parameter is a requirement for the caller to never modifyWell this explanation on the matter was simple, solid and comprehensive enough. Bubba.
Feb 02 2016
On 02/03/2016 02:31 AM, bubbasaur wrote:import std.stdio; struct Data { int x; } auto func1(Data* d) { return d.x; } auto func2(const(Data)* d) { return d.x; } auto func3(immutable(Data)* d) { return d.x; } void main() { Data d; auto value1 = d.x*func1(&d) + d.x; auto value2 = d.x*func2(&d) + d.x; auto value3 = d.x*func3(cast(immutable)&d) + d.x; d.x++; writeln(d.x++); } Functions 2 and 3 are acting in the same way and different from what you said I can change the d.x in main.Casting immutable and violating it is undefined behavior and once you do it all bets are off - compiler is even allowed to attempt formatting your hard drive when compiling this program :) The fact DMD doesn't do anything scary right now when you do it is a mere coincidence and may change in any release with no notice.
Feb 02 2016
On Wednesday, 3 February 2016 at 00:43:36 UTC, Dicebot wrote:Casting immutable and violating it is undefined behavior and once you do it all bets are off - compiler is even allowed to attempt formatting your hard drive when compiling this program :) The fact DMD doesn't do anything scary right now when you do it is a mere coincidence and may change in any release with no notice.Well if anything bad happen it will mess with dpaste. :) By the way, now you and Ali are saying this isn't correct, so I took a look on this page: http://dlang.org/spec/const3.html And looking on the bottom: "Implicit Conversions" - I wonder, is this page missing something or what? Look what I'm seeing right now: http://i.imgur.com/L4a6bx6.png It shouldn't be some circles or crosses showing the conversion on that table? Bubba.
Feb 02 2016
On 02/02/2016 04:56 PM, bubbasaur wrote:I took a look on this page: http://dlang.org/spec/const3.htmlThat table has a bunch of check marks, which happens to be a Unicode character: ✔. It looks like a font issue. Perhaps we should update that page and use a more available character like 'x'. :p Ali
Feb 02 2016
On Wednesday, 3 February 2016 at 00:56:41 UTC, bubbasaur wrote:http://i.imgur.com/L4a6bx6.png It shouldn't be some circles or crosses showing the conversion on that table? Bubba.Works for me. Something isn't loading properly for you. If you have any plugins, try disabling them to see if that helps. If that isn't it, hit alt-super-j if you're on chrome and paste here what it says there.
Feb 02 2016
On Wednesday, 3 February 2016 at 02:00:09 UTC, Jack Stouffer wrote:Works for me. Something isn't loading properly for you. If you have any plugins, try disabling them to see if that helps. If that isn't it, hit alt-super-j if you're on chrome and paste here what it says there.I just have Ublock Origin here, I tried dev-tools on chrome and there are NO errors or anything, them I changed the Font family from "ROBOT SLAB" to "SAN SERIF" and this is what I got: http://i.imgur.com/zuaLXx0.png Bubba.
Feb 02 2016
On 02/02/2016 06:14 PM, bubbasaur wrote:On Wednesday, 3 February 2016 at 02:00:09 UTC, Jack Stouffer wrote:Yay! Now assume that those empty boxes are check marks. :) AliWorks for me. Something isn't loading properly for you. If you have any plugins, try disabling them to see if that helps. If that isn't it, hit alt-super-j if you're on chrome and paste here what it says there.I just have Ublock Origin here, I tried dev-tools on chrome and there are NO errors or anything, them I changed the Font family from "ROBOT SLAB" to "SAN SERIF" and this is what I got: http://i.imgur.com/zuaLXx0.png Bubba.
Feb 02 2016
On Wednesday, 3 February 2016 at 00:43:36 UTC, Dicebot wrote:The fact DMD doesn't do anything scary right now when you do it is a mere coincidence and may change in any release with no notice.DMD performs some immutable optimizations and people noticed it.
Feb 03 2016
On Tue, 02 Feb 2016 15:41:07 -0800, H. S. Teoh via Digitalmars-d wrote:Furthermore, since const provides actual guarantees that the called function isn't going to touch the data, this opens up optimization opportunities for the compiler.const opens up optimizations at the call site, so it's useful. immutable is useful on top of const because it allows optimizations within the function. Want to memoize a function? If it takes const(char[]), you have to copy your input and later check the entire array to see if the parameters match a previous call. If it takes an immutable(char[]), you can compare pointers. Do you need to acquire a lock to read this data? If it's immutable, no, you don't.
Feb 02 2016
On 2/2/16 8:42 PM, Chris Wright wrote:On Tue, 02 Feb 2016 15:41:07 -0800, H. S. Teoh via Digitalmars-d wrote:This isn't exactly right. If I call a function with "hello", I'd want it to memoize if the function is called with "hello" that resides elsewhere. What *is* true is that you can safely save the array (pointer + len) of "hello" and be sure it won't change when you check against it later. With const(char[]), you'd need to allocate a new block to make sure it doesn't change. -SteveFurthermore, since const provides actual guarantees that the called function isn't going to touch the data, this opens up optimization opportunities for the compiler.const opens up optimizations at the call site, so it's useful. immutable is useful on top of const because it allows optimizations within the function. Want to memoize a function? If it takes const(char[]), you have to copy your input and later check the entire array to see if the parameters match a previous call. If it takes an immutable(char[]), you can compare pointers.
Feb 03 2016
On Wed, 03 Feb 2016 09:29:30 -0500, Steven Schveighoffer wrote:On 2/2/16 8:42 PM, Chris Wright wrote:In the general case, yes. It's much faster to look up a pointer/length pair in a hashtable than to look up a very long string, so if you expect long strings and many calls with the same addresses, you might have a fast cache by pointer. You might also have values that are automatically generated, and you're relatively certain that it will be rare to have duplicate values. Or you might have a complex data structure that's immutable and has an id and a revision. If you know for certain that id+revision is unique, you can memoize based on that, and immutable gives you some extra protection.On Tue, 02 Feb 2016 15:41:07 -0800, H. S. Teoh via Digitalmars-d wrote:This isn't exactly right. If I call a function with "hello", I'd want it to memoize if the function is called with "hello" that resides elsewhere.Furthermore, since const provides actual guarantees that the called function isn't going to touch the data, this opens up optimization opportunities for the compiler.const opens up optimizations at the call site, so it's useful. immutable is useful on top of const because it allows optimizations within the function. Want to memoize a function? If it takes const(char[]), you have to copy your input and later check the entire array to see if the parameters match a previous call. If it takes an immutable(char[]), you can compare pointers.
Feb 03 2016
On Tuesday, 2 February 2016 at 23:41:07 UTC, H. S. Teoh wrote:You're misunderstanding D's type system. Immutable is not a "better const", as though const is somehow defective. Perhaps the following diagram may help to clear things up: const / \ (mutable) immutable What this means is that both mutable and immutable are implicitly convertible to const. Or, to put it another way, const is a kind of "wildcard" that can point to underlying data that's either mutable or immutable. Mutable data is, well, mutable -- anybody who can get to it, can modify it. Immutable means *nobody* can modify it once it's initialized. Why const, then? Const is useful for when a function doesn't care whether the underlying data is mutable or not, because it doesn't need to change the data. Const provides guarantees to the caller that the function won't touch the data -- even if the data is actually mutable in the caller's context. It's a "no-mutation view" on data that's possibly mutable by a third party. Furthermore, since const provides actual guarantees that the called function isn't going to touch the data, this opens up optimization opportunities for the compiler. E.g., it can assume that any part(s) of the data that are held in registers will remain valid after the function call (provided said registers aren't touched by the function), so it doesn't need to issue another load after the function returns. As a contrived example, say you have code like this: struct Data { int x; } int func1(Data* d) { ... } int func2(const(Data)* d) { ... } ... void main() { Data d; int value1 = d.x*func1(&d) + d.x; int value2 = d.x*func2(&d) + d.x; d.x++; } When evaluating value1, the compiler may have issued a load for the first occurrence of d.x, then it calls func1. But since func1 may modify d.x, the second d.x needs another load in order to ensure the correct value is used. When evaluating value2, however, since func2 takes a const pointer to the Data, the compiler knows the value of d.x cannot possibly change across that function call, so it can safely reuse the value of d.x that was previously loaded. It may also go further and refactor the expression as d.x*(func2(&d) + 1), because the const guarantees that func2 can't mutate d.x behind our backs and invalidate the result. Such a refactoring is invalid with func1, because there is no guarantee that d.x will have the same value after func1 returns. Now, the same argument applies if immutable was used in place of const. However, the last line in main() illustrates why we need const rather than immutable in this case: we actually *want* to modify d.x in main(). We just don't want func2 to touch anything. So we can't use immutable -- since immutable means *nobody* can touch the data. So, const provides both the guarantee that func2 won't touch the data, thus allowing the aforementioned optimization, and also continues to let main() mutate the data at its leisure. TIn C90+, const can apply to both values and pointers to those values. And since pointers are themselves values of a memory address that is consistent usage. That seems to be the only meaningful distinction here. Pointing to a const value makes the pointer mutable but the value immutable. Pointing a const to a value makes the pointer immutable but the value mutable. etc. Immutable accomplishes nothing distinct here that I can see, other than making the use of const confusing. To make a function not change a value you declare a const input. Because it is the value declared in the function definition that is a const, not the value you pass it. "Passing as const" doesn't make any logical sense. To be honest, it smells like the kind of opaque cleverness D is ostensibly supposed to obviate.
Feb 03 2016
On Wednesday, 3 February 2016 at 11:38:06 UTC, Bambi wrote:Immutable accomplishes nothing distinct here that I can see, other than making the use of const confusing. To make a function not change a value you declare a const input.Immutablity provides stronger guarantee that allows more optimizations, e.g. reading the same immutable value is known to result in the same value so such repeated reading can be optimized out, in C such optimization is illegal, because const data can change over time.
Feb 03 2016
On Wednesday, 3 February 2016 at 12:12:03 UTC, Kagamin wrote:Immutability provides stronger guarantee that allows more optimizations, e.g. reading the same immutable value is known to result in the same value so such repeated reading can be optimized out, in C such optimization is illegal, because const data can change over time.In C, you can only make pointers to const data a const pointer. The guarantee is built in there. Sure you can cast the address of a const to a regular pointer but then you are kind of going out of your way to break the rules and deliberately shoot yourself in the foot. I'm pretty sure casting away a const pointer to a const value is undefined behaviour.
Feb 03 2016
On Wednesday, 3 February 2016 at 20:30:01 UTC, Bambi wrote:I'm pretty sure casting away a const pointer to a const value is undefined behaviour.const data in C can be immutable, but also can be mutable and change over time, that's why immutable optimizations are illegal on it: you can't tell if it's immutable, the const qualifier tells nothing about that, it only helps the callee to not modify the data.
Feb 03 2016
On Thursday, 4 February 2016 at 06:34:15 UTC, Kagamin wrote:On Wednesday, 3 February 2016 at 20:30:01 UTC, Bambi wrote:I tend to take away the meanings in D: Immutable: This data Cannot/Will not change Const: I promise not to change your data on you (but the owner might make changes to it at some point) So converting a const pointer to a const value... it still remains const (and it's value doesn't/won't change if const is honored). You could throw away the constness; This assumes that it doesn't have referenced data/pointers and you're editing only a local copy (or duplicated it first); But that's it's own thing to discuss.I'm pretty sure casting away a const pointer to a const value is undefined behaviour.const data in C can be immutable, but also can be mutable and change over time, that's why immutable optimizations are illegal on it: you can't tell if it's immutable, the const qualifier tells nothing about that, it only helps the callee to not modify the data.
Feb 04 2016
Another nice property of immutable data is that it can be safely shared between threads: const data that is a readonly view into changing mutable data may require locking to get consistent view of data; immutable data doesn't require locking, since it doesn't change.
Feb 03 2016
On Tue, Feb 02, 2016 at 07:50:57PM +0000, Bambi via Digitalmars-d wrote:On Tuesday, 2 February 2016 at 15:48:02 UTC, anonymous wrote:[...] It's an unfortunate historical accident that function attributes can easily be conflated with return type attributes. Different people have pushed for prohibiting (apparently) ambiguous cases, but so far Walter has been resistant to the idea. Because of this, my own recommendation is to always use parenthesis when writing type qualifiers, and always write function attributes on the right rather than on the left: struct S { // Do write: immutable(int) func() { ... } int func() immutable { ... } immutable(int) func() immutable { ... } // Don't write: immutable int func() { ... } immutable immutable int func() { ... } // may not compile } I'd even recommend using parenthesis in variable declarations, just for consistency's sake: // Do write: immutable(int) x; // Don't write: immutable int x; Even though the two are identical, I think it's better to always write parentheses so that you get into the habit of thinking of the type in terms of parentheses, and don't get confused when you encounter ambiguous cases (or at least you'll be on the alert when parentheses are absent, and be sure read the function signature more carefully). T -- Debian GNU/Linux: Cray on your desktop."immutable" is not a homonym here. It means the same thing ("cannot ever change"). And it's not redundant either, as the two instances apply to different targets. It's clear what the first "immutable" ties to: It qualifies the return type. The second one is less clear: It qualifies the type of the object, meaning the method can only be called on an immutable object. Leaving either of them out changes the meaning of the signature: `int[] bar() immutable {}` - Return type is mutable now. `immutable(int[]) bar() {}` - Object type is mutable now. I.e., this method can be called on a mutable object, and it cannot be called on an immutable object.Making the return value immutable is a very different thing from making every value of the object immutable to the method alone. These are different meanings. It reads like a redundancy but has different meanings. This isn't good in my eyes.
Feb 02 2016
On Tuesday, 2 February 2016 at 14:36:05 UTC, Bambi wrote:1. const isn't constantThe idea was to ease porting C code to D, so many things work the same in C and D except for maybe integer types that were borrowed from java.The example snippet ' immutable(int[]) bar() immutable {} ' brings back bad memories of redundant declarations of the style ' Object object = new Object(); '.Redundancy is not all that bad, but if you want less of it, you can: `auto bar() immutable {}` - the compiler will infer the return type.2. when is an extern an extern? The wiki page on interfacing with C states that C globals require an extra extern.extern attribute is optimized for binding extern functions, which is what you need most of the time. In C you would need two attributes `extern cdecl` - one for extern and one for calling convention, in D it's done with one attribute, though it only specifies calling convention, because everything is implicitly extern anyway. It works well for functions, but not for variables, when you can't differentiate between declaration and definition.3. typeof is an operator, sizeof is a propertysizeof is a property because it can work that way, and making it a whole special syntactical construct for this single purpose would be overkill. Now it can be implemented as a template, but it wasn't always this way.
Feb 03 2016