Operators don’t differ that much from regular functions, so yes, we can do this and we do this in exactly the same way as usual, for a non-operator function. It will require 5 times more code than in above example and it is generally discouraged to replace named params with DSLs, but yes, this is possible.
Can you explain to me why is this discouraged? and also how can we achieve that, I want to explore all the possibilities for using DSL to know the next time when and where should I use it , thanks
I think I read somewhere in official docs that DSLs are not meant to replace constructors with named optional parameters. I can’t find the source of this information right now. DSL is harder to implement, harder to maintain and in many cases it doesn’t provide the same level of compile-time guarantees as a regular function.
Anyway, you said specifically that the above is just a simple example. DSL doesn’t make sense for this example, but in your real case DSL could be justified, so please just ignore my comment.
Thanks, @kyay10 I knew that I must use Lambda with receivers but I couldn’t achieve it, now I understand better, maybe this doesn’t make sense to use it here as @broot said, but I would know how we can achieve such elegant DSLish style
That is more idiomatic definitely. For instance, require takes a lazy message argument that is a lambda. Keep in mind that this is almost the same as this:
No, I meant that if we need to pass a single name parameter, then there is nothing elegant in doing this with DSL. I don’t see how greeter { name = "Zinou" } is better than greeter(name = "Zinou"). But I see how it is worse: it requires more code, more maintenance and we can only check required params at runtime, but we can’t at the compile time.
In Java if we have to instantiate a class with many parameters (10+) and most of them are optional, then the builder pattern is a good alternative to a constructor/function with all these params. In Kotlin we have named params and we have optional params and they are better and cleaner approach than bulders or DSLs. At least this is my opinion
DSLs are for more complicated cases than just passing some params. If your real case is one of such more complicated cases, just use DSL, sure. @kyay10 example shows how you can do this.
I didn’t say using DSL, in this case, will be useful, I know that DSLs are used for more complicated things, I would just explore the ability to use DSL with invoke operator, maybe if I had a class like :
class Broot {
fun teaching(){
//do something
}
fun explain(){
//do something
}
operator fun invoke(): {
// do something
}
}
and with DSLs, I would achieve something like
val broot = Broot()
broot{
teaching()
explain()
}
This will make more sense, isn’t it? But this wasn’t my goal
I agree with you that passing a single parameter is not useful but what if you want to use invoke with 3 or 4 parameters that are all required? I prefer to write something like :
{
firstName = "Broot"
lastName = "The Best"
}
more than: (firstName = "Broot”, lastName = "The Best" ), this is not the best as you said but neater even if you don’t agree
Well, this is exactly my point. To do this with DSL you need more code, it is more complicated for the user of this function and you get only a limited functionality of the “normal” approach. While using normal function it is clearly visible, which params are required, which of them are optional and the compiler detects if we passed all required params. With DSL we can pass no params at all and the compiler will be fine with that only to crash the application at runtime.