Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions exercises/concept/backyard-birdwatcher/.docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ rest ( seq -- tailseq ) ! everything but the first element
last ( seq -- elt )
but-last ( seq -- headseq ) ! everything but the last element
nth ( n seq -- elt ) ! 0-based
?nth ( n seq -- elt/f ) ! 0-based; f when out of bounds
```

```factor
Expand All @@ -37,6 +38,14 @@ nth ( n seq -- elt ) ! 0-based
1 { 10 20 30 } nth . ! => 20
```

`?nth` is the bounds-safe version: you can probe a position without
checking the length first.

```factor
1 { 10 20 30 } ?nth . ! => 20
9 { 10 20 30 } ?nth . ! => f (out of bounds, no error)
```

## Slicing

```
Expand Down
24 changes: 24 additions & 0 deletions exercises/concept/boutique-bookkeeping/.docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,30 @@ sift ( seq -- newseq ) ! drop every `f`, keep the rest
element except `f`, handy for clearing out the gaps a previous `map`
left behind.

### Keeping the result of the test

`find` hands back the matching *element*. When the test already
*computes* the value you actually want, `map-find` saves you a
second pass: it runs the quotation over each element and returns the
first non-`f` result **and** the element that produced it.

```
map-find ( seq quot: ( elt -- result/f ) -- result elt )
```

```factor
USING: kernel math sequences ;

! First multiple of 3, paired with that multiple divided by 3.
{ 11 13 15 17 } [ dup 3 mod 0 = [ 3 /i ] [ drop f ] if ] map-find .s
! => 5 (result: 15/3)
! => 15 (element)
```

The quotation returns `f` for elements that don't qualify and the
result you want to keep for the one that does. If nothing qualifies,
`map-find` leaves `f f`, just like `find`.

### Filtering records by a slot

When the elements are *tuples*, the predicate usually projects
Expand Down
18 changes: 15 additions & 3 deletions exercises/concept/lighthouse-logbook/.docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@ USING: hash-sets prettyprint ;
## Adjoining and removing

```
adjoin ( elt set -- ) ! insert in place; no-op if already present
delete ( elt set -- ) ! remove in place; no-op if absent
adjoin ( elt set -- ) ! insert in place; no-op if already present
adjoin-all ( seq set -- ) ! insert every element of seq in place
delete ( elt set -- ) ! remove in place; no-op if absent
```

Both mutate the set; neither returns anything on the stack.
All three mutate the set; none returns anything on the stack.

```factor
USING: hash-sets kernel sets ;
Expand All @@ -52,6 +53,17 @@ HS{ } clone
. ! => HS{ "NS-1024" "WB-203" }
```

`adjoin-all` is the bulk form: it adjoins each element of a
sequence, skipping duplicates just like `adjoin` does one at a time.

```factor
USING: hash-sets kernel sets ;

HS{ "NS-1024" } clone
{ "WB-203" "NS-1024" "QR-7" } over adjoin-all
. ! => HS{ "QR-7" "NS-1024" "WB-203" } (order not guaranteed)
```

## Asking the set

```
Expand Down
31 changes: 31 additions & 0 deletions exercises/concept/mixed-juices/.docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,37 @@ body `dup . 1 -` prints it and decrements it; the loop stops once
the counter reaches `0`. The trailing `drop` discards that final
`0` from the stack.

## `while*` — keep the predicate's value

```
while* ( pred body -- )
```

`while` only cares whether its predicate left a true value — it
throws the value itself away before running the body. `while*`
instead *hands that value to the body*. Reach for it whenever the
test and the body want the same freshly-computed thing: a lookup,
a match, a parsed token.

Here each name points to the next one in a chain. The predicate
looks the current name up; as long as there is a next name, `while*`
passes it to the body, which prints it and carries on from there:

```factor
USING: assocs kernel locals prettyprint ;

:: print-chain ( start links -- )
start [ links at ] [ dup . ] while* ;

"a" H{ { "a" "b" } { "b" "c" } } print-chain
! prints "b" then "c"
```

`links at` returns the next name, or `f` once a name has no entry.
While it returns a name, `while*` gives that name to `dup .`, which
prints it and leaves it as the key for the next lookup. The first
`f` stops the loop — `while*` discards it, so nothing is left over.

## Multiple state values with locals

When the loop carries more than one value — a remaining list and
Expand Down
19 changes: 19 additions & 0 deletions exercises/concept/pursers-pantry/.docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,25 @@ H{ { "wood" 11 } { "coal" 7 } } sort-keys .
! => { { "coal" 7 } { "wood" 11 } }
```

## From pairs back to a hashtable

`>hashtable` (in [`hashtables`][hashtables]) is the inverse of
`>alist`: it turns any assoc — most often an alist of
`{ key value }` pairs — into a hashtable with O(1) lookup.

```
>hashtable ( assoc -- hashtable )
```

```factor
{ { "coal" 7 } { "wood" 11 } } >hashtable .
! => H{ { "wood" 11 } { "coal" 7 } } (entry order not guaranteed)
```

Handy when you've assembled or transformed a list of pairs and
want to fold it back into a hashtable to look entries up by key.

[assocs]: https://docs.factorcode.org/content/vocab-assocs.html
[fry]: https://docs.factorcode.org/content/article-fry.html
[hashtables]: https://docs.factorcode.org/content/vocab-hashtables.html
[sorting]: https://docs.factorcode.org/content/vocab-sorting.html
Loading