6 ms·
I really wish they'd add string interpolation to Go. After being able to use s"My name is $name and surname is $surname" in Scala and "My name is #{name} and su
by thescrewdriver 12y ago
I really wish they'd add string interpolation to Go. After being able to use s"My name is $name and surname is $surname" in Scala and "My name is #{name} and surname is #{surname}" in Ruby I find working with printf a giant step backwards.
- DrJokepu 12y agoI wish they didn't! Magic features like this belong to magic languages like Ruby. Go is not meant to be a magic language.
- thescrewdriver 12y agoGo is designed to be a very practical and productive language. It's not quite clear how you're defining "magic" ... String interpolation is both practical and useful.
- DrJokepu 12y agoString interpolation is magic because it's not entirely obvious when it happens, what scope rules are followed, if there are any side effects, if the original string is overwritten or whether a new instance is created, what happens when they are used within bodies of loops, what happens when they are used within closures etc., it just works. Sure these can be specified explicitly but they aren't obvious. It's the kind of feature that is useful when you write an application but not that useful when you're trying to debug it.
- thescrewdriver 12y ago> It's the kind of feature that is useful when you write an application but not that useful when you're trying to debug it. It's largely used in log messages and the like where it's used for debugging issues after the fact. I've yet to encounter a case where anyone was ever confused by the behaviour.
- DrJokepu 12y agoRight, if this gets in then I officially demand that the much more innocent ternary operator and prefix/postfix increment/decrement operators get in as well.
- LanceH 12y agoIf I had to choose, I'd pick string interpolation. i += 1 means an extra line, but that extra line is very clear. Ternary vs an if-else arguably loses on clarity except for the simplest of cases. "Today's date is #{date}. Your balance on account #{account.Number} is #{account.Balance}" "Today's date is " + date + " Your balance on account " + account.Number + " is " + account.Balance The second is a mess of +'s and "'s to me, not to mention the awkwardness of formatting spaces before and after each quote. The first, you write a sentence and plug in the variables where they belong. Not saying you're wrong, just what I would choose.
- ajanuary 12y agoI'm not really familiar with Go, but surely the answer to almost all of those can be "the same as variables in the same scope as the string"?
- jongraehl 12y agoIt would be defined as sugar for the regular syntax "blah" + var. Not sure what specifically you find confusing.
- laumars 12y agoI can understand if you don't like the syntax of string interpolation, but that argument is a cop-out. If you're genuinely confused by it's behaviour then I'd suggest steering clear of the Printf (and even the vanilla Print/Println functions which does concatenation and automatic type conversion). Or perhaps, a better suggestion would be to read the language specs and learn interpolation's behaviour since this "magic" is almost always well documented [hint: it's actually less complicated than Printf ;)]
- ahuth 12y agoThere isn't much difference between this: "My name is #{name} and surname is #{surname}" and this: "My name is " + name + " and surname is " + surname or this: fmt.Println("My name is %s and surname is %s", name, surname) Except the first one is much more readable. String interpolation seems like a small thing, but I find myself wanting to use it all the time. It's definitely not a "magic" feature. Javascript really needs it as well.
- lazyjones 12y ago> Except the first one is much more readable. I disagree, especially in the presence of syntax highlighting editors. String interpolation would be a redundant alternative to existing mechanisms (the above plus text/template for longer strings) and just make parsing more complex. I don't think it would fit in well with Go's philosophy of providing pleasant, minimalistic syntax.
- ahuth 12y agoYou're probably right. Also, I obviously should've said, "Except the first one is much more readable to me." I definitely don't have a problem with the Go developers keeping out random syntax additions unless they think its a really good idea. Along the same lines, I really miss not having `map`, `reduce`, and `filter` in Go. However, it doesn't seem like those would be efficient in Go, or that they fit in with as well with systems programming, which Go was designed for. So I can't hate them for not including these.
- NateDad 12y agoFor what it's worth, I do think it's more readable, but it's just not a good idea. It's too easy for people to inject variables into their strings and get your code to print out data that's in memory. map, reduce, filter, etc will be easy to code up once there are generics. There will almost certainly be generics in Go at some point, that point is just not right now (and almost certainly not before 2.0).
- 12y ago
- coldtea 12y agoThere's nothing "magical" about it. The intention of the programmer and the result is actually even more explicit than passing the values as arguments to some printf function.
- NateDad 12y agoUh, grabbing variables out of the current scope to format your string is most certainly magical. It's also way less explicit than actually passing variables into a formatting function. It might be a little harder to read, but that's a lot different than explicit. fmt.Sprintf("Hello %s!", username) is very explicitly using the username variable from the local scope, and nothing but the username variable can ever get included in the output string. At most, a user could put a %s in their string, and get the username to appear somewhere else in the output... but they wouldn't be revealing data that wasn't already intended to be printed out. In comparison, interpolation is opening a door to let anyone extract whatever variables happen to be in scope at the time by putting #{password} or #{secret_key} in their string. By moving the definition of what variables get printed out into the data, you're opening a really big hole in your code... it also makes it a lot harder for the compiler to check for correctness.
- ajanuary 12y agoCan you give an example of your last point? A language like Ruby will only perform interpolation on string literals, so there isn't a way (that I know of) for data to inject interpolated strings. Interpolation isn't the same thing as eval.
- NateDad 12y agoI guess that's my lack of knowledge of how Ruby's string interpolation works. I assumed it worked like any old string format, which in other languages can use whatever string is passed into the formatting function. It sounds like that's not the case for Ruby's string interpolation. My apologies for jumping to conclusions. I guess it's my statically compiled mindset that assumes a string is a string.
- ImJasonH 12y agohttp://play.golang.org/p/DdwCOZwiCk http://play.golang.org/p/DdwCOZwiCk
- jerf 12y agoOne thing Go won't do, is pull the variables out of the local scope into the string interpolation automatically. As I think easy string interpolation is an antipattern, and I'm comfortable having to feed values into the string formatter, I'm not upset, but you're not going to convince people with that. As we slowly, oh so slowly, but surely move into languages where buffer overflows are not possible to write (or at least require scary excursions into some sort of "unsafe" package), easy string interpolations that allow the programmer to believe they don't have to think about the correct encoding of the value become the next most pressing security threat. Pretty much every "injection" is due to over-simplified string interpolation. Unfortunately, if your string interpolation syntax is as easy is "This is an interpolated $string"... it's also wrong. Dead wrong, very wrong, run away screaming wrong wrong wrong! String interpolation is actually a very hard problem, and this must irreducibly manifest itself in the API. ImJasonH's example, while it isn't "string interpolation" in the Ruby/Perl/etc. sense, does involve using a template system with sensible escaping mechanisms... it's HTML-specific, though, but for HTML it's incredibly powerful and easy to use correctly. In fact Go's HTML templating is the most powerful and easy-to-use correct HTML templating system I've ever seen that isn't in Haskell. Presumably there are others out there, but I've seen a lot of the competition and most of them will sit by, twiddling their thumbs and whistling idly, while you put 100 injections of every kind into your HTML page. My guess is Go will never grow this style of string interpolation, pretty much because it is so very, very frequently wrong. The way Go is already doing it is as easy as it can feasibly be, without encouraging wrongness.
- dragonwriter 12y agoI don't understand your claim that strong interpolation is wrong and the source of injection attacks, which are well known where building strings is much harder than interpolation. They come from not validating input data before use; requiring lots of work to build strings doesn't make it any more likely that people will do it safely.
- NateDad 12y agoI'm actually hugely not a fan of magically rendering code variables in strings. It's super error prone, and way too magical. If you really want named variables in format strings you can make a template like "My name is {{.Name}} and surname is {{.Surname}}", and render the template with either a map of strings to strings, or a struct with the right named values.
- why-el 12y agoAh, I think there should be a formula that spills out how many minutes will pass before language discussion descends to syntax assassination. I understand your pain, but this is nowhere near a real issue for systems that Go is designed to help build. I mean, in the thread that announces a new version of a language whose designers made it abundantly clear that it is intended to solve Google's problems, the top comment is about how to interpolate strings? I think they made a very good move by ignoring most syntax requests (There are a lot) and move on. Even better is their decision to harmonize formatting and build the formatter right into the language. Syntax is extremely overrated, and evidence for it has been provided years ago. [1] [1] http://c2.com/cgi/wiki?ProgrammingLanguagesAnInterpreterBasedApproach http://c2.com/cgi/wiki?ProgrammingLanguagesAnInterpreterBase... Edit: typos.
- thescrewdriver 12y ago> I understand your pain, but this is nowhere near a real issue for systems that Go is designed to help build. I spend most of my day designing and coding the sorts of systems which Go was designed to help build. I'll agree that this isn't a major issue, but it is affecting whether or not I actually enjoy using Go.
- laumars 12y agoI appreciate something like this is best served in the compiler, but would it not be possible to build your own function that provides this functionality?
- NateDad 12y agoSorta impossible. You can't suck values out of the current context, even with reflection. You always would need to pass values into a function, in which case you might as well use fmt.
- laumars 12y agoI suspected that might have been the case but I haven't played around with reflection enough personally. Shame :(
- dilap 12y agoPretty much impossible to add at this point w/o breaking back-compat, though, right?
- thescrewdriver 12y agofmt.RichPrint("....")
- greiskul 12y agoAnd how would this function capture variables from the local scope? The only way this could be added would be with new syntax.
- dilap 12y agoThat's what I was thinking, but now that you mention it, all that is needed is to have introspection gain the ability to examine local variables up the stack, so I guess it's do-able w/ back compat after all. I wouldn't hold my breath, though.
- thescrewdriver 12y agoI haven't dug into the details, but here's how Scala went about adding string interpolation: https://docs.google.com/document/d/1NdxNxZYodPA-c4MLr33KzwzKFkzm9iW9POexT9PkJsU/edit?hl=en_US&pli=1 https://docs.google.com/document/d/1NdxNxZYodPA-c4MLr33KzwzK...