On Wednesday, April 29, 2015 at 4:41:38 PM UTC-4, Stefan Karpinski wrote:
>
> Tom, this is a very legitimate concern. A simple solution is to have a 
> coding standard not to use `using` when writing packages. Google has 
> created coding standards for both C++ and Python, which are now widely used 
> beyond the company.
>
> Automatic function merging goes in the opposite direction: with this 
> feature it becomes impossible to even say which package a function comes 
> from – it's not even a meaningful question anymore. That is the point of 
> Jeff's Base.sin versus Transgression.sin example – map(sin, [1.0, "greed", 
> 2pi, "sloth"]). There is no answer to the question of which of the function 
> Base.sin and Transgreassion.sin the `sin` function refers to – it can only 
> refer to some new `sin` that exists only in the current module and calls 
> either Base.sin or Transgressions.sin depending on the runtime values of 
> its arguments. Perhaps this can be made clearer with an even nastier 
> example, assuming hypothetical code with function merging:
>
> module Foo
>     export f
>     immutable F end
>     f(::F) = "this is Foo"
> end
>
> module Bar
>     export f
>     immutable B end
>     f(::B) = "this is Bar"
> end
>
> julia> using Foo, Bar
>
> julia> f(rand(Bool) ? Foo.F() : Bar.B()) # which `f` is this?
>
>
> Which `f` is intended to be called here? It cannot be statically 
> determined – it's not well-defined since it depends on the value of 
> rand(Bool). Some dynamic languages are Ok with this kind of thing, but in 
> Julia, the *meaning* of code should be decidable statically even if some of 
> the behavior may be dynamic. Compare with this slightly different version 
> of the above code (works on 0.4-dev):
>

I think this is easier to solve than you think.
The compiler should see this call as having a signature of Union(F,B), 
which *neither* Foo.f nor Bar.f have...
So, it can either, give an error, or be even smarter, and see that it 
should be equivalent to:
rand(Bool) ? f(Foo.F()) : f(Bar.B()),
which is *totally* determined statically!

What's the real problem here?

