update to new interpolation syntax

This commit is contained in:
Anton-4 2024-02-02 13:39:10 +01:00
parent fc6b519b59
commit 3c7a834da1
No known key found for this signature in database
GPG Key ID: 0971D718C0A9B937
45 changed files with 402 additions and 402 deletions

View File

@ -883,7 +883,7 @@ mod cli_run {
provides [main] to pf
main =
Stdout.line "\nThis roc file can print it's own source code. The source is:\n\n\(ownCode)"
Stdout.line "\nThis roc file can print it's own source code. The source is:\n\n$(ownCode)"
"#
),

View File

@ -3,4 +3,4 @@ app "packages-test"
imports [json.JsonParser, csv.Csv]
provides [main] to pf
main = "Hello, World! \(JsonParser.example) \(Csv.example)"
main = "Hello, World! $(JsonParser.example) $(Csv.example)"

View File

@ -10,7 +10,7 @@ show = \list ->
|> List.map Num.toStr
|> Str.joinWith ", "
"[\(content)]"
"[$(content)]"
sortBy : List a, (a -> Num *) -> List a
sortBy = \list, toComparable ->

View File

@ -26,7 +26,7 @@ showRBTree = \tree, showKey, showValue ->
sL = nodeInParens left showKey showValue
sR = nodeInParens right showKey showValue
"Node \(sColor) \(sKey) \(sValue) \(sL) \(sR)"
"Node $(sColor) $(sKey) $(sValue) $(sL) $(sR)"
nodeInParens : RedBlackTree k v, (k -> Str), (v -> Str) -> Str
nodeInParens = \tree, showKey, showValue ->
@ -37,7 +37,7 @@ nodeInParens = \tree, showKey, showValue ->
Node _ _ _ _ _ ->
inner = showRBTree tree showKey showValue
"(\(inner))"
"($(inner))"
showColor : NodeColor -> Str
showColor = \color ->

View File

@ -14,7 +14,7 @@ main =
#
# _ ->
# ns = Num.toStr n
# Task.putLine "No test \(ns)"
# Task.putLine "No test $(ns)"
showBool : Bool -> Str
showBool = \b ->
if

View File

@ -857,7 +857,7 @@ increaseSize = \@Dict { data, maxBucketCapacity, maxLoadFactor, shifts } ->
shifts: newShifts,
}
else
crash "Dict hit limit of \(Num.toStr maxBucketCount) elements. Unable to grow more."
crash "Dict hit limit of $(Num.toStr maxBucketCount) elements. Unable to grow more."
allocBucketsFromShift : U8, F32 -> (List Bucket, U64)
allocBucketsFromShift = \shifts, maxLoadFactor ->

View File

@ -844,7 +844,7 @@ replaceFirst : Str, Str, Str -> Str
replaceFirst = \haystack, needle, flower ->
when splitFirst haystack needle is
Ok { before, after } ->
"\(before)\(flower)\(after)"
"$(before)$(flower)$(after)"
Err NotFound -> haystack
@ -862,7 +862,7 @@ replaceLast : Str, Str, Str -> Str
replaceLast = \haystack, needle, flower ->
when splitLast haystack needle is
Ok { before, after } ->
"\(before)\(flower)\(after)"
"$(before)$(flower)$(after)"
Err NotFound -> haystack

View File

@ -1831,7 +1831,7 @@ mod test_can {
// "abcd\$(efg)hij"
// "#
// ),
// Str(r"abcd\(efg)hij".into()),
// Str(r"abcd$(efg)hij".into()),
// );
// }

View File

@ -5549,7 +5549,7 @@ mod test_reporting {
r#"
greeting = "Privet"
if Bool.true then 1 else "\(greeting), World!"
if Bool.true then 1 else "$(greeting), World!"
"#,
),
@r#"
@ -5557,7 +5557,7 @@ mod test_reporting {
This `if` has an `else` branch with a different type from its `then` branch:
6 if Bool.true then 1 else "\(greeting), World!"
6 if Bool.true then 1 else "$(greeting), World!"
^^^^^^^^^^^^^^^^^^^^^
The `else` branch is a string of type:

View File

@ -86,7 +86,7 @@ pub enum CalledVia {
UnaryOp(UnaryOp),
/// This call is the result of desugaring string interpolation,
/// e.g. "\(first) \(last)" is transformed into Str.concat (Str.concat first " ") last.
/// e.g. "$(first) $(last)" is transformed into Str.concat (Str.concat first " ") last.
StringInterpolation,
/// This call is the result of desugaring a Record Builder field.

View File

@ -312,7 +312,7 @@ mod solve_expr {
r#"
whatItIs = "great"
"type inference is \(whatItIs)!"
"type inference is $(whatItIs)!"
"#
),
"Str",
@ -326,7 +326,7 @@ mod solve_expr {
r#"
whatItIs = "great"
str = "type inference is \(whatItIs)!"
str = "type inference is $(whatItIs)!"
whatItIs
"#
@ -342,7 +342,7 @@ mod solve_expr {
r#"
rec = { whatItIs: "great" }
str = "type inference is \(rec.whatItIs)!"
str = "type inference is $(rec.whatItIs)!"
rec
"#
@ -4739,7 +4739,7 @@ mod solve_expr {
r#"
setRocEmail : _ -> { name: Str, email: Str }_
setRocEmail = \person ->
{ person & email: "\(person.name)@roclang.com" }
{ person & email: "$(person.name)@roclang.com" }
setRocEmail
"#
),

View File

@ -948,7 +948,7 @@ fn specialize_unique_newtype_records() {
main =
when Str.fromUtf8 (Encode.toBytes {a: Bool.true} TotallyNotJson.json) is
Ok s -> when Str.fromUtf8 (Encode.toBytes {b: Bool.true} TotallyNotJson.json) is
Ok t -> "\(s)\(t)"
Ok t -> "$(s)$(t)"
_ -> "<bad>"
_ -> "<bad>"
"#

View File

@ -330,7 +330,7 @@ fn list_map_try_ok() {
List.mapTry [1, 2, 3] \num ->
str = Num.toStr (num * 2)
Ok "\(str)!"
Ok "$(str)!"
"#,
// Result Str [] is unwrapped to just Str
RocList::<RocStr>::from_slice(&[
@ -3738,10 +3738,10 @@ fn issue_3571_lowlevel_call_function_with_bool_lambda_set() {
List.concat state mappedVals
add2 : Str -> Str
add2 = \x -> "added \(x)"
add2 = \x -> "added $(x)"
mul2 : Str -> Str
mul2 = \x -> "multiplied \(x)"
mul2 = \x -> "multiplied $(x)"
foo = [add2, mul2]
bar = ["1", "2", "3", "4"]

View File

@ -3197,7 +3197,7 @@ fn recursively_build_effect() {
hi = "Hello"
name = "World"
"\(hi), \(name)!"
"$(hi), $(name)!"
main =
when nestHelp 4 is
@ -3953,8 +3953,8 @@ fn compose_recursive_lambda_set_productive_toplevel() {
compose = \f, g -> \x -> g (f x)
identity = \x -> x
exclaim = \s -> "\(s)!"
whisper = \s -> "(\(s))"
exclaim = \s -> "$(s)!"
whisper = \s -> "($(s))"
main =
res: Str -> Str
@ -3976,8 +3976,8 @@ fn compose_recursive_lambda_set_productive_nested() {
compose = \f, g -> \x -> g (f x)
identity = \x -> x
exclaim = \s -> "\(s)!"
whisper = \s -> "(\(s))"
exclaim = \s -> "$(s)!"
whisper = \s -> "($(s))"
res: Str -> Str
res = List.walk [ exclaim, whisper ] identity compose
@ -3998,8 +3998,8 @@ fn compose_recursive_lambda_set_productive_inferred() {
compose = \f, g -> \x -> g (f x)
identity = \x -> x
exclaim = \s -> "\(s)!"
whisper = \s -> "(\(s))"
exclaim = \s -> "$(s)!"
whisper = \s -> "($(s))"
res = List.walk [ exclaim, whisper ] identity compose
res "hello"
@ -4024,8 +4024,8 @@ fn compose_recursive_lambda_set_productive_nullable_wrapped() {
else \x -> f (g x)
identity = \x -> x
exclame = \s -> "\(s)!"
whisper = \s -> "(\(s))"
exclame = \s -> "$(s)!"
whisper = \s -> "($(s))"
main =
res: Str -> Str
@ -4552,7 +4552,7 @@ fn reset_recursive_type_wraps_in_named_type() {
Cons x xs ->
strX = f x
strXs = printLinkedList xs f
"Cons \(strX) (\(strXs))"
"Cons $(strX) ($(strXs))"
"#
),
RocStr::from("Cons 2 (Cons 3 (Cons 4 (Nil)))"),

View File

@ -1679,7 +1679,7 @@ fn lambda_capture_niches_with_other_lambda_capture() {
when val is
_ -> ""
capture2 = \val -> \{} -> "\(val)"
capture2 = \val -> \{} -> "$(val)"
x : [A, B, C]
x = A
@ -1984,7 +1984,7 @@ fn polymorphic_expression_unification() {
]
parseFunction : Str -> RenderTree
parseFunction = \name ->
last = Indent [Text ".trace(\"\(name)\")" ]
last = Indent [Text ".trace(\"$(name)\")" ]
Indent [last]
values = parseFunction "interface_header"
@ -2540,7 +2540,7 @@ fn recursively_build_effect() {
hi = "Hello"
name = "World"
"\(hi), \(name)!"
"$(hi), $(name)!"
main =
when nestHelp 4 is
@ -2856,8 +2856,8 @@ fn compose_recursive_lambda_set_productive_nullable_wrapped() {
else \x -> f (g x)
identity = \x -> x
exclame = \s -> "\(s)!"
whisper = \s -> "(\(s))"
exclame = \s -> "$(s)!"
whisper = \s -> "($(s))"
main =
res: Str -> Str

View File

@ -45,7 +45,7 @@ shape = \@Types types, id ->
Err OutOfBounds ->
idStr = Num.toStr (InternalTypeId.toNat id)
crash "TypeId #\(idStr) was not found in Types. This should never happen, and means there was a bug in `roc glue`. If you have time, please open an issue at <https://github.com/roc-lang/roc/issues>"
crash "TypeId #$(idStr) was not found in Types. This should never happen, and means there was a bug in `roc glue`. If you have time, please open an issue at <https://github.com/roc-lang/roc/issues>"
alignment : Types, TypeId -> U32
alignment = \@Types types, id ->
@ -54,7 +54,7 @@ alignment = \@Types types, id ->
Err OutOfBounds ->
idStr = Num.toStr (InternalTypeId.toNat id)
crash "TypeId #\(idStr) was not found in Types. This should never happen, and means there was a bug in `roc glue`. If you have time, please open an issue at <https://github.com/roc-lang/roc/issues>"
crash "TypeId #$(idStr) was not found in Types. This should never happen, and means there was a bug in `roc glue`. If you have time, please open an issue at <https://github.com/roc-lang/roc/issues>"
size : Types, TypeId -> U32
size = \@Types types, id ->
@ -63,4 +63,4 @@ size = \@Types types, id ->
Err OutOfBounds ->
idStr = Num.toStr (InternalTypeId.toNat id)
crash "TypeId #\(idStr) was not found in Types. This should never happen, and means there was a bug in `roc glue`. If you have time, please open an issue at <https://github.com/roc-lang/roc/issues>"
crash "TypeId #$(idStr) was not found in Types. This should never happen, and means there was a bug in `roc glue`. If you have time, please open an issue at <https://github.com/roc-lang/roc/issues>"

File diff suppressed because it is too large Load Diff

View File

@ -739,14 +739,14 @@ fn type_problem_unary_operator() {
#[test]
fn type_problem_string_interpolation() {
expect_failure(
"\"This is not a string -> \\(1)\"",
"\"This is not a string -> $(1)\"",
indoc!(
r#"
TYPE MISMATCH
This argument to this string interpolation has an unexpected type:
4 "This is not a string -> \(1)"
4 "This is not a string -> $(1)"
^
The argument is a number of type:
@ -1503,7 +1503,7 @@ fn interpolation_with_nested_strings() {
expect_success(
indoc!(
r#"
"foo \(Str.joinWith ["a", "b", "c"] ", ") bar"
"foo $(Str.joinWith ["a", "b", "c"] ", ") bar"
"#
),
r#""foo a, b, c bar" : Str"#,
@ -1515,7 +1515,7 @@ fn interpolation_with_num_to_str() {
expect_success(
indoc!(
r#"
"foo \(Num.toStr Num.maxI8) bar"
"foo $(Num.toStr Num.maxI8) bar"
"#
),
r#""foo 127 bar" : Str"#,
@ -1527,7 +1527,7 @@ fn interpolation_with_operator_desugaring() {
expect_success(
indoc!(
r#"
"foo \(Num.toStr (1 + 2)) bar"
"foo $(Num.toStr (1 + 2)) bar"
"#
),
r#""foo 3 bar" : Str"#,
@ -1542,7 +1542,7 @@ fn interpolation_with_nested_interpolation() {
expect_failure(
indoc!(
r#"
"foo \(Str.joinWith ["a\(Num.toStr 5)", "b"] "c")"
"foo $(Str.joinWith ["a$(Num.toStr 5)", "b"] "c")"
"#
),
indoc!(
@ -1551,7 +1551,7 @@ fn interpolation_with_nested_interpolation() {
This string interpolation is invalid:
4 "foo \(Str.joinWith ["a\(Num.toStr 5)", "b"] "c")"
4 "foo $(Str.joinWith ["a$(Num.toStr 5)", "b"] "c")"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
String interpolations cannot contain newlines or other interpolations.

View File

@ -345,7 +345,7 @@ fn joinpoint_with_closure() {
catSound = makeSound Cat
dogSound = makeSound Dog
gooseSound = makeSound Goose
"Cat: \(catSound), Dog: \(dogSound), Goose: \(gooseSound)"
"Cat: $(catSound), Dog: $(dogSound), Goose: $(gooseSound)"
test
)
@ -374,7 +374,7 @@ fn joinpoint_with_reuse() {
Cons x xs ->
strX = f x
strXs = printLinkedList xs f
"Cons \(strX) (\(strXs))"
"Cons $(strX) ($(strXs))"
test =
newList = mapLinkedList (Cons 1 (Cons 2 (Cons 3 Nil))) (\x -> x + 1)
@ -461,7 +461,7 @@ fn tree_rebalance() {
sL = nodeInParens left showKey showValue
sR = nodeInParens right showKey showValue
"Node \(sColor) \(sKey) \(sValue) \(sL) \(sR)"
"Node $(sColor) $(sKey) $(sValue) $(sL) $(sR)"
nodeInParens : RedBlackTree k v, (k -> Str), (v -> Str) -> Str
nodeInParens = \tree, showKey, showValue ->
@ -472,7 +472,7 @@ fn tree_rebalance() {
Node _ _ _ _ _ ->
inner = showRBTree tree showKey showValue
"(\(inner))"
"($(inner))"
showColor : NodeColor -> Str
showColor = \color ->
@ -521,7 +521,7 @@ fn joinpoint_nullpointer() {
Nil -> "Nil"
Cons x xs ->
strXs = printLinkedList xs
"Cons \(x) (\(strXs))"
"Cons $(x) ($(strXs))"
linkedListHead : LinkedList Str -> LinkedList Str
linkedListHead = \linkedList ->
@ -533,7 +533,7 @@ fn joinpoint_nullpointer() {
test =
cons = printLinkedList (linkedListHead (Cons "foo" Nil))
nil = printLinkedList (linkedListHead (Nil))
"\(cons) - \(nil)"
"$(cons) - $(nil)"
test
)

View File

@ -149,7 +149,7 @@ bool = \b ->
str : Str -> Inspector GuiFormatter
str = \s ->
f0 <- Inspect.custom
addNode f0 (Text "\"\(s)\"")
addNode f0 (Text "\"$(s)\"")
opaque : * -> Inspector GuiFormatter
opaque = \_ ->

View File

@ -13,6 +13,6 @@ tick = \n ->
_ <- await (Stdout.line "🎉 SURPRISE! Happy Birthday! 🎂")
Task.ok (Done {})
else
_ <- await (n |> Num.toStr |> \s -> "\(s)..." |> Stdout.line)
_ <- await (n |> Num.toStr |> \s -> "$(s)..." |> Stdout.line)
_ <- await Stdin.line
Task.ok (Step (n - 1))

View File

@ -9,7 +9,7 @@ main =
(Effect.getLine)
\line ->
Effect.after
(Effect.putLine "You entered: \(line)")
(Effect.putLine "You entered: $(line)")
\{} ->
Effect.after
(Effect.putLine "It is known")

View File

@ -7,7 +7,7 @@ main : Task {} I32
main =
task =
Env.decode "EDITOR"
|> Task.await (\editor -> Stdout.line "Your favorite editor is \(editor)!")
|> Task.await (\editor -> Stdout.line "Your favorite editor is $(editor)!")
|> Task.await (\{} -> Env.decode "SHLVL")
|> Task.await
(\lvl ->
@ -16,7 +16,7 @@ main =
n ->
lvlStr = Num.toStr n
Stdout.line "Your current shell level is \(lvlStr)!")
Stdout.line "Your current shell level is $(lvlStr)!")
|> Task.await \{} -> Env.decode "LETTERS"
Task.attempt task \result ->
@ -24,7 +24,7 @@ main =
Ok letters ->
joinedLetters = Str.joinWith letters " "
Stdout.line "Your favorite letters are: \(joinedLetters)"
Stdout.line "Your favorite letters are: $(joinedLetters)"
Err _ ->
Stderr.line "I couldn't find your favorite letters in the environment variables!"

View File

@ -55,7 +55,7 @@ toStr = \{ scopes, stack, state, vars } ->
stackStr = Str.joinWith (List.map stack toStrData) " "
varsStr = Str.joinWith (List.map vars toStrData) " "
"\n============\nDepth: \(depth)\nState: \(stateStr)\nStack: [\(stackStr)]\nVars: [\(varsStr)]\n============\n"
"\n============\nDepth: $(depth)\nState: $(stateStr)\nStack: [$(stackStr)]\nVars: [$(varsStr)]\n============\n"
with : Str, (Context -> Task {} a) -> Task {} a
with = \path, callback ->

View File

@ -21,7 +21,7 @@ InterpreterErrors : [BadUtf8, DivByZero, EmptyStack, InvalidBooleanValue, Invali
main : Str -> Task {} []
main = \filename ->
interpretFile filename
|> Task.onFail \StringErr e -> Stdout.line "Ran into problem:\n\(e)\n"
|> Task.onFail \StringErr e -> Stdout.line "Ran into problem:\n$(e)\n"
interpretFile : Str -> Task {} [StringErr Str]
interpretFile = \filename ->
@ -44,7 +44,7 @@ interpretFile = \filename ->
Task.fail (StringErr "Ran into an invalid boolean that was neither false (0) or true (-1)")
Err (InvalidChar char) ->
Task.fail (StringErr "Ran into an invalid character with ascii code: \(char)")
Task.fail (StringErr "Ran into an invalid character with ascii code: $(char)")
Err MaxInputNumber ->
Task.fail (StringErr "Like the original false compiler, the max input number is 320,000")

View File

@ -18,15 +18,15 @@ main =
cwd <- Env.cwd |> Task.await
cwdStr = Path.display cwd
_ <- Stdout.line "cwd: \(cwdStr)" |> Task.await
_ <- Stdout.line "cwd: $(cwdStr)" |> Task.await
dirEntries <- Dir.list cwd |> Task.await
contentsStr = Str.joinWith (List.map dirEntries Path.display) "\n "
_ <- Stdout.line "Directory contents:\n \(contentsStr)\n" |> Task.await
_ <- Stdout.line "Directory contents:\n $(contentsStr)\n" |> Task.await
_ <- Stdout.line "Writing a string to out.txt" |> Task.await
_ <- File.writeUtf8 path "a string!" |> Task.await
contents <- File.readUtf8 path |> Task.await
Stdout.line "I read the file back. Its contents: \"\(contents)\""
Stdout.line "I read the file back. Its contents: \"$(contents)\""
Task.attempt task \result ->
when result is

View File

@ -11,7 +11,7 @@ main =
_ <- await (Stdout.line "What's your last name?")
lastName <- await Stdin.line
Stdout.line "Hi, \(unwrap firstName) \(unwrap lastName)! 👋"
Stdout.line "Hi, $(unwrap firstName) $(unwrap lastName)! 👋"
unwrap : [Input Str, End] -> Str
unwrap = \input ->

View File

@ -7,4 +7,4 @@ app "ingested-file"
provides [main] to pf
main =
Stdout.line "\nThis roc file can print it's own source code. The source is:\n\n\(ownCode)"
Stdout.line "\nThis roc file can print it's own source code. The source is:\n\n$(ownCode)"

View File

@ -39,7 +39,7 @@ Just so you know what to expect, our Roc functions look like this;
``` coffee
interpolateString : Str -> Str
interpolateString = \name ->
"Hello from Roc \(name)!!!🤘🤘🤘"
"Hello from Roc $(name)!!!🤘🤘🤘"
mulArrByScalar : List I32, I32 -> List I32

View File

@ -5,7 +5,7 @@ app "rocdemo"
interpolateString : Str -> Str
interpolateString = \name ->
"Hello from Roc \(name)!!!🤘🤘🤘"
"Hello from Roc $(name)!!!🤘🤘🤘"
# jint is i32
mulArrByScalar : List I32, I32 -> List I32

View File

@ -5,4 +5,4 @@ app "libhello"
main : Str -> Str
main = \message ->
"TypeScript said to Roc: \(message)! 🎉"
"TypeScript said to Roc: $(message)! 🎉"

View File

@ -21,7 +21,7 @@ main =
|> List.map \_ -> 1
|> List.sum
|> Num.toStr
|> \countLetterA -> Stdout.line "I counted \(countLetterA) letter A's!"
|> \countLetterA -> Stdout.line "I counted $(countLetterA) letter A's!"
Err _ -> Stderr.line "Ooops, something went wrong parsing letters"

View File

@ -26,20 +26,20 @@ main =
|> Str.joinWith ("\n")
nMovies = List.len movies |> Num.toStr
Stdout.line "\(nMovies) movies were found:\n\n\(moviesString)\n\nParse success!\n"
Stdout.line "$(nMovies) movies were found:\n\n$(moviesString)\n\nParse success!\n"
Err problem ->
when problem is
ParsingFailure failure ->
Stderr.line "Parsing failure: \(failure)\n"
Stderr.line "Parsing failure: $(failure)\n"
ParsingIncomplete leftover ->
leftoverStr = leftover |> List.map strFromUtf8 |> List.map (\val -> "\"\(val)\"") |> Str.joinWith ", "
leftoverStr = leftover |> List.map strFromUtf8 |> List.map (\val -> "\"$(val)\"") |> Str.joinWith ", "
Stderr.line "Parsing incomplete. Following leftover fields while parsing a record: \(leftoverStr)\n"
Stderr.line "Parsing incomplete. Following leftover fields while parsing a record: $(leftoverStr)\n"
SyntaxError error ->
Stderr.line "Parsing failure. Syntax error in the CSV: \(error)"
Stderr.line "Parsing failure. Syntax error in the CSV: $(error)"
MovieInfo := { title : Str, releaseYear : U64, actors : List Str }
@ -57,7 +57,7 @@ movieInfoExplanation = \@MovieInfo { title, releaseYear, actors } ->
enumeratedActors = enumerate actors
releaseYearStr = Num.toStr releaseYear
"The movie '\(title)' was released in \(releaseYearStr) and stars \(enumeratedActors)"
"The movie '$(title)' was released in $(releaseYearStr) and stars $(enumeratedActors)"
enumerate : List Str -> Str
enumerate = \elements ->

View File

@ -10,4 +10,4 @@ main = \num ->
else
str = Num.toStr num
"The number was \(str), OH YEAH!!! 🤘🤘"
"The number was $(str), OH YEAH!!! 🤘🤘"

View File

@ -10,4 +10,4 @@ main = \num ->
else
str = Num.toStr num
"The number was \(str), OH YEAH!!! 🤘🤘"
"The number was $(str), OH YEAH!!! 🤘🤘"

View File

@ -208,29 +208,29 @@ renderHelp = \buffer, node ->
Str.concat buffer content
Element tagName _ attrs children ->
withTagName = "\(buffer)<\(tagName)"
withTagName = "$(buffer)<$(tagName)"
withAttrs =
if List.isEmpty attrs then
withTagName
else
List.walk attrs "\(withTagName) " renderAttr
List.walk attrs "$(withTagName) " renderAttr
withTag = Str.concat withAttrs ">"
withChildren = List.walk children withTag renderHelp
"\(withChildren)</\(tagName)>"
"$(withChildren)</$(tagName)>"
UnclosedElem tagName _ attrs ->
if List.isEmpty attrs then
"\(buffer)<\(tagName)>"
"$(buffer)<$(tagName)>"
else
attrs
|> List.walk "\(buffer)<\(tagName) " renderAttr
|> List.walk "$(buffer)<$(tagName) " renderAttr
|> Str.concat ">"
# internal helper
renderAttr : Str, Attribute -> Str
renderAttr = \buffer, Attribute key val ->
"\(buffer) \(key)=\"\(val)\""
"$(buffer) $(key)=\"$(val)\""
# Main root
html = element "html"

View File

@ -184,7 +184,7 @@ coords = attribute "coords"
crossorigin = attribute "crossorigin"
csp = attribute "csp"
data = attribute "data"
dataAttr = \dataName, dataVal -> Attribute "data-\(dataName)" dataVal
dataAttr = \dataName, dataVal -> Attribute "data-$(dataName)" dataVal
datetime = attribute "datetime"
decoding = attribute "decoding"
default = attribute "default"

View File

@ -28,7 +28,7 @@ render = \state ->
head [] [],
body [] [
h1 [] [text "The app"],
div [] [text "The answer is \(num)"],
div [] [text "The answer is $(num)"],
],
]

View File

@ -762,7 +762,7 @@ expect
# Sizes don't matter, use zero. We are not creating a HTML string so we don't care what size it would be.
Element "body" 0 [] [
Element "h1" 0 [] [Text "The app"],
Element "div" 0 [onClickAttr] [Text "The answer is \(num)"],
Element "div" 0 [onClickAttr] [Text "The answer is $(num)"],
]
app : App State State

View File

@ -38,7 +38,7 @@ logRequest : Request -> Task {} AppError
logRequest = \req ->
dateTime <- Utc.now |> Task.map Utc.toIso8601Str |> Task.await
Stdout.line "\(dateTime) \(Http.methodToStr req.method) \(req.url)"
Stdout.line "$(dateTime) $(Http.methodToStr req.method) $(req.url)"
readUrlEnv : Str -> Task Str AppError
readUrlEnv = \target ->
@ -60,7 +60,7 @@ handleErr = \err ->
HttpError _ -> "Http error fetching content"
# Log error to stderr
{} <- Stderr.line "Internal Server Error: \(message)" |> Task.await
{} <- Stderr.line "Internal Server Error: $(message)" |> Task.await
_ <- Stderr.flush |> Task.attempt
# Respond with Http 500 Error

View File

@ -13,7 +13,7 @@ main = \req ->
# Log request date, method and url
date <- Utc.now |> Task.map Utc.toIso8601Str |> Task.await
{} <- Stdout.line "\(date) \(Http.methodToStr req.method) \(req.url)" |> Task.await
{} <- Stdout.line "$(date) $(Http.methodToStr req.method) $(req.url)" |> Task.await
# Respond with request body
when req.body is

View File

@ -36,7 +36,7 @@ view =
Newline,
Desc [Ident "user", Kw "&lt;-", Ident "Http.get", Ident "url", Ident "Json.codec", Kw "|>", Ident "Task.await"] "<p>This fetches the contents of the URL and decodes them as <a href=\"https://www.json.org\">JSON</a>.</p><p>If the shape of the JSON isn't compatible with the type of <code>user</code> (based on type inference), this will give a decoding error immediately.</p><p>As with all the other lines ending in <code>|> Task.await</code>, if there's an error, nothing else in <code>storeEmail</code> will be run, and <code>handleErr</code> will end up handling the error.</p>",
Newline,
Desc [Ident "dest", Kw "=", Ident "Path.fromStr", StrInterpolation "\"" "user.name" ".txt\""] "<p>The <code>\\(user.name)</code> in this string literal will be replaced with the value in <code>name</code>. This is <a href=\"/tutorial#string-interpolation\">string interpolation</a>.</p><p>Note that this line doesn't end with <code>|> Task.await</code>. Earlier lines needed that because they were I/O <a href=\"/tutorial#tasks\">tasks</a>, but this is a plain old <a href=\"/tutorial#defs\">definition</a>, so there's no task to await.</p>",
Desc [Ident "dest", Kw "=", Ident "Path.fromStr", StrInterpolation "\"" "user.name" ".txt\""] "<p>The <code>\$(user.name)</code> in this string literal will be replaced with the value in <code>name</code>. This is <a href=\"/tutorial#string-interpolation\">string interpolation</a>.</p><p>Note that this line doesn't end with <code>|> Task.await</code>. Earlier lines needed that because they were I/O <a href=\"/tutorial#tasks\">tasks</a>, but this is a plain old <a href=\"/tutorial#defs\">definition</a>, so there's no task to await.</p>",
Newline,
Desc [Literal "_", Kw "&lt;-", Ident "File.writeUtf8", Ident "dest", Ident "user.email", Kw "|>", Ident "Task.await"] "<p>This writes <code>user.email</code> to the file, encoded as <a href=\"https://en.wikipedia.org/wiki/UTF-8\">UTF-8</a>.</p><p>We won't be using the output of <code>writeUtf8</code>, so we name it <code>_</code>. The special name <code>_</code> is for when you don't want to use something.</p><p>You can name as many things as you like <code>_</code>, but you can never reference anything named <code>_</code>. So it's only useful for when you don't want to choose a name.</p>",
Newline,
@ -89,7 +89,7 @@ tokensToStr = \tokens ->
# Don't put spaces after opening parens or before closing parens
argsWithCommas =
args
|> List.map \ident -> "<span class=\"ident\">\(ident)</span>"
|> List.map \ident -> "<span class=\"ident\">$(ident)</span>"
|> Str.joinWith "<span class=\"literal\">,</span> "
bufWithSpace
@ -98,32 +98,32 @@ tokensToStr = \tokens ->
|> Str.concat "<span class=\"kw\"> -></span>"
Kw str ->
Str.concat bufWithSpace "<span class=\"kw\">\(str)</span>"
Str.concat bufWithSpace "<span class=\"kw\">$(str)</span>"
Num str | Str str | Literal str -> # We may render these differently in the future
Str.concat bufWithSpace "<span class=\"literal\">\(str)</span>"
Str.concat bufWithSpace "<span class=\"literal\">$(str)</span>"
Comment str ->
Str.concat bufWithSpace "<span class=\"comment\"># \(str)</span>"
Str.concat bufWithSpace "<span class=\"comment\"># $(str)</span>"
Ident str ->
Str.concat bufWithSpace (identToHtml str)
StrInterpolation before interp after ->
bufWithSpace
|> Str.concat (if Str.isEmpty before then "" else "<span class=\"literal\">\(before)</span>")
|> Str.concat "<span class=\"kw\">\\(</span>\(identToHtml interp)<span class=\"kw\">)</span>"
|> Str.concat (if Str.isEmpty after then "" else "<span class=\"literal\">\(after)</span>")
|> Str.concat (if Str.isEmpty before then "" else "<span class=\"literal\">$(before)</span>")
|> Str.concat "<span class=\"kw\">\$(</span>$(identToHtml interp)<span class=\"kw\">)</span>"
|> Str.concat (if Str.isEmpty after then "" else "<span class=\"literal\">$(after)</span>")
identToHtml : Str -> Str
identToHtml = \str ->
List.walk (Str.split str ".") "" \accum, ident ->
identHtml = "<span class=\"ident\">\(ident)</span>"
identHtml = "<span class=\"ident\">$(ident)</span>"
if Str.isEmpty accum then
identHtml
else
"\(accum)<span class=\"kw\">.</span>\(identHtml)"
"$(accum)<span class=\"kw\">.</span>$(identHtml)"
sectionsToStr : List Section -> Str
sectionsToStr = \sections ->
@ -168,5 +168,5 @@ radio = \index, labelHtml, descHtml ->
checkedHtml = if index == 0 then " checked" else ""
"""
<input class="interactive-radio" type="radio" name="r" id="r\(Num.toStr index)" \(checkedHtml)><label for="r\(Num.toStr index)" title="Tap to learn about this syntax">\(labelHtml)</label><span class="interactive-desc" role="presentation"><button class="close-desc">X</button>\(descHtml)</span>
<input class="interactive-radio" type="radio" name="r" id="r$(Num.toStr index)" $(checkedHtml)><label for="r$(Num.toStr index)" title="Tap to learn about this syntax">$(labelHtml)</label><span class="interactive-desc" role="presentation"><button class="close-desc">X</button>$(descHtml)</span>
"""

View File

@ -9,7 +9,7 @@ Roc's syntax isn't trivial, but there also isn't much of it to learn. It's desig
- `user.email` always accesses the `email` field of a record named `user`. <span class="nowrap">(Roc has</span> no inheritance, subclassing, or proxying.)
- `Email.isValid` always refers to something named `isValid` exported by a module named `Email`. (Module names are always capitalized, and variables/constants never are.) Modules are always defined statically and can't be modified at runtime; there's no [monkey patching](https://en.wikipedia.org/wiki/Monkey_patch) to consider either.
- `x = doSomething y z` always declares a new constant `x` (Roc has [no mutable variables, reassignment, or shadowing](/functional)) to be whatever the `doSomething` function returns when passed the arguments `y` and `z`. (Function calls in Roc don't need parentheses or commas.)
- `"Name: \(Str.trim name)"` uses *string interpolation* syntax: a backslash inside a string literal, followed by an expression in parentheses. This code is the same as combining the string `"Name: "` with the string returned by the function call `Str.trim name`.<br><br>Because Roc's string interpolation syntax begins with a backslash (just like other backlash-escapes such as `\n` and `\"`), you can always tell which parts of a string involve special handling: the parts that begin with backslashes. Everything else works as normal.
- `"Name: $(Str.trim name)"` uses *string interpolation* syntax: a backslash inside a string literal, followed by an expression in parentheses. This code is the same as combining the string `"Name: "` with the string returned by the function call `Str.trim name`.<br><br>Because Roc's string interpolation syntax begins with a backslash (just like other backlash-escapes such as `\n` and `\"`), you can always tell which parts of a string involve special handling: the parts that begin with backslashes. Everything else works as normal.
Roc also ships with a source code formatter that helps you maintain a consistent style with little effort. The `roc format` command neatly formats your source code according to a common style, and it's designed with the time-saving feature of having no configuration options. This feature saves teams all the time they would otherwise spend debating which stylistic tweaks to settle on!

View File

@ -65,7 +65,7 @@ A benefit of this design is that it makes Roc code easier to rearrange without c
<pre><samp class="code-snippet">func <span class="kw">=</span> <span class="kw">\</span>arg <span class="kw">-&gt;</span>
greeting <span class="kw">=</span> <span class="string">"Hello"</span>
welcome <span class="kw">=</span> <span class="kw">\</span>name <span class="kw">-&gt;</span> <span class="string">"</span><span class="kw">\(</span>greeting<span class="kw">)</span><span class="string">, </span><span class="kw">\(</span>name<span class="kw">)</span><span class="string">!"</span>
welcome <span class="kw">=</span> <span class="kw">\</span>name <span class="kw">-&gt;</span> <span class="string">"</span><span class="kw">$(</span>greeting<span class="kw">)</span><span class="string">, </span><span class="kw">$(</span>name<span class="kw">)</span><span class="string">!"</span>
<span class="comment"># …</span>
@ -82,7 +82,7 @@ Suppose I decide to extract the `welcome` function to the top level, so I can re
<span class="comment"># …</span>
welcome <span class="kw">=</span> <span class="kw">\</span>prefix<span class="punctuation section">,</span> name <span class="kw">-&gt;</span> <span class="string">"</span><span class="kw">\(</span>prefix<span class="kw">)</span><span class="string">, </span><span class="kw">\(</span>name<span class="kw">)</span><span class="string">!"</span></samp></pre>
welcome <span class="kw">=</span> <span class="kw">\</span>prefix<span class="punctuation section">,</span> name <span class="kw">-&gt;</span> <span class="string">"</span><span class="kw">$(</span>prefix<span class="kw">)</span><span class="string">, </span><span class="kw">$(</span>name<span class="kw">)</span><span class="string">!"</span></samp></pre>
Even without knowing the rest of `func`, we can be confident this change will not alter the code's behavior.
@ -90,7 +90,7 @@ In contrast, suppose Roc allowed reassignment. Then it's possible something in t
<pre><samp class="code-snippet">func <span class="kw">=</span> <span class="kw">\</span>arg <span class="kw">-&gt;</span>
greeting <span class="kw">=</span> <span class="string">"Hello"</span>
welcome <span class="kw">=</span> <span class="kw">\</span>name <span class="kw">-&gt;</span> <span class="string">"</span><span class="kw">\(</span>greeting<span class="kw">)</span><span class="string">, </span><span class="kw">\(</span>name<span class="kw">)</span><span class="string">!"</span>
welcome <span class="kw">=</span> <span class="kw">\</span>name <span class="kw">-&gt;</span> <span class="string">"</span><span class="kw">$(</span>greeting<span class="kw">)</span><span class="string">, </span><span class="kw">$(</span>name<span class="kw">)</span><span class="string">!"</span>
<span class="comment"># …</span>

View File

@ -40,10 +40,10 @@ const repl = {
},
{
match: (input) => input.replace(/ /g, "").match(/^name="/i),
show: '<p>This created a new <a href="https://www.roc-lang.org/tutorial#defs">definition</a>&mdash;<code>name</code> is now defined to be equal to the <a href="/tutorial#strings-and-numbers">string</a> you entered.</p><p>Try using this definition by entering <code>"Hi, \\(name)!"</code></p>',
show: '<p>This created a new <a href="https://www.roc-lang.org/tutorial#defs">definition</a>&mdash;<code>name</code> is now defined to be equal to the <a href="/tutorial#strings-and-numbers">string</a> you entered.</p><p>Try using this definition by entering <code>"Hi, \$(name)!"</code></p>',
},
{
match: (input) => input.match(/^["][^\\]+\\\(name\)/i),
match: (input) => input.match(/^["][^\\]+\\$(name\)/i),
show: `<p>Nicely done! This is an example of <a href=\"/tutorial#string-interpolation\">string interpolation</a>, which replaces part of a string with whatever you put inside the parentheses after a <code>\\</code>.</p><p>Now that youve written a few <a href=\"/tutorial#naming-things\">expressions</a>, you can either continue exploring in this REPL, or move on to the <a href=\"/tutorial\">tutorial</a> to learn how to make full programs.<p><p><span class='welcome-to-roc'>Welcome to Roc!</span> <a href='/tutorial' class='btn-small'>${tutorialButtonSvg} Start Tutorial</a></p>`,
},
],