Skip to content

Incoming #2684

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jun 21, 2012
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
67 changes: 16 additions & 51 deletions doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -330,24 +330,32 @@ An _integer literal_ has one of three forms:
* A _binary literal_ starts with the character sequence `U+0030` `U+0062`
(`0b`) and continues as any mixture binary digits and underscores.

By default, an integer literal is of type `int`. An integer literal may be
followed (immediately, without any spaces) by an _integer suffix_, which
changes the type of the literal. There are two kinds of integer literal
suffix:
An integer literal may be followed (immediately, without any spaces) by an
_integer suffix_, which changes the type of the literal. There are two kinds
of integer literal suffix:

* The `u` suffix gives the literal type `uint`.
* The `i` and `u` suffixes give the literal type `int` or `uint`,
respectively.
* Each of the signed and unsigned machine types `u8`, `i8`,
`u16`, `i16`, `u32`, `i32`, `u64` and `i64`
give the literal the corresponding machine type.

The type of an _unsuffixed_ integer literal is determined by type inference.
If a integer type can be _uniquely_ determined from the surrounding program
context, the unsuffixed integer literal has that type. If the program context
underconstrains the type, the unsuffixed integer literal's type is `int`; if
the program context overconstrains the type, it is considered a static type
error.

Examples of integer literals of various forms:

~~~~
123; // type int
123; 0xff00; // type determined by program context;
// defaults to int in absence of type
// information

