Ship

Book · String Literals

String Literals

Draft

Write text with escapes and holes, or verbatim with raw strings.

On this page · 2 sections

Quoted strings

A quoted string reads backslash escapes and ${…} holes. A hole holds any expression and renders it through Display; \$ writes a literal dollar sign.

Quoted Strings

test✓
  let namename: String = "Ship""Ship": String;
  expect ✓"say \"hi\" to ${namename: String}" == "say \"hi\" to Ship""say \"hi\" to Ship": String;
  expect ✓"\${name}""\${name}": String == "\$""\$": String ++ "{name}""{name}": String;

Raw strings

#"…"# keeps every character exactly as written: quotes, backslashes, ${, and newlines need no escaping. JSON fixtures, SQL, and regular expressions read the way they will be used.

Raw Strings Are Verbatim

test✓
  let fixturefixture: String = #"{"id":"blank","title":""}"##"{"id":"blank","title":""}"#: String;
  expect ✓fixturefixture: String == "{\"id\":\"blank\",\"title\":\"\"}""{\"id\":\"blank\",\"title\":\"\"}": String;

  let patternpattern: String = #"\d+\.\d+"##"\d+\.\d+"#: String;
  expect ✓patternpattern: String == "\\d+\\.\\d+""\\d+\\.\\d+": String;

  let templatetemplate: String = #"cost: ${price}"##"cost: ${price}"#: String;
  expect ✓templatetemplate: String == "cost: \${price}""cost: \${price}": String;

  let lineslines: String = #"one
two"##"one
two"#: String;
  expect ✓lineslines: String == "one\ntwo""one\ntwo": String;

A raw string opens a hole with $, its fence, and {, so $#{…} holes sit beside text that only looks like interpolation.

Raw Holes Use The Fence

test✓
  let idid: String = "blank""blank": String;
  let bodybody: String = #"{"id":"$#{idid: String}","note":"${kept}"}"#;
  expect ✓bodybody: String == "{\"id\":\"blank\",\"note\":\"\${kept}\"}""{\"id\":\"blank\",\"note\":\"\${kept}\"}": String;

When the text contains "#, add hashes. The closing quote and the hole opener both use the longer fence.

Longer Fences

test✓
  let countcount: Int = 22: Int;
  let texttext: String = ##"a "# inside, $##{countcount: Int} holes, $#{kept}"##;
  expect ✓texttext: String == "a \"# inside, 2 holes, \$#{kept}""a \"# inside, 2 holes, \$#{kept}": String;

Raw strings are ordinary String values, so they also work as patterns.

Raw String Patterns

test✓
  let classifyclassify: fn(String) -> String = function {
    | #"""# -> "quote""quote": String
    | #"\"# -> "backslash""backslash": String
    | _ -> "other""other": String
  };
  expect ✓classifyclassify: fn(String) -> String("\"""\"": String) == "quote""quote": String;
  expect ✓classifyclassify: fn(String) -> String("\\""\\": String) == "backslash""backslash": String;
  expect ✓classifyclassify: fn(String) -> String("x""x": String) == "other""other": String;