Which is better?
# codereview
e
Which is better?
2️⃣ 3
j
I'd rather go with a third option - like option 1 but with a named param for the lambda:
Copy code
val options = listOf(
    Option("Option1", action = { foo(3) }),
    Option("Option2", action = { bar(27) }),
)
Also, took the liberty to rename
function
to
action
, and add a trailing comma to make git diffs clearer when people add new options
e
@Joffrey I hadn't thought of named arguments. I like that. IntelliJ wants me to change version 1 to version 2, but it looks wrong to me. I'm teaching Intro CS in Kotlin and haven't introduced the trailing comma, but maybe I should take this opportunity to do so.
j
Another equally interesting option would be to extract the logic of lambdas into functions with names, and use function references there instead of lambdas:
Copy code
val options = listOf(
    Option("Option1", ::doOption1Stuff),
    Option("Option2", ::doOption2Stuff),
)

fun doOption1Stuff() = foo(3)
fun doOption2Stuff() = bar(27)
e
Thanks, but I need to reference free variables.
j
What do you mean by "free"?
e
ones in the enclosing function
j
I guess it's usually cleaner if you can refactor the code so you don't capture the values of local variables
e
I agree, but it's necessary for the style of programming I want to teach in this assignment.
j
Ok. It looks like this setup calls for a polymorphic
Option
type, though, where you could create subclasses of options that implement the single action method, and those subtypes can take parameters via their constructors
e
Here's some of the real code (for a test-based Reddit client for a homework exercise):
Copy code
private fun showPost(posts: List<RedditPost>, postNumber: Int) {
            showPost(posts[postNumber])
            val options = listOf(
                Option("Show post author", { showAuthor(posts, postNumber) }),
                Option("Check for comments", { checkForComments(posts, postNumber) }),
                Option("Show next post", { showPost(posts, postNumber + 1) })
            )
            offerOptions(options)
        }
I can see that the polymorphic approach would be better for production code. I'm more at the getting them comfortable with anonymous functions stage.
j
Got it 😉
Note that polymorphic is also more boilerplate. Also it might not be better in all cases, it really depends on usage. Another approach could be a Ktor-like DSL to present options:
Copy code
offerOptions {
    option("Show post author") {
        showAuthor(posts, postNumber)
    }
    option("Check for comments") {
        checkForComments(posts, postNumber)
    }
    option("Show next post") {
        showPost(posts, postNumber + 1)
    }
}
But I guess that's far out of scope of such lesson
c
@Ellen Spertus yesssss. option 2 would deffff be more confusing to me as a newcomer to cs/kotlin.
it really is just a shortcut, but i wish that kotlin/ide didn't yell at you about it making it seem wrong
then again, maybe its just best to leave out passing in functions to methods in an intro cs thing?
e
@Colton Idle You'd think, but it's a big part of intro CS at Northeastern, where I recently began teaching. Normally they teach in Racket (a dialect of Scheme, a dialect of Lisp). Teaching it in a multi-paradigm language instead of a functional language has already been a big step into the real world.