I suggest we ...

Add string interpolation to println syntax (from Swift)

The new language from Apple, Swift has a really nice syntax for println:
http://en.wikipedia.org/wiki/Swift_(programming_language)

let people = ["Anna": 67, "Beto": 8, "Jack": 33, "Sam": 25]
for (name, age) in people {
println("\(name) is \(age) years old.")
}

We could steal the idea but use % instead of \ for a better fit. It would also be compatible, and combinable (is that a word?) with existing printfn syntax:

let name = "Robert"
printfn "Hi %(name), your age is %d"
printfn : int -> string

Naturally there would be compiler errors if name does not exist.

179 votes
Vote
Sign in
Check!
(thinking…)
Reset
or sign in with
  • facebook
  • google
    Password icon
    I agree to the terms of service
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    Robert Jeppesen shared this idea  ·   ·  Admin →

    19 comments

    Sign in
    Check!
    (thinking…)
    Reset
    or sign in with
    • facebook
    • google
      Password icon
      I agree to the terms of service
      Signed in as (Sign out)
      Submitting...
      • Anonymous commented  · 

        Also vote that interpolation apply to all string literals.

      • Jason Hurdlow commented  · 

        Make version 1 exactly the same as the C# implementation:

        let greeting = $"Hello {name}!"

        Boom! Huge win. *printf could still be enhanced later.

      • Robert Jeppesen commented  · 

        I'd prefer it if this feature isn't limited to printf functions, but applied generally to all string literals, like literals in C# with '$' prefix.

      • Jon Nyman commented  · 

        or rather
        printfn : unit -> string

      • Jon Nyman commented  · 

        type Person = {name: string; age: int}
        let person = {name = "Robert"; age=5}
        printfn "Hi %(person, A), your age is %(person.age, 5i) with space or age %(person.age) without."
        printfn : int -> unit

      • Vladimir Matveev commented  · 

        ok, I took a stab on this feature and have a working prototype (https://visualfsharp.codeplex.com/SourceControl/network/forks/vladima/primary?branch=fsharp4)
        briefly: when analyzing format string compiler splits it into chunks: textblocks and embedded expressions (that are denoted by wrapping them in %()).Then final string that will be passed as a parameter to the constructor of PrintFormat is evaluated as ' string.Concat([| textblock1; expr1; textblock2; expr2... |]) '. All logic that manufactures phantom types remains intact. To evaluate expressions typechecker tries to parse it using provided access point to parser and typecheck it.

        Pros: implementation is relatively simple, supports both %(expr) and %(d) specifiers, embedded expressions are regular F# expressions so long names or operators inside are not problem.
        Cons: the entire feature is implemented on the semantic level so purely syntax based goodies will require extra effort to work with it, As an example if syntax highlighting is implemented only based on syntactic information then embedded expressions will be highlighted as a string.

      • Don Syme commented  · 

        I am very positively predisposed to this feature - at least where only a variable name can be interpolated.

        Questions

        - Could you use a long identifer %(name1.name2)? I presume not, but it may be a relatively simple extension to allow this.

        - What formatting would be used, e.g. for floating point values. Is it %A? Can you modify formatting specifiers?

        - Could you use a mix of %d and %(name) specifiers in a single printf format string? My intuition is to allow this, but if the implementation becomes too complex then to disallow it.

        Do other people have detailed questions about the specification and scope of this feature?

        Note that I have begun labelling some features as "approved" (actually the label is currently called "planned", though I think of it as "approved"), see https://fslang.uservoice.com/forums/245727-f-language/status/1225914.

        Labelling something as "approved" is not committing to "doing" the feature, but it does mean we would in theory accept implementations (with corresponding testing) of these features into the "fsharp4" branch at https://visualfsharp.codeplex.com/.

        So we would ask you to consider implementing this feature and submitting it. The implementation would then flow throughout all delivery vehicles for F#. We would provide lots of assistance to those seeking to implement the feature.

        I already labelled a couple of printf suggestions as "approved".

        If you disagree with labelling a feature as "approved", please argue your case through the User Voice comments, at least initially :)

        Thanks
        Don Syme

      • Robert Jeppesen commented  · 

        It's worth noting that in Swift (and Nemerle), these interpolations are expressions, so you can do

        printfn "The sum is %(a + b)"

        This would be nice here, but if that raises the amount of work to prohibiting levels, I think it can be skipped.

      • Loic Denuziere commented  · 

        General string interpolation exists in many languages, including Nemerle as you noted Heather. A big inconvenient is that it would require yet another string delimiter (we have 3 already...). This is about having it as an extra *printf format character, which is probably a smaller can of worms to open.

      • Mauricio Scheffer commented  · 

        @Marcin: not really. The Roslyn thread is about general string interpolation. This one is a limited application for printf. See my link above for the F# discussion about general string interpolation.

      • Jarle Stabell commented  · 

        I've "always" wanted something like this in F#. It feels very old-fashioned having to manually specify the "types" in printf in a language with type inference. Also, it's a totally separate, although simple, "type language".
        (Scala has a much more generic mechanism, perhaps overkill though).

      F# Language

      Feedback and Knowledge Base