Suggestion: prefix fun

I’d like to propose a new syntax sugar to help create even terser DSLs. When creating them, one would desire to have an analog of infix fun for functions (with or without reeiver) that take a single parameter, so that we can invoke them as funName someValue instead of funName(someValue). This’d be specially useful when the argument is a literal (say log "some entry" or score 1234 instead of log("some entry") and score(1234), respectively.

2 Likes

Aaah,

another request to ‘import’ a feature from Ruby :slight_smile:
I am curious what other programming languages have this feature?
(I am sure there are some, just don’t know them all)

tecnically you got setter for “some value” variable and can use someVar = someValue with custom setter description

like

class SomeClass {
    var someVar: Int = 0
        set(value) {
            field = value
            someProcess(field)
        }

    fun someProcess(value: Int) {
        println("we have $value")
    }
}

fun someDescription(init: SomeClass.() -> Unit) = SomeClass().apply { init() }

// then this runs your someProcess fun with given parameter
someDescription {
    someVar = 1
}
// it prints "we have 1"

Haskell (kind of)

As a DSL lib creator, I’d also love this feature.

As a workaround, I usually use object:

object Log {
    infix fun entry(value: String) {}
}

This enables the following syntax: Log entry "some entry" or Record score 1234.

1 Like

This language feature makes the sequence of tokens like “a b c d e f” very ambiguous (it can have multiple interpretations as to what are properties here and what are function calls) and resolution of this ambiguity will have to be tied to the function call resolution process in an ugly and appealing ways from the compiler implementation standpoint.

4 Likes

I am curious whether implementation complexity is the only objection from the JetBrains Team against this feature, or is this also an argument about language complexity?

In this case implementation complexity comes with overall language complexity. It is going to be hard to parse and to disambiguate both for the compiler and for a person reading code.

3 Likes

Isn’t it possible to add a rule that whenever a prefix function is used without parentheses its argument can only be a simple expression and not an expression with multiple parts?
This feature is going to be used by DSLs mostly and they won’t really be effected by this.

1 Like

This is not a good language design.

5 Likes

Maybe not, but it’s still worth considering it IMO. It’s a feature intended for DSLs (mostly) so restricting it based on this use case is a valid option.

1 Like

It would not be the first language feature that goes live in a limited form, although the feature can potentially be much more generic.

1 Like

I’m not convinced by the argument that DSLs wouldn’t be affected by having it only work for “simple” expressions. That means, when I decide to change an expression from simple to complex, I have to add parenthesis or I’ll get an error (or a successful but unexpected parse). That sort if thing is the reason why I always use ${foo} instead of just $foo in string interpolation in Kotlin (and - shudder - Groovy). I’ve been caught out a few times changing something like that to $foo+bar (instead of ${foo+bar}) and seeing 3+bar in my output :-\

I’d rather have DSLs carry on being normal Kotlin code, even if that makes them slightly less “human” (modulo @DslMarker, I suppose ;-)).

As a previous Ruby on Rails developer, I don’t like this feature at all.

  1. it confuses people whether it’s a function call or not
  2. passing variables and function as variable is hard to read
  3. from language design perspective, it’s not good for parser to understand
1 Like