Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow double dollar signs for interpolated strings as in C# 11 #1150

Closed
5 tasks done
alfonsogarciacaro opened this issue Jun 7, 2022 · 21 comments
Closed
5 tasks done

Comments

@alfonsogarciacaro
Copy link

alfonsogarciacaro commented Jun 7, 2022

F# interpolated strings, together with editor support, make for a great way to embed a language within F#, one example is Fable.Lit with the F# Template Highlighting VS Code extension that allows you to embed HTML/CSS directly into F#.

Unfortunately the experience becomes a bit impeded when using a language that includes frequent brackets and percent symbols, as users need to remember continuously to double them to escape them, and copy and pasting doesn't work. See attached image:

image

C# 11 has solved this by allowing users to use two (or more) dollar signs. In that case brackets work normally, and we need to use double brackets to open interpolation "holes". The example above would become just CSS:

    cfg.styles <- [
        css $$"""
        :host {
            display: block;
            width: 100%;
            margin: 0.25em 0;
            cursor: pointer;
        }
        div, details {
            padding: 1em;
            color: white;
            display: block;
        }
        """
        ]

This specific example doesn't include interpolation holes. But I still cannot use a non-interpolated string because the css expects a FormattableString. In any case, we don't want users to have to double all brackets either when they have to convert a raw string into an interpolated string.

Pros and Cons

The advantages of making this adjustment to F# are:

  • Nicer way to use embedded languages in F#
  • Better consistency with C# 11 raw interpolated strings

The disadvantages of making this adjustment to F# are:

  • More syntax for raw/interpolated strings
  • C# doesn't have the format specifiers for the template holes, so handling % would be an F# specificity. Definitely we should allow single % when using double dollar, so probably format specifiers should be doubled then: margin: %%.2f{{value}}em 0;

Extra information

Estimated cost: Not sure, I guess it's mostly work in the parser?

Affidavit

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this

For Readers

If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.

@jbeeko
Copy link

jbeeko commented Jun 7, 2022

@alfonsogarciacaro this tries to solve the same problem:

fsharp/fslang-design#368 (comment)

@geodanila
Copy link

IMHO this feels like an elegant solution to the problem.

@dsyme
Copy link
Collaborator

dsyme commented Jun 7, 2022

Seems pretty reasonable

@isaacabraham
Copy link

This would also be useful for when working with JSON.

@CyrusNajmabadi
Copy link

As twitter has pointed out, the corresponding C# feature was clearly designed by someone deranged. Are you sure you want to follow what it does?

@alfonsogarciacaro
Copy link
Author

@CyrusNajmabadi As you're probably aware:

  1. Not everybody reads every tweet in Twitter (I personally don't know which tweet(s) you mention)
  2. Not every tweet in Twitter are absolute truths :)

So it'd be nice if you could elaborate why this feature is not desirable. If it's about the fact you can use more than two dollar signs in C#, I've also doubts about it, but using 2 dollar signs to avoid scaping braces would really be useful when handling JSON, CSS, etc.

@CyrusNajmabadi
Copy link

@alfonsogarciacaro dotnet/csharplang#4304 :)

@alfonsogarciacaro
Copy link
Author

alfonsogarciacaro commented Jun 8, 2022

@CyrusNajmabadi Haha, sorry, I don't follow too closely the C# feature proposals so I didn't get the joke 😅 I just read the blog post announcing the C# 11 features. Actually, it's super nice that C# raw template strings are consistent with F# in using the triple quotes. Now the only thing we need is the double dollar in F# too for even better consistency 👍

@cartermp
Copy link
Member

cartermp commented Jun 8, 2022

I think this feature would be great for F# vNext as-suggested (and modulo some details in an RFC of course)

@dsyme
Copy link
Collaborator

dsyme commented Jun 9, 2022

Marking as approved in principle

@abonie
Copy link

abonie commented Oct 6, 2022

I'd like to take a stab at this. I assume an RFC is required?

@CyrusNajmabadi
Copy link

