I agree that declaring types is an effective way of increasing clarity.
(Fundamentally I suspect that suggests inadequacies in our documentation.)
Aside from the more "valid" use in controlling which version of a function
will run on which types of data.
However, you don't have to leave off type information from optional arguments:
function findsmallest(v::Vector, issorted::Bool = false)
if issorted
return v[1]
else
return minimum(v)
end
end
will be callable either as findsmallest(v, false) or findsmallest(v). If you do
supply the extra argument, it must be a Bool. Doesn't that do what you're
hoping for?
You can also supply types to keyword arguments, i.e.,
function findsmallest(v::Vector; issorted::Bool = false)
which will then be callable either as findsmallest(v) or findsmallest(v,
issorted=true).
--Tim
On Thursday, May 08, 2014 07:00:42 AM Adam Smith wrote:
> That makes sense. The other (primary) reason I want this is still valid:
> assisting multiple dispatch (and clarity for other developers) by having
> the correct types on optional arguments. Since there are no objects for
> encapsulation of related behaviors, the only good way to explore an API
> (other than just reading its source) is to use Julia's reflection utilities
> like names() and methods(). I want to be able to use brief function names
> like "add!()" on my types, but if every optional argument requires leaving
> off the type information, there will quickly be ambiguity/collisions with
> the definitions in different places. Since each one is really intended for
> a specific type, having that in the function signature would improve
> clarity quite a bit. That's why I spent a bit of time trying to construct
> the @optional macro.
>
> On Thursday, May 8, 2014 9:18:01 AM UTC-4, Tim Holy wrote:
> > I'm not sure I understand. Except for one particular situation (tuple
> > arguments), declaring the type of inputs has no impact on performance. The
> > JIT
> > will compile a separate version of the function for each different set of
> > input
> > types. See the "performance tips" section of the manual.
> >
> > --Tim
> >
> > On Thursday, May 08, 2014 01:34:12 AM Adam Smith wrote:
> > > Actually performance is one of the reasons I wanted to do it this way,
> > > rather than leaving off type info and just dealing with Anys, which is
> > > slower (and makes multiple dispatch very messy). I will read through
> > > Julia's parser a bit more and then file an issue.
> > >
> > > a d a m
> > >
> > > On May 8, 2014, at 1:25 AM, "Kevin Squire"
> > > <[email protected]<javascript:>>>
> > wrote:
> > > > Hi Adam,
> > > >
> > > > While working with optional and union types won't be as performant as
> > > > regular types, this seems like it would be useful. Why don't you file
> >
> > an
> >
> > > > issue? It might not be easy or feasible to do what you want, but it's
> > > > good to bring it to the attention of the main devs.
> > > >
> > > > Cheers,
> > > >
> > > > Kevin
> > > >>
> > > >> On Wed, May 7, 2014 at 5:15 PM, Adam Smith
> >
> > > >> <[email protected] <javascript:>> wrote:
> > Did you make any progress on
> >
> > > >> this? I tried to do the exact same thing as you, got the exact same
> > > >> error, googled, and found this post. It seems that Julia parses
> >
> > default
> >
> > > >> values for arguments separately from the name/type of the arguments.
> > > >> This was the macro I attempted:
> > > >> macro optional(name, ptype)
> > > >>
> > > >> esc(:($name::Union(Nothing, $ptype) = nothing))
> > > >>
> > > >> end
> > > >>
> > > >> With the desired usage being:
> > > >> function do_stuff(x::Int, y::String, @optional(z, Float))
> > > >>
> > > >> # do stuff
> > > >>
> > > >> end
> > > >>
> > > >> What I _really_ want (but I knew wouldn't be possible) would be:
> > > >> function do_stuff(x::Int, y::String, z::@optional(Float))
> > > >>
> > > >> # do stuff
> > > >>
> > > >> end
> > > >>
> > > >> The Julia documentation at
> >
> > http://julia.readthedocs.org/en/latest/manual/metaprogramming/#hygiene
> >
> > > >> makes the exaggerated claim "An expression wrapped in this manner is
> > > >> left alone by the macro expander and simply pasted into the output
> > > >> verbatim."
> > > >>
> > > >> The documentation is clearly oversimplifying a bit, otherwise my
> >
> > macro
> >
> > > >> should work.
> > > >>
> > > >>> On Friday, February 21, 2014 3:36:07 PM UTC-5, Joosep Pata wrote:
> > > >>> Hi,
> > > >>>
> > > >>> I’m trying to write a macro that would generate functions with
> >
> > optional
> >
> > > >>> arguments. However, I can’t figure out why the following code
> >
> > behaves
> >
> > > >>> as it does. I’d appreciate if someone told me what I’m doing wrong.
> > > >>>
> > > >>> ~~~
> > > >>> #1) def. value in quote, works
> > > >>> ex = :(x)
> > > >>> q = quote
> > > >>>
> > > >>> function f1($ex=1)
> > > >>>
> > > >>> x
> > > >>>
> > > >>> end
> > > >>>
> > > >>> end
> > > >>> macroexpand(q)|>println
> > > >>> eval(q)
> > > >>> f1()|>println
> > > >>>
> > > >>>
> > > >>> #2) def. value in expression, does not work
> > > >>> ex = :(x=1)
> > > >>> q = quote
> > > >>>
> > > >>> function f2($ex)
> > > >>>
> > > >>> x
> > > >>>
> > > >>> end
> > > >>>
> > > >>> end
> > > >>> println("does not work")
> > > >>> macroexpand(q)|>println
> > > >>> eval(q)
> > > >>> f2()|>println
> > > >>> ~~~
> > > >>>
> > > >>> 1) does not allow me to conveniently construct a list of arguments
> >
> > with
> >
> > > >>> values, whereas
> >
> > 2) gives me
> >
> > > >>> > ERROR: syntax: "x=1" is not a valid function argument name
> > > >>>
> > > >>> The macroexpand of either expression looks identical, except for
> >
> > spaces
> >
> > > >>> around the “=“ sign for 2), which should not make a syntactical
> > > >>> difference.
> > > >>>
> > > >>> cheers, Joosep