10 ms·
Some random things that the author seem to have missed: > but TypeScript, Swift, Kotlin, and Scala take string interpolation to the furthest extreme of encoura
by pdw 2y ago
Some random things that the author seem to have missed:
> but TypeScript, Swift, Kotlin, and Scala take string interpolation to the furthest extreme of encouraging actual code being embedded inside strings
Many more languages support that:
C# $"{x} plus {y} equals {x + y}"
Python f"{x} plus {y} equals {x + y}"
JavaScript `${x} plus ${y} equals ${x + y}`
Ruby "#{x} plus #{y} equals #{x + y}"
Shell "$x plus $y equals $(echo "$x+$y" | bc)"
Make :) echo "$(x) plus $(y) equals $(shell echo "$x+$y" | bc)"
> Tcl
Tcl is funny because comments are only recognized in code, and since it's a homoiconic, it's very hard to distinguish code and data. { } are just funny string delimiters. E.g.:
xyzzy {#hello world}
Is xyzzy a command that takes a code block or a string? There's no way to tell. (Yes, that means that the Tcl tokenizer/parser cannot discard comments: only at evaluation time it's possible to tell if something is a comment or not.)
> SQL
PostgreSQL has the very convenient dollar-quoted strings: https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING https://www.postgresql.org/docs/current/sql-syntax-lexical.h...
E.g. these are equivalent:
'Dianne''s horse'
$$Dianne's horse$$
$SomeTag$Dianne's horse$SomeTag$
- deleted 2y ago[deleted]
- autarch 2y agoPerl lets you do this too: my $foo = 5; my $bar = 'x'; my $quux = "I have $foo $bar\'s: @{[$bar x $foo]}"; print "$quux\n"; This prints out: I have 5 x's: xxxxx The "@{[...]}" syntax is abusing Perl's ability to interpolate an _array_ as well as a scalar. The inner "[...]" creates an array reference and the outer "@{...}" dereferences it. For reasons I don't remember, the Perl interpreter allows arbitrary code in the inner "[...]" expression that creates the array reference.
- Izkata 2y ago> For reasons I don't remember, the Perl interpreter allows arbitrary code in the inner "[...]" expression that creates the array reference. ...because it's an array value? Aside from how the languages handle references, how is that part any different from, for example, this in python: >>> [5 * 'x'] ['xxxxx'] You can put (almost) anything there, as long as it's an expression that evaluates to a value. The resulting value is what goes into the array.
- autarch 2y agoI understand that's constructing an array. What's a bit odd is that the interpreter allows you to string interpolate any expression when constructing the array reference inside the string.
- Izkata 2y agoIt's not...? Well, not directly: It's string interpolating an array of values, and the array is constructed using values from the results of expressions. These are separate features that compose nicely.
- JadeNB 2y ago> What's a bit odd is that the interpreter allows you to string interpolate any expression when constructing the array reference inside the string. Why? Surely it is easier for both the language and the programmer to have a rule for what you can do when constructing references to anonymous arrays, without having to special case whether that anonymous array is or is not in a string (or in any one of the many other contexts in which such a construct may appear in Perl).
- weinzierl 2y agoYou also don't need quotes around strings (barewords). So my $bar = x; should give the same result. Good luck with lexing that properly. https://perlmaven.com/barewords-in-perl https://perlmaven.com/barewords-in-perl
- shawn_w 2y agoIf you're writing anything approaching decent perl that won't be accepted.
- emmelaich 2y ago"use strict" will prevent it and I think strict will be assumed/default soon.
- JadeNB 2y agoAs of Perl 5.12, `use`ing a version (necessary to ensure availability of some of the newer features) automatically implies `use strict`. https://perldoc.perl.org/strict#HISTORY https://perldoc.perl.org/strict#HISTORY
- weinzierl 2y agoDoesn't really matter for a syntax highlighter, because it is out of your control what you get. For the llamafile highlighter even more so since it supports other legacy quirks, like C trigraphs as well.
- layer8 2y ago> actual code being embedded inside strings My view on this is that it shouldn’t be interpreted as code being embedded inside strings, but as a special form of string concatenation syntax. In turn, this would mean that you can nest the syntax, for example: "foo { toUpper("bar { x + y } bar") } foo" The individual tokens being (one per line): "foo { toUpper ( "bar { x + y } bar" ) } foo" If `+` does string concatenation, the above would effectively be equivalent to: "foo " + toUpper("bar " + (x + y) + " bar") + " foo" I don’t know if there is a language that actually works that way.
- panzi 2y agoIndeed in some of the listed languages you can nest it like that, but in others (e.g. Python) you can't. I would guess they deliberately don't want to enable that and it's not a problem in their parser or something.
- layer8 2y agoEven when nesting is disallowed, my point is that I find it preferable to not view it (and syntax-highlight it) as a “special string” with embedded magic, but as multiple string literals with just different delimiters that allow omitting the explicit concatenation operator, and normal expressions interspersed in between. I think it’s important to realize that it is really just very simple syntactic sugar for normal string concatenation.
- Timwi 2y agoWhile you're conceptually right, in practice I think it bears mentioning that in C# the two syntaxes compile differently. This is because C#’s target platform, the .NET Framework, has always had a function called `string.Format` that lets you write this: var str = string.Format("{0} is {1} years old.", name, age); When interpolated strings were introduced later, it was natural to have them compile to this instead of concatenation.
- 2y ago
- panzi 2y agoIs this a bash-ism? "$x plus $y equals $((x+y))"
- jonahx 2y agoThis works in "sh" as well for me.
- jwilk 2y agoNo, it's portable shell syntax.
- LukeShu 2y ago"$((" arithmetic expansion is POSIX (XCU 2.6.4 "Arithmetic Expansion"). But if I'm not mistaken, it originated in csh.
- susam 2y ago> Is this a bash-ism? > "$x plus $y equals $((x+y))" No, it is specified in POSIX: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04 https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V...
- therein 2y ago> PostgreSQL has the very convenient dollar-quoted strings I did not know that. Today I learned.
- sundarurfriend 2y ago> Many more languages support that: Julia as well: Julia "$x plus $y equals $(x+y)"
- thesz 2y agoVHDL There is a record constructor syntax in VHDL using attribute invocation syntax: RECORD_TYPE'(field1expr, ..., fieldNexpr). This means that if your record has a first field a subtype of a character type, you can get record construction expression like this one: REC'('0',1,"10101"). Good luck distinguishing between '(' as a character literal and "'", "(" and "'0'" at lexical level. Haskell. Haskell has context-free syntax for bracketed ("{-" ... "-}") comments. Lexer has to keep bracketed comment syntax balanced (for every "{-" there should be accompanying "-}" somewhere).
- 1vuio0pswjnm7 2y agoShell "$x plus $y equals $((x+y))" Shell "$x plus $y equals $((expr $x + $y))"
- 1vuio0pswjnm7 2y agoCorrection: Shell "$x plus $y equals $(expr $x + $y)"
- Izkata 2y agoMake :) echo "$(x) plus $(y) equals $(shell echo "$x+$y" | bc)" I'm guessing this is the reason for the :) but to be clear for anyone else: Make is only doing half of the work, whatever comes after "shell" is being passed to another executable, then make captures its stdout and interpolates that. The other executable is "sh" by default but can be changed to whatever.
- mbo 2y ago> Scala Note about Scala's string interpolation. They can be used as pattern match targets. val s"${a} + ${b}" = "1 + 2"; println(a) // 1 println(b) // 2
- vidarh 2y agoRuby takes this to 100. As much as a I love Ruby, this is valid Ruby, and I can't defend this: puts "This is #{<<HERE.strip} evil" incredibly HERE Just to combine the string interpolation with her concern over Ruby heredocs. My other favorite evil quirk in Ruby is that whitespace is a valid quote character in Ruby. The string (without the quotes) "% hello " is a quoted string containing "hello" (without the quotes), as "%" in contexts where there is no left operand initiates a quoted string and the next characters indicates the type of quotes. This is great when you do e.g. "%(this is a string)" or "%{this is a string}". It's not so great if you use space (I've never seen that in the wild, so it'd be nice if it was just removed - even irb doesn't handle it correctly)
- jart 2y agohttps://pbs.twimg.com/media/GbEfj6fbQAQRUB7?format=png&name=small https://pbs.twimg.com/media/GbEfj6fbQAQRUB7?format=png&name=... That's so going in the blog post later today.
- vidarh 2y agoHeh. I love Ruby, but, yes, the parser is "interesting", for values of interesting left undefined for its high obscenity content.
- mdaniel 2y agoAnd don't overlook the fact that the bare-world, or its "HERE" friend, are still in an interpolation context, so... puts "hello #{<<onoz.strip} world" recursion is #{<<onoz.strip} recursive onoz onoz puts "that was fun" yields hello recursion is recursive world that was fun and then there's its backtick friend puts "hello #{<<`onoz`.strip} world" date -u onoz coughs up hello Sun Nov 3 17:25:32 UTC 2024 world and for those trying out your percent-space trick, be aware that it only tolerates such a thing in a standalone expression context so puts (% hello )+" world" # or x = % hello # puts x because when I tried it "normally" I got $ /usr/bin/ruby -e 'puts % hello + "world"' -e:1:in `<main>': undefined local variable or method `hello' for main:Object (NameError) $ /usr/bin/ruby -v ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.x86_64-darwin21] but, at the intersection is "ruby parsing is the 15th circle of hell" ruby -e 'puts (% #{<<FOO.strip} )+ " world" hello FOO '
- cryptonector 2y agojq: "\("hello" + "world")!!" I wish PG had dollar-bracket quoting where you have to use the closing bracket to close, that way vim showmatch would work trivially. Something like ${...}$.
- bastawhiz 2y agoPython f-strings are kind of wild. They can even contain comments! They also have slightly different rules for parsing certain kinds of expressions, like := and lambdas. And until fairly recently, strings inside the expressions couldn't use the quote type of the f-string itself (or backslashes).
- orthoxerox 2y agoOne cool feature of C# interpolated strings is that they are lazy. Many loggers used to implement their own interpolation because something like log.trace($"Entering iteration {i} for customer {c.ID} [{c.ShortName}]"); in a hot loop would call string.Concat every time it was called before the logger could bail out of the method. C# lets you declare an overload that accepts a `DefaultInterpolatedStringHandler` (or your own custom implementation of the handler pattern) and this overload will take precedence and allow you to delay the building of the string until after you've checked whether logging it is required.