Skip to content

Commit

Permalink
Select anything
Browse files Browse the repository at this point in the history
  • Loading branch information
lpil committed Aug 7, 2022
1 parent ffba6d8 commit 316e7ba
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- The `gleam/erlang/process` module's `selecting_subjectless_record` function
has been replaced by the `selecting_record2`, `selecting_record3`, and
`selecting_record4` functions.
- The `gleam/erlang/process` module gains the `select_anything` function.

## v0.14.0 - 2022-08-01

Expand Down
18 changes: 18 additions & 0 deletions src/gleam/erlang/process.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,24 @@ pub fn selecting_record4(
insert_selector_handler(selector, #(tag, 4), handler)
}

type AnythingSelectorTag {
Anything
}

/// Add a catch-all handler to a selector that will be used when no other
/// handler in a selector is suitable for a given message.
///
/// This may be useful for when you want to ensure that any message in the inbox
/// is handled, or when you need to handle messages from other BEAM languages
/// which do not use subjects or record format messages.
///
pub fn selecting_anything(
selector: Selector(payload),
mapping handler: fn(Dynamic) -> payload,
) -> Selector(payload) {
insert_selector_handler(selector, Anything, handler)
}

external fn insert_selector_handler(
Selector(payload),
for: tag,
Expand Down
6 changes: 5 additions & 1 deletion src/gleam_erlang_ffi.erl
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ select(Selector) ->
Message.

select({selector, Handlers}, Timeout) ->
AnythingHandler = maps:get(anything, Handlers, undefined),
receive
% Monitored process down messages.
% This is special cased so we can selectively receive based on the
Expand All @@ -178,7 +179,10 @@ select({selector, Handlers}, Timeout) ->

Msg when is_map_key({element(1, Msg), tuple_size(Msg)}, Handlers) ->
Fn = maps:get({element(1, Msg), tuple_size(Msg)}, Handlers),
{ok, Fn(Msg)}
{ok, Fn(Msg)};

Msg when AnythingHandler =/= undefined ->
{ok, AnythingHandler(Msg)}
after Timeout ->
{error, nil}
end.
Expand Down
16 changes: 16 additions & 0 deletions test/gleam/erlang/process_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,22 @@ pub fn selecting_record_test() {
|> process.select(0)
}

pub fn selecting_anything_test() {
process.flush_messages()
send(process.self(), 1)
send(process.self(), 2.0)

let selector =
process.new_selector()
|> process.selecting_anything(dynamic.int)

assert Ok(Ok(1)) = process.select(selector, 0)
assert Ok(Error([
dynamic.DecodeError(expected: "Int", found: "Float", path: []),
])) = process.select(selector, 0)
assert Error(Nil) = process.select(selector, 0)
}

pub fn linking_self_test() {
assert True = process.link(process.self())
}
Expand Down

0 comments on commit 316e7ba

Please sign in to comment.