carbon-language / carbon-lang

Carbon Language's main repository: documents, design, implementation, and related tools. (NOTE: Carbon Language is experimental; see README)
https://github.com/carbon-language/carbon-lang/blob/trunk/README.md
Other
32.32k stars 1.48k forks source link

Domain Specific Languages and Extension Functions #1978

Open Oliver-makes-code opened 1 year ago

Oliver-makes-code commented 1 year ago

Here's a proposal for Domain Specific Languages (DSLs), and by proxy, Extension Functions.

In Kotlin and C#, an extension function/method allows you to create functions/methods that take place in the context of a class, while not directly being a member of the class. See the Kotlin and Java code below for an example

// This kotlin code
fun String.foo() {
    println(this)
}
// Corresponds to this Java code
public void foo(String thiz) {
    System.out.println(thiz);
}

This allows you to call String.foo() in Kotlin (as Java doesn't have extension functions) and it will run the code inside the extension function.

Another concept in Kotlin, and a couple other languages, is the DSL. Kotlin's implementation passes a function reference, usually an extension function, into the parameters, and calls that function on the DSL class. Provided below is an example

// DSL class
class FooDsl {
    fun bar() {
        println("Called bar!")
    }
    fun baz() {
        println("Called baz!")
    }
}

// Runs the DSL
fun fooDsl(block: FooDsl.() -> Unit /*This is an extension function reference*/): FooDsl {
    val dsl = FooDsl()
    // Call block on the DSL
    dsl.block()
    // Return the DSL with the block applied
    return dsl
}

// Calls the DSL
fun callDsl() {
    fooDsl {
        // Calls FooDsl.bar
        bar()
        // Calls FooDsl.baz
        baz()
    }
}

Adding these concepts to Carbon would help modernize the language, and to stand out more from C++ or Rust

geoffromer commented 1 year ago

See #1122 for a previous attempt to add extension methods to Carbon. In particular, the section on "Problems with extension methods" discusses some issues that any proposal in this space will need to address. It will probably also be important to articulate what problems these features would solve -- "modernize" is pretty vague, and "standing out more from C++" arguably goes against our C++ interop and migration goal.

Oliver-makes-code commented 1 year ago

"standing out more from C++" arguably goes against our C++ interop and migration goal.

Kotlin keeps interop with Java in this context by having the method signature have the class it's adding to as the first parameter

fun String.foo() would have the method signature foo(Ljava/lang/String;)V

JamesJCode commented 1 year ago

We have discussed the block-like syntax (as shown for DSLs) fairly extensively in the context of it being a candidate syntax for lambdas, and also the associated plumbing to make it work, such as implicit block parameters, receiver objects, scoped return statements etc.

We have taken the view for the time being to focus on an 'MVP' of explicit lambdas, with both terse (e.g. for algorithm predicates) and verbose (generics, capture specifiers, explicit arguments, etc) syntaxes.

This is not to say we won't revisit the block-like approach, it just has a whole load of couplings that need to be considered, along with some readability and usibility concerns.

geoffromer commented 1 year ago

"standing out more from C++" arguably goes against our C++ interop and migration goal.

Kotlin keeps interop with Java in this context by having the method signature have the class it's adding to as the first parameter

Sure, there are probably plenty of ways to address the interop/migration concerns. My point was just that "standing out from C++" isn't a compelling rationale for adding this feature, because it's at best a non-goal, and at worst an anti-goal.

github-actions[bot] commented 1 year ago

We triage inactive PRs and issues in order to make it easier to find active work. If this issue should remain active or becomes active again, please comment or remove the inactive label. The long term label can also be added for issues which are expected to take time. This issue is labeled inactive because the last activity was over 90 days ago.