module Sup
>     export f
>     f(::Void) = nothing # declare generic function without a la #8283 
> <https://github.com/JuliaLang/julia/issues/8283>
> end
>
> module Foo
>     export f
>     import Sup: f
>     immutable F end
>     f(::F) = "this is Foo"
> end
>
> module Bar
>     export f
>     import Sup: f
>     immutable B end
>     f(::B) = "this is Bar"
> end
>
> julia> using Foo, Bar
>
> julia> f(rand(Bool) ? Foo.F() : Bar.B())
>
>
> Why is this ok, while the previous code was problematic? Here you can say 
> which `f` is called: Foo and Bar share `f` so the answer is well-defined – 
> `f` is always `Sup.f`.
>
> On Wed, Apr 29, 2015 at 3:36 PM, Tom Breloff <[email protected] 
> <javascript:>> wrote:
>
>> Stefan:  I agree that typing Distributions.Normal(0,1) in the REPL when 
>> you're just doing data exploration is really frustrating.  However, when 
>> you're building a package or a larger system, it can be really important to 
>> either explicitly qualify your types/functions or to explicitly "import 
>> Distributions: Normal".  Frequently I'll be looking at some code within a 
>> large package with a call to "Normal", but I don't know what function will 
>> be called here.  If I do some type of explicit importing, then I can do a 
>> simple find command on my directory to figure out what package it may have 
>> been defined in.  If I did a "using", then I have a lot more searching to 
>> figure out the correct function.  Not to mention the silent overwriting of 
>> functions by "using" different modules can cause unexpected problems.  For 
>> that reason, I try to keep "using" to an absolute minimum in most of my 
>> code.
>>
>> On Wednesday, April 29, 2015 at 2:49:34 PM UTC-4, Stefan Karpinski wrote:
>>>
>>> This scheme seems overly focused on object-oriented programming styles 
>>> at the cost of making other programming styles much more inconvenient. In 
>>> an o-o language that might be fine, but non-o-o styles are quite common in 
>>> Julia. The `connect` example keeps coming up because it is one of those 
>>> cases where o-o works well. That is not the norm in numerical package, 
>>> however. This proposal would, for example, make using Distributions 
>>> <https://github.com/JuliaStats/Distributions.jl> a nightmare – you'd 
>>> have to explicitly import almost everything that it exports 
>>> <https://github.com/JuliaStats/Distributions.jl/blob/dacb401cfcfc7463f69af0009497960038b25dd5/src/Distributions.jl#L18-L238>
>>>  to 
>>> use. That includes type constructors for distributions etc., since those 
>>> are themselves (basically) generic functions and their arguments are just 
>>> built-ins. Instead of doing this:
>>>
>>> using Distributions
>>> X = Normal(0.0, 1.0)
>>> p = pdf(X, 0.1)
>>>
>>>
>>> you'd have to do this:
>>>
>>> using Distributions
>>> X = Distributions.Normal(0.0, 1.0)
>>> p = Distributions.pdf(X, 0.1)
>>>
>>>
>>> Or you'd have to explicitly import every Distributions type and generic 
>>> stats function that you want to use. Instead of being able to write `using 
>>> Distributions` and suddenly having all of the stats stuff you might want 
>>> available easily, you'd have to keep qualifying everything or explicitly 
>>> importing it. Both suck for interactive usage – and frankly even for 
>>> non-interactive usage, qualifying or explicitly importing nearly every name 
>>> you use is a massive and unnecessary hassle.
>>>
>>> On Wed, Apr 29, 2015 at 2:06 PM, Michael Francis <[email protected]> 
>>> wrote:
>>>
>>>> I would expect the user to explicitly import those method, I did not 
>>>> preclude their existence. And it would be quite reasonable to support the 
>>>> existing import all syntax hence 
>>>>
>>>> using MyModule
>>>> ^ imports only those functions which explicitly reference user types 
>>>> defined in the module 
>>>> importall MyModule.Extensions
>>>> ^imports the additional functionality on base types
>>>>
>>>> if I subsequently import another function which conflicts then we throw 
>>>> an error. This would mean that the vast majority of non conflicting 
>>>> functions can be trivially exported and used without a namespace qualifier 
>>>> and extensions to base types would also work, but with the name collision 
>>>> check in place. 
>>>>
>>>> I don't believe this violates the expression problem ? 
>>>>
>>>>
>>>> On Wednesday, April 29, 2015 at 1:55:14 PM UTC-4, Stefan Karpinski 
>>>> wrote:
>>>>>
>>>>>
>>>>> I made the point at the outset that it isn't hard (or expensive) if 
>>>>>> the *exported *functions from a module *must reference types defined 
>>>>>> in that module*. Hence the suggestion that module developers should 
>>>>>> only be able to export functions which reference 
>>>>>> owned/hard/contained/user 
>>>>>> types.
>>>>>>
>>>>>
>>>>> Unless I'm misunderstanding, this is a very limiting restriction. It 
>>>>> would mean, for example, that you can't define and export a generic 
>>>>> square(::Number) function. That's a silly example, but it's completely 
>>>>> standard for packages to export new functions that operate on 
>>>>> pre-existing 
>>>>> types that don't dispatch on any type that "belongs" to the exporting 
>>>>> module.
>>>>>
>>>>> Another way of looking at this is that such a restriction would 
>>>>> prevent solving half of the expression problem 
>>>>> <http://en.wikipedia.org/wiki/Expression_problem>. In object-oriented 
>>>>> languages, extending existing operations to new types is easily done via 
>>>>> subtyping, but adding new operations to existing types is awkward or 
>>>>> impossible. In functional languages, adding new operations to existing 
>>>>> types is easy, but extending existing operations to new types is awkward 
>>>>> or 
>>>>> impossible. Multiple dispatch lets you do both easily and intuitively – 
>>>>> so 
>>>>> much so that people can easily forget why the expression problem was a 
>>>>> problem in the first place. Preventing the export of new functions 
>>>>> operating only on existing types would hobble the language, making it no 
>>>>> more expressive than traditional object-oriented languages.
>>>>>
>>>>
>>>
>

Reply via email to