Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create generic functions with no methods #8283

Closed
mauro3 opened this issue Sep 9, 2014 · 14 comments
Closed

create generic functions with no methods #8283

mauro3 opened this issue Sep 9, 2014 · 14 comments
Assignees

Comments

@mauro3
Copy link
Contributor

mauro3 commented Sep 9, 2014

Currently, a generic function can only be created by making a method. However, it may be useful to declare generic functions without having to provide an implementation. For instance Common Lisp provides this functionality with its defgeneric macro. Examples where this could be useful:

This issue touches on: documentation (e.g. #3988), function types (e.g. #1090), interface-oriented programming (e.g. #6975), and method ambiguity warnings (#6190 (comment)). In particular, @StefanKarpinski's comment on how to potentially specify (interfaces)[https://github.com//issues/6975#issuecomment-44502467] also has syntax to define generic functions within an interface specification.

Declaring a generic function should:

  • not break any existing code
  • make a generic function if none exists already
  • associate the given documentation with the generic function
  • generate an appropriate error message if there is no matching method when calling the generic function
  • maybe impose restrictions on the associated methods signatures, or if methods are already defined, check that they all comply.

Implementations:

The most straight forward implementation would just create the generic function and allow documentation to be associated with it:

doc"""
Returns the size of a container.
"""
generic size

More complicated would be to allow to constrain the call signature. Inspired by Common Lisp, the syntax could look like:

doc"""
A function taking arguments:
- a: one input of type T
- b: another input
...
"""
generic afun{T<:Integer, S<:String}(a::T, [b::S]; y::Int=7, ...)-->T

The names of the arguments would be dummy-names useful for documentation and consistency in method implementations. a would be a required argument, b would be optional, likewise for keyword arguments, and ... would allow any number of other optional arguments (the [] and ... couldn't be allowed at the same time).

Example size:

doc"""
Returns a tuple containing the dimensions of A.  If specified, along a particular
dimension of a multidimensional collection.
"""
generic size(obj::Any, [dim::Integer])

size(a::Array) = arraysize(a)
size(a::Array, d) = arraysize(a, d)

Thus, the generic declarations could follow largely what is defined in the standard library documentation https://github.com/JuliaLang/julia/tree/master/doc/stdlib in a more formal way.

To think about:

  • should/could restrictions on method-signature be part of the generic definition?
    • should method-signature be a recommendation or be enforced?
  • what to do when there are several definitions of a generic function?
    • within the same module it should be an error.
    • otherwise warn: this would probably mean that two packages export the same generic function.
  • how would this fit with a future interface specification Interfaces for Abstract Types #6975? Is it needed as well, is it redundant or even inconsistent? If all generic functions are only part of a single interface, then this feature is probably not needed. But I suspect that some functions will not belong to any interface, whereas others may belong to several interfaces.
@ivarne ivarne added the feature label Sep 9, 2014
@simonster simonster added the speculative Whether the change will be implemented is speculative label Sep 9, 2014
@JeffBezanson JeffBezanson changed the title Generic function definitions (feature request) create generic functions with no methods Sep 9, 2014
@mauro3
Copy link
Contributor Author

mauro3 commented Nov 10, 2014

Having this feature would also go well with the new help system #8791: so the @doc in front of a generic function definition would document the function as opposed to the method.

@StefanKarpinski
Copy link
Member

Here's another relevant thread:

https://groups.google.com/forum/#!searchin/julia-users/caller$20scope/julia-users/hneeTFB_OEs/FKHsOKaHXVMJ

I'm not sure if this can address the doc issue, but for the issue in Sam's example code, this would do:

module Persons
export Person, something, say_something
abstract Person
say_something(person::Person) = println(something(person))
end

using Persons
import Persons.something

type Boy <: Person end
type Girl <: Person end

something(::Boy) = "I'm a boy." # <== Persons.something generic function created now
something(::Girl) = "I'm a girl."

say_something(Boy())
say_something(Girl())

Not sure how good an idea that is, but the main point is that all we really need is a way of knowing that something should exist in the Persons module and not be create in Main.

@mauro3
Copy link
Contributor Author

mauro3 commented Dec 14, 2014

Just exporting something seems a bit too implicit to me. Could lead to some strange bugs: when refactoring, removing a type but forgetting the export and now suddenly it's a generic function with no methods.

But we should probably forget about all the complications of signature specification, which I laid out about, and just have declaration, doc + a helpful error message when called without an implemented method.

@StefanKarpinski
Copy link
Member

I agree. I was mostly just trying to think of ways to avoid adding new keywords.

@mauro3
Copy link
Contributor Author

mauro3 commented Dec 14, 2014

a macro couldn't work? @generic something

@JeffBezanson
Copy link
Member

The syntax

function foo;

might work. Might be possible even without the semicolon; that also gives a syntax error now.

@StefanKarpinski
Copy link
Member

I thought of that too, but it's weird to have one place in the language where trailing ; is non-optional.

@lendle
Copy link
Contributor

lendle commented Dec 14, 2014

What about

function foo end

?

@JeffBezanson
Copy link
Member

Although the semicolon is not necessary (updated my comment), function foo end would help out editor modes that treat function as a block open. They wouldn't need to add a special case for this.

@StefanKarpinski
Copy link
Member

I'd be down with that. It keeps the fact that function is always paired with end which is nice.

@mauro3
Copy link
Contributor Author

mauro3 commented Dec 15, 2014

+1

@JeffBezanson JeffBezanson self-assigned this Apr 25, 2015
@JeffBezanson JeffBezanson removed the speculative Whether the change will be implemented is speculative label Apr 25, 2015
@tpapp
Copy link
Contributor

tpapp commented Apr 26, 2015

+1, especially since indentation in ESS/Julia is kind of a mess right now and introducing yet another special case would be cumbersome, whereas function foo end just works (tried it).

@mauro3
Copy link
Contributor Author

mauro3 commented May 26, 2015

Excellent, thanks! This probably impacts on how function documentation is made: @MichaelHatherly @one-more-minute

@MichaelHatherly
Copy link
Member

Thanks Jeff!

This probably impacts on how function documentation is made

It's likely to impact Base.@doc a little more than Docile's plain docstrings. (I've already added support for this in MichaelHatherly/Docile.jl@185a9c5.) It's probably not worth adding support for this to Docile.@doc since this is a 0.4-only feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants