Add Scheme-style cond!
macro to syntax::ext::expand
Addresses issue #6037
This commit is contained in:
parent
d217174987
commit
b9824e18c2
@ -33,45 +33,40 @@ enum TreeNode<K, V> {
|
||||
pub fn init<K, V>() -> Treemap<K, V> { @Empty }
|
||||
|
||||
/// Insert a value into the map
|
||||
pub fn insert<K:Copy + Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K, v: V)
|
||||
-> Treemap<K, V> {
|
||||
pub fn insert<K:Copy + Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K, v: V) -> Treemap<K, V> {
|
||||
@match m {
|
||||
@Empty => Node(@k, @v, @Empty, @Empty),
|
||||
@Node(@copy kk, vv, left, right) => {
|
||||
if k < kk {
|
||||
Node(@kk, vv, insert(left, k, v), right)
|
||||
} else if k == kk {
|
||||
Node(@kk, @v, left, right)
|
||||
} else { Node(@kk, vv, left, insert(right, k, v)) }
|
||||
}
|
||||
}
|
||||
@Empty => Node(@k, @v, @Empty, @Empty),
|
||||
@Node(@copy kk, vv, left, right) => cond!(
|
||||
| k < kk { Node(@kk, vv, insert(left, k, v), right) }
|
||||
| k == kk { Node(@kk, @v, left, right) }
|
||||
_ { Node(@kk, vv, left, insert(right, k, v)) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Find a value based on the key
|
||||
pub fn find<K:Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K) -> Option<V> {
|
||||
match *m {
|
||||
Empty => None,
|
||||
Node(@ref kk, @copy v, left, right) => {
|
||||
if k == *kk {
|
||||
Some(v)
|
||||
} else if k < *kk { find(left, k) } else { find(right, k) }
|
||||
}
|
||||
Empty => None,
|
||||
Node(@ref kk, @copy v, left, right) => cond!(
|
||||
| k == *kk { Some(v) }
|
||||
| k < *kk { find(left, k) }
|
||||
_ { find(right, k) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Visit all pairs in the map in order.
|
||||
pub fn traverse<K, V: Copy>(m: Treemap<K, V>, f: &fn(&K, &V)) {
|
||||
match *m {
|
||||
Empty => (),
|
||||
/*
|
||||
Previously, this had what looked like redundant
|
||||
matches to me, so I changed it. but that may be a
|
||||
de-optimization -- tjc
|
||||
*/
|
||||
Node(@ref k, @ref v, left, right) => {
|
||||
traverse(left, f);
|
||||
f(k, v);
|
||||
traverse(right, f);
|
||||
}
|
||||
Empty => (),
|
||||
// Previously, this had what looked like redundant
|
||||
// matches to me, so I changed it. but that may be a
|
||||
// de-optimization -- tjc
|
||||
Node(@ref k, @ref v, left, right) => {
|
||||
traverse(left, f);
|
||||
f(k, v);
|
||||
traverse(right, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ pub mod flatpipes;
|
||||
|
||||
pub mod bitv;
|
||||
pub mod deque;
|
||||
#[cfg(not(stage0))]
|
||||
pub mod fun_treemap;
|
||||
pub mod list;
|
||||
pub mod priority_queue;
|
||||
|
@ -542,7 +542,41 @@ pub fn core_macros() -> ~str {
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
//
|
||||
// A scheme-style conditional that helps to improve code clarity in some instances when
|
||||
// the `if`, `else if`, and `else` keywords obscure predicates undesirably.
|
||||
//
|
||||
// # Example
|
||||
//
|
||||
// ~~~
|
||||
// let clamped =
|
||||
// if x > mx { mx }
|
||||
// else if x < mn { mn }
|
||||
// else { x };
|
||||
// ~~~
|
||||
//
|
||||
// Using `cond!`, the above could be written as:
|
||||
//
|
||||
// ~~~
|
||||
// let clamped = cond!(
|
||||
// | x > mx { mx }
|
||||
// | x < mn { mn }
|
||||
// _ { x }
|
||||
// );
|
||||
// ~~~
|
||||
//
|
||||
// The optional default case is denoted by `_`.
|
||||
//
|
||||
macro_rules! cond (
|
||||
($( | $pred:expr $body:block)+ _ $default:block ) => (
|
||||
$(if $pred $body else)+
|
||||
$default
|
||||
);
|
||||
// for if the default case was ommitted
|
||||
( $( | $pred:expr $body:block )+ ) => (
|
||||
$(if $pred $body)else+
|
||||
);
|
||||
)
|
||||
}";
|
||||
}
|
||||
|
||||
|
23
src/test/run-pass/cond-macro-no-default.rs
Normal file
23
src/test/run-pass/cond-macro-no-default.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn clamp<T:Copy + Ord + Signed>(x: T, mn: T, mx: T) -> T {
|
||||
cond!(
|
||||
| x > mx { return mx; }
|
||||
| x < mn { return mn; }
|
||||
)
|
||||
return x;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(clamp(1, 2, 4), 2);
|
||||
assert_eq!(clamp(8, 2, 4), 4);
|
||||
assert_eq!(clamp(3, 2, 4), 3);
|
||||
}
|
23
src/test/run-pass/cond-macro.rs
Normal file
23
src/test/run-pass/cond-macro.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn clamp<T:Copy + Ord + Signed>(x: T, mn: T, mx: T) -> T {
|
||||
cond!(
|
||||
| x > mx { mx }
|
||||
| x < mn { mn }
|
||||
_ { x }
|
||||
)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(clamp(1, 2, 4), 2);
|
||||
assert_eq!(clamp(8, 2, 4), 4);
|
||||
assert_eq!(clamp(3, 2, 4), 3);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user