digitalmars.D - about const and immutable (again)
- Gor Gyolchanyan (23/23) Oct 06 2011 Hi, guys.
- Steven Schveighoffer (16/32) Oct 06 2011 What it does is make it so during the function, the parameter cannot be ...
- Gor Gyolchanyan (54/90) Oct 06 2011 I see. Thanks for the detailed answer.
- Steven Schveighoffer (15/23) Oct 06 2011 I should clarify one point, I realized I am somewhat inaccurate on the
- Gor Gyolchanyan (10/33) Oct 09 2011 Also, this would be a whole lot easier if D got a full built-in tuple
- Don (18/29) Oct 10 2011 That seems like the discussed-and-discarded 'final' storage class for
- Andrei Alexandrescu (12/26) Oct 10 2011 Walter and I have agreed for a long time that upon function calls with
- Don (2/29) Oct 10 2011 Excellent! That'd be a huge improvement.
- Steven Schveighoffer (10/36) Oct 11 2011 I agree, this would help tremendously. Would this apply to function
- Gor Gyolchanyan (8/50) Oct 11 2011 assert(is(typeof(&foo) : void function(int));
Hi, guys. I just made my handy parsing struct take an arbitrary range, instead of a dstring and immediately rain head-first into a brick wall of errors. There's this function: bool next(bool function(ElementType!InputType) pred) , where InputType is bound to be dstring and which gets called like this: parser.next(&isAlpha) , where isAlpha is from std.uni. When i do that, i get this error: Error: cannot implicitly convert expression (& isAlpha) of type bool function(dchar c) pure nothrow safe to bool function(immutable(dchar)) Yes, I understand why do i get this error. What i don't understand is: does the dchar being immutable really change anything? I would, if dchar was indirected type, but it's not. isAlpha has no way to change my original dchar, that i passed it. What's the point of disallowing this? And by `this` i mean, initializing mutable cariables of non-indirected types with immutable values of those types? Cheers, Gor.
Oct 06 2011
On Thu, 06 Oct 2011 10:56:43 -0400, Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> wrote:Hi, guys. I just made my handy parsing struct take an arbitrary range, instead of a dstring and immediately rain head-first into a brick wall of errors. There's this function: bool next(bool function(ElementType!InputType) pred) , where InputType is bound to be dstring and which gets called like this: parser.next(&isAlpha) , where isAlpha is from std.uni. When i do that, i get this error: Error: cannot implicitly convert expression (& isAlpha) of type bool function(dchar c) pure nothrow safe to bool function(immutable(dchar)) Yes, I understand why do i get this error. What i don't understand is: does the dchar being immutable really change anything?What it does is make it so during the function, the parameter cannot be changed. It technically has no effect on what you can pass to the function, since as you rightly point out, ints implicitly cast between const, immutable, and mutable. Why did someone do it? To ensure they didn't accidentally write code that changed the value inside the function. The compiler might also use that information to do some optimization (i.e. avoid reloading into a register), but I doubt it's necessary for that. To answer your underlying question, why doesn't the delegate "just work"? It's because D does not allow implicit casting of delegates or functions at all. I assume this will get better at some point, because implicit casting of delegates would make things just so much smoother in generic programming. -Steve
Oct 06 2011
I see. Thanks for the detailed answer. I love D's support for functional programming. Everything about it, except the readability of function and delegate literals: * Function and delegate literals are way too long because of the "function" and "delegate" keywords being too long to be used inside expressions. * One-liners introduce extra braces and a "return" keyword, which further litters the supposedly small expression, containing a literal. * Parameter types are always required, despite the fact, that if the literal is being assigned somewhere they can be inferred from the assignee's type. The best way to avoid this is making the delegate take 0 arguments, in which case the whole thing can be reduced to a single expression via a lazy parameter. The second best way (when lazy parameters are not accessible) is to wrap the expression into a single return-statement in braces. But that's as good as it can get with readability. Adding parameters is a huge pain particularly because often you really don't want to specify their types and storage classes, since those are known from the type of variable, that is being initialized by the literal. I just looked up Wikipedia for lambdas in different languages and x =3D> x * x (x, y) =3D> x =3D=3D y (int x, string s) =3D> s.Length > x () =3D> SomeMethod() n =3D> { string s =3D n + " " + "World"; Console.WriteLine(s); } The fat arrow operator (=3D>) isn't used in D and cannot be confused with anything (there's no way to write that and not get an error). The fat arrow operator looks confusing (especially with equality operators in the lambda's body), so the arrow operator (->) can be used instead (which is also unused and unambiguous). Specifying the literal type is easily accomplished by adding the appropriate keyword in front of the expression (as it's done now). The only remaining problem are the keywords being too long, which is not gonna change, since even adding new keywords is a breaking change. In the future, though, it would be great to shorten them to something like "fn" and "dg" or something. Nonetheless, this would be a great-looking D code: alias int function(int, int) Fn; alias int delegate(int, int) Dg; Fn a0 =3D function (a, b) -> a + b; Dg a1 =3D delegate (a, b) -> a + b; Dg a2 =3D (c, f) -> a + b; On Thu, Oct 6, 2011 at 7:32 PM, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Thu, 06 Oct 2011 10:56:43 -0400, Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> wrote::Hi, guys. I just made my handy parsing struct take an arbitrary range, instead of a dstring and immediately rain head-first into a brick wall of errors. There's this function: =A0 =A0bool next(bool function(ElementType!InputType) pred) , where InputType is bound to be dstring and which gets called like this=tion,=A0 =A0parser.next(&isAlpha) , where isAlpha is from std.uni. When i do that, i get this error: =A0 =A0Error: cannot implicitly convert expression (& isAlpha) of type bool function(dchar c) pure nothrow safe to bool function(immutable(dchar)) Yes, I understand why do i get this error. What i don't understand is: does the dchar being immutable really change anything?What it does is make it so during the function, the parameter cannot be changed. =A0It technically has no effect on what you can pass to the func=since as you rightly point out, ints implicitly cast between const, immutable, and mutable. Why did someone do it? =A0To ensure they didn't accidentally write code t=hatchanged the value inside the function. =A0The compiler might also use tha=tinformation to do some optimization (i.e. avoid reloading into a register=),but I doubt it's necessary for that. To answer your underlying question, why doesn't the delegate "just work"? It's because D does not allow implicit casting of delegates or functions =atall. =A0I assume this will get better at some point, because implicit cas=tingof delegates would make things just so much smoother in generic programmi=ng.-Steve
Oct 06 2011
On Thu, 06 Oct 2011 12:27:16 -0400, Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> wrote:I see. Thanks for the detailed answer.I should clarify one point, I realized I am somewhat inaccurate on the reason the type is set to immutable(dchar). In fact, nobody actually wrote the immutable(dchar) function, it's just that the element type is immutable(dchar). However, the reasons why someone would want to create a function that takes an immutable(dchar) function are as I stated -- so you don't accidentally change the value. Still no excuse that delegates cannot be implicitly cast to compatible versions.I just looked up Wikipedia for lambdas in different languages and x => x * x (x, y) => x == y (int x, string s) => s.Length > x () => SomeMethod() n => { string s = n + " " + "World"; Console.WriteLine(s); }In the not so distant past, Walter explored different ways to improve the lambda syntax on this news group (which included similarities to the above). This usually means he is considering adding that change, let's hope so :) -Steve
Oct 06 2011
Also, this would be a whole lot easier if D got a full built-in tuple support, because then all functions would always take a single argument. :-) On Thu, Oct 6, 2011 at 10:56 PM, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Thu, 06 Oct 2011 12:27:16 -0400, Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> wrote:roteI see. Thanks for the detailed answer.I should clarify one point, I realized I am somewhat inaccurate on the reason the type is set to immutable(dchar). =A0In fact, nobody actually w=the immutable(dchar) function, it's just that the element type is immutable(dchar). =A0However, the reasons why someone would want to creat=e afunction that takes an immutable(dchar) function are as I stated -- so yo=udon't accidentally change the value. Still no excuse that delegates cannot be implicitly cast to compatible versions.e).I just looked up Wikipedia for lambdas in different languages and x =3D> x * x (x, y) =3D> x =3D=3D y (int x, string s) =3D> s.Length > x () =3D> SomeMethod() n =3D> { string s =3D n + " " + "World"; Console.WriteLine(s); }In the not so distant past, Walter explored different ways to improve the lambda syntax on this news group (which included similarities to the abov==A0This usually means he is considering adding that change, let's hope so=:)-Steve
Oct 09 2011
On 06.10.2011 20:56, Steven Schveighoffer wrote:On Thu, 06 Oct 2011 12:27:16 -0400, Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> wrote:That seems like the discussed-and-discarded 'final' storage class for parameters. But this is worse. It has an *enormous* cost. Making immutable(dchar) parameters different from dchar causes *massive* code bloat. Every n parameter template gets 3^^n copies!! And that has a speed cost (use of code cache, branch prediction, etc). You can see the 2^^n explosion in action in std.writefln; executables bloat up enormously. But it gets worse -- it makes it harder to write templates correctly. For example, if the signature is: bool foo(X)(X a, X b) if (is(X : double)) {...} then foo doesn't accept (double, const(double)). And it's entirely unnecessary. The question of whether a function can modify its value parameters is an internal implementation detail of that function. It has no consequences for the caller, so it shouldn't be externally visible. Nobody else needs to know or care. We need to reconsider this. I think it's the way it is by accident; I don't remember any discussion about it.I see. Thanks for the detailed answer.I should clarify one point, I realized I am somewhat inaccurate on the reason the type is set to immutable(dchar). In fact, nobody actually wrote the immutable(dchar) function, it's just that the element type is immutable(dchar). However, the reasons why someone would want to create a function that takes an immutable(dchar) function are as I stated -- so you don't accidentally change the value.Still no excuse that delegates cannot be implicitly cast to compatible versions.
Oct 10 2011
On 10/10/11 5:55 PM, Don wrote:On 06.10.2011 20:56, Steven Schveighoffer wrote:Walter and I have agreed for a long time that upon function calls with by-value passing, there should be some simple transforms done: 1. If a parameter has no indirections, qual(T) becomes T. 2. qual(T[]) becomes qual(T)[]. 3. qual(T*) becomes qual(T)*. This would improve many aspects of the language. Walter never got to implementing it, but I'm bringing this up in case one of the wonderful compiler contributors would want to take it up. Again, I have reasons to believe Walter would approve of the change. Thanks, AndreiOn Thu, 06 Oct 2011 12:27:16 -0400, Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> wrote:That seems like the discussed-and-discarded 'final' storage class for parameters. But this is worse. It has an *enormous* cost.I see. Thanks for the detailed answer.I should clarify one point, I realized I am somewhat inaccurate on the reason the type is set to immutable(dchar). In fact, nobody actually wrote the immutable(dchar) function, it's just that the element type is immutable(dchar). However, the reasons why someone would want to create a function that takes an immutable(dchar) function are as I stated -- so you don't accidentally change the value.
Oct 10 2011
On 11.10.2011 03:29, Andrei Alexandrescu wrote:On 10/10/11 5:55 PM, Don wrote:Excellent! That'd be a huge improvement.On 06.10.2011 20:56, Steven Schveighoffer wrote:Walter and I have agreed for a long time that upon function calls with by-value passing, there should be some simple transforms done: 1. If a parameter has no indirections, qual(T) becomes T. 2. qual(T[]) becomes qual(T)[]. 3. qual(T*) becomes qual(T)*. This would improve many aspects of the language. Walter never got to implementing it, but I'm bringing this up in case one of the wonderful compiler contributors would want to take it up. Again, I have reasons to believe Walter would approve of the change. Thanks, AndreiOn Thu, 06 Oct 2011 12:27:16 -0400, Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> wrote:That seems like the discussed-and-discarded 'final' storage class for parameters. But this is worse. It has an *enormous* cost.I see. Thanks for the detailed answer.I should clarify one point, I realized I am somewhat inaccurate on the reason the type is set to immutable(dchar). In fact, nobody actually wrote the immutable(dchar) function, it's just that the element type is immutable(dchar). However, the reasons why someone would want to create a function that takes an immutable(dchar) function are as I stated -- so you don't accidentally change the value.
Oct 10 2011
On Mon, 10 Oct 2011 21:29:08 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 10/10/11 5:55 PM, Don wrote:I agree, this would help tremendously. Would this apply to function pointers/delegates as well? For example: void foo(const(int) i) {} assert(is(typeof(&foo) == void function(int)); I would prefer it not be this way, and rather start defining some implicit delegate/function casting. I think D really needs this, not just in the area of const. -SteveOn 06.10.2011 20:56, Steven Schveighoffer wrote:Walter and I have agreed for a long time that upon function calls with by-value passing, there should be some simple transforms done: 1. If a parameter has no indirections, qual(T) becomes T. 2. qual(T[]) becomes qual(T)[]. 3. qual(T*) becomes qual(T)*. This would improve many aspects of the language. Walter never got to implementing it, but I'm bringing this up in case one of the wonderful compiler contributors would want to take it up. Again, I have reasons to believe Walter would approve of the change.On Thu, 06 Oct 2011 12:27:16 -0400, Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> wrote:That seems like the discussed-and-discarded 'final' storage class for parameters. But this is worse. It has an *enormous* cost.I see. Thanks for the detailed answer.I should clarify one point, I realized I am somewhat inaccurate on the reason the type is set to immutable(dchar). In fact, nobody actually wrote the immutable(dchar) function, it's just that the element type is immutable(dchar). However, the reasons why someone would want to create a function that takes an immutable(dchar) function are as I stated -- so you don't accidentally change the value.
Oct 11 2011
assert(is(typeof(&foo) : void function(int)); On Tue, Oct 11, 2011 at 6:35 PM, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Mon, 10 Oct 2011 21:29:08 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:sOn 10/10/11 5:55 PM, Don wrote:On 06.10.2011 20:56, Steven Schveighoffer wrote:On Thu, 06 Oct 2011 12:27:16 -0400, Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> wrote:I see. Thanks for the detailed answer.I should clarify one point, I realized I am somewhat inaccurate on the reason the type is set to immutable(dchar). In fact, nobody actually wrote the immutable(dchar) function, it's just that the element type i=eimmutable(dchar). However, the reasons why someone would want to creat=soa function that takes an immutable(dchar) function are as I stated -- =tI agree, this would help tremendously. Would this apply to function pointers/delegates as well? =A0For example: void foo(const(int) i) {} assert(is(typeof(&foo) =3D=3D void function(int)); I would prefer it not be this way, and rather start defining some implici=Walter and I have agreed for a long time that upon function calls with by-value passing, there should be some simple transforms done: 1. If a parameter has no indirections, qual(T) becomes T. 2. qual(T[]) becomes qual(T)[]. 3. qual(T*) becomes qual(T)*. This would improve many aspects of the language. Walter never got to implementing it, but I'm bringing this up in case one of the wonderful compiler contributors would want to take it up. Again, I have reasons to believe Walter would approve of the change.you don't accidentally change the value.That seems like the discussed-and-discarded 'final' storage class for parameters. But this is worse. It has an *enormous* cost.delegate/function casting. =A0I think D really needs this, not just in th=earea of const. -Steve
Oct 11 2011