123u; // type uint
123_u; // type uint
0xff00; // type int
0xff_u8; // type u8
0b1111_1111_1001_0000_i32; // type i32
~~~~
Expand Down Expand Up @@ -980,7 +988,7 @@ fn pure_foldl<T, U: copy>(ls: list<T>, u: U, f: fn(&&T, &&U) -> U) -> U {
pure fn pure_length<T>(ls: list<T>) -> uint {
fn count<T>(_t: T, &&u: uint) -> uint { u + 1u }
unchecked {
pure_foldl(ls, 0u, count(_, _))
pure_foldl(ls, 0u, count)
}
}
~~~~
Expand Down Expand Up @@ -1941,49 +1949,6 @@ An example of a call expression:
let x: int = add(1, 2);
~~~~


### Bind expressions

A _bind expression_ constructs a new function from an existing function.^[The
`bind` expression is analogous to the `bind` expression in the Sather
language.] The new function has zero or more of its arguments *bound* into a
new, hidden boxed tuple that holds the bindings. For each concrete argument
passed in the `bind` expression, the corresponding parameter in the existing
function is *omitted* as a parameter of the new function. For each argument
passed the placeholder symbol `_` in the `bind` expression, the corresponding
parameter of the existing function is *retained* as a parameter of the new
function.

Any subsequent invocation of the new function with residual arguments causes
invocation of the existing function with the combination of bound arguments
and residual arguments that was specified during the binding.

An example of a `bind` expression:

~~~~{.xfail-test}
fn add(x: int, y: int) -> int {
ret x + y;
}
type single_param_fn = fn(int) -> int;

let add4: single_param_fn = bind add(4, _);

let add5: single_param_fn = bind add(_, 5);

assert (add(4,5) == add4(5));
assert (add(4,5) == add5(4));

~~~~

A `bind` expression generally stores a copy of the bound arguments in a
hidden, boxed tuple, owned by the resulting first-class function. For each
bound slot in the bound function's signature, space is allocated in the hidden
tuple and populated with a copy of the bound value.

A `bind` expression is an alternative way of constructing a shared function
closure; the [`fn@` expression](#shared-function-expressions) form is another
way.

### Shared function expressions

*TODO*.
Expand Down
70 changes: 51 additions & 19 deletions doc/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -396,22 +396,67 @@ synonym.

## Literals

### Numeric literals

Integers can be written in decimal (`144`), hexadecimal (`0x90`), and
binary (`0b10010000`) base. Without a suffix, an integer literal is
considered to be of type `int`. Add a `u` (`144u`) to make it a `uint`
instead. Literals of the fixed-size integer types can be created by
the literal with the type name (`255u8`, `50i64`, etc).
binary (`0b10010000`) base.

If you write an integer literal without a suffix (`3`, `-500`, etc.),
the Rust compiler will try to infer its type based on type annotations
and function signatures in the surrounding program. For example, here
the type of `x` is inferred to be `u16` because it is passed to a
function that takes a `u16` argument:

~~~~~
let x = 3;

fn identity_u16(n: u16) -> u16 { n }

identity_u16(x);
~~~~

On the other hand, if the program gives conflicting information about
what the type of the unsuffixed literal should be, you'll get an error
message.

~~~~~{.xfail-test}
let x = 3;
let y: i32 = 3;

fn identity_u8(n: u8) -> u8 { n }
fn identity_u16(n: u16) -> u16 { n }

identity_u8(x); // after this, `x` is assumed to have type `u8`
identity_u16(x); // raises a type error (expected `u16` but found `u8`)
identity_u16(y); // raises a type error (expected `u16` but found `i32`)
~~~~

In the absence of any type annotations at all, Rust will assume that
an unsuffixed integer literal has type `int`.

~~~~
let n = 50;
log(error, n); // n is an int
~~~~

It's also possible to avoid any type ambiguity by writing integer
literals with a suffix. The suffixes `i` and `u` are for the types
`int` and `uint`, respectively: the literal `-3i` has type `int`,
while `127u` has type `uint`. For the fixed-size integer types, just
suffix the literal with the type name: `255u8`, `50i64`, etc.

Note that, in Rust, no implicit conversion between integer types
happens. If you are adding one to a variable of type `uint`, you must
type `v += 1u`—saying `+= 1` will give you a type error.
happens. If you are adding one to a variable of type `uint`, saying
`+= 1u8` will give you a type error.

Floating point numbers are written `0.0`, `1e6`, or `2.1e-4`. Without
a suffix, the literal is assumed to be of type `float`. Suffixes `f32`
and `f64` can be used to create literals of a specific type. The
suffix `f` can be used to write `float` literals without a dot or
exponent: `3f`.

### Other literals

The nil literal is written just like the type: `()`. The keywords
`true` and `false` produce the boolean literals.

Expand Down Expand Up @@ -903,19 +948,6 @@ argument to every element of a vector, producing a new vector.
Even when a closure takes no parameters, you must still write the bars
for the parameter list, as in `{|| ...}`.

## Binding

Partial application is done using the `bind` keyword in Rust.

~~~~
let findx = bind str::find_char(_, 'x');
~~~~

Binding a function produces a boxed closure (`fn@` type) in which some
of the arguments to the bound function have already been provided.
`findx` will be a function taking a single string argument, and
returning the position where the letter `x` occurs.

## Iteration

Functions taking closures provide a good way to define non-trivial
Expand Down
4 changes: 2 additions & 2 deletions src/cargo/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,8 @@ fn load_crate(filename: str) -> option<crate> {
mut deps: []
};
let v = visit::mk_simple_visitor(@{
visit_view_item: bind goto_view_item(e, _),
visit_item: bind goto_item(e, _),
visit_view_item: {|a|goto_view_item(e, a)},
visit_item: {|a|goto_item(e, a)},
with *visit::default_simple_visitor()
});

Expand Down
2 changes: 1 addition & 1 deletion src/compiletest/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ fn compose_and_run_compiler(
let abs_ab = path::connect(config.aux_base, rel_ab);
let aux_args =
make_compile_args(config, props, ["--lib"] + extra_link_args,
bind make_lib_name(_, _, testfile), abs_ab);
{|a,b|make_lib_name(a, b, testfile)}, abs_ab);
let auxres = compose_and_run(config, abs_ab, aux_args, [],
config.compile_lib_path, option::none);
if auxres.status != 0 {
Expand Down
32 changes: 16 additions & 16 deletions src/fuzzer/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ fn steal(crate: ast::crate, tm: test_mode) -> stolen_stuff {
let exprs = @mut [];
let tys = @mut [];
let v = visit::mk_simple_visitor(@{
visit_expr: bind stash_expr_if(safe_to_steal_expr, exprs, _, tm),
visit_ty: bind stash_ty_if(safe_to_steal_ty, tys, _, tm)
visit_expr: {|a|stash_expr_if(safe_to_steal_expr, exprs, a, tm)},
visit_ty: {|a|stash_ty_if(safe_to_steal_ty, tys, a, tm)}
with *visit::default_simple_visitor()
});
visit::visit_crate(crate, (), v);
Expand Down Expand Up @@ -188,8 +188,8 @@ fn replace_expr_in_crate(crate: ast::crate, i: uint,
}
}
let afp =
@{fold_expr: fold::wrap(bind fold_expr_rep(j, i,
newexpr.node, _, _, tm))
@{fold_expr: fold::wrap({|a,b|
fold_expr_rep(j, i, newexpr.node, a, b, tm)})
with *fold::default_ast_fold()};
let af = fold::make_fold(afp);
let crate2: @ast::crate = @af.fold_crate(crate);
Expand All @@ -211,7 +211,7 @@ fn replace_ty_in_crate(crate: ast::crate, i: uint, newty: ast::ty,
} else { fold::noop_fold_ty(original, fld) }
}
let afp =
@{fold_ty: fold::wrap(bind fold_ty_rep(j, i, newty.node, _, _, tm))
@{fold_ty: fold::wrap({|a,b|fold_ty_rep(j, i, newty.node, a, b, tm)})
with *fold::default_ast_fold()};
let af = fold::make_fold(afp);
let crate2: @ast::crate = @af.fold_crate(crate);
Expand All @@ -235,7 +235,7 @@ fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap,
filename: str, cx: context) {
let stolen = steal(crate, cx.mode);
let extra_exprs = vec::filter(common_exprs(),
bind safe_to_use_expr(_, cx.mode));
{|a|safe_to_use_expr(a, cx.mode)});
check_variants_T(crate, codemap, filename, "expr",
extra_exprs + stolen.exprs, pprust::expr_to_str,
replace_expr_in_crate, cx);
Expand Down Expand Up @@ -268,13 +268,13 @@ fn check_variants_T<T: copy>(
// testing the string for stability is easier and ok for now.
let handler = diagnostic::mk_handler(none);
let str3 =
@as_str(bind pprust::print_crate(
@as_str({|a|pprust::print_crate(
codemap,
diagnostic::mk_span_handler(handler, codemap),
crate2,
filename,
io::str_reader(""), _,
pprust::no_ann()));
io::str_reader(""), a,
pprust::no_ann())});
alt cx.mode {
tm_converge {
check_roundtrip_convergence(str3, 1u);
Expand Down Expand Up @@ -421,12 +421,12 @@ fn parse_and_print(code: @str) -> str {
let crate = parse::parse_crate_from_source_str(
filename, code, [], sess);
io::with_str_reader(*code) { |rdr|
as_str(bind pprust::print_crate(sess.cm,
as_str({|a|pprust::print_crate(sess.cm,
sess.span_diagnostic,
crate,
filename,
rdr, _,
pprust::no_ann()))
rdr, a,
pprust::no_ann())})
}
}

Expand All @@ -439,7 +439,7 @@ fn has_raw_pointers(c: ast::crate) -> bool {
}
}
let v =
visit::mk_simple_visitor(@{visit_ty: bind visit_ty(has_rp, _)
visit::mk_simple_visitor(@{visit_ty: {|a|visit_ty(has_rp, a)}
with *visit::default_simple_visitor()});
visit::visit_crate(c, (), v);
ret *has_rp;
Expand Down Expand Up @@ -565,12 +565,12 @@ fn check_variants(files: [str], cx: context) {
s, [], sess);
io::with_str_reader(*s) { |rdr|
#error("%s",
as_str(bind pprust::print_crate(sess.cm,
as_str({|a|pprust::print_crate(sess.cm,
sess.span_diagnostic,
crate,
file,
rdr, _,
pprust::no_ann())));
rdr, a,
pprust::no_ann())}));
}
check_variants_of_ast(*crate, sess.cm, file, cx);
}
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,11 @@ fn peek<T: send>(p: port<T>) -> bool { peek_(***p) }

#[doc(hidden)]
fn recv_chan<T: send>(ch: comm::chan<T>) -> T {
as_raw_port(ch, recv_(_))
as_raw_port(ch, {|x|recv_(x)})
}

fn peek_chan<T: send>(ch: comm::chan<T>) -> bool {
as_raw_port(ch, peek_(_))
as_raw_port(ch, {|x|peek_(x)})
}

#[doc = "Receive on a raw port pointer"]
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/extfmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ mod ct {
let curr: [flag] = [f];
ret {flags: curr + rest, next: j};
}
let more = bind more_(_, s, i, lim);
let more = {|x|more_(x, s, i, lim)};
let f = s[i];
ret if f == '-' as u8 {
more(flag_left_justify)
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/bitv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ Converts the bitvector to a vector of uint with the same length.
Each uint in the resulting vector has either value 0u or 1u.
"]
fn to_vec(v: bitv) -> [uint] {
let sub = bind init_to_vec(v, _);
let sub = {|x|init_to_vec(v, x)};
ret vec::from_fn::<uint>(v.nbits, sub);
}

Expand Down
2 changes: 1 addition & 1 deletion src/libstd/c_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ mod tests {
assert mem as int != 0;

ret unsafe { c_vec_with_dtor(mem as *mut u8, n as uint,
bind free(mem)) };
{||free(mem)}) };
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ mod tests {
two(17, 42));

#debug("*** test parameterized: taggypar<int>");
let eq4: eqfn<taggypar<int>> = bind taggypareq::<int>(_, _);
let eq4: eqfn<taggypar<int>> = {|x,y|taggypareq::<int>(x, y)};
test_parameterized::<taggypar<int>>(eq4, onepar::<int>(1),
twopar::<int>(1, 2),
threepar::<int>(1, 2, 3),
Expand Down
8 changes: 4 additions & 4 deletions src/libstd/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ fn run_tests_console(opts: test_opts,
mut ignored: 0u,
mut failures: []};

run_tests(opts, tests, bind callback(_, st));
run_tests(opts, tests, {|x|callback(x, st)});

assert (st.passed + st.failed + st.ignored == st.total);
let success = st.failed == 0u;
Expand Down Expand Up @@ -349,7 +349,7 @@ fn filter_tests(opts: test_opts,
} else { ret option::none; }
}

let filter = bind filter_fn(_, filter_str);
let filter = {|x|filter_fn(x, filter_str)};

vec::filter_map(filtered, filter)
};
Expand All @@ -367,7 +367,7 @@ fn filter_tests(opts: test_opts,
} else { ret option::none; }
};

vec::filter_map(filtered, bind filter(_))
vec::filter_map(filtered, {|x|filter(x)})
};

// Sort the tests alphabetically
Expand All @@ -376,7 +376,7 @@ fn filter_tests(opts: test_opts,
fn lteq(t1: test_desc, t2: test_desc) -> bool {
str::le(t1.name, t2.name)
}
sort::merge_sort(bind lteq(_, _), filtered)
sort::merge_sort({|x,y|lteq(x, y)}, filtered)
};

ret filtered;
Expand Down
Loading