Skip to content

Commit 269f9b8

Browse files
committed
fix: Updated text and improved code extraction
1 parent ae29526 commit 269f9b8

18 files changed

Lines changed: 311 additions & 208 deletions

chapters/bindings.fs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ let json: IExports = nativeOnly
3434
(**
3535
This generates: `import json`
3636
37-
The `[<Erase>]` attribute means the interface only exists at compile time -
38-
no code is generated for it. The `nativeOnly` placeholder tells Fable the
39-
value will be resolved at runtime.
37+
The `[<Erase>]` attribute means the interface only exists at compile time
38+
(erased = no code generated for it). The `nativeOnly` placeholder tells Fable
39+
the value will be resolved at runtime.
4040
4141
## Import Attributes
4242
@@ -107,7 +107,8 @@ let upper (s: string) : string = nativeOnly
107107
(**
108108
## Function Overloads
109109
110-
**Prefer overloads over erased unions.** Instead of:
110+
**Why prefer overloads over erased unions?** Erased unions like `U2<string, bytes>`
111+
require callers to wrap values explicitly, creating friction. Instead of:
111112
112113
```fsharp
113114
// ❌ Avoid this - creates friction for callers

chapters/compatibility.fs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ module Compatibility
33
(**
44
# F# Compatibility in Fable.Python
55
6-
Understanding what works and what doesn't is crucial when targeting Python
7-
with Fable. This chapter covers supported features, limitations, and
8-
important differences from .NET.
6+
This chapter covers supported features, limitations, and important differences
7+
from .NET when targeting Python with Fable.
98
109
## Common Types and Objects
1110
@@ -94,6 +93,11 @@ let mutableList = ResizeArray<int>()
9493
(*** include-python: greeting, is_enabled, coordinates, numbers, mutable_list ***)
9594

9695
(**
96+
Each of these F# values compiles to its Python equivalent. Strings become `str`,
97+
booleans become `bool`, and tuples become Python tuples. The F# `list` uses the
98+
fable-library implementation for immutable semantics, while `ResizeArray`
99+
compiles directly to Python's mutable `list`.
100+
97101
### Functions and Lambdas
98102
99103
First-class functions work as expected:
@@ -106,6 +110,10 @@ let applyTwice f x = f (f x)
106110
let result = applyTwice (add 1) 5 // 7
107111

108112
(**
113+
Functions are first-class values in F#. The `applyTwice` function takes another
114+
function `f` as a parameter and applies it twice. Partial application works
115+
naturally - `(add 1)` creates a new function that adds 1 to its argument.
116+
109117
### Pattern Matching
110118
111119
Full pattern matching support:

chapters/fable-v5.fs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ The Python target has received special attention in v5:
3030
## Rust Core with PyO3
3131
3232
One of the biggest changes is that the core of fable-library is now written
33-
in **Rust** using PyO3. This isn't primarily for performance - it's for
34-
**correctness**:
33+
in **Rust** using PyO3. The motivation is **correctness**, not performance:
3534
*)
3635

3736
(*** hide ***)
@@ -94,5 +93,5 @@ Then compile your F# to Python:
9493
dotnet fable YourProject.fsproj --lang python -o output/
9594
```
9695
97-
The generated Python code will be modern, type-hinted, and ready to run!
96+
The generated Python code will be modern, type-hinted, and ready to run.
9897
*)

chapters/getting-started.fs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,12 @@ Fable-generated Python code requires the `fable-library` runtime:
4040
pip install "fable-library==5.0.0a17"
4141
```
4242
43-
> **Note:** Version pinning is important! The fable-library version must match
44-
> your Fable compiler version. PyPI uses `5.0.0a17` format instead of `5.0.0-alpha.17`.
43+
---
44+
45+
**Note:** Version pinning matters. The fable-library version must match
46+
your Fable compiler version. PyPI uses `5.0.0a17` format instead of `5.0.0-alpha.17`.
47+
48+
---
4549
4650
## Your First Program
4751

chapters/interop.fs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ let length = builtins.len [ 1; 2; 3 ]
6262
let absValue = builtins.abs (-42)
6363

6464
(**
65+
The `builtins` module provides typed access to Python's built-in functions.
66+
These calls compile directly to `len([1, 2, 3])` and `abs(-42)` in Python.
67+
6568
### Working with sys Module
6669
*)
6770

@@ -79,6 +82,9 @@ let fileName = os.path.basename "/path/to/file.txt"
7982
let dirName = os.path.dirname "/path/to/file.txt"
8083

8184
(**
85+
The `os.path` functions work with arrays of path segments. These compile to
86+
Python's `os.path.join`, `os.path.basename`, and `os.path.dirname` calls.
87+
8288
## Environment Variables
8389
8490
Use `os.getenv` to safely retrieve environment variables:
@@ -292,18 +298,11 @@ type DecoratedUser() =
292298
member val Name: string = "" with get, set
293299
member val Age: int = 0 with get, set
294300

295-
(**
296-
This generates:
301+
(** This generates: *)
297302

298-
```python
299-
from dataclasses import dataclass
300-
301-
@dataclass
302-
class DecoratedUser:
303-
Name: str = ""
304-
Age: int = 0
305-
```
303+
(*** include-python: DecoratedUser ***)
306304

305+
(**
307306
## Class Attributes and DataClasses
308307
309308
### Py.ClassAttributes
@@ -316,15 +315,11 @@ type PydanticModel() =
316315
member val Name: string = "" with get, set
317316
member val Age: int = 0 with get, set
318317

319-
(**
320-
This generates class-level type annotations suitable for Pydantic:
318+
(** This generates class-level type annotations suitable for Pydantic: *)
321319

322-
```python
323-
class PydanticModel:
324-
Name: str = ""
325-
Age: int = 0
326-
```
320+
(*** include-python: PydanticModel ***)
327321

322+
(**
328323
### Py.DataClass Shorthand
329324
330325
`Py.DataClass` is shorthand for `ClassAttributes(Attributes, false)`:

chapters/introduction.fs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,29 +39,33 @@ Fable.Python is a great choice when:
3939
## When NOT to Use Fable.Python
4040
4141
- When your F# code depends on .NET libraries without Fable support
42-
- Performance-critical code (Python is still slow)
42+
- Performance-critical code (Python has runtime overhead)
4343
- Team won't learn F#
4444
4545
**Best fit:** You love F#, but need Python's ecosystem.
4646
47-
## A Simple Example
47+
## A First Example
4848
49-
Let's start with something simple. Here's F# code that will compile to Python:
49+
Let's start with F# code that compiles to Python:
5050
*)
5151

5252
let greet name = $"Hello, {name}!"
5353

5454
let message = greet "Fable.Python"
5555

5656
(**
57-
When compiled with Fable, this generates clean, readable Python:
57+
When compiled with Fable, this generates the following Python:
58+
*)
5859

59-
```python
60-
def greet(name):
61-
return f"Hello, {name}!"
60+
(*** include-python: greet, message ***)
6261

63-
message = greet("Fable.Python")
64-
```
62+
(**
63+
The `name: Any | None = None` signature may look odd at first. This happens because
64+
F# infers the type from usage - since we only call `greet` with a string, the compiler
65+
doesn't know if it might also be called with unit `()` (no argument). If it were,
66+
Python would call it as `greet()` instead of `greet("Fable.Python")`. Adding an
67+
explicit type annotation `let greet (name: string) = ...` would generate a cleaner
68+
`name: str` parameter.
6569
6670
## The Power of Types
6771
@@ -82,9 +86,11 @@ let shapes = [ Circle 5.0; Rectangle(3.0, 4.0) ]
8286
let totalArea = shapes |> List.sumBy area
8387

8488
(**
85-
This compiles to Python while preserving the semantic meaning. The discriminated
86-
union becomes a tagged class structure, and pattern matching becomes clean
87-
conditional logic.
89+
This compiles to Python while preserving the semantic meaning. The `Shape` type
90+
becomes a tagged class structure, and the `match` expression becomes clean
91+
conditional logic. The compiler ensures you handle all cases - if you add a
92+
new shape variant, the compiler will warn you about unhandled cases in
93+
the `area` function.
8894
8995
## What's Next?
9096
@@ -94,5 +100,5 @@ In the following chapters, we'll cover:
94100
- **Bindings** - Working with Python libraries from F#
95101
- **Compatibility** - Understanding what F# features are supported
96102
97-
Let's dive in!
103+
Let's begin.
98104
*)

chapters/python.fs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ module ForPythonDevelopers
33
(**
44
# Are You a Python Developer?
55
6-
If you're coming from Python, welcome! This chapter will help you understand
7-
the F# code you'll see throughout this guide. Don't worry - F# is more
8-
approachable than it might first appear, and many concepts will feel familiar.
6+
If you're coming from Python, welcome. This chapter will help you understand
7+
the F# code you'll see throughout this guide. F# is more approachable than
8+
it might appear, and many concepts are familiar.
99
1010
## What is F#?
1111
@@ -104,8 +104,8 @@ let area shape =
104104
| Rectangle(width, height) -> width * height
105105

106106
(**
107-
The compiler will warn you if you forget to handle a case. No more runtime
108-
`AttributeError` because you forgot a shape type!
107+
The compiler warns you if you forget to handle a case. No more runtime
108+
`AttributeError` because you forgot a shape type.
109109
110110
### Records
111111

chapters/units-of-measure.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ let speed = distance / time // Automatically inferred as float<m/s>
4848

4949
(**
5050
The compiler tracks units through all operations. Division of meters by
51-
seconds gives meters-per-second. This is all checked at compile time!
51+
seconds gives meters-per-second. This is all checked at compile time.
5252
5353
## Preventing Errors
5454
@@ -58,7 +58,7 @@ Try to add incompatible units and the compiler stops you:
5858
let distance = 100.0<m>
5959
let mass = 50.0<kg>
6060
61-
// This won't compile!
61+
// This won't compile:
6262
// let nonsense = distance + mass
6363
// Error: The unit of measure 'm' does not match 'kg'
6464
```

docs/bindings.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ let json: IExports = nativeOnly
3131

3232
This generates: `import json`
3333

34-
The `[<Erase>]` attribute means the interface only exists at compile time -
35-
no code is generated for it. The `nativeOnly` placeholder tells Fable the
36-
value will be resolved at runtime.
34+
The `[<Erase>]` attribute means the interface only exists at compile time
35+
(erased = no code generated for it). The `nativeOnly` placeholder tells Fable
36+
the value will be resolved at runtime.
3737

3838
## Import Attributes
3939

@@ -104,7 +104,8 @@ let upper (s: string) : string = nativeOnly
104104

105105
## Function Overloads
106106

107-
**Prefer overloads over erased unions.** Instead of:
107+
**Why prefer overloads over erased unions?** Erased unions like `U2<string, bytes>`
108+
require callers to wrap values explicitly, creating friction. Instead of:
108109

109110
```fsharp
110111
// ❌ Avoid this - creates friction for callers

0 commit comments

Comments
 (0)