[Issue 13579] Add limitations to Uniform Function Call Syntax
https://issues.dlang.org/show_bug.cgi?id=13579 tyckesak changed: What|Removed |Added Status|NEW |RESOLVED CC||jos...@live.de Resolution|--- |MOVED --- Comment #6 from tyckesak --- Potentially moved already into forums as a Language Design Issue. --
[Issue 8381] Uniform function call syntax (pseudo member) enhancement suggestions
https://issues.dlang.org/show_bug.cgi?id=8381 Vladimir Panteleevchanged: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |INVALID --- Comment #8 from Vladimir Panteleev --- (In reply to Tommi from comment #0) > So, I'm suggesting these two features to be added to the language: Hello, Changes to the language need to be proposed through the DIP process: https://github.com/dlang/DIPs Bugzilla is not the correct place for language enhancements. If you still believe your proposal has merit, please submit a DIP. The current DIP manager can assist you through the process. --
Re: Uniform Function Call Syntax?
On Tue, 08 Mar 2016 18:59:47 +, Ola Fosheim Grøstad wrote: > On Monday, 7 March 2016 at 19:09:47 UTC, Chris Wright wrote: >> I don't think history bears that out. I've never seen this happen in >> Java, C#, or Python. > > You haven't seen people do it in D? No.
Re: Uniform Function Call Syntax?
On Monday, 7 March 2016 at 19:09:47 UTC, Chris Wright wrote: I don't think history bears that out. I've never seen this happen in Java, C#, or Python. You haven't seen people do it in D?
Re: Uniform Function Call Syntax?
On 07.03.2016 01:19, Xinok wrote: On Sunday, 6 March 2016 at 07:45:58 UTC, Ola Fosheim Grøstad wrote: I think it would be better idea to just add the ability to add unicode operators, and to avoid precedence issues one could just require them to use parentheses. That way you could define opCustom"•" and use it as: ( point1 • point2 ) Please no. If I need to open up Character Map just to write code, something has gone horribly wrong. That "something" is your editor configuration. Seriously, this is a trivial problem.
Re: Uniform Function Call Syntax?
On 07.03.2016 18:49, Wyatt wrote: But I really don't want any language features predicated on the programmer having an APL keyboard. I can't think of any language feature that would be.
Re: Uniform Function Call Syntax?
On Monday, 7 March 2016 at 18:57:03 UTC, Chris Wright wrote: It's still not inconsistent to disallow math symbols. It is inconsistent if you accept that different communities have different notations/languages. Why you would you want to exclude the scientific community? here: I want to guide people toward using descriptive names, because that makes it easier to read code, which makes it easier to verify correctness. Err, no, the contrary. What you get is an incomprehensible and overly verbose mess that hide problems and/or result in excessive overloading of the "*" symbol. Try some geometric computing problems, it gets messy quickly. People don't write descriptive names, they write short names, if you provide a very limited set of symbols. Like "dot".
Re: Uniform Function Call Syntax?
On Mon, 07 Mar 2016 18:45:34 +, Ola Fosheim Grøstad wrote: > There are lots of interesting letters from various languages that can be > used, so prohibiting access to the proper symbols is kinda pointless. > The end result is that people just pick inappropriate characters > instead. I don't think history bears that out. I've never seen this happen in Java, C#, or Python.
Re: Uniform Function Call Syntax?
On Mon, 07 Mar 2016 18:45:34 +, Ola Fosheim Grøstad wrote: > On Monday, 7 March 2016 at 18:35:44 UTC, Chris Wright wrote: >> The partial integral symbol is not a letter or digit under any >> circumstances. It is a mathematical symbol. Identifiers cannot contain >> mathematical symbols in D or C99 or even C#. > > Well, but that argument is kinda bogus. Scientists have "invented" their > own notation using whatever symbols (characters) > they had access to since forever. It's not like they will stop just > because language designers are reactionary. :-) It's still not inconsistent to disallow math symbols. There's a simple rule that the C99 standards writers were attempting to approximate, and that simple rule excludes mathematical symbols. You dislike and disagree with that decision, which is a separate complaint. I'm sympathetic to the language designers here: I want to guide people toward using descriptive names, because that makes it easier to read code, which makes it easier to verify correctness. Math notation tends to be very compact and inscrutable, and I don't want to encourage users of my language to use inscrutable identifiers.
Re: Uniform Function Call Syntax?
On Mon, 07 Mar 2016 12:58:51 +, Lass Safin wrote: > Have you ever heard of .XCompose? > For linux: https://github.com/kragen/xcompose For windows: > https://github.com/samhocevar/wincompose How it works: > You choose a compose key, then use it to compose special characters with > specific sequences. Alternatively, you can create a custom keyboard layout for Linux relatively easily. The text format is relatively legible, but to simplify, you can use a utility such as https://github.com/simos/keyboardlayouteditor . For instance, I find myself using the characters ðþƹāē often for personal reasons, plus åøæ when I was learning Norwegian, so I created a keyboard layout to simplify that. Still doesn't make it a great idea, but if your code's audience is sufficiently constrained, you might find it makes some things more usable.
Re: Uniform Function Call Syntax?
On Monday, 7 March 2016 at 18:35:44 UTC, Chris Wright wrote: The partial integral symbol is not a letter or digit under any circumstances. It is a mathematical symbol. Identifiers cannot contain mathematical symbols in D or C99 or even C#. Well, but that argument is kinda bogus. Scientists have "invented" their own notation using whatever symbols (characters) they had access to since forever. It's not like they will stop just because language designers are reactionary. :-) There are lots of interesting letters from various languages that can be used, so prohibiting access to the proper symbols is kinda pointless. The end result is that people just pick inappropriate characters instead.
Re: Uniform Function Call Syntax?
On Mon, 07 Mar 2016 10:32:09 +, Ola Fosheim Grøstad wrote: > D is inconsistent in what parts > of unicode you can use in names though. The basic idea is that you can use any letter or '_' as the first element of an identifier, and you can use any letter or number or '_' as a subsequent element of an identifier. That's simple and consistent, right? Except it's based on C99's fixed list of characters. So the actual rule is, you can use symbols from about 25 different writing systems that the designers of C99 thought prevalent enough to include, so long as they were in Unicode before 1999. C#, in contrast, uses Unicode categories. You can use the Cherokee alphabet in C# identifiers, and there are under 400,000 speakers of Cherokee. Making that work took far less effort for the C# standard authors than the choice of identifier characters for C99. I'm relatively certain that Walter went with C99's rules in large part because he had already implemented them, whereas he didn't have a readily available library with an appropriate license to give the Unicode category for a given codepoint. > But you can already use "π" in D code? U+03C0 (π) is from the Greek alphabet section of the Unicode inventory. It's for writing in the Greek language, which is currently spoken by about thirteen million people. It is primarily a letter, with incidental usage as a mathematical symbol. Therefore, based on the rule that you can always start an identifier with a letter, you can use π as an identifier. > I don't think you can use "∂"... The partial integral symbol is not a letter or digit under any circumstances. It is a mathematical symbol. Identifiers cannot contain mathematical symbols in D or C99 or even C#.
Re: Uniform Function Call Syntax?
On Monday, 7 March 2016 at 17:49:35 UTC, Wyatt wrote: I've mentioned this before, but I think a constrained set of user-defined operators using annotations/affixes on the existing set is a better fit for D. It's a lesson well-learned from other languages (cf. OCaml; F#), and fits with D's generally practical bent. Not sure what you mean by annotations/affixes and what lesson there is to be learned? What problems have other languages had with this? I mean, if you want to alias them to Lucky Charms or various hieroglyphs of birds disemboweling men later, I guess maybe that's could work? But I really don't want any language features predicated on the programmer having an APL keyboard. I don't see how mixfix notation makes this "problem" larger than the current prefix notation. Why is the current situation that allows "ø(x,y)" less problematic than the proposed "(x ø y)" ?
Re: Uniform Function Call Syntax?
On Sunday, 6 March 2016 at 07:45:58 UTC, Ola Fosheim Grøstad wrote: I think it would be better idea to just add the ability to add unicode operators, and to avoid precedence issues one could just require them to use parentheses. That way you could define opCustom"•" and use it as: I've mentioned this before, but I think a constrained set of user-defined operators using annotations/affixes on the existing set is a better fit for D. It's a lesson well-learned from other languages (cf. OCaml; F#), and fits with D's generally practical bent. I mean, if you want to alias them to Lucky Charms or various hieroglyphs of birds disemboweling men later, I guess maybe that's could work? But I really don't want any language features predicated on the programmer having an APL keyboard. -Wyatt
Re: Uniform Function Call Syntax?
On Monday, 7 March 2016 at 07:58:53 UTC, Era Scarecrow wrote: On Monday, 7 March 2016 at 06:57:48 UTC, Ola Fosheim Grøstad wrote: immutable π = 3.14; Oh, the horror! With the assumption pi is declared elsewhere (say, in std.math), what i wonder is the number for pi vs 2 letters. Unicode 03C0h, so now i have to convert that to decimal, code 960. Alt+960 = └ That's not pi... Looking up the symbol by itself in the character map was annoying enough. No, this is not a good idea unless it's easily accessible, preferably with 2 or fewer keystrokes to symbolize pi. As a reminder most of us are programmers, not scientists or mathematicians. Having specialized symbols won't give us any benefit. It's not like we're filling out a complex formula with college level math for a thesis. Have you ever heard of .XCompose? For linux: https://github.com/kragen/xcompose For windows: https://github.com/samhocevar/wincompose How it works: You choose a compose key, then use it to compose special characters with specific sequences. Examples: ComposeKey, *, p: π. ComposeKey, s, s: ß ComposeKey, ComposeKey, d, e, g, c (degree Celsius): ℃ It is not impossible to use unicode special characters on a daily base easily, with the use of this tool. No need to use the character map or anything. I think it would be very nice, if one had the option of using these special characters. E.g. → instead of >>, if you desire that; std.math defining π as π. Small gimmicks like these are things I find to be good for a language to have.
Re: Uniform Function Call Syntax?
On Monday, 7 March 2016 at 07:58:53 UTC, Era Scarecrow wrote: On Monday, 7 March 2016 at 06:57:48 UTC, Ola Fosheim Grøstad wrote: immutable π = 3.14; Oh, the horror! With the assumption pi is declared elsewhere (say, in std.math), what i wonder is the number for pi vs 2 letters. Unicode 03C0h, so now i have to convert that to decimal, code 960. Alt+960 = └ That's not pi... Looking up the symbol by itself in the character map was annoying enough. No, this is not a good idea unless it's easily accessible, preferably with 2 or fewer keystrokes to symbolize pi. But you can already use "π" in D code? D is inconsistent in what parts of unicode you can use in names though. I don't think you can use "∂"... As a reminder most of us are programmers, not scientists or mathematicians. Having specialized symbols won't give us any benefit. It's not like we're filling out a complex formula with college level math for a thesis. Well, but you already have this possibility in D. Adding custom operators is just a small extension. And you don't have to use it if you don't want to. There is no standard english notation for the inner product either, "dot" refers to the sigil... But if you want both, you can have both. You can both have "innerProduct(v1,v2)" and "(v1 • v2)". In a commercial setting you want as high level of legibility as possible. D is doing slightly better than C++, but is far away from providing a good legible syntax. More time is spent reading code than writing it. In some cases people want to use their own language. D supports that. Math notation is no different than using a non-english language in that regard. Why shouldn't mathematicians be allowed to user the language they are familiar with if national languages are supported?
Re: Uniform Function Call Syntax?
On Monday, 7 March 2016 at 07:58:53 UTC, Era Scarecrow wrote: On Monday, 7 March 2016 at 06:57:48 UTC, Ola Fosheim Grøstad wrote: immutable π = 3.14; Oh, the horror! With the assumption pi is declared elsewhere (say, in std.math), what i wonder is the number for pi vs 2 letters. Unicode 03C0h, so now i have to convert that to decimal, code 960. Alt+960 = └ That's not pi... Looking up the symbol by itself in the character map was annoying enough. No, this is not a good idea unless it's easily accessible, preferably with 2 or fewer keystrokes to symbolize pi. As a reminder most of us are programmers, not scientists or mathematicians. Having specialized symbols won't give us any benefit. It's not like we're filling out a complex formula with college level math for a thesis. Didn't we have "pitching D to academia" thread recently? Honestly, any tool can be abused. Javascript, Swift and even partially Haskell allow unicode names and I'm sure we all saw that toy example that was full of emojis, but can you say it has been a problem in practice?
Re: Uniform Function Call Syntax?
On Monday, 7 March 2016 at 06:57:48 UTC, Ola Fosheim Grøstad wrote: immutable π = 3.14; Oh, the horror! With the assumption pi is declared elsewhere (say, in std.math), what i wonder is the number for pi vs 2 letters. Unicode 03C0h, so now i have to convert that to decimal, code 960. Alt+960 = └ That's not pi... Looking up the symbol by itself in the character map was annoying enough. No, this is not a good idea unless it's easily accessible, preferably with 2 or fewer keystrokes to symbolize pi. As a reminder most of us are programmers, not scientists or mathematicians. Having specialized symbols won't give us any benefit. It's not like we're filling out a complex formula with college level math for a thesis.
Re: Uniform Function Call Syntax?
On Monday, 7 March 2016 at 06:48:10 UTC, Era Scarecrow wrote: I'm reminded. Weren't there standard 50-something keyboards, and then 101 keyboards? And you actually COULDN'T do programming on the 50-key keyboards because literally standard symbols were missing? No unicode. No keys. No mouse. No bitmap graphics. Just a hardwired terminal. Welcome to the 60s and 70s. I have an excellent idea! I'll start programming using nothing but the greek alphabet, better yet unicode characters! immutable π = 3.14; writeln( ∑(values) ); x = x + ∆; Oh, the horror!
Re: Uniform Function Call Syntax?
On Monday, 7 March 2016 at 06:02:46 UTC, Patience wrote: On Monday, 7 March 2016 at 00:19:07 UTC, Xinok wrote: Please no. If I need to open up Character Map just to write code, something has gone horribly wrong. A proper code editor could handle this. Type something like ctrl + ? and it pops up all the implemented uni-code operators. Else we are stuck in the past until you decide to change... I'm reminded. Weren't there standard 50-something keyboards, and then 101 keyboards? And you actually COULDN'T do programming on the 50-key keyboards because literally standard symbols were missing? Honestly it would be annoying to have to pull up character map, memorize ascii or unicode characters, or even require a helper program which isn't present on most tools. I have an excellent idea! I'll start programming using nothing but the greek alphabet, better yet unicode characters! //謎機能 int æ(File ß, int Ɣ, int Ʊ) { return Ɣ 乘 Ɣ 加 Ʊ 子 7; } Actually let's alias off the ints too because, we don't need those. //謎機能 數 æ(數 Ɣ, 數 Ʊ) { return Ɣ 乘 Ɣ 加 Ʊ 子 7; } i happy i cut & paste everywhere (instead of relying on standardized ascii characters that actually mean something to me... Okay maybe this went off track)
Re: Uniform Function Call Syntax?
On Monday, 7 March 2016 at 00:19:07 UTC, Xinok wrote: Please no. If I need to open up Character Map just to write code, something has gone horribly wrong. Modern languages support Unicode in names, so it is too late: import std.stdio; real Ø(real radius){ return 6.28*radius; } void main() { writeln(Ø(3)); }
Re: Uniform Function Call Syntax?
On Monday, 7 March 2016 at 00:19:07 UTC, Xinok wrote: On Sunday, 6 March 2016 at 07:45:58 UTC, Ola Fosheim Grøstad wrote: I think it would be better idea to just add the ability to add unicode operators, and to avoid precedence issues one could just require them to use parentheses. That way you could define opCustom"•" and use it as: ( point1 • point2 ) Please no. If I need to open up Character Map just to write code, something has gone horribly wrong. A proper code editor could handle this. Type something like ctrl + ? and it pops up all the implemented uni-code operators. Else we are stuck in the past until you decide to change...
Re: Uniform Function Call Syntax?
On Sunday, 6 March 2016 at 07:45:58 UTC, Ola Fosheim Grøstad wrote: I think it would be better idea to just add the ability to add unicode operators, and to avoid precedence issues one could just require them to use parentheses. That way you could define opCustom"•" and use it as: ( point1 • point2 ) Please no. If I need to open up Character Map just to write code, something has gone horribly wrong.
Re: Uniform Function Call Syntax?
On Friday, 4 March 2016 at 01:56:34 UTC, user001 wrote: "dot". For mathematical purposes it is a lot easier to understand "dot(a, b)" than "a.dot(b)", at least in my opinion. Why don't you just define it as "dot(a,b)" to begin with? I think it would be better idea to just add the ability to add unicode operators, and to avoid precedence issues one could just require them to use parentheses. That way you could define opCustom"•" and use it as: ( point1 • point2 ) An often stated golden rule in language design is that there should be one way to do something. When you break that rule it often is due to a language design deficiency. UFCS in both D and C++ are hacks. IMO that makes things more confusing, not more clear.
Re: Uniform Function Call Syntax?
On 3/3/2016 5:56 PM, user001 wrote: It may not add as much value but I think it'd be a bit better as now you no longer have a global function with a simple name "dot". For mathematical purposes it is a lot easier to understand "dot(a, b)" than "a.dot(b)", at least in my opinion. Just curious that's all. If that's how you want to call dot, add the following: float dot(Vec3 a, Vec3 b) { return a.dot(b); }
Re: Uniform Function Call Syntax?
On Friday, 4 March 2016 at 02:09:25 UTC, Era Scarecrow wrote: On Friday, 4 March 2016 at 01:56:34 UTC, user001 wrote: Was just wondering why UFCS only works in one direction, that is why functions can be used as if it were part of a struct/class but not the other way around. int dot; float value = dot(a, b); // would be same as a.dot(b) // doesn't try to use local "int dot" Immediately looking at only that part of the code, i have to ask 'how the hell are you calling the int???'. Of course i can tell from your source dot is also a function in the vector. Considering dot could now shadow the variables or function names, it would quickly QUICKLY become annoying. A hierarchy of how the call is used plus the documentation of what it's obviously doing is a much better approach. Not to mention we've been using . and -> and * so long for accessing/de-referencing members that are attached so long that changing it is probably not an option. You can say the same thing about how it is currently implemented. int[] arr = [ 0, 1, 2, 3 ]; static map(alias F)(int[]) { } writeln(arr.map!(a => a * 2)); // what does this mean array doesnt have a map function, does it use the local map function or the global one? MAYBE if you were starting a language from scratch, but in this case i would firmly say no, this is ugly and confusing. Well it could possibly be happening with C++17 so it's not that big of stretch to add it to an existing language, especially if that language already has it half implemented.
Re: Uniform Function Call Syntax?
On Friday, 4 March 2016 at 01:56:34 UTC, user001 wrote: Was just wondering why UFCS only works in one direction, that is why functions can be used as if it were part of a struct/class but not the other way around. int dot; float value = dot(a, b); // would be same as a.dot(b) // doesn't try to use local "int dot" Immediately looking at only that part of the code, i have to ask 'how the hell are you calling the int???'. Of course i can tell from your source dot is also a function in the vector. Considering dot could now shadow the variables or function names, it would quickly QUICKLY become annoying. A hierarchy of how the call is used plus the documentation of what it's obviously doing is a much better approach. Not to mention we've been using . and -> and * so long for accessing/de-referencing members that are attached so long that changing it is probably not an option. MAYBE if you were starting a language from scratch, but in this case i would firmly say no, this is ugly and confusing.
Uniform Function Call Syntax?
Was just wondering why UFCS only works in one direction, that is why functions can be used as if it were part of a struct/class but not the other way around. struct Vec3 { float x; float y; float z; float dot(Vec3 o) { return x * o.x + y * o.y + z * o.z; } } int dot; Vec3 a, b; float value = dot(a, b); // would be same as a.dot(b) // doesn't try to use local "int dot" It may not add as much value but I think it'd be a bit better as now you no longer have a global function with a simple name "dot". For mathematical purposes it is a lot easier to understand "dot(a, b)" than "a.dot(b)", at least in my opinion. Just curious that's all.
[Issue 13579] Add limitations to Uniform Function Call Syntax
https://issues.dlang.org/show_bug.cgi?id=13579 Andrei Alexandrescu and...@erdani.com changed: What|Removed |Added Version|unspecified |D2 --
[Issue 8381] Uniform function call syntax (pseudo member) enhancement suggestions
https://issues.dlang.org/show_bug.cgi?id=8381 Andrei Alexandrescu and...@erdani.com changed: What|Removed |Added Version|unspecified |D2 --
[Issue 13579] Add limitations to Uniform Function Call Syntax
https://issues.dlang.org/show_bug.cgi?id=13579 Andrej Mitrovic andrej.mitrov...@gmail.com changed: What|Removed |Added CC||andrej.mitrov...@gmail.com --- Comment #2 from Andrej Mitrovic andrej.mitrov...@gmail.com --- I don't yet have much personal experience writing D code Well then, let's change the language and break all code while your seat hasn't even gotten warm yet. --
[Issue 13579] Add limitations to Uniform Function Call Syntax
https://issues.dlang.org/show_bug.cgi?id=13579 --- Comment #3 from DBN deathbynu...@gmail.com --- (In reply to Andrej Mitrovic from comment #2) Well then, let's change the language and break all code while your seat hasn't even gotten warm yet. ad hominem... --
[Issue 13579] Add limitations to Uniform Function Call Syntax
https://issues.dlang.org/show_bug.cgi?id=13579 bearophile_h...@eml.cc changed: What|Removed |Added CC||bearophile_h...@eml.cc --- Comment #4 from bearophile_h...@eml.cc --- (In reply to Vladimir Panteleev from comment #1) Language design issues are best discussed in the newsgroups/forums. Yes, I suggest to open a discussion thread in the main D newsgroup, and show bug-prone examples, and some syntax and/or semantics to reduce such supposed source of bugs. --
[Issue 13579] Add limitations to Uniform Function Call Syntax
https://issues.dlang.org/show_bug.cgi?id=13579 --- Comment #5 from DBN deathbynu...@gmail.com --- Sorry, I don't personally have time for such a demanding discussion. (And I don't have any examples right now, other than this old thing http://redd.it/vvpfy) Please don't hesitate to start such a thread in my place if you want or just close/ignore this issue. --
[Issue 13579] New: Add limitations to Uniform Function Call Syntax
https://issues.dlang.org/show_bug.cgi?id=13579 Issue ID: 13579 Summary: Add limitations to Uniform Function Call Syntax Product: D Version: unspecified Hardware: All OS: All Status: NEW Keywords: spec Severity: enhancement Priority: P2 Component: DMD Assignee: nob...@puremagic.com Reporter: deathbynu...@gmail.com I don't yet have much personal experience writing D code but I have a strong suspicion that extension methods are superior to UFCS. First I want to note that the Dr. Dobb's UFCS article (http://www.drdobbs.com/blogs/cpp/232700394) describes extension methods incorrectly. Extension methods can be called with infix notation or with function notation; marking a method as an extension method only increases the ways it can be used. 1. UFCS is not self-documenting. I assume that in most use cases, a function is intended either to be called as a function, or to be called via UFCS. D doesn't give us a way to express this intention. 2. As a result of #1, UFCS will pollute auto-complete lists and similar tools. Tools will probably end up needing to add tool-specific ways to mark up UFCS functions. 3. I think UFCS has pitfalls similar to C++'s conversion constructors, except D doesn't even have the explicit keyword to opt out of it and it's not limited to single-parameter functions. If breaking backward compatibility is at all an option, I suggest requiring functions to opt in to UFCS syntax in some way. Probably by adding an attribute. If someone wants to use UFCS on a function that doesn't allow it, they might be allowed to declare an identical function with the attribute added which forwards the call. A template or keyword could automate this. Perhaps when old-style UFCS is deprecated a DMD flag could be added that automatically generates source files with the attribute added to functions with UFCS usage. If it's too late to fix it or opt-in is undesirable, I suggest something like C++'s explicit keyword which allows us to disable UFCS for specific functions. I was unable to find any good pre-existing discussion on these problems but please close this Issue without warning if it has already been thoroughly considered. --
[Issue 13579] Add limitations to Uniform Function Call Syntax
https://issues.dlang.org/show_bug.cgi?id=13579 DBN deathbynu...@gmail.com changed: What|Removed |Added CC||deathbynu...@gmail.com --
[Issue 13579] Add limitations to Uniform Function Call Syntax
https://issues.dlang.org/show_bug.cgi?id=13579 Vladimir Panteleev thecybersha...@gmail.com changed: What|Removed |Added CC||thecybersha...@gmail.com --- Comment #1 from Vladimir Panteleev thecybersha...@gmail.com --- Language design issues are best discussed in the newsgroups/forums. --
Overloading external functions for use in a separate module and... uniform function call syntax!
Some of you StackOverflow-folks may have already seen this question. That said... http://stackoverflow.com/questions/18320610/overloading-external-function-for-use-in-a-separate-module That describes the question. Now... Andrei Alexandrescu was awesome enough to throw me a bone, but... no dice. Under the assumption that the double-spacing between the `runrun` decldef and the `import mod_a` represents a separation of files, GDC 4.8.1 spits out template mod.run does not match any function template declaration. Candidates are: the `run` decldef that doesn't accept doubles/. Given the feel of the situation, I wanted to check with dlang.org-folk to make sure that this isn't a hole I've inadvertently fallen into as far as D features go with respect to uniform function call syntax and the semantics surrounding it. For the sake of discussion, I'm modifying my question a little bit... Let's say I have some function in some module: = BEGIN CODE = == file mod.d module mod; void doStuff(T)(T v) { v.doOtherStuff(); } == file adooblydoo.d module adooblydoo; import mod; struct A; doOtherStuff(A a) { ... } void main() { A a; doStuff(a); } = END CODE = This fails to compile with both DMD 2.063 and GDC 4.8.1 informing me that doOtherStuff is an undefined identifier while instantiating doStuff. Given that Andrei Alexandrescu gave me an answer implying that at least the C++-STL-style of calling was possible, I'm inclined to guess that this is either a bugfeature or at the very least an obscure feature with respect to what I'd assume to be the intended semantics of uniform function call syntax. Soo... What is this behavior? (( THANKS FOR READING THAT WHOLE THING [if you didn't and you're reading this little message, I take the thanks back and instead chuck silly putty at your face] ))
Re: Making uniform function call syntax more complete a feature
Simen Kjaeraas , dans le message (digitalmars.D:172349), a écrit : On Thu, 12 Jul 2012 16:31:34 +0200, Christophe Travert trav...@phare.normalesup.org wrote: By the way, would it be possible to implement an opCmp that returns a double, to allow it to return a NaN ? That may allow to create values that are neither superior, nor inferior to other value, like NaNs. It's not possible to implement opCmp for a floating point comparison if opCmp is bound to return an int. Why don't you just test it? Not like it'd be many lines of code. Anyways, yes this works. Thanks. I don't always have a d compiler at hand when I read this newsgroup. Maybe I should just write myself a todo to make this kind of test back home rather than directly posting the idea.
Re: Making uniform function call syntax more complete a feature
On Thu, 12 Jul 2012 16:31:34 +0200, Christophe Travert trav...@phare.normalesup.org wrote: By the way, would it be possible to implement an opCmp that returns a double, to allow it to return a NaN ? That may allow to create values that are neither superior, nor inferior to other value, like NaNs. It's not possible to implement opCmp for a floating point comparison if opCmp is bound to return an int. Why don't you just test it? Not like it'd be many lines of code. Anyways, yes this works. -- Simen
Re: Making uniform function call syntax more complete a feature
I posted this as an enhancement request over there: http://d.puremagic.com/issues/show_bug.cgi?id=8381
Re: Making uniform function call syntax more complete a feature
Have you considered adding operator overloading using UFCS while you're at it?
Re: Making uniform function call syntax more complete a feature
On 07/12/2012 12:05 PM, Thiez wrote: Have you considered adding operator overloading using UFCS while you're at it? There is already an open issue about that iirc.
Re: Making uniform function call syntax more complete a feature
On Thursday, 12 July 2012 at 10:05:16 UTC, Thiez wrote: Have you considered adding operator overloading using UFCS while you're at it? I assumed it's already possible to add operators non-intrusively, because operators are just syntactic sugar for method calls: ++var; // actual code var.opUnary!++(); // lowered once opUnary!++(var); // lowered twice (if necessary) If you're talking about overloading existing operators (which have been implemented as member functions) non-intrusively for other types, then I don't know, doesn't it work?
Re: Making uniform function call syntax more complete a feature
On Thursday, 12 July 2012 at 12:43:24 UTC, Tommi wrote: On Thursday, 12 July 2012 at 10:05:16 UTC, Thiez wrote: Have you considered adding operator overloading using UFCS while you're at it? I assumed it's already possible to add operators non-intrusively, because operators are just syntactic sugar for method calls: ++var; // actual code var.opUnary!++(); // lowered once opUnary!++(var); // lowered twice (if necessary) If you're talking about overloading existing operators (which have been implemented as member functions) non-intrusively for other types, then I don't know, doesn't it work? I actually tried those yesterday (with opEquals and opCmp on structs) and couldn't get it to work. Code still used what appeared to be an automatically generated opEquals (that appears to perform a bitwise comparison) instead of my UFCS opEquals. It's already quite obvious that the compiler does not obey its own rewrite rules (see http://dlang.org/operatoroverloading.html#compare) Consider opCmp: a b is rewritten to a.opCmp(b) 0 or b.opCmp(a) 0 Let's assume the first rule is always chosen. According to the very rewrite rule we just applied, this must be rewritten to a.opCmp(b).opCmp(0) 0 which must be rewritten to a.opCmp(b).opCmp(0).opCmp(0) 0 and then a.opCmp(b).opCmp(0).opCmp(0).opCmp(0) 0 and so on, to infinity. It seems quite obvious the compiler does not rewrite compares on integers or all hell would break loose... The language reference should be more specific about these things.
Re: Making uniform function call syntax more complete a feature
On Thursday, 12 July 2012 at 13:19:00 UTC, Thiez wrote: It's already quite obvious that the compiler does not obey its own rewrite rules (see http://dlang.org/operatoroverloading.html#compare) Consider opCmp: a b is rewritten to a.opCmp(b) 0 or b.opCmp(a) 0 Let's assume the first rule is always chosen. According to the very rewrite rule we just applied, this must be rewritten to a.opCmp(b).opCmp(0) 0 which must be rewritten to a.opCmp(b).opCmp(0).opCmp(0) 0 and then a.opCmp(b).opCmp(0).opCmp(0).opCmp(0) 0 and so on, to infinity. It seems quite obvious the compiler does not rewrite compares on integers or all hell would break loose... The language reference should be more specific about these things. Quote from 'The D Programming Language' chapter 12.1: D’s approach to operator overloading is simple: whenever at least one participant in an operator expression is of user-defined type, the compiler rewrites the expression into a regular method call with a specific name. Then the regular language rules apply. So, assuming opCmp returns integer, then a.opCmp(b) 0 doesn't get rewritten (lowered) any further, because user-defined types are not involved.
Re: Making uniform function call syntax more complete a feature
Thiez , dans le message (digitalmars.D:172060), a écrit : Have you considered adding operator overloading using UFCS while you're at it? I assumed it's already possible to add operators non-intrusively, because operators are just syntactic sugar for method calls: ++var; // actual code var.opUnary!++(); // lowered once opUnary!++(var); // lowered twice (if necessary) If you're talking about overloading existing operators (which have been implemented as member functions) non-intrusively for other types, then I don't know, doesn't it work? I actually tried those yesterday (with opEquals and opCmp on structs) and couldn't get it to work. Code still used what appeared to be an automatically generated opEquals (that appears to perform a bitwise comparison) instead of my UFCS opEquals. This behavior for opEquals is debatable, but make sense. If the designer of a struct did not implement opEquals, it may be that he intended opEqual to be the default opEqual. If you overload opEquals for such struct, you may be hijacking it's intended behavior: your not just adding a functionality, your overriding an existing functionality. Did you try operators that are not automatically generated ? It's already quite obvious that the compiler does not obey its own rewrite rules (see http://dlang.org/operatoroverloading.html#compare) Consider opCmp: a b is rewritten to a.opCmp(b) 0 or b.opCmp(a) 0 Let's assume the first rule is always chosen. According to the very rewrite rule we just applied, this must be rewritten to a.opCmp(b).opCmp(0) 0 It seems quite obvious the compiler does not rewrite compares on integers or all hell would break loose... The language reference should be more specific about these things. The rewrite rule obviously apply only if the comparison operator is not already defined for those types by the langage. That could be precised in the web site, but it's consistent. By the way, would it be possible to implement an opCmp that returns a double, to allow it to return a NaN ? That may allow to create values that are neither superior, nor inferior to other value, like NaNs. It's not possible to implement opCmp for a floating point comparison if opCmp is bound to return an int. Another reason to ban Object imposing a specific signature for opCmp in all classes...
Re: Making uniform function call syntax more complete a feature
On Thursday, 12 July 2012 at 14:31:34 UTC, trav...@phare.normalesup.org (Christophe Travert) wrote: This behavior for opEquals is debatable, but make sense. I don't think it's debatable at all. You must be able to figure out how a class is going to behave just by looking at its definition.
[Issue 8381] New: Uniform function call syntax (pseudo member) enhancement suggestions
http://d.puremagic.com/issues/show_bug.cgi?id=8381 Summary: Uniform function call syntax (pseudo member) enhancement suggestions Product: D Version: unspecified Platform: All OS/Version: All Status: NEW Severity: enhancement Priority: P2 Component: DMD AssignedTo: nob...@puremagic.com ReportedBy: tommitiss...@hotmail.com --- Comment #0 from Tommi tommitiss...@hotmail.com 2012-07-12 01:54:22 PDT --- As I see it, the goal of uniform function call syntax, as described here http://www.drdobbs.com/blogs/cpp/232700394, is to allow non-intrusively extending the functionality of a type. I think the current implementation falls short in accomplishing this goal on two accounts: 1) You can't non-intrusively add static member functions 2) You can't non-intrusively add constructors So, I'm suggesting these two features to be added to the language: 1. Static members as free functions If function invocations like the following are encountered... A) Type.func(ARGUMENTS); B) Type.func; // it's a static @property function ...and those functions haven't been implemented as members, the function invocations get lowered into: A) func!Type(ARGUMENTS); B) func!Type; For example: enum Fruit {apple, orange} // CODE // LOWERED CODE Fruit.letEmRot(); // .letEmRot!Fruit(); if (Fruit.isEatable) // if (.isEatable!Fruit) { Fruit myfruit; myfruit.split(3); // .split!Fruit(3); // only if it can't // be lowered into: // .split(myfruit, 3) } 2. Class struct constructors as free functions - If a constructor call hasn't been implemented by Type... auto t = Type(ARGUMENTS); ...then it get's lowered into a free function call... auto t = .make!Type(ARGUMENTS); For example: enum Fruit {apple, orange} // CODE // LOWERED CODE auto f = Fruit(red); // auto f = .make!Fruit(red); -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 8381] Uniform function call syntax (pseudo member) enhancement suggestions
http://d.puremagic.com/issues/show_bug.cgi?id=8381 David Piepgrass qwertie...@gmail.com changed: What|Removed |Added CC||qwertie...@gmail.com --- Comment #1 from David Piepgrass qwertie...@gmail.com 2012-07-12 09:11:28 PDT --- To some extent I like the goal of the proposal, but I don't like the implementation: - The rule is non-obvious. How could a new developer possibly guess that this happens? - It would get lowered to a call to a template function, but usually the programmer wants to extend one specific type. So I offer the following counterproposal: 1) Adding static member functions Supposing that I would like to extend the set of static members in class Foo. How about: module A; // assuming static class does not already have any meaning? static class Foo { static void F(); static int x; } This block defines members in a class namespace Foo. If regular class Foo is defined in module A then these static members go into the same class. However, if the original Foo is defined in module B then static class Foo goes into module A and is considered a separate class. Now consider some code that tries to use F(): module C; import A; import B; void code() { Foo.F(); } Currently, the compiler complains that B.Foo and A.Foo conflict with each other. I propose changing this rule when accessing static members. The compiler does not need to declare a conflict as soon as it sees Foo, instead it can look for static members in ALL Foo classes, using the same anti-hijacking rules that it uses for free-standing module functions. The purpose of static class is not to facilitate this method lookup per se; if A and B both contain non-static Foo classes, the compiler should still search both classes for static members rather than giving an error immediately. Rather, the main purpose of static class is to declare that the class has no constructor (not merely a @disabled default constructor, but no constructor at all). Therefore, new Foo() cannot mean new A.Foo, leading the compiler to the interpretation new B.Foo. Also, multiple static classes can be defined with the same name in the same module, and their contents are merged. IMO, when searching for static members, a class scope should pretty much behave the same way as module scope. So the compiler should not report an ambiguous call if the call has only one interpretation. In the above case, the compiler should report an error if and only if a B.F() function exists. One more thing, if module C declares a class Foo then it takes priority over A.Foo and B.Foo. But if C declares static class Foo then C.Foo should allow the same overloading behavior just described; thus new Foo() should still mean new B.Foo() and Foo.F() should still mean A.Foo.F(). I think an equivalent way to say this is that, inside C, the lookup rules proceed as if C.Foo were declared outside module C and imported into C. 2) Adding constructors aka Constructors Considered Harmful Ahh, constructors, constructors. In my opinion the constructor design in most languages including C++, C#, D and Java is flawed, because it exposes an implementation detail that should not be exposed, namely, which class gets allocated and when. I offer you as exhibit L the LazyT class in the .NET framework. This class's main purpose is to compute a value the first time you access it. For example: int x; Lazyint lazy = new Lazyint(() = 7 * x); x = 3; x = lazy.Value; // 21 x = lazy.Value; // still 21 (Value is initialized only once) There is an annoying issue though LazyT operates in some different modes, and it also contains a member and extra code to aid debugging. So in addition to holding the value itself and a reference to the initializer delegate, it's got a couple of other member variables and the Value property has to check a couple of things before it returns the value. So what if, in the future, MS decided to optimize LazyT for its default mode of operation, and factor out other modes into derived class(es)? Well, they can't do that. If MS wants to return a LazyThreadSafeT object (derived from LazyT) when the user requests the thread-safe mode, they can't do that because all the clients are saying new Lazy, which can only return the exact class Lazy and nothing else. MS could add a static function, Lazy.New(...) but it's too late now that the interface is already defined with all those public constructors. As exhibit 2, a.k.a. exhibit Foo, I recently wrote a library where I needed to provide a constructor that does a bunch of initialization work (that may fail) before it actually creates the object. By far the most natural implementation was a static member function: // Constructor with dependency injection public Foo(arg1, arg2, arg3) { } // Static helper method provides an easy way to create MyClass public static Foo
[Issue 8381] Uniform function call syntax (pseudo member) enhancement suggestions
http://d.puremagic.com/issues/show_bug.cgi?id=8381 --- Comment #2 from David Piepgrass qwertie...@gmail.com 2012-07-12 09:24:36 PDT --- (not merely a @disabled default constructor, but no constructor at all). Also, declaring an instance of a static class is not possible either, so that given module Q; static class Foo { static P.Foo new(Bar b, Baz z) { ... return new P.Foo(...); } } The meaning is unambiguous in: Foo f = new Foo(Bar(...), Baz(...)); // equivalent to P.Foo f = Q.Foo.new(Bar(...), Baz(...)); -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 8381] Uniform function call syntax (pseudo member) enhancement suggestions
http://d.puremagic.com/issues/show_bug.cgi?id=8381 --- Comment #3 from Tommi tommitiss...@hotmail.com 2012-07-12 10:08:16 PDT --- (In reply to comment #1) - The rule is non-obvious. How could a new developer possibly guess that this happens? You could also argue that it's not obvious that: var.func(arg); ...can transform itself into: func(var, arg); I don't think it's that much different to transform: MyType.func(arg); ...into: func!(MyType)(arg); It almost looks like we're trying to pass MyType as first argument to the function, but because we can't pass type as function argument, we pass it as first template argument. But you're right that none of that is very obvious. Maybe the whole uniform function call syntax could have been implemented somehow differently so that it had been more intuitive to people new to the language. (In reply to comment #1) Supposing that I would like to extend the set of static members in class Foo. How about: module A; // assuming static class does not already have any meaning? static class Foo { static void F(); static int x; } But I really mean type when I say, extending the functionality of a type. I mean not only class but all user defined types as well, like enum, struct and union. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 8381] Uniform function call syntax (pseudo member) enhancement suggestions
http://d.puremagic.com/issues/show_bug.cgi?id=8381 deadalnix deadal...@gmail.com changed: What|Removed |Added CC||deadal...@gmail.com --- Comment #4 from deadalnix deadal...@gmail.com 2012-07-12 10:23:56 PDT --- (In reply to comment #3) (In reply to comment #1) - The rule is non-obvious. How could a new developer possibly guess that this happens? You could also argue that it's not obvious that: var.func(arg); ...can transform itself into: func(var, arg); I don't think it's that much different to transform: MyType.func(arg); ...into: func!(MyType)(arg); This is the most obvious way to transform that. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 8381] Uniform function call syntax (pseudo member) enhancement suggestions
http://d.puremagic.com/issues/show_bug.cgi?id=8381 --- Comment #5 from Tommi tommitiss...@hotmail.com 2012-07-12 10:50:58 PDT --- One small point I forgot to mention about my lowering proposal, which is that besides adding static pseudo-member functions, you can also add types. For example: struct WrapInt { int m_value; } template ValueType(T) if (is(T == WrapInt)) { alias int ValueType; } void main(string[] args) { WrapInt.ValueType value = 12; // gets lowered into: // ValueType!WrapInt value = 12; } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 8381] Uniform function call syntax (pseudo member) enhancement suggestions
http://d.puremagic.com/issues/show_bug.cgi?id=8381 --- Comment #6 from David Piepgrass qwertie...@gmail.com 2012-07-12 12:06:36 PDT --- Argh, so many typos, I should be careful when I rename things... // Static helper method provides an easy way to create MyClass public static Foo LoadFrom(string filename, ...) However, the client didn't like that, and insisted that Create() should be a constructor for consistency. I was able to rearrange things to make Create() into a constructor, but my code was a little clunkier that way. s/MyClass/Foo/ s/Create/LoadFrom/ Oh how nice it would be if we could simply correct our posts. You could also argue that it's not obvious that: var.func(arg); ...can transform itself into: func(var, arg); That feature is used very often, so newcomers will learn it quickly. And it is definitely a more obvious transformation than func!Type(...). P.S. I'm just throwing it out there, but couldn't classes themselves be treated as objects, a la Objective C? That could open the door to another approach, in which UFCS applies to class objects. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 8381] Uniform function call syntax (pseudo member) enhancement suggestions
http://d.puremagic.com/issues/show_bug.cgi?id=8381 --- Comment #7 from David Piepgrass qwertie...@gmail.com 2012-07-12 12:21:21 PDT --- It almost looks like we're trying to pass MyType as first argument to the function, but because we can't pass type as function argument, we pass it as first template argument. But you're right that none of that is very obvious. Maybe the whole uniform function call syntax could have been implemented somehow differently so that it had been more intuitive to people new to the language. Well, yeah, maybe. I could probably think of some alternatives that are a bit more intuitive than UFCS. For example I think it would be nice to allow alternate interfaces to types, something like: alias MyInt : int { bool isPrime() const { ... } } MyInt x = 7; writeln(x.isPrime()); // OK int y = x+1; writeln(y.isPrime()); // ERROR, no such function in int But I really mean type when I say, extending the functionality of a type. I mean not only class but all user defined types as well, like enum, struct and union. My proposal could easily include enums and structs, too: static enum Goo { static Goo g() {...} } static struct Hoo { static void f() {...} } It reminds me that C# allows new Hoo() for structs even though they are not allocated on the heap. If that existed in D then the static new part of my proposal could work well for structs, too. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
Re: Uniform Function Call Syntax in D - GameDev.net
Thanks to C++ for inspiration, I even have proposal for such syntax! obj.free myFunc( args ) obj.member myFunc( args ) How about: obj.myFunc( args ); // calls member function, even if free function exists myFunc( obj, args ); // calls free function, even if member function exists That is the current behavior. :-) Regards - Puneet
Re: Uniform Function Call Syntax in D - GameDev.net
Jonathan M Davis: Yes, but as I said, if it _didn't_ select the member function when there was a conflict, it would be impossible to call the member function whenever there was a conflict. There is no way to indicate that you mean a member function rather than a free function. The normal way to do that is to use member function call syntax, and UFCS allows you to then use that for free functions. With conflicts between free functions, you can do path.to.func or other.place.func instead of just func, but with a member function, that's not possible. So, without adding new syntax to the language, I understand. This is Nick Sabalausky example: import std.stdio; void bar(Foo f) { writeln(UFCS); } struct Foo { void bar() { writeln(Member); } } void main() { Foo f; f.bar(); } So let's assume the language gives an compile error here, because there is a conflict. If you want to call the free function you use bar(f). If you want to call the bar method of Foo, you can't, because it's ambiguous, and as you say there is no alternative (simple) syntax to specify you want the method of Foo. This is a limitation. But is this a problem? If you want to call Foo.bar then you don't import the free function bar in the current scope. How often do you want to keep both the free function and a method with the same name and you wan to call the method? So maybe it's worth accepting this limitation, to reduce confusion for the people the read the code. Bye, bearophile
Re: Uniform Function Call Syntax in D - GameDev.net
On Tuesday, July 03, 2012 21:55:47 bearophile wrote: So maybe it's worth accepting this limitation, to reduce confusion for the people the read the code. I would give a resounding no on that one. The confusion on how to actually manage to be able to use your member function would t hen be even greater, and if you need lots of other stuff from the module which provides the offending free function, then _not_ importing it becomes a royal pain. I think that the current approach works just fine. - Jonathan M Davis
Re: Uniform Function Call Syntax in D - GameDev.net
On 07/03/2012 09:55 PM, bearophile wrote: Jonathan M Davis: Yes, but as I said, if it _didn't_ select the member function when there was a conflict, it would be impossible to call the member function whenever there was a conflict. There is no way to indicate that you mean a member function rather than a free function. The normal way to do that is to use member function call syntax, and UFCS allows you to then use that for free functions. With conflicts between free functions, you can do path.to.func or other.place.func instead of just func, but with a member function, that's not possible. So, without adding new syntax to the language, I understand. This is Nick Sabalausky example: import std.stdio; void bar(Foo f) { writeln(UFCS); } struct Foo { void bar() { writeln(Member); } } void main() { Foo f; f.bar(); } So let's assume the language gives an compile error here, because there is a conflict. There is no conflict. The method takes precedence. If you want to call the free function you use bar(f). If you want to call the bar method of Foo, you can't, because it's ambiguous, and as you say there is no alternative (simple) syntax to specify you want the method of Foo. This is a limitation. But is this a problem? Certainly. If you want to call Foo.bar then you don't import the free function bar in the current scope. How often do you want to keep both the free function and a method with the same name and you wan to call the method? Every time you want the free function to be a generic implementation that works for everything and the method to be a specialisation for the respective type if present. The question you should be asking is: How often do you want to keep both the function and a method with the same name and don't want to call the method? I cannot think of a single case. So maybe it's worth accepting this limitation, to reduce confusion for the people the read the code. It does not do that. It does not matter whether or not a function is a member function. Why would it make any difference?
Re: Uniform Function Call Syntax in D - GameDev.net
On Monday, 2 July 2012 at 05:55:20 UTC, dennis luehring wrote: Am 02.07.2012 07:13, schrieb Jonathan M Davis: On Monday, July 02, 2012 07:00:23 dennis luehring wrote: Am 01.07.2012 23:02, schrieb Walter Bright: On 7/1/2012 11:53 AM, Nick Sabalausky wrote: That successfully compiles and prints Member. Same thing happens if you move the UFCS func and Foo definition out into their own separate modules. But I was expecting a conflict error at compile-time. Is this a bug? No, it's correct behavior. A real member overrides. isn't that some sort of highjacking then? More like it avoids hijacking. It stops you from creating a function which is used instead of the one which is on the class or struct. Granted, this does mean that you could be surprised about your external function not being called, and adding a new member function could cause your existing external function to no longer be called (which could be a problem), but realistically there's no other way to handle the situation. It's possible to explicitly give a path to the free function (e.g. path.to.function), but there's no way to do that for a member function, since there's only one way to call it. So, if you were forced to disambiguate, you could never indicate anything else other than the free function - not without introducing a new syntax to indicate the member function. - Jonathan M Davis but the compiler selects the member-functions silently - thats odd, ok i will see it very fast - but then i need to change my code anyway - so whats the reason for the silent overwrite? If it didn't overwrite silently, it would mean every single free function is now not a valid member function name. Better hope your users don't import a module that uses said free function. In my opinion, the current way is the one that makes sense. And extension methods in C# do this as well.
Re: Uniform Function Call Syntax in D - GameDev.net
On Monday, July 02, 2012 07:54:56 dennis luehring wrote: Am 02.07.2012 07:13, schrieb Jonathan M Davis: On Monday, July 02, 2012 07:00:23 dennis luehring wrote: Am 01.07.2012 23:02, schrieb Walter Bright: On 7/1/2012 11:53 AM, Nick Sabalausky wrote: That successfully compiles and prints Member. Same thing happens if you move the UFCS func and Foo definition out into their own separate modules. But I was expecting a conflict error at compile-time. Is this a bug? No, it's correct behavior. A real member overrides. isn't that some sort of highjacking then? More like it avoids hijacking. It stops you from creating a function which is used instead of the one which is on the class or struct. Granted, this does mean that you could be surprised about your external function not being called, and adding a new member function could cause your existing external function to no longer be called (which could be a problem), but realistically there's no other way to handle the situation. It's possible to explicitly give a path to the free function (e.g. path.to.function), but there's no way to do that for a member function, since there's only one way to call it. So, if you were forced to disambiguate, you could never indicate anything else other than the free function - not without introducing a new syntax to indicate the member function. - Jonathan M Davis but the compiler selects the member-functions silently - thats odd, ok i will see it very fast - but then i need to change my code anyway - so whats the reason for the silent overwrite? Yes, but as I said, if it _didn't_ select the member function when there was a conflict, it would be impossible to call the member function whenever there was a conflict. There is no way to indicate that you mean a member function rather than a free function. The normal way to do that is to use member function call syntax, and UFCS allows you to then use that for free functions. With conflicts between free functions, you can do path.to.func or other.place.func instead of just func, but with a member function, that's not possible. So, without adding new syntax to the language, it was essentially impossible to do anything other than pick the member function whenever there's a conflict. - Jonathan M Davis
Re: Uniform Function Call Syntax in D - GameDev.net
On 07/01/2012 11:11 PM, Jonathan M Davis wrote: Yes, but as I said, if it _didn't_ select the member function when there was a conflict, it would be impossible to call the member function whenever there was a conflict. I wouldn't be a fan of it but I think it would still be possible: class C { void foo() {} } void main() { auto c = new C(); auto c_foo = c.foo; c_foo(); } Ali
Re: Uniform Function Call Syntax in D - GameDev.net
On Monday, 2 July 2012 at 06:11:22 UTC, Jonathan M Davis wrote: So, without adding new syntax to the language, it was essentially impossible to do anything other than pick the member function whenever there's a conflict. Thanks to C++ for inspiration, I even have proposal for such syntax! obj.free myFunc( args ) obj.member myFunc( args ) :D
Uniform Function Call Syntax in D - GameDev.net
http://www.reddit.com/r/programming/comments/vvpfy/uniform_function_call_syntax_in_d_gamedevnet/ Andrei
Re: Uniform Function Call Syntax in D - GameDev.net
On Sun, 01 Jul 2012 11:13:10 -0400 Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: http://www.reddit.com/r/programming/comments/vvpfy/uniform_function_call_syntax_in_d_gamedevnet/ Andrei Good article. One of the commenters brought up a point about confusion from possible conflicts between UFCS funcs and member funcs. I was just about to reply saying that's not an issue in D because it would be a conflict error, but I did a little test first: --- import std.stdio; void bar(Foo f) { writeln(UFCS); } struct Foo { void bar() { writeln(Member); } } void main() { Foo f; f.bar(); } --- That successfully compiles and prints Member. Same thing happens if you move the UFCS func and Foo definition out into their own separate modules. But I was expecting a conflict error at compile-time. Is this a bug?
Re: Uniform Function Call Syntax in D - GameDev.net
Am 01.07.2012 23:02, schrieb Walter Bright: On 7/1/2012 11:53 AM, Nick Sabalausky wrote: That successfully compiles and prints Member. Same thing happens if you move the UFCS func and Foo definition out into their own separate modules. But I was expecting a conflict error at compile-time. Is this a bug? No, it's correct behavior. A real member overrides. isn't that some sort of highjacking then?
Re: Uniform Function Call Syntax in D - GameDev.net
On Monday, July 02, 2012 07:00:23 dennis luehring wrote: Am 01.07.2012 23:02, schrieb Walter Bright: On 7/1/2012 11:53 AM, Nick Sabalausky wrote: That successfully compiles and prints Member. Same thing happens if you move the UFCS func and Foo definition out into their own separate modules. But I was expecting a conflict error at compile-time. Is this a bug? No, it's correct behavior. A real member overrides. isn't that some sort of highjacking then? More like it avoids hijacking. It stops you from creating a function which is used instead of the one which is on the class or struct. Granted, this does mean that you could be surprised about your external function not being called, and adding a new member function could cause your existing external function to no longer be called (which could be a problem), but realistically there's no other way to handle the situation. It's possible to explicitly give a path to the free function (e.g. path.to.function), but there's no way to do that for a member function, since there's only one way to call it. So, if you were forced to disambiguate, you could never indicate anything else other than the free function - not without introducing a new syntax to indicate the member function. - Jonathan M Davis
Re: Uniform Function Call Syntax in D - GameDev.net
Am 02.07.2012 07:13, schrieb Jonathan M Davis: On Monday, July 02, 2012 07:00:23 dennis luehring wrote: Am 01.07.2012 23:02, schrieb Walter Bright: On 7/1/2012 11:53 AM, Nick Sabalausky wrote: That successfully compiles and prints Member. Same thing happens if you move the UFCS func and Foo definition out into their own separate modules. But I was expecting a conflict error at compile-time. Is this a bug? No, it's correct behavior. A real member overrides. isn't that some sort of highjacking then? More like it avoids hijacking. It stops you from creating a function which is used instead of the one which is on the class or struct. Granted, this does mean that you could be surprised about your external function not being called, and adding a new member function could cause your existing external function to no longer be called (which could be a problem), but realistically there's no other way to handle the situation. It's possible to explicitly give a path to the free function (e.g. path.to.function), but there's no way to do that for a member function, since there's only one way to call it. So, if you were forced to disambiguate, you could never indicate anything else other than the free function - not without introducing a new syntax to indicate the member function. - Jonathan M Davis but the compiler selects the member-functions silently - thats odd, ok i will see it very fast - but then i need to change my code anyway - so whats the reason for the silent overwrite?
Making uniform function call syntax more complete a feature
As I see it, the goal of uniform function call syntax, as described here http://www.drdobbs.com/blogs/cpp/232700394, is to allow non-intrusively extending the functionality of a type. I think the current implementation comes short in accomplishing this goal on two accounts: 1) You can't non-intrusively add static member functions 2) You can't non-intrusively add constructors So, I'm suggesting these two features to be added to the language: 1. Static method lowering rules If function calls like the following are encountered... A) Type.compute(ARGUMENTS); B) Type.compute; // it's a static @property function ...and the compute functions haven't been implemented by Type, they get lowered into free function calls... A) compute!(Type)(ARGUMENTS); B) compute!(Type); 2. Constructors as free functions If a constructor call hasn't been implemented by Type... auto t = Type(ARGUMENTS); ...then it get's lowered into a free function call... auto t = this!(Type)(ARGUMENTS); (or something like that)
Re: Making uniform function call syntax more complete a feature
On 2012-06-17 08:39, Tommi wrote: As I see it, the goal of uniform function call syntax, as described here http://www.drdobbs.com/blogs/cpp/232700394, is to allow non-intrusively extending the functionality of a type. I think the current implementation comes short in accomplishing this goal on two accounts: 1) You can't non-intrusively add static member functions 2) You can't non-intrusively add constructors So, I'm suggesting these two features to be added to the language: 1. Static method lowering rules If function calls like the following are encountered... A) Type.compute(ARGUMENTS); B) Type.compute; // it's a static @property function ...and the compute functions haven't been implemented by Type, they get lowered into free function calls... A) compute!(Type)(ARGUMENTS); B) compute!(Type); 2. Constructors as free functions If a constructor call hasn't been implemented by Type... auto t = Type(ARGUMENTS); ...then it get's lowered into a free function call... auto t = this!(Type)(ARGUMENTS); (or something like that) I like that idea. -- /Jacob Carlborg
[Issue 3382] [tdpl] Implement uniform function call syntax
http://d.puremagic.com/issues/show_bug.cgi?id=3382 Walter Bright bugzi...@digitalmars.com changed: What|Removed |Added Status|NEW |RESOLVED Resolution||FIXED -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3382] [tdpl] Implement uniform function call syntax
http://d.puremagic.com/issues/show_bug.cgi?id=3382 --- Comment #5 from github-bugzi...@puremagic.com 2012-03-07 23:19:18 PST --- Commit pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/b7742f7a733ff73d364c6ed54af70d875d7e911b Merge pull request #582 from 9rnsr/fix3382_ufcs Issue 3382 - [tdpl] Implement uniform function call syntax -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3382] [tdpl] Implement uniform function call syntax
http://d.puremagic.com/issues/show_bug.cgi?id=3382 --- Comment #3 from Kenji Hara k.hara...@gmail.com 2011-12-26 05:42:06 PST --- Related: - Issue 662 - Allow UFCS for basic types and enums - Issue 6277 - Disallow short floating point literals -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3382] [tdpl] Implement uniform function call syntax
http://d.puremagic.com/issues/show_bug.cgi?id=3382 Kenji Hara k.hara...@gmail.com changed: What|Removed |Added Keywords||patch --- Comment #4 from Kenji Hara k.hara...@gmail.com 2011-12-26 06:16:50 PST --- https://github.com/D-Programming-Language/dmd/pull/582 https://github.com/D-Programming-Language/phobos/pull/378 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 3382] TDPL Implement uniform function call syntax
http://d.puremagic.com/issues/show_bug.cgi?id=3382 Nick Sabalausky cbkbbej...@mailinator.com changed: What|Removed |Added CC||a11160...@nepwk.com --- Comment #2 from Nick Sabalausky cbkbbej...@mailinator.com 2011-11-18 07:33:09 PST --- *** Issue 6970 has been marked as a duplicate of this issue. *** -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
Re: Uniform Function Call Syntax(UFCS) and @property
On Sat, 05 Mar 2011 19:15:17 -0500, kenji hara k.hara...@gmail.com wrote: 2011/3/4 Steven Schveighoffer schvei...@yahoo.com: Also, keep in mind that I think UFCS should be restricted to builtins only (i.e. primitives + arrays, not AA's, since they map to a struct that can be customized in druntime). To provide multiple ways for one to add members to classes/structs causes huge ambiguity/hijacking issues. I think the ambiguity/hijacking will be resolved by overload set. You do? The problem is when there is a conflict between an actual member funtion, and a free function which takes the type as its first argument. Who wins? The obvious choice is the member function. But let's say the member function is added to the type long after the external function exists. People who have written code that uses the external function via UFCS all of a sudden are now calling the member function, without warning. This is a form of hijacking. You could say an ambiguous case should be an error, but then someone is able to issue a sort of denial of service attack by simply defining a free function which coincides with a member function. With builtins, there is no conflict. You cannot define member functions for integers or for arrays, so the ambiguity is gone. And let's also not forget the WTF factor of when you read code that uses a UFCS function, where would be the first place you look for it? In the class or struct. I see almost no benefit for having UFCS on classes and structs. It is already possible to add member functions to those types, and the difference between x(y) and y.x() is extremely trivial. If anything, this makes member functions lose their specificity -- a member function is no longer attributed to the struct or class, it can be defined anywhere. -Steve
Re: Uniform Function Call Syntax(UFCS) and @property
On Mon, 07 Mar 2011 13:28:26 -0500, kenji hara k.hara...@gmail.com wrote: The problem is when there is a conflict between an actual member funtion, and a free function which takes the type as its first argument. Who wins? The obvious choice is the member function. But let's say the member function is added to the type long after the external function exists. People who have written code that uses the external function via UFCS all of a sudden are now calling the member function, without warning. This is a form of hijacking. Why do you prefer module functions? It will be selected by UFCS only when there is no member that has the same name in class/struct. It is clear. I'll give you an example. This assumes that the compiler silently prefers member functions over free ones. Say you are using a struct from a library you didn't write like this: struct Foo { int x; } And you want to read data into it. So you write your own function: void read(ref Foo f) { readf(%d, f.x); } So now, you can write stuff like: Foo f; f.read(); and things work great! But a few years later, the author of foo decides to add serialization to Foo, and does: struct Foo { int x; void read() { readf(%x, f.x); } void write() { writef(%x, f.x); } } All of a sudden, all the code you had that did f.read() now calls the member, which does something subtly different. You could say an ambiguous case should be an error, but then someone is able to issue a sort of denial of service attack by simply defining a free function which coincides with a member function. I don't understand the meaning of denial of service what you say. Is it causing compile error? It is same behavior with overload set conflict. If the ambiguity is simply flagged as an error by the compiler, by simply defining a function with the same name outside the class or struct, you can deny access to the member function. Following the above example, if my localized read(ref Foo f) is defined in a common library module, anyone who uses my code (but not my read function) now wants to use the new Foo.read member function, it always results in a compile error. In essence, there is actually no way to access that member unless you stop importing my module. Maybe I could care less that it's a problem you have, I've since changed all my code to read(f) instead of f.read() to workaround my problem. These problems allow either hijacking of a function, or denying an object it's basic ability to define new members that are specific to itself. For all this confusion and pain, I think it's not worth the benefit of being able to do f.read() vs. read(f). With builtins, there is no conflict. You cannot define member functions for integers or for arrays, so the ambiguity is gone. Almost yes. (Builtin array has 'length' property. It may conflict module function 'length'.) Yes, but those are builtin properties, disallowed from day 1. Essentially, there is no way for an ambiguity to 'creep' into the code, since you could never call your length function via arr.length(). I see almost no benefit for having UFCS on classes and structs. It is already possible to add member functions to those types, and the difference between x(y) and y.x() is extremely trivial. If anything, this makes member functions lose their specificity -- a member function is no longer attributed to the struct or class, it can be defined anywhere. UFCS is veri usuful. It reduce fat interfaces of class/struct, and separate 'useful but surrounded operation' from core operations of the object. A simple example is std.stdio.File.writefln. This function does the almost same job std.stdio.writefln. Correct UFCS will cut wastes like this. std.stdio.writefln forwards *directly* to stdout.writefln. Boilerplate code like this should be inlined out. I see zero waste here. Actually, the way writefln works, I think you picked an example that would not be affected by UFCS. writefln without a File argument would still need to exist in order to select stdout as the destination. But in any case, the difference between calling a free function and a member is so small that there really is no gain. You want to define a function that works on multiple types? It works, you just have to call func(t, ...) instead of t.func(...). I'd rather keep member functions as members, and external functions as external functions, as it adds to the understanding/readability. And the potential for abuse grows. For example, this should probably work today (not tested): %d.writefln(5); And with UFCS, I now have a slew of types which allow this kind of abuse. -Steve
Re: Uniform Function Call Syntax(UFCS) and @property
2011/3/8 Steven Schveighoffer schvei...@yahoo.com: I'll give you an example. This assumes that the compiler silently prefers member functions over free ones. Say you are using a struct from a library you didn't write like this: struct Foo { int x; } And you want to read data into it. So you write your own function: void read(ref Foo f) { readf(%d, f.x); } So now, you can write stuff like: Foo f; f.read(); and things work great! But a few years later, the author of foo decides to add serialization to Foo, and does: struct Foo { int x; void read() { readf(%x, f.x); } void write() { writef(%x, f.x); } } All of a sudden, all the code you had that did f.read() now calls the member, which does something subtly different. On last version, f.read should be compile error. Foo.read forms a single overload set, and module function forms another overload set. The overlap generates error. An overload set is formed by a group of functions with the same name declared in the same scope. http://www.digitalmars.com/d/2.0/hijack.html This is the definition of overload set, therefore It is appropriate to me that Foo.read and module function read form two overload set. If the ambiguity is simply flagged as an error by the compiler, by simply defining a function with the same name outside the class or struct, you can deny access to the member function. Following the above example, if my localized read(ref Foo f) is defined in a common library module, anyone who uses my code (but not my read function) now wants to use the new Foo.read member function, it always results in a compile error. In essence, there is actually no way to access that member unless you stop importing my module. Maybe I could care less that it's a problem you have, I've since changed all my code to read(f) instead of f.read() to workaround my problem. These problems allow either hijacking of a function, or denying an object it's basic ability to define new members that are specific to itself. For all this confusion and pain, I think it's not worth the benefit of being able to do f.read() vs. read(f). Yes. In my opinnion, UFCS refuse hijacking based on overload set rule. With builtins, there is no conflict. You cannot define member functions for integers or for arrays, so the ambiguity is gone. Almost yes. (Builtin array has 'length' property. It may conflict module function 'length'.) Yes, but those are builtin properties, disallowed from day 1. Essentially, there is no way for an ambiguity to 'creep' into the code, since you could never call your length function via arr.length(). Builtin property vs UFCS should generate error because it makes overload set overlapping. std.stdio.writefln forwards *directly* to stdout.writefln. Boilerplate code like this should be inlined out. I see zero waste here. Actually, the way writefln works, I think you picked an example that would not be affected by UFCS. writefln without a File argument would still need to exist in order to select stdout as the destination. But in any case, the difference between calling a free function and a member is so small that there really is no gain. You want to define a function that works on multiple types? It works, you just have to call func(t, ...) instead of t.func(...). I'd rather keep member functions as members, and external functions as external functions, as it adds to the understanding/readability. Sorry, it does not work exactly same. In my opinion: 1. File will be changed with range based design. 2. writef/writefln may replace using formattedWrite. Then, File and formatting output will be following code: File f;// future: File will have output-range interface f.formattedWrite(%s, ...); // UFCS - formattedWrite(f, %s, ...); // f.writef(%s, ...); // naming may be replaced..? This approach separate File I/O and string formatting preciously. And `any` string output range can have formattedWrite/writef. And the potential for abuse grows. For example, this should probably work today (not tested): %d.writefln(5); And with UFCS, I now have a slew of types which allow this kind of abuse. This bad syntax should be refused. My first suggestion Only the free function its first parameter named 'this' can use with UFCS. achieve this purpose. I don't deny that the benefit of UFCS is only 'looks'. But natural syntax has well worth for code reading. And UFCS is possible to add 'members' non-intrusive. If member name conflict occurs, overload set rule make it an error. Necessary to realize useful UFCS is appropriate annotations. 'named this first parameter' is low cost, cachy, and doesn't need ugly annotation syntax like @UFCS. Kenji
Re: Uniform Function Call Syntax(UFCS) and @property
Additional point in my opinion: Calling UFCS-able annotated function by normal function call syntax is still vaild. But not annotatied function shouldn't be allowed with member-like call syntax. void f(T)(T this, int n){...} // UFCS annotated void g(T)(T x, int n){...}// do not UFCS annotated struct Foo{} Foo foo; foo.f(10); // member-like syntax - ok f(foo, 10); // normal call syntax - still ok - UNIFIED function call syntax. //foo.g(10); // Invalid g(foo, 10);// normal call syntax - ok Kenji
Re: Uniform Function Call Syntax(UFCS) and @property
On Monday, March 07, 2011 15:43:27 kenji hara wrote: Necessary to realize useful UFCS is appropriate annotations. 'named this first parameter' is low cost, cachy, and doesn't need ugly annotation syntax like @UFCS. Using an attribute (whatever it would be) would be far more in keeping with how the rest of the language works. That's the sort of thing that attributes are _for_. - Jonathan M Davis
Re: Uniform Function Call Syntax(UFCS) and @property
On 03/05/2011 03:50 AM, Michel Fortin wrote: On 2011-03-04 13:04:59 -0500, Jim bitcir...@yahoo.com said: Jonathan M Davis Wrote: On Friday 04 March 2011 04:59:14 David Nadlinger wrote: On 3/3/11 10:27 PM, Jonathan M Davis wrote: I'd strongly argue that global/module properties make no sense. What are they a property of? The module? You could as well say: I'd strongly argue that global/module variables make no sense. What are they a variable of? The module? In my opinion, allowing global variables but not global properties just creates yet another unneeded special case. I see no special case or inconsistency. The original idea behind a property (as I understand it) is to abstract member variables so that you can easily switch between having a public member variable and having a public member function without having to change code. The term property implies that it is a property or attribute of whatever it's on. A global variable or a local variable or any kind of variable not on a class or struct is free-floating and not a property or attribute of anything. How many languages which have properties have them on _anything_ other than objects? I was surprised that anyone would suggest that @property could be used on anything other than a class or struct's member function. I strongly suspect that the main reason that anyone is thinking that way is because properties in D grew out of being able to call pretty much any old function without parens as long as it had no parameters instead of based on the concept of properties to begin with as it likely would have been in other languages. - Jonathan M Davis Let's talk about accessors instead of properties because we are talking about the functions, right, not the storage per se? @getter, @setter as proposed by Michel Fortin. Actually, there's a big drawback in having separate @getter and @setter attributes: grouping functions under one attribute declaration like this becomes impractical: @property { int length(); void length(int); int capacity(); void capacity(int); } This let me think at the actual functionality provided by the so-called property feature. The following is more or less thinking out loud: * An implicite getter allows 1. calling a method running computations while letting think it's just data member access. I find this bad. The good point is a change in implementation, from data to method member, won't break code, *if and only if* the new feature does not require any param (!). Even then, silently adding a method call possibly costly computation is imo bad. 2. Implementing a setter for 4. * An implicite setter allows: 3. Implementing a getter for 1. 4. Performing effects which are a logical consequence of the data member change. Eg p.x = 1; would actually /move/ p. I find this bad: there should be a move method, and a read-only x data member. * A getter without setter allows: 5. Read-only data members (to the price of language complication a method call). Finally, I think what we actually need is a read-only qualifier for data members. (E basta!) Denis -- _ vita es estrany spir.wikidot.com
Re: Uniform Function Call Syntax(UFCS) and @property
2011/3/4 Steven Schveighoffer schvei...@yahoo.com: Also, keep in mind that I think UFCS should be restricted to builtins only (i.e. primitives + arrays, not AA's, since they map to a struct that can be customized in druntime). To provide multiple ways for one to add members to classes/structs causes huge ambiguity/hijacking issues. I think the ambiguity/hijacking will be resolved by overload set. You do? Kenji
Re: Uniform Function Call Syntax(UFCS) and @property
On Saturday 05 March 2011 16:15:17 kenji hara wrote: 2011/3/4 Steven Schveighoffer schvei...@yahoo.com: Also, keep in mind that I think UFCS should be restricted to builtins only (i.e. primitives + arrays, not AA's, since they map to a struct that can be customized in druntime). To provide multiple ways for one to add members to classes/structs causes huge ambiguity/hijacking issues. I think the ambiguity/hijacking will be resolved by overload set. You do? It likely would be, but once you add in alias this and opDispatch, it gets rather complicated (I'm still not sure how alias this and opDispatch gets sorted out when there's a conflict between them). So, we're going to have to look at all of the various combinations of what could happen fairly carefully to be sure of what exactly the ramifications will be. Personally, I see little point to UFCS if it's just for primitive types. Calls such as 7.max(5) seem quite pointless to me. The only advantage is that templated code could treat primitive types exactly the same as user-defined types, but how often do you really have a function which could be called on any type which would be a member function of a user-defined type but a free function for primitive types? I don't think that I've _ever_ seen that. So, I see the benefit of UFCS with regards to primitives to be limited. If that's all that we're going to get out of it, I see no reason to complicate things by adding UFCS to the language. - Jonathan M Davis
Re: Uniform Function Call Syntax(UFCS) and @property
2011/3/6 Jonathan M Davis jmdavisp...@gmx.com: It likely would be, but once you add in alias this and opDispatch, it gets rather complicated (I'm still not sure how alias this and opDispatch gets sorted out when there's a conflict between them). So, we're going to have to look at all of the various combinations of what could happen fairly carefully to be sure of what exactly the ramifications will be. In my opinion, UFCS should have low priority than member variable/function/alias this/opDispatch. UFCS is outermost level of name lookup. (Speaking of adding, alias this may be preferred rather than opDispatch.) Personally, I see little point to UFCS if it's just for primitive types. Calls such as 7.max(5) seem quite pointless to me. The only advantage is that templated code could treat primitive types exactly the same as user-defined types, but how often do you really have a function which could be called on any type which would be a member function of a user-defined type but a free function for primitive types? I don't think that I've _ever_ seen that. So, I see the benefit of UFCS with regards to primitives to be limited. If that's all that we're going to get out of it, I see no reason to complicate things by adding UFCS to the language. I also think that 7.max(5) quite pointless. But @property has similar problem, because of current dmd implementation. Now @property has no enforcement. I think the function anotated with @property should be called with no paren. E.g. member property attribute call with paren: obj.attribute() - It's occurs serious semantic conflict. UFCS has same circumstance. I want to prevent writing it (7.max(5)). My suggestion that first parameter named 'this' provides information enough to archives this purpose. Kenji
Re: Uniform Function Call Syntax(UFCS) and @property
On Saturday 05 March 2011 16:59:35 kenji hara wrote: 2011/3/6 Jonathan M Davis jmdavisp...@gmx.com: It likely would be, but once you add in alias this and opDispatch, it gets rather complicated (I'm still not sure how alias this and opDispatch gets sorted out when there's a conflict between them). So, we're going to have to look at all of the various combinations of what could happen fairly carefully to be sure of what exactly the ramifications will be. In my opinion, UFCS should have low priority than member variable/function/alias this/opDispatch. UFCS is outermost level of name lookup. (Speaking of adding, alias this may be preferred rather than opDispatch.) Personally, I see little point to UFCS if it's just for primitive types. Calls such as 7.max(5) seem quite pointless to me. The only advantage is that templated code could treat primitive types exactly the same as user-defined types, but how often do you really have a function which could be called on any type which would be a member function of a user-defined type but a free function for primitive types? I don't think that I've _ever_ seen that. So, I see the benefit of UFCS with regards to primitives to be limited. If that's all that we're going to get out of it, I see no reason to complicate things by adding UFCS to the language. I also think that 7.max(5) quite pointless. But @property has similar problem, because of current dmd implementation. Now @property has no enforcement. I think the function anotated with @property should be called with no paren. E.g. member property attribute call with paren: obj.attribute() - It's occurs serious semantic conflict. Eventually, it _will_ be enforced that @property functions be called without parens and that non-property functions be called _with_ parens, but that hasn't happened yet. And there are a number of bugs related to @property which should probably be sorted out _before_ that happens, or there's code which will become illegal to call, because you won't be able to call it with the property syntax in spite of the fact that you _have_ to (for instance, I believe that there are some problems with functions which return ref and are both setters and getters which have to be called with () to work at the moment). UFCS has same circumstance. I want to prevent writing it (7.max(5)). My suggestion that first parameter named 'this' provides information enough to archives this purpose. Well, it's not really universal if it doesn't generally work for anything, rather than only specific functions, and I do _not_ want it to get overly complicated, so I definitely dislike the idea of having a parameter named this do it. That strikes me as being way to fragile and unclear a rule. _If_ we want to restrict UFCS in that way, then I think that we should simply add a new property (e.g. @UFCS or @universal) which enables it. That would be far clearer and require less in the way of special casing by the compiler. - Jonathan M Davis
Re: Uniform Function Call Syntax(UFCS) and @property
On Thursday 03 March 2011 21:44:20 kenji hara wrote: 2011/3/4 Jonathan M Davis jmdavisp...@gmx.com: On Thursday, March 03, 2011 14:07:30 Steven Schveighoffer wrote: On Thu, 03 Mar 2011 16:56:45 -0500, Jonathan M Davis jmdavisp...@gmx.com wrote: Conceptually, a property makes no sense unless it's a property _of_ something. This is your opinion, not fact. It is a property of the program/global namespace/module whatever you want to call it. Per the definition of the word property, a property must be property _of_ something. Anything else would violate the definition of the word (not that programming has ever held itself all that firmly to English definitions). You can certainly argue that a global property is a property of a module, at which point it _does_ make sense in the sense that it is then a property _of_ the module. However, I definitely think that that's pushing it. Modules are really only organizational entities, not things that you deal with directly in the code. And I can basically agree with you. But that reason can not limit the design of the module. Some of D users may consider a module as a singleton. We can't prohibit it. if you have a property of a module, then it's more like treating @property purely as an abstraction of a variable rather than really being a property of something. At that point, I'd almost argue that the annotation should have been @variable instead. I still have the opposite viewpoint with you. A property of a module should be annotated with @property. Regardless, I'd still argue that @property shouldn't be allowed at the module level as long as it's going to create ambiguities. And adding extra rules or syntax to make it unambiguous as Kenji is suggesting seems like overkill. Current @property annotation does not have enforcement. When this has been improved in the future, the way annotating ’this' on UFCS will be also necessary. Only if you allow functions which are properties of modules. - Jonathan M Davis
Re: Uniform Function Call Syntax(UFCS) and @property
Jonathan M Davis Wrote: On Thursday 03 March 2011 21:44:20 kenji hara wrote: 2011/3/4 Jonathan M Davis jmdavisp...@gmx.com: On Thursday, March 03, 2011 14:07:30 Steven Schveighoffer wrote: On Thu, 03 Mar 2011 16:56:45 -0500, Jonathan M Davis jmdavisp...@gmx.com wrote: Conceptually, a property makes no sense unless it's a property _of_ something. This is your opinion, not fact. It is a property of the program/global namespace/module whatever you want to call it. Per the definition of the word property, a property must be property _of_ something. Anything else would violate the definition of the word (not that programming has ever held itself all that firmly to English definitions). You can certainly argue that a global property is a property of a module, at which point it _does_ make sense in the sense that it is then a property _of_ the module. However, I definitely think that that's pushing it. Modules are really only organizational entities, not things that you deal with directly in the code. And I can basically agree with you. But that reason can not limit the design of the module. Some of D users may consider a module as a singleton. We can't prohibit it. if you have a property of a module, then it's more like treating @property purely as an abstraction of a variable rather than really being a property of something. At that point, I'd almost argue that the annotation should have been @variable instead. I still have the opposite viewpoint with you. A property of a module should be annotated with @property. Regardless, I'd still argue that @property shouldn't be allowed at the module level as long as it's going to create ambiguities. And adding extra rules or syntax to make it unambiguous as Kenji is suggesting seems like overkill. Current @property annotation does not have enforcement. When this has been improved in the future, the way annotating this' on UFCS will be also necessary. Only if you allow functions which are properties of modules. - Jonathan M Davis This @property thing where: if(t.empty); is translated to if(empty(t)); looks a lot like reversed functional composition in mathematics where: fun.gun(); would be translated to gun(fun()); if fun: X - Y and gun: Y - Z (I say reversed because it's usually written in the other order, like this g #8728; f, that is g /circle/ f.) So, what do you think about this translation? Although it is the same type of transformation, but I wouldn't call this @property because it isn't a property _of_ something.
Re: Uniform Function Call Syntax(UFCS) and @property
On 3/4/11 1:44 PM, Jim wrote: […] So, what do you think about this translation? Although it is the same type of transformation, but I wouldn't call this @property because it isn't a property _of_ something. This isn't what @property is about, but describes uniform function call syntax. The @property annotation is just about being able to omit the parentheses on a parameterless function call and to pass in a single parameter via the equals sign. David
Re: Uniform Function Call Syntax(UFCS) and @property
On 3/3/11 10:27 PM, Jonathan M Davis wrote: I'd strongly argue that global/module properties make no sense. What are they a property of? The module? You could as well say: I'd strongly argue that global/module variables make no sense. What are they a variable of? The module? In my opinion, allowing global variables but not global properties just creates yet another unneeded special case. David
Re: Uniform Function Call Syntax(UFCS) and @property
On Thu, 03 Mar 2011 18:03:48 -0500, Jonathan M Davis jmdavisp...@gmx.com wrote: On Thursday, March 03, 2011 14:07:30 Steven Schveighoffer wrote: On Thu, 03 Mar 2011 16:56:45 -0500, Jonathan M Davis jmdavisp...@gmx.com wrote: Conceptually, a property makes no sense unless it's a property _of_ something. This is your opinion, not fact. It is a property of the program/global namespace/module whatever you want to call it. Per the definition of the word property, a property must be property _of_ something. Anything else would violate the definition of the word (not that programming has ever held itself all that firmly to English definitions). You can certainly argue that a global property is a property of a module, at which point it _does_ make sense in the sense that it is then a property _of_ the module. However, I definitely think that that's pushing it. I was debating this assumption you have made in making your statement, not the statement itself. Sorry, I sometimes don't express myself very well. I'll try again: It is your opinion that modules or classes/structs do not qualify as entities to define properties on. Not a fact. I disagree completely, and have given several counter-cases. What do you say about the examples, such as the Singleton, or the cache variable I use in druntime? Regardless, I'd still argue that @property shouldn't be allowed at the module level as long as it's going to create ambiguities. And adding extra rules or syntax to make it unambiguous as Kenji is suggesting seems like overkill. I don't disagree that making syntax might be overkill. But making rules that are not consistent doesn't make sense either. If I have a place I can put a variable, I should be also able to put a property there. Note that there is only one (currently) ambiguous case, the case of a getter on an array or a setter on the module. A setter on an array cannot be confused with something else, as well as a getter for the module. What we need is a syntax to disambiguate. So essentially, we take the most common case, and declare that as the default. But if you define the property this way * then it becomes a property the other way. Also, keep in mind that I think UFCS should be restricted to builtins only (i.e. primitives + arrays, not AA's, since they map to a struct that can be customized in druntime). To provide multiple ways for one to add members to classes/structs causes huge ambiguity/hijacking issues. Just thought of this, I think this might be good enough: @property(out) denotes a getter on its single argument for functions that are at the module level and have one argument: * if the property is inside a class or struct, then properties with no args are always getters, properties with a single arg are always setters. * if the property is outside a class or struct, and it has no arguments, it's a module getter * if the property is outside a class or struct, and it has one argument, it's a module setter (use @property(out) to change it to a getter on the first argument) * if the property is outside a class or struct, and it has two arguments, it's a setter on the first argument, as long as that first argument supports UFCS. We could define @property(in) also, and allow the syntax everywhere, but I think nobody will ever use it in unambiguous cases. Other possibilities could be used inside the parens. -Steve
Re: Uniform Function Call Syntax(UFCS) and @property
On Friday 04 March 2011 04:59:14 David Nadlinger wrote: On 3/3/11 10:27 PM, Jonathan M Davis wrote: I'd strongly argue that global/module properties make no sense. What are they a property of? The module? You could as well say: I'd strongly argue that global/module variables make no sense. What are they a variable of? The module? In my opinion, allowing global variables but not global properties just creates yet another unneeded special case. I see no special case or inconsistency. The original idea behind a property (as I understand it) is to abstract member variables so that you can easily switch between having a public member variable and having a public member function without having to change code. The term property implies that it is a property or attribute of whatever it's on. A global variable or a local variable or any kind of variable not on a class or struct is free-floating and not a property or attribute of anything. How many languages which have properties have them on _anything_ other than objects? I was surprised that anyone would suggest that @property could be used on anything other than a class or struct's member function. I strongly suspect that the main reason that anyone is thinking that way is because properties in D grew out of being able to call pretty much any old function without parens as long as it had no parameters instead of based on the concept of properties to begin with as it likely would have been in other languages. - Jonathan M Davis
Re: Uniform Function Call Syntax(UFCS) and @property
On 2011-03-04 08:30:44 -0500, Steven Schveighoffer schvei...@yahoo.com said: Note that there is only one (currently) ambiguous case, the case of a getter on an array or a setter on the module. A setter on an array cannot be confused with something else, as well as a getter for the module. What we need is a syntax to disambiguate. So essentially, we take the most common case, and declare that as the default. But if you define the property this way * then it becomes a property the other way. Perhaps instead of @property we should have had @getter and @setter. It's shorter to write and easier to disambiguate. It might be too late to change that however. Another idea someone proposed (I can't find the exact post to give proper credit) would be to allow having a parameter named 'this'. This would allow the creation of non-member functions using the member syntax as with the Uniform Function Call Syntax but without the Uniform part: only function specially labeled this way would be eligible to the member call syntax. This would solve our property problem, but is dependent on how UFCS is implemented. Disallowing global-scope properties isn't very appealing to me. I hear Jonathan's plea that the word property means a property *of* something, implying it should be a member, but I think it's hair splitting. D has always allowed properties at global scope, I see no reason to change that only because we used the perhaps-not-totally-appropriate word property to name such a concept. -- Michel Fortin michel.for...@michelf.com http://michelf.com/
Re: Uniform Function Call Syntax(UFCS) and @property
Jonathan M Davis Wrote: On Friday 04 March 2011 04:59:14 David Nadlinger wrote: On 3/3/11 10:27 PM, Jonathan M Davis wrote: I'd strongly argue that global/module properties make no sense. What are they a property of? The module? You could as well say: I'd strongly argue that global/module variables make no sense. What are they a variable of? The module? In my opinion, allowing global variables but not global properties just creates yet another unneeded special case. I see no special case or inconsistency. The original idea behind a property (as I understand it) is to abstract member variables so that you can easily switch between having a public member variable and having a public member function without having to change code. The term property implies that it is a property or attribute of whatever it's on. A global variable or a local variable or any kind of variable not on a class or struct is free-floating and not a property or attribute of anything. How many languages which have properties have them on _anything_ other than objects? I was surprised that anyone would suggest that @property could be used on anything other than a class or struct's member function. I strongly suspect that the main reason that anyone is thinking that way is because properties in D grew out of being able to call pretty much any old function without parens as long as it had no parameters instead of based on the concept of properties to begin with as it likely would have been in other languages. - Jonathan M Davis Let's talk about accessors instead of properties because we are talking about the functions, right, not the storage per se? @getter, @setter as proposed by Michel Fortin.
Re: Uniform Function Call Syntax(UFCS) and @property
On 03/04/2011 06:26 PM, Michel Fortin wrote: Another idea someone proposed (I can't find the exact post to give proper credit) would be to allow having a parameter named 'this'. This would allow the creation of non-member functions using the member syntax as with the Uniform Function Call Syntax but without the Uniform part: only function specially labeled this way would be eligible to the member call syntax. This would solve our property problem, but is dependent on how UFCS is implemented. Lua version (center on add a new method): -- hand-baked Lua OO type Point = { this = function (p, coords) point = {x=0, y=0} for k,v in pairs(coords) do point[k] = v end return setmetatable(point, Point) end , __tostring = function (point) return Point( .. point.x .. , .. point.y .. ) end , } Point.__call = Point.this Point.__index = Point setmetatable(Point, Point) -- a point point = Point {x=1, y=2} print (point) -- Point(1,2) -- add a new method Point.move = function (point, offset) point.x = point.x + offset.x point.y = point.y + offset.y end -- applicate added method (special syntax ':') point:move {x=3, y=4} print (point) -- Point(4,6) Denis -- _ vita es estrany spir.wikidot.com
Re: Uniform Function Call Syntax(UFCS) and @property
On 2011-03-04 13:04:59 -0500, Jim bitcir...@yahoo.com said: Jonathan M Davis Wrote: On Friday 04 March 2011 04:59:14 David Nadlinger wrote: On 3/3/11 10:27 PM, Jonathan M Davis wrote: I'd strongly argue that global/module properties make no sense. What are they a property of? The module? You could as well say: I'd strongly argue that global/module variables make no sense. What are they a variable of? The module? In my opinion, allowing global variables but not global properties just creates yet another unneeded special case. I see no special case or inconsistency. The original idea behind a property (as I understand it) is to abstract member variables so that you can easily switch between having a public member variable and having a public member function without having to change code. The term property implies that it is a property or attribute of whatever it's on. A global variable or a local variable or any kind of variable not on a class or struct is free-floating and not a property or attribute of anything. How many languages which have properties have them on _anything_ other than objects? I was surprised that anyone would suggest that @property could be used on anything other than a class or struct's member function. I strongly suspect that the main reason that anyone is thinking that way is because properties in D grew out of being able to call pretty much any old function without parens as long as it had no parameters instead of based on the concept of properties to begin with as it likely would have been in other languages. - Jonathan M Davis Let's talk about accessors instead of properties because we are talking about the functions, right, not the storage per se? @getter, @setter as proposed by Michel Fortin. Actually, there's a big drawback in having separate @getter and @setter attributes: grouping functions under one attribute declaration like this becomes impractical: @property { int length(); void length(int); int capacity(); void capacity(int); } -- Michel Fortin michel.for...@michelf.com http://michelf.com/
Re: Uniform Function Call Syntax(UFCS) and @property
On Friday 04 March 2011 18:50:59 Michel Fortin wrote: On 2011-03-04 13:04:59 -0500, Jim bitcir...@yahoo.com said: Jonathan M Davis Wrote: On Friday 04 March 2011 04:59:14 David Nadlinger wrote: On 3/3/11 10:27 PM, Jonathan M Davis wrote: I'd strongly argue that global/module properties make no sense. What are they a property of? The module? You could as well say: I'd strongly argue that global/module variables make no sense. What are they a variable of? The module? In my opinion, allowing global variables but not global properties just creates yet another unneeded special case. I see no special case or inconsistency. The original idea behind a property (as I understand it) is to abstract member variables so that you can easily switch between having a public member variable and having a public member function without having to change code. The term property implies that it is a property or attribute of whatever it's on. A global variable or a local variable or any kind of variable not on a class or struct is free-floating and not a property or attribute of anything. How many languages which have properties have them on _anything_ other than objects? I was surprised that anyone would suggest that @property could be used on anything other than a class or struct's member function. I strongly suspect that the main reason that anyone is thinking that way is because properties in D grew out of being able to call pretty much any old function without parens as long as it had no parameters instead of based on the concept of properties to begin with as it likely would have been in other languages. - Jonathan M Davis Let's talk about accessors instead of properties because we are talking about the functions, right, not the storage per se? @getter, @setter as proposed by Michel Fortin. Actually, there's a big drawback in having separate @getter and @setter attributes: grouping functions under one attribute declaration like this becomes impractical: @property { int length(); void length(int); int capacity(); void capacity(int); } Personally, I don't find that to be any great loss. I've never liked the ability to apply attributes to functions in bulk like that. The only attributes that I ever do that sort of thing with are private, protected, package, and public. And those I use : for. Regardless, the other problem is functions like @property auto ref front() {...} They're both the getter and the setter thanks to the ref. So, unless it was legal to mark such functions with both @getter and @setter, you'd need an attribute for marking functions which were both. - Jonathan M Davis
Uniform Function Call Syntax(UFCS) and @property
The two semantics have no relation with each other. My idea is that we allow 'this' keyword as the first parameter of free function: T t; void method(T)(ref T this){...} -- t.method(); void method(T, A...)(ref T this, A args){...} -- t.method(arg1, arg2); @property bool empty(T)(ref T this){...} -- if (t.empty){...} @property void empty(T)(ref T this, bool f){...} -- t.empty = true; Do you think?
Re: Uniform Function Call Syntax(UFCS) and @property
On 03/03/2011 10:52 AM, kenji hara wrote: The two semantics have no relation with each other. My idea is that we allow 'this' keyword as the first parameter of free function: T t; void method(T)(ref T this){...} -- t.method(); void method(T, A...)(ref T this, A args){...} -- t.method(arg1, arg2); @property bool empty(T)(ref T this){...} -- if (t.empty){...} @property void empty(T)(ref T this, bool f){...} -- t.empty = true; Do you think? This is about Lua's solution on the topic (except there is no 'this' keyword, the object's name is free.) Denis -- _ vita es estrany spir.wikidot.com
Re: Uniform Function Call Syntax(UFCS) and @property
On Thursday 03 March 2011 01:52:09 kenji hara wrote: The two semantics have no relation with each other. My idea is that we allow 'this' keyword as the first parameter of free function: T t; void method(T)(ref T this){...} -- t.method(); void method(T, A...)(ref T this, A args){...} -- t.method(arg1, arg2); @property bool empty(T)(ref T this){...} -- if (t.empty){...} @property void empty(T)(ref T this, bool f){...} -- t.empty = true; Do you think? Why use this like that? UFCS is supposed to work with any function just like using the member function call syntax works with arrays and any function - otherwise it's not universal. And I would expect @property to work without this. The functions you list should work just fine with arrays without the use of the keyword this and without the first parameter being a ref. The same should be true for UFCS if it's ever implemented. - Jonathan M Davis