JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.9k stars 5.49k forks source link

passing common keywords to nested functions #8643

Open berceanu opened 10 years ago

berceanu commented 10 years ago

I often find myself passing long lists of parameters from one function to another. A simple, contrived example would be the following

function fun3(; kw1 = 1, kw2 = 2, kw5 = 8, kw6 = 4)
    fun2(; kw1 = kw1, kw2 = kw2)
end
function fun2(; kw1 = 1, kw2 = 2)
    fun1(; kw1 = kw1, kw2 = kw2)
end
function fun1(; kw1 = 1, kw2 = 2, kw3 = 3)
    kw1 + kw2 + kw3
end

This results in code which is not easy to maintain. Notice that kw1 and kw2 are common to all 3 functions. The way the code is written now, if I decide I want kw3 of fun1 to be accesible from fun3, I need to do:

function fun3(; kw1 = 1, kw2 = 2, kw5 = 8, kw6 = 4, kw3=3)
    fun2(; kw1 = kw1, kw2 = kw2, kw3=kw3)
end
function fun2(; kw1 = 1, kw2 = 2, kw3=3)
    fun1(; kw1 = kw1, kw2 = kw2, kw3=kw3)
end
function fun1(; kw1 = 1, kw2 = 2, kw3 = 3)
    kw1 + kw2 + kw3
end

Suggestions for improving current behavior are welcome :)

StefanKarpinski commented 10 years ago

This is related to the fact that function taking keyword arguments are hard to deprecate: you can add a deprecation for a now-regretted method of a function easily and in a separate deprecations file; if you want to deprecate keywords for a function, there's no clean easily separable way to do it.

johnmyleswhite commented 10 years ago

One potential solution is to allow one to define groups of keywords and allow groups to passed around atomically.

StefanKarpinski commented 10 years ago

Yeah, that's a good way to go, but I'm not sure how to express that.

johnmyleswhite commented 10 years ago

Seems like you need syntax: f(x, y, $a(kw1 = 1, kw2 = 2)) = g(x + y, $a) with a better group indicator might get you started.

tonyhffong commented 10 years ago

or apply( f, args; params=d ) where d is typed Dict{Symbol,Any}

PythonNut commented 10 years ago

Doesn't Julia already support splatting a Dict{Symbol,Any} (or is it Dict{String,Any}?) as keyword arguments.

We do still need a syntax for capturing a group. Syntax for that is up for grabs.

JeffBezanson commented 10 years ago

Yes splatting a Dict works.

SimonDanisch commented 10 years ago

This is a huge thing for me as well. My work around:

immutable Style{StyleValue}
end
mergedefault!{S}(style::Style{S}, styles, customdata) = merge!(styles[S], Dict{Symbol, Any}(customdata))
#Text Rendering:
TEXT_DEFAULTS = [
:Default => [
  :start            => Vec3(0),
  :offset           => Vec2(1, 1.5), #Multiplicator for advance, newline
  :color            => rgbaU8(248.0/255.0, 248.0/255.0,242.0/255.0, 1.0),
  :backgroundcolor  => rgbaU8(0,0,0,0),
  :model            => eye(Mat4),
  :newline          => -Vec3(0, getfont().props[1][2], 0),
  :advance          => Vec3(getfont().props[1][1], 0, 0),
  :camera           => pcamera
]
]
# High Level text rendering for one line or multi line text, which is decided by searching for the occurence of '\n' in text
visualize(text::String,                 style=Style(:Default); customization...) = visualize(style, text, mergedefault!(style, TEXT_DEFAULTS, customization))
# Low level text rendering for one line text
visualize(text::Texture{GLGlyph, 1, 1}, style=Style(:Default); customization...) = visualize(style, text, mergedefault!(style, TEXT_DEFAULTS, customization))
# Low level text rendering for multiple line text
visualize(text::Texture{GLGlyph, 1, 2}, style=Style(:Default); customization...) = visualize(style, text, mergedefault!(style, TEXT_DEFAULTS, customization))