Skip to content

Commit a154a9e

Browse files
author
José Valim
committed
Allow &1.foo syntax inside capture
1 parent 2ed1c37 commit a154a9e

File tree

4 files changed

+19
-2
lines changed

4 files changed

+19
-2
lines changed

lib/elixir/lib/kernel/special_forms.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,12 @@ defmodule Kernel.SpecialForms do
897897
iex> fun.(1, 2, 3)
898898
6
899899
900+
Record-like calls are also allowed:
901+
902+
iex> fun = &(&1.first)
903+
iex> fun.(1..3)
904+
1
905+
900906
Remember tuple and lists are represented as calls in the AST and
901907
therefore are also allowed:
902908

lib/elixir/src/elixir_parser.yrl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Terminals
3333
comp_op at_op unary_op and_op or_op arrow_op match_op
3434
range_op in_op inc_op when_op than_op default_op tail_op
3535
dual_op add_op mult_op exp_op two_op type_op stab_op
36-
'true' 'false' 'nil' 'do' eol ',' '.'
36+
'true' 'false' 'nil' 'do' eol ',' '.' '&'
3737
'(' ')' '[' ']' '{' '}' '<<' '>>'
3838
.
3939

@@ -205,6 +205,7 @@ base_expr -> bin_string : build_bin_string('$1').
205205
base_expr -> list_string : build_list_string('$1').
206206
base_expr -> bit_string : '$1'.
207207
base_expr -> sigil : build_sigil('$1').
208+
base_expr -> '&' number : { '&', [{line,?line('$1')}], [?exprs('$2')] }.
208209

209210
%% Blocks
210211

@@ -490,7 +491,7 @@ build_op({ _Kind, Line, '/' }, { '&', _, [{ { '.', _, [_, _] }, _, [] } = Left]
490491
build_op({ _Kind, Line, BOp }, { UOp, _, [Left] }, Right) when ?rearrange_bop(BOp), ?rearrange_uop(UOp) ->
491492
{ UOp, [{line,Line}], [{ BOp, [{line,Line}], [Left, Right] }] };
492493

493-
build_op({ _Kind, Line, Op } = A, Left, Right) ->
494+
build_op({ _Kind, Line, Op }, Left, Right) ->
494495
{ Op, [{line,Line}], [Left, Right] }.
495496

496497
build_unary_op({ _Kind, Line, Op }, Expr) ->

lib/elixir/src/elixir_tokenizer.erl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,11 @@ tokenize([T1,T2|Rest], Line, Scope, Tokens) when ?type_op(T1, T2) ->
423423
handle_op(Rest, Line, type_op, list_to_atom([T1, T2]), Scope, Tokens);
424424

425425
% ## Single Token Operators
426+
427+
%% Handle &1 and friends with special precedence.
428+
tokenize([$&,D|Rest], Line, Scope, Tokens) when ?is_digit(D) ->
429+
tokenize([D|Rest], Line, Scope, [{ '&', Line }|Tokens]);
430+
426431
tokenize([T|Rest], Line, Scope, Tokens) when ?at_op(T) ->
427432
handle_nonl_op(Rest, Line, at_op, list_to_atom([T]), Scope, Tokens);
428433

lib/elixir/test/elixir/kernel/fn_test.exs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ defmodule Kernel.FnTest do
6060
assert (&[&1|&2]).(1, 2) == [1|2]
6161
end
6262

63+
test "capture and partially apply on call" do
64+
assert (&(&1.file)).(__ENV__) == __FILE__
65+
assert (&(&1.file(&2))).(__ENV__, "Hello").file == "Hello"
66+
end
67+
6368
test "failure on non-continuous" do
6469
assert_compile_fail CompileError, "nofile:1: capture &2 cannot be defined without &1", "&(&2)"
6570
end

0 commit comments

Comments
 (0)