I personally find underscores to be plenty good as "private" indicators. Yes people may still reach in and access those fields directly, but I bet they'll hesitate a little bit, which is all I ask. I certainly do NOT want to force people to jump through extra hoops (boilerplate code), but establishing good practice as a community is valuable. If someone submits a pull request that accesses a field with an underscore directly, give them crap about it. If there's a good reason: add comments, add tests, and make sure someone is ready to maintain it.
On Monday, July 6, 2015 at 9:37:59 AM UTC-4, Scott Jones wrote: > > > > On Monday, July 6, 2015 at 9:23:22 AM UTC-4, andrew cooke wrote: >> >> >> i feel like these conversations are often driven by people who want "new >> language" to be like whatever language they are most familiar with. and >> those people, since they are naturally in an uncomfortable place (away from >> their "old" language) tend to be the most vocal. >> > > No, my proposal is just about adding an *extra* capability, which is > necessary if you want to be able to make any sorts of guarantees about > about separation of interfaces from implementations. > As I've already seen a lot of evidence that the "consenting adults" > approach is not working in many cases, and there is frequent breakage when > anybody changes something inside their module/package, > not expecting that somebody else has used some internal function (I just > got bit by this last week, because the JSON.jl package was using two > undocumented and unexported functions that were defined in utf16.jl. > Those were not really safe to be called externally, because they make > certain assumptions about the type of the arguments, but since julia has no > way of marking something as private, and people consistently ignore that > something is not part of the interface, breakage occurred. > > >> so i just wanted to add a voice saying, no. i don't want this. i think >> the initial design of the language was correct. the added complexity here >> seems unnecessary to me. things work just fine in more functional >> languages that do not have this kind of constraint. they also work fine in >> python - if you want to use underscores in names as a sign to others, go >> ahead. >> > > underscores in names, and name mangling, is no solution, because people > will just ignore that if they want to. > Remember, my idea would NOT change any current code, just allow > programmers who *need* to have things more disciplined to be able to do so. > > >> more than that, there are more important problems still to be addressed. >> inheritance of fields, for example. >> > > Being able to make secure, reliable programs in Julia I think is one of > the most important issues, if julia is ever going to be used in real > critical code. > Inheritance of fields sounds like something where you want "new language" > to be like some other language. > > >> >> andrew >> >> >> On Monday, 6 July 2015 09:42:13 UTC-3, Scott Jones wrote: >>> >>> @julian Unlike C++/Java, Julia usually doesn't do run-time dispatching >>> (and when it has to, the performance can drop drastically). >>> Not only that, because of the JIT nature of Julia, it can take some >>> generic code, that operates on the abstract type Unsigned, for example, >>> and generate different methods based on whether it is used with UInt8, >>> UInt16, or UInt32. (I noticed this when writing some Unicode handling code, >>> that a function that had a test something like `if ch <= 0xff ; return >>> false ; elseif is_surrogate_char(ch) ; ... ; elseif ch > 0x10ffff`, in a >>> loop, it actually generated >>> 3 different methods, so that the UInt8 case, it simply returned false >>> (which I think got inlined also into the calling function), and for the >>> UInt16 case, >>> it eliminated the check for ch > 0x10ffff, because Julia knew that >>> 0x10ffff is greater than typemax(UInt16). >>> That is what really brought home to me the power of Julia, because in >>> other languages, I'd have to write the three versions myself. >>> >>> @mauro, I've seen no indication that fields of types are considered >>> private in Julia, they are frequently accessed far away from where they are >>> implemented. >>> I also think, from a number of conversations at JuliaCon, that many >>> people would welcome the ability to make things more disciplined. >>> Remember, my proposal is for *optionally* marking a type, field, >>> function or method as private to a module, so that if somebody tried to >>> access it with >>> Foo.privatemethod(blah) or str.privatedata, it would give a compiler (or >>> run-time, if the type of str is not known at compile-time) error. >>> People who don't care that anybody can fiddle with their private parts >>> would just keep working exactly as they do now. >>> Also, Julia already has the concept of inner and outer constructors, >>> this essentially is no different, methods within a module are like >>> inner constructors, they would have access to all of the "private" >>> fields, functions, methods, types of the module, just as only inner >>> constructors can use new(). >>> That doesn't prevent you from writing methods that just use the public >>> (even if not exported) types, methods, etc. to extend the interface. >>> I think also that this would be a fairly simple change to make to Julia, >>> that would break absolutely nothing. >>> >>> @julian, mangling names etc. I think just makes life more difficult for >>> debugging and a lot of other things, and doesn't even get you the >>> guarantees that a software engineer >>> would want when trying to make show the correctness of a package. >>> >>> Also, saying that these "private" methods etc. are only visible within >>> the module isn't really restrictive at all for the author, I've noticed >>> that large modules tend to have a file at the top level >>> which includes all of the files that make up the implementation, and >>> exports all of the public interface, so this doesn't at all mean that one >>> has to throw everything into one file. >>> >>> Scot >>> >>> On Monday, July 6, 2015 at 8:09:45 AM UTC-4, Mauro wrote: >>>> >>>> > Thanks a lot for your comments. >>>> > >>>> > @Jameson Regarding 1) I agree. Regarding point 2) Single dispatch in >>>> C++ >>>> > and Java is polymorphic and the type is known only at runtime: Base >>>> *p; >>>> > if( inputFromUser() ) p = new A; else p = new B; p->foo(). For A and >>>> B >>>> > subclasses of Base, p will created of type A or B at run time and >>>> therefore >>>> > which implementation of foo() will be called will be decided at run >>>> time. >>>> > Multiple dispatch in C++ and Java, same story but with a composition >>>> of >>>> > several dynamic single dispatches. Still do not see a significant >>>> > difference apart from the convenience of avoiding method composition. >>>> > >>>> > Regarding point 3) I am not advocating for a solution that will >>>> prevent the >>>> > user from accessing fields. For me it would be nice just to see >>>> something >>>> > where you could at least annotate that some fields as 'internal'. In >>>> this >>>> > way I would know immediately what I can use and what I can not >>>> (without >>>> > breaking invariants or creating unnecessary coupling). As you point >>>> out in >>>> > Python we annotate fields with '__' and Python will mangle those >>>> names so >>>> > if you try to use them naively it will not work. May be in Julia we >>>> could >>>> > annotate a group of fields with 'internal' such that only functions >>>> > annotated 'impl' can access those fields without getting warnings. >>>> This is >>>> > even weaker than Scott's proposal because an an owner/implementer of >>>> a type >>>> > you could have access to those fields even outside the module where >>>> the >>>> > type was defined. >>>> >>>> My understanding is that fields of types are considered private in >>>> Julia >>>> (public is the type itself and its parameters), so really no need to >>>> annotate them further (but issue #1974 makes me worry). Although >>>> sometimes a underscore is used to denote functions/fields as >>>> extra-private. Of course, nothing stops you to access the fields. A >>>> lax approach is often taken by Julia (by choice), so I suspect it will >>>> be difficult to get support for adding language features which are >>>> purely there to impose discipline. >>>> >>>> However, there are many places in Base and elsewhere where the >>>> fields-are-private is violated. Scott gave an example and here another >>>> one: there is no accessor methods to get at Expr.head and Expr.args. >>>> This should probably be refactored if someone has some time... >>>> >>>> > My two cents. >>>> > Julian >>>> > On Monday, July 6, 2015 at 3:15:34 AM UTC+2, Scott Jones wrote: >>>> >> >>>> >> >>>> >> >>>> >> On Sunday, July 5, 2015 at 4:24:50 PM UTC-4, Jameson wrote: >>>> >>> >>>> >>> Just to get it out of the way, I'll point out first that since all >>>> of the >>>> >>> aforementioned languages are turing-complete, they can all solve >>>> all of the >>>> >>> same programming problems. Therefore, there is never a question of >>>> whether >>>> >>> one language can be used to emulate the features of another >>>> language. >>>> >>> Instead, the question is whether one programming language makes the >>>> right >>>> >>> paradigms sufficiently more useful or obvious than another >>>> language, for >>>> >>> achieving the objectives of a particular programming problem. >>>> >>> >>>> >>> 1) OO-style dispatch is essentially single-dispatch on the first >>>> >>> (implicit/hidden) argument. Multiple dispatch is a strict superset >>>> of that. >>>> >>> So you could provide both, but there's no benefit. It complicates >>>> the >>>> >>> user's mental model of the language to provide these as two >>>> independent >>>> >>> features, rather than one unified system. >>>> >>> >>>> >>> 2) In C++ and Java, the type signature of the dispatch delegate is >>>> fully >>>> >>> resolved at compile time. By contrast, in Julia, the dispatch >>>> occurs at >>>> >>> runtime, when the actual type is known. The visitor design is >>>> exactly the >>>> >>> sort of anti-pattern that Julia seeks to eliminate by removing the >>>> forced >>>> >>> distinction between multiple dispatch functions (interfaces) and >>>> methods >>>> >>> associated with types (ref. question #1). >>>> >>> >>>> >>> 3) As noted by the wikipedia article, this is a design problem, not >>>> a >>>> >>> language problem. Some languages, like Python and Julia, therefore >>>> choose >>>> >>> not to hide anything from the user, but simply provide >>>> recommendations >>>> >>> against certain patterns. In Julia, it is generally discouraged to >>>> directly >>>> >>> access the fields of an object outside some set of methods that are >>>> >>> understood to be implementing the informal API for that type. >>>> Similarly, in >>>> >>> Python, the convention is to prefix private data with `_`, since in >>>> general >>>> >>> the dot-oriented access is the approved access API, but the general >>>> >>> principle is the same. >>>> >>> >>>> >> >>>> >> I agree with your first two points, and find Julia to be much more >>>> >> powerful with multiple dispatch instead of single dispatch, however >>>> I think >>>> >> Julian's third point is something that is a problem with Julia >>>> (although I >>>> >> believe it could be solved, without too much trouble). >>>> >> If there were a way to have functions and types (or members of >>>> types) that >>>> >> are not accesible outside >>>> >> the module they are defined in, then one could define an interface, >>>> and >>>> >> not have to worry about code breaking the encapsulation. (For >>>> example, >>>> >> I've found hundreds of cases of accesses of .data in strings in >>>> >> the registered packages, as well as others in different modules in >>>> Base) >>>> >> >>>> >> Scott >>>> >> >>>> >> On Sun, Jul 5, 2015 at 3:55 PM Julian Manzano <[email protected]> >>>> >>>> >>> wrote: >>>> >>> >>>> >>>> Hi All, >>>> >>>> >>>> >>>> I have been using C++ and Python for several years and I am very >>>> curious >>>> >>>> about Julia, I've got the REPL working on my workstation and I am >>>> >>>> really impressed so far with what I've seen. >>>> >>>> However there are some design decisions in the language that I >>>> fail to >>>> >>>> understand and I would really appreciate if someone could explain >>>> the >>>> >>>> rationale: >>>> >>>> >>>> >>>> The main point that I fail to understand is the decision not to >>>> allow >>>> >>>> member functions. >>>> >>>> The typical explanation that I find everywhere is that Julia >>>> designers >>>> >>>> have chosen all the methods to be external because this is cleaner >>>> >>>> (specially for mathematical methods where there is no clear owner) >>>> and >>>> >>>> allows for multiple dispatch. >>>> >>>> This explanation does not convince me for the following reasons: >>>> >>>> >>>> >>>> 1) We can have multiple dispatch a la Julia and still allow types >>>> to >>>> >>>> have methods. These two things seeem independent to me. >>>> >>>> 2) Dynamic multiple dispatch can also be done as a byproduct of >>>> single >>>> >>>> dispatch using the visitor pattern (C++, Java, etc.), so in that >>>> sense, >>>> >>>> multiple dispatch is not a new feature. >>>> >>>> 3) Lack of member functions forces all field to be public and >>>> therefore >>>> >>>> I cannot understand how Julia will avoid the object orgy >>>> anti-pattern ( >>>> >>>> https://en.wikipedia.org/wiki/Object_orgy) >>>> >>>> >>>> >>>> But hey, Julia still looks great, it is just that I would really >>>> like if >>>> >>>> someone could explain away my concerns, most likely I am missing >>>> something >>>> >>>> here. >>>> >>>> Thanks! >>>> >>>> Julian >>>> >>>> >>>> >>> >>>> >>>>