Note: just so it's not an accidental design decision. In C# it's not that we allow double-dollar-signs. We allow any number of them. So you can have 5 dollar signs. That means that any sequence of 4 or less is just text, and you need 5 to actually start the interpolation. The idea here (and a principle of hte c# design) is that there are no escapes. So if you need single curlies, you use double-dollar on the string. if you need doubled-curlies, you use triple-dollar on the string. etc. etc. you can always pick some number higher than the number of consecutive curlies in the content.

Now, it's up to you if you want that complexity. But i just wanted to make sure the C# feature was understood, and people didn't accidentally think it was either one-or-two dollars, and nothing more. Thanks!

@abonie
Copy link

abonie commented Oct 18, 2022

I've just noticed that we likely shouldn't fully align with C# on how raw string (aka triple quote string) interpolation works, as in C#, a raw string starting with N x $ signs allows only for up to 2*N-1 consecutive {'s (or }'s) (see a spec here). Which means that in particular for single $ raw string literal, only a single consecutive curly brace is ever allowed, so e.g. this is not legal

$"""{{"""

(see in sharplab here)
That would be a breaking change in F# where interpolated triple quote strings are already supported with no such limitation.

@abonie
Copy link

abonie commented Oct 25, 2022

I have a work in progress PR with RFC for this suggestion here: fsharp/fslang-design#715

@abonie
Copy link

abonie commented Oct 27, 2022

The RFC template has a Scaling section, it says:

Please list the dimensions that describe the inputs for this new feature (...) For each, estimate a reasonable upper bound for the expected size in human-written code and machine-generated code that the compiler will accept.

I understand in this case it asks: Up to how many $ starting string literals should we reasonably expect?

But I don't know what to base this on. @alfonsogarciacaro - perhaps you have some idea?

@CyrusNajmabadi
Copy link

For c# we placed no upper bound here. You can have as many $ as you want.

@alfonsogarciacaro
Copy link
Author

In theory, it'd be nice to keep consistency with C# (although you mention above that would bring breaking changes in some cases), although in practice I cannot think of case where three or more $ would be need (but you never know). If I remember correctly, when I tried to implement this, it was not easy to detect N $ and pass it as state in the parser, so I only tried to implement it for two $. Still failed miserably nonetheless.

BTW, great work with the RFC @abonie! Only thing is I would expect % not to have to be escaped when using double dollar. That would be important when embedding CSS, for example.

@abonie
Copy link

abonie commented Oct 31, 2022

Thanks @alfonsogarciacaro!

I also initially thought that dealing with N $ might not be feasible, but eventually arrived at a working proof of concept - not sure if that's the best approach (if anyone can see any issues there, let me know) but seems good enough to move forward with RFC.

And the breaking change would be if we wanted to change how single-$ triple quoted strings work to be consistent with C#, because currently they already work differently in F# than in C#. So, I suggest leaving that as is, and keeping the consistency with C# on $$+ essentially.

Which means, we should be able to support any count of $ in theory (or up to max int at least without any acrobatics).

Regarding the %, I am afraid it is trickier than the curly braces and related to things I don't understand yet, but I'll see what I can do.

I will start a discussion thread for this RFC.

@abelbraaksma
Copy link
Member

abelbraaksma commented Nov 1, 2022

I will start a discussion thread for this RFC.

That’s gonna be a good thing to have. Make sure to add a link to it here and from the rfc. On the scaling comment, I think it’s fine to leave it, or mention that it can limited by resources. Quite likely, the IDE language service will come to a grinding halt long before fsc itself would complain about it. Wrt tests, I guess we can write one or two tests with 10 or more dollars just to show the implemented feature is stable and applies the correct ranges for syntax colouring. In practice, this will rarely happen.

On %, which is good to keep as it gives type safety, the only two ways out to disabling it are, I think:

  • make the number of curlies needed for interpolation also apply to percent signs. I.e., if it’s two curlies, you’ll also need two percent signs (which need to be coloured in the editor just like now) and a single sign is just taken literally.
  • add a variant, for instance: after the multiple dollars, the char that follows, which must not be a letter, digit, hash sign (and some others), quote or dollar, can be used for printf style type specification: $$&"You are &i{{age}} years old".

Obviously, the 2nd choice, while more flexible, will be harder to implement, I think.

@abonie
Copy link

abonie commented Nov 2, 2022

Discussion started on fslang-design: fsharp/fslang-design#716

@edgarfgp
Copy link
Member

This is done by dotnet/fsharp#14640

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests