You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: pages/docs/manual/latest/function.mdx
+1-28Lines changed: 1 addition & 28 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -388,34 +388,7 @@ function callFirst(_param) {
388
388
389
389
</CodeTab>
390
390
391
-
## Uncurried Function
392
-
393
-
ReScript's functions are curried by default, which is one of the few performance penalties we pay in the compiled JS output. The compiler does a best-effort job at removing those currying whenever possible. However, in certain edge cases, you might want guaranteed uncurrying. In those cases, put a dot in the function's parameter list:
394
-
395
-
<CodeTablabels={["ReScript", "JS Output"]}>
396
-
397
-
```res example
398
-
let add = (. x, y) => x + y
399
-
400
-
add(. 1, 2)
401
-
```
402
-
```js
403
-
functionadd(x, y) {
404
-
return x + y |0;
405
-
}
406
-
407
-
add(1, 2);
408
-
```
409
-
410
-
</CodeTab>
411
-
412
-
If you write down the uncurried function's type, you'll add a dot there as well.
413
-
414
-
**Note**: both the declaration site and the call site need to have the uncurry annotation. That's part of the guarantee/requirement.
415
-
416
-
**This feature seems trivial**, but is actually one of our most important features, as a primarily functional language. We encourage you to use it if you'd like to remove any mention of `Curry` runtime in the JS output.
417
-
418
-
## Async/Await (from v10.1)
391
+
## Async/Await
419
392
420
393
Just as in JS, an async function can be declared by adding `async` before the definition, and `await` can be used in the body of such functions.
Copy file name to clipboardExpand all lines: pages/docs/manual/latest/installation.mdx
+9Lines changed: 9 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,6 +21,15 @@ npm run res:build
21
21
node src/Demo.bs.js
22
22
```
23
23
24
+
or use the create-rescript-app tool:
25
+
26
+
```sh
27
+
npm create rescript-app // Select basic template
28
+
cd<your-rescript-project-name>
29
+
npm run res:build
30
+
node src/Demo.bs.js
31
+
```
32
+
24
33
That compiles your ReScript into JavaScript, then uses Node.js to run said JavaScript. **We recommend you use our unique workflow of keeping a tab open for the generated `.bs.js` file**, so that you can learn how ReScript transforms into JavaScript. Not many languages output clean JavaScript code you can inspect and learn from!
25
34
26
35
During development, instead of running `npm run res:build` each time to compile, use `npm run res:dev` to start a watcher that recompiles automatically after file changes.
Copy file name to clipboardExpand all lines: pages/docs/manual/latest/primitive-types.mdx
+1-20Lines changed: 1 addition & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -48,7 +48,6 @@ There's a special syntax for string that allows
48
48
- multiline string just like before
49
49
- no special character escaping
50
50
- Interpolation
51
-
- Proper unicode handling
52
51
53
52
<CodeTablabels={["ReScript", "JS Output"]}>
54
53
@@ -71,27 +70,9 @@ var greeting = "Hello\nWorld\n👋\n" + name + "\n";
71
70
72
71
This is just like JavaScript's backtick string interpolation, except without needing to escape special characters.
73
72
74
-
### Unsafe String Interpolation (Deprecated)
75
-
76
-
> ReScript v10.1.4 deprecated unsafe string interpolation and will be removed in v11.
77
-
78
-
For interpolation, you'll have to convert the binding (`name` in the example) into a string if it isn't one. If you want the interpolation to implicitly convert a binding into a string, prepend a `j`:
79
-
80
-
<CodeTablabels={["ReScript", "JS Output"]}>
81
-
82
-
```res example
83
-
let age = 10
84
-
let message = j`Today I am $age years old.`
85
-
```
86
-
```js
87
-
var message ="Today I am "+10+" years old.";
88
-
```
89
-
90
-
</CodeTab>
91
-
92
73
### Usage
93
74
94
-
See the familiar `Js.String` API in the [API docs](api/js/string). Since a ReScript string maps to a JavaScript string, you can mix & match the string operations in both standard libraries.
75
+
See the familiar `String` API in the [API docs](api/js/string). Since a ReScript string maps to a JavaScript string, you can mix & match the string operations in all standard libraries.
Copy file name to clipboardExpand all lines: pages/docs/manual/latest/record.mdx
+117Lines changed: 117 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -394,6 +394,122 @@ var me = {
394
394
395
395
</CodeTab>
396
396
397
+
## Record Type Spread
398
+
399
+
In ReScript v11, you can now spread one or more record types into a new record type. It looks like this:
400
+
401
+
```rescript
402
+
type a = {
403
+
id: string,
404
+
name: string,
405
+
}
406
+
407
+
type b = {
408
+
age: int
409
+
}
410
+
411
+
type c = {
412
+
...a,
413
+
...b,
414
+
active: bool
415
+
}
416
+
```
417
+
418
+
`type c` will now be:
419
+
420
+
```rescript
421
+
type c = {
422
+
id: string,
423
+
name: string,
424
+
age: int,
425
+
active: bool,
426
+
}
427
+
```
428
+
429
+
Record type spreads act as a 'copy-paste' mechanism for fields from one or more records into a new record. This operation inlines the fields from the spread records directly into the new record definition, while preserving their original properties, such as whether they are optional or mandatory. It's important to note that duplicate field names are not allowed across the records being spread, even if the fields have the same type.
430
+
431
+
## Record Type Coercion
432
+
433
+
Record type coercion gives us more flexibility when passing around records in our application code. In other words, we can now coerce a record `a` to be treated as a record `b` at the type level, as long as the original record `a` contains the same set of fields in `b`. Here's an example:
434
+
435
+
```rescript
436
+
type a = {
437
+
name: string,
438
+
age: int,
439
+
}
440
+
441
+
type b = {
442
+
name: string,
443
+
age: int,
444
+
}
445
+
446
+
let nameFromB = (b: b) => b.name
447
+
448
+
let a: a = {
449
+
name: "Name",
450
+
age: 35,
451
+
}
452
+
453
+
let name = nameFromB(a :> b)
454
+
```
455
+
456
+
Notice how we _coerced_ the value `a` to type `b` using the coercion operator `:>`. This works because they have the same record fields. This is purely at the type level, and does not involve any runtime operations.
457
+
458
+
Additionally, we can also coerce records from `a` to `b` whenever `a` is a super-set of `b` (i.e. `a` containing all the fields of `b`, and more). The same example as above, slightly altered:
459
+
460
+
```rescript
461
+
type a = {
462
+
id: string,
463
+
name: string,
464
+
age: int,
465
+
active: bool,
466
+
}
467
+
468
+
type b = {
469
+
name: string,
470
+
age: int,
471
+
}
472
+
473
+
let nameFromB = (b: b) => b.name
474
+
475
+
let a: a = {
476
+
id: "1",
477
+
name: "Name",
478
+
age: 35,
479
+
active: true,
480
+
}
481
+
482
+
let name = nameFromB(a :> b)
483
+
```
484
+
485
+
Notice how `a` now has more fields than `b`, but we can still coerce `a` to `b` because `b` has a subset of the fields of `a`.
486
+
487
+
In combination with [optional record fields](/docs/manual/latest/record#optional-record-fields), one may coerce a mandatory field of an `option` type to an optional field:
488
+
489
+
```rescript
490
+
type a = {
491
+
name: string,
492
+
493
+
// mandatory, but explicitly typed as option<int>
494
+
age: option<int>,
495
+
}
496
+
497
+
type b = {
498
+
name: string,
499
+
// optional field
500
+
age?: int,
501
+
}
502
+
503
+
let nameFromB = (b: b) => b.name
504
+
505
+
let a: a = {
506
+
name: "Name",
507
+
age: Some(35),
508
+
}
509
+
510
+
let name = nameFromB(a :> b)
511
+
```
512
+
397
513
## Tips & Tricks
398
514
399
515
### Record Types Are Found By Field Name
@@ -438,3 +554,4 @@ After reading the constraints in the previous sections, and if you're coming fro
438
554
439
555
1. The truth is that most of the times in your app, your data's shape is actually fixed, and if it's not, it can potentially be better represented as a combination of variant (introduced next) + record instead.
440
556
2. Since a record type is resolved through finding that single explicit type declaration (we call this "nominal typing"), the type error messages end up better than the counterpart ("structural typing", like for tuples). This makes refactoring easier; changing a record type's fields naturally allows the compiler to know that it's still the same record, just misused in some places. Otherwise, under structural typing, it might get hard to tell whether the definition site or the usage site is wrong.
0 commit comments