diff --git a/src/lib/builtins/exists.rs b/src/lib/builtins/exists.rs
index 0844ada3ffb8165c6e4c7d3f52f7d834b04adc1f..95a733ac619a445193eb47eefd14b38944e2ff15 100644
--- a/src/lib/builtins/exists.rs
+++ b/src/lib/builtins/exists.rs
@@ -5,7 +5,6 @@ use std::{fs, os::unix::fs::PermissionsExt};
 #[cfg(test)]
 use shell::{
     self,
-    variables::VariableType,
     flow_control::Statement,
 };
 use shell::{
@@ -172,11 +171,11 @@ fn test_evaluate_arguments() {
     assert_eq!(evaluate_arguments(&["-a".to_owned()], &shell), Ok(true));
     shell
         .variables
-        .set_variable("emptyarray", VariableType::Array(Vec::new().into()));
+        .set("emptyarray", types::Array::new());
     assert_eq!(evaluate_arguments(&["-a".to_owned(), "emptyarray".to_owned()], &shell), Ok(false));
-    let mut vec = Vec::new();
-    vec.push("element".to_owned());
-    shell.variables.set_variable("array", VariableType::Array(vec.into()));
+    let mut array = types::Array::new();
+    array.push("element".to_owned());
+    shell.variables.set("array", array);
     assert_eq!(evaluate_arguments(&["-a".to_owned(), "array".to_owned()], &shell), Ok(true));
     shell.variables.remove_variable("array");
     assert_eq!(evaluate_arguments(&["-a".to_owned(), "array".to_owned()], &shell), Ok(false));
@@ -186,7 +185,7 @@ fn test_evaluate_arguments() {
     // no argument means we treat it as a string
     assert_eq!(evaluate_arguments(&["-b".to_owned()], &shell), Ok(true));
     let oldpath = shell.get::<types::Value>("PATH").unwrap_or("/usr/bin".to_owned());
-    shell.set_variable("PATH", VariableType::Str("testing/".into()));
+    shell.set("PATH", "testing/".to_string());
 
     assert_eq!(
         evaluate_arguments(&["-b".to_owned(), "executable_file".to_owned()], &shell),
@@ -200,7 +199,7 @@ fn test_evaluate_arguments() {
 
     // restore original PATH. Not necessary for the currently defined test cases
     // but this might change in the future? Better safe than sorry!
-    shell.set_variable("PATH", VariableType::Str(oldpath));
+    shell.set("PATH", oldpath);
 
     // check `exists -d`
     // no argument means we treat it as a string
@@ -231,17 +230,17 @@ fn test_evaluate_arguments() {
     // check `exists -s`
     // no argument means we treat it as a string
     assert_eq!(evaluate_arguments(&["-s".to_owned()], &shell), Ok(true));
-    shell.set_variable("emptyvar", VariableType::Str("".into()));
+    shell.set("emptyvar", "".to_string());
     assert_eq!(evaluate_arguments(&["-s".to_owned(), "emptyvar".to_owned()], &shell), Ok(false));
-    shell.set_variable("testvar", VariableType::Str("foobar".into()));
+    shell.set("testvar", "foobar".to_string());
     assert_eq!(evaluate_arguments(&["-s".to_owned(), "testvar".to_owned()], &shell), Ok(true));
     shell.variables.remove_variable("testvar");
     assert_eq!(evaluate_arguments(&["-s".to_owned(), "testvar".to_owned()], &shell), Ok(false));
     // also check that it doesn't trigger on arrays
-    let mut vec = Vec::new();
-    vec.push("element".to_owned());
+    let mut array = types::Array::new();
+    array.push("element".to_owned());
     shell.variables.remove_variable("array");
-    shell.variables.set_variable("array", VariableType::Array(vec.into()));
+    shell.variables.set("array", array);
     assert_eq!(evaluate_arguments(&["-s".to_owned(), "array".to_owned()], &shell), Ok(false));
 
     // check `exists --fn`
@@ -256,9 +255,9 @@ fn test_evaluate_arguments() {
     statements.push(Statement::End);
     let description = "description".to_owned();
 
-    shell.variables.set_variable(
+    shell.variables.set(
         &name,
-        VariableType::Function(Function::new(Some(description), name.clone(), args, statements)),
+        Function::new(Some(description), name.clone(), args, statements),
     );
 
     assert_eq!(evaluate_arguments(&["--fn".to_owned(), name_str.to_owned()], &shell), Ok(true));
@@ -339,7 +338,7 @@ fn test_binary_is_in_path() {
     // TODO: PATH containing directories without read permission (for user)
     // TODO: PATH containing directories without execute ("enter") permission (for
     // user) TODO: empty PATH?
-    shell.set_variable("PATH", VariableType::Str("testing/".into()));
+    shell.set("PATH", "testing/".to_string());
 
     assert_eq!(binary_is_in_path("executable_file", &shell), true);
     assert_eq!(binary_is_in_path("empty_file", &shell), false);
@@ -364,12 +363,12 @@ fn test_string_is_nonzero() {
 fn test_array_var_is_not_empty() {
     let mut shell = shell::ShellBuilder::new().as_library();
 
-    shell.variables.set_variable("EMPTY_ARRAY", VariableType::Array(Vec::new().into()));
+    shell.variables.set("EMPTY_ARRAY", types::Array::new());
     assert_eq!(array_var_is_not_empty("EMPTY_ARRAY", &shell), false);
 
-    let mut not_empty_vec = Vec::new();
-    not_empty_vec.push("array not empty".to_owned());
-    shell.variables.set_variable("NOT_EMPTY_ARRAY", VariableType::Array(not_empty_vec.into()));
+    let mut not_empty_array = types::Array::new();
+    not_empty_array.push("array not empty".to_owned());
+    shell.variables.set("NOT_EMPTY_ARRAY", not_empty_array);
     assert_eq!(array_var_is_not_empty("NOT_EMPTY_ARRAY", &shell), true);
 
     // test for array which does not even exist
@@ -378,7 +377,7 @@ fn test_array_var_is_not_empty() {
 
     // array_var_is_not_empty should NOT match for non-array variables with the
     // same name
-    shell.set_variable("VARIABLE", VariableType::Str("notempty-variable".into()));
+    shell.set("VARIABLE", "notempty-variable".to_string());
     assert_eq!(array_var_is_not_empty("VARIABLE", &shell), false);
 }
 
@@ -386,16 +385,16 @@ fn test_array_var_is_not_empty() {
 fn test_string_var_is_not_empty() {
     let mut shell = shell::ShellBuilder::new().as_library();
 
-    shell.set_variable("EMPTY", VariableType::Str("".into()));
+    shell.set("EMPTY", "".to_string());
     assert_eq!(string_var_is_not_empty("EMPTY", &shell), false);
 
-    shell.set_variable("NOT_EMPTY", VariableType::Str("notempty".into()));
+    shell.set("NOT_EMPTY", "notempty".to_string());
     assert_eq!(string_var_is_not_empty("NOT_EMPTY", &shell), true);
 
     // string_var_is_not_empty should NOT match for arrays with the same name
-    let mut vec = Vec::new();
-    vec.push("not-empty".to_owned());
-    shell.variables.set_variable("ARRAY_NOT_EMPTY", VariableType::Array(vec.into()));
+    let mut array = types::Array::new();
+    array.push("not-empty".to_owned());
+    shell.variables.set("ARRAY_NOT_EMPTY", array);
     assert_eq!(string_var_is_not_empty("ARRAY_NOT_EMPTY", &shell), false);
 
     // test for a variable which does not even exist
@@ -420,9 +419,9 @@ fn test_function_is_defined() {
     statements.push(Statement::End);
     let description = "description".to_owned();
 
-    shell.variables.set_variable(
+    shell.variables.set(
         &name,
-        VariableType::Function(Function::new(Some(description), name.clone(), args, statements)),
+        Function::new(Some(description), name.clone(), args, statements),
     );
 
     assert_eq!(function_is_defined(name_str, &shell), true);
diff --git a/src/lib/builtins/is.rs b/src/lib/builtins/is.rs
index e862eaa3a2ff450ada4d2fe42eba75c11262f761..b191e970870577eda4332702bf8edeacee49d01d 100644
--- a/src/lib/builtins/is.rs
+++ b/src/lib/builtins/is.rs
@@ -1,6 +1,3 @@
-#[cfg(test)]
-use shell::variables::VariableType;
-
 use shell::Shell;
 use types;
 
@@ -47,8 +44,8 @@ fn test_is() {
     }
     use shell::ShellBuilder;
     let mut shell = ShellBuilder::new().as_library();
-    shell.set_variable("x", VariableType::Str("value".into()));
-    shell.set_variable("y", VariableType::Str("0".into()));
+    shell.set("x", "value".to_string());
+    shell.set("y", "0".to_string());
 
     // Four arguments
     assert_eq!(
diff --git a/src/lib/builtins/set.rs b/src/lib/builtins/set.rs
index 556d215be77ec766cb52746482710138f781d10c..98446b69dc98e9db1c115b6aceacb5e0b86c31af 100644
--- a/src/lib/builtins/set.rs
+++ b/src/lib/builtins/set.rs
@@ -1,5 +1,5 @@
 use liner::KeyBindings;
-use shell::{flags::*, variables::VariableType, Shell};
+use shell::{flags::*, Shell};
 use types;
 use std::iter;
 
@@ -79,13 +79,13 @@ pub(crate) fn set(args: &[String], shell: &mut Shell) -> i32 {
             // This used to take a `&[String]` but cloned them all, so although
             // this is non-ideal and could probably be better done with `Rc`, it
             // hasn't got any slower.
-            let arguments = iter::once(command)
+            let arguments: types::Array = iter::once(command)
                 .chain(args_iter.map(|i| i.to_string()))
                 .collect();
             match kind {
-                UnsetIfNone => { shell.variables.set_variable("args", VariableType::Array(arguments)); }
+                UnsetIfNone => { shell.variables.set("args", arguments); }
                 RetainIfNone => if arguments.len() != 1 {
-                    shell.variables.set_variable("args", VariableType::Array(arguments));
+                    shell.variables.set("args", arguments);
                 },
             }
         }
diff --git a/src/lib/builtins/variables.rs b/src/lib/builtins/variables.rs
index 0792850db964372c8b11558a3b24a019dee1825a..98fc23a0c93a7d92d3f3e1b124be3a6e5fa302a0 100644
--- a/src/lib/builtins/variables.rs
+++ b/src/lib/builtins/variables.rs
@@ -2,7 +2,7 @@
 
 use std::io::{self, Write};
 
-use shell::{status::*, variables::{Variables, VariableType}};
+use shell::{status::*, variables::Variables};
 use types::*;
 
 fn print_list(vars: &Variables) {
@@ -74,7 +74,7 @@ pub(crate) fn alias(vars: &mut Variables, args: &str) -> i32 {
             return FAILURE;
         }
         Binding::KeyValue(key, value) => {
-            vars.set_variable(&key, VariableType::Alias(Alias(value)));
+            vars.set(&key, Alias(value));
         }
         Binding::ListEntries => print_list(&vars),
         Binding::KeyOnly(key) => {
@@ -177,7 +177,7 @@ mod test {
     #[test]
     fn drop_deletes_variable() {
         let mut variables = Variables::default();
-        variables.set_variable("FOO", VariableType::Str("BAR".into()));
+        variables.set("FOO", "BAR".to_string());
         let return_status = drop_variable(&mut variables, &["drop", "FOO"]);
         assert_eq!(SUCCESS, return_status);
         let expanded = expand_string("$FOO", &VariableExpander(variables), false).join("");
@@ -201,7 +201,7 @@ mod test {
     #[test]
     fn drop_deletes_array() {
         let mut variables = Variables::default();
-        variables.set_variable("FOO", VariableType::Array(array!["BAR"]));
+        variables.set("FOO", array!["BAR"]);
         let return_status = drop_array(&mut variables, &["drop", "-a", "FOO"]);
         assert_eq!(SUCCESS, return_status);
         let expanded = expand_string("@FOO", &VariableExpander(variables), false).join("");
diff --git a/src/lib/parser/loops.rs b/src/lib/parser/loops.rs
index c5d23f6db0dcff167568156c880f4d32ff958886..6161a3ed4e67cad22d448f750a1766e0754fb54d 100644
--- a/src/lib/parser/loops.rs
+++ b/src/lib/parser/loops.rs
@@ -65,7 +65,7 @@ impl ForExpression {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use shell::variables::{Variables, VariableType};
+    use shell::variables::Variables;
 
     struct VariableExpander(pub Variables);
 
@@ -112,7 +112,7 @@ mod tests {
     #[test]
     fn for_variable() {
         let mut variables = Variables::default();
-        variables.set_variable("A", VariableType::Str("1 2 3 4 5".into()));
+        variables.set("A", "1 2 3 4 5".to_string());
         assert_eq!(
             ForExpression::new(&["$A".to_owned()], &VariableExpander(variables)),
             ForExpression::Normal("1 2 3 4 5".to_owned())
diff --git a/src/lib/shell/assignments.rs b/src/lib/shell/assignments.rs
index e27f8b8c873bb3defaeb125d0b52a5ec0457c469..0fad4fe729df9db191a3d2912ed36af0da493afe 100644
--- a/src/lib/shell/assignments.rs
+++ b/src/lib/shell/assignments.rs
@@ -269,7 +269,7 @@ impl VariableStore for Shell {
                     match collected.remove(key.name) {
                         map @ Some(VariableType::HashMap(_)) => {
                             if let Primitive::HashMap(_) = key.kind {
-                                self.variables.set_variable(key.name, map.unwrap());
+                                self.variables.set(key.name, map.unwrap());
                             } else if let Primitive::Indexed(_, _) = key.kind {
                                 eprintln!("ion: cannot insert hash map into index");
                                 return FAILURE;
@@ -280,7 +280,7 @@ impl VariableStore for Shell {
                                 eprintln!("ion: multi-dimensional arrays are not yet supported");
                                 return FAILURE;
                             } else {
-                                self.variables.set_variable(key.name, array.unwrap());
+                                self.variables.set(key.name, array.unwrap());
                             }
                         }
                         Some(VariableType::Str(value)) => {
@@ -329,8 +329,8 @@ impl VariableStore for Shell {
                 }
                 Ok(Action::UpdateString(key, _, _)) => {
                     match collected.remove(key.name) {
-                        str_ @ Some(VariableType::Str(_)) => { self.variables.set_variable(key.name, str_.unwrap()); }
-                        array @ Some(VariableType::Array(_)) => { self.variables.set_variable(key.name, array.unwrap()); }
+                        str_ @ Some(VariableType::Str(_)) => { self.variables.set(key.name, str_.unwrap()); }
+                        array @ Some(VariableType::Array(_)) => { self.variables.set(key.name, array.unwrap()); }
                         _ => ()
                     }
                 }
diff --git a/src/lib/shell/binary/mod.rs b/src/lib/shell/binary/mod.rs
index df279112790a8b41a5eee05f851af1609ceffeb7..03bce01ed8de7f7bc7dbfce236e696bb7e5ebd35 100644
--- a/src/lib/shell/binary/mod.rs
+++ b/src/lib/shell/binary/mod.rs
@@ -8,7 +8,7 @@ use self::{
     prompt::{prompt, prompt_fn}, readln::readln,
     terminate::{terminate_quotes, terminate_script_quotes},
 };
-use super::{flow_control::Statement, status::*, variables::VariableType, FlowLogic, Shell, ShellHistory};
+use super::{flow_control::Statement, status::*, FlowLogic, Shell, ShellHistory};
 use types;
 use liner::{Buffer, Context};
 use std::{env, fs::File, io::ErrorKind, iter, path::Path, process, sync::Mutex};
@@ -128,7 +128,7 @@ impl Binary for Shell {
         self.evaluate_init_file();
 
         self.variables
-            .set_variable("args", VariableType::Array(iter::once(env::args().next().unwrap()).collect()));
+            .set("args", iter::once(env::args().next().unwrap()).collect::<types::Array>());
 
         loop {
             if let Some(command) = self.readln() {
diff --git a/src/lib/shell/flow.rs b/src/lib/shell/flow.rs
index 5ea0442509a519df5da5b569f052834faa019c1d..5a6df96df07bf6c3acb02afed325ea2f74cee40e 100644
--- a/src/lib/shell/flow.rs
+++ b/src/lib/shell/flow.rs
@@ -89,11 +89,11 @@ impl FlowLogic for Shell {
             // Execute a Let Statement
             Statement::Let(action) => {
                 self.previous_status = self.local(action);
-                self.variables.set_variable("?", VariableType::Str(self.previous_status.to_string()));
+                self.variables.set("?", self.previous_status.to_string());
             }
             Statement::Export(action) => {
                 self.previous_status = self.export(action);
-                self.variables.set_variable("?", VariableType::Str(self.previous_status.to_string()));
+                self.variables.set("?", self.previous_status.to_string());
             }
             // Collect the statements for the while loop, and if the loop is complete,
             // execute the while loop with the provided expression.
@@ -192,9 +192,9 @@ impl FlowLogic for Shell {
 
                 if self.flow_control.level == 0 {
                     // All blocks were read, thus we can add it to the list
-                    self.variables.set_variable(
+                    self.variables.set(
                         &name,
-                        VariableType::Function(Function::new(description, name.clone(), args, statements)),
+                        Function::new(description, name.clone(), args, statements),
                     );
                 } else {
                     // Store the partial function declaration in memory.
@@ -294,7 +294,7 @@ impl FlowLogic for Shell {
                         _ => (),
                     }
                     let status = self.previous_status.to_string();
-                    self.set_variable("?", VariableType::Str(status));
+                    self.set("?", status);
                 } else {
                     // A statement wasn't executed , which means that current_statement has been
                     // set to the inner statement. We fix this here.
@@ -370,7 +370,7 @@ impl FlowLogic for Shell {
                 }
             },
             ForExpression::Multiple(values) => for value in &values {
-                self.set_variable(variable, VariableType::Str(value.clone()));
+                self.set(variable, value.clone());
                 match self.execute_statements(statements.clone()) {
                     Condition::Break => break,
                     Condition::SigInt => return Condition::SigInt,
@@ -385,7 +385,7 @@ impl FlowLogic for Shell {
                 }
             },
             ForExpression::Normal(values) => for value in values.lines() {
-                self.set_variable(variable, VariableType::Str(value.into()));
+                self.set(variable, value.to_string());
                 match self.execute_statements(statements.clone()) {
                     Condition::Break => break,
                     Condition::SigInt => return Condition::SigInt,
@@ -400,7 +400,7 @@ impl FlowLogic for Shell {
                 }
             },
             ForExpression::Range(start, end) => for value in (start..end).map(|x| x.to_string()) {
-                self.set_variable(variable, VariableType::Str(value.clone()));
+                self.set(variable, value.clone());
                 match self.execute_statements(statements.clone()) {
                     Condition::Break => break,
                     Condition::SigInt => return Condition::SigInt,
@@ -431,11 +431,11 @@ impl FlowLogic for Shell {
             Statement::Error(number) => self.previous_status = number,
             Statement::Let(action) => {
                 self.previous_status = self.local(action);
-                self.variables.set_variable("?", VariableType::Str(self.previous_status.to_string()));
+                self.variables.set("?", self.previous_status.to_string());
             }
             Statement::Export(action) => {
                 self.previous_status = self.export(action);
-                self.variables.set_variable("?", VariableType::Str(self.previous_status.to_string()));
+                self.variables.set("?", self.previous_status.to_string());
             }
             Statement::While {
                 expression,
@@ -494,9 +494,9 @@ impl FlowLogic for Shell {
             } => {
                 self.flow_control.level += 1;
                 collect_loops(&mut iterator, &mut statements, &mut self.flow_control.level);
-                self.variables.set_variable(
+                self.variables.set(
                     &name,
-                    VariableType::Function(Function::new(description, name.clone(), args, statements)),
+                    Function::new(description, name.clone(), args, statements),
                 );
             }
             Statement::Pipeline(mut pipeline) => {
@@ -569,8 +569,7 @@ impl FlowLogic for Shell {
                     SUCCESS => self.previous_status = FAILURE,
                     _ => (),
                 }
-                let status = self.previous_status.to_string();
-                self.set_variable("?", VariableType::Str(status));
+                self.set("?", self.previous_status.to_string());
             }
             Statement::Break => return Condition::Break,
             Statement::Continue => return Condition::Continue,
@@ -658,13 +657,13 @@ impl FlowLogic for Shell {
                                 .variables
                                 .get::<types::Array>(bind)
                                 .map(|x| VariableType::Array(x));
-                            self.variables.set_variable(&bind, VariableType::Array(value.clone()));
+                            self.variables.set(&bind, value.clone());
                         } else {
                             previous_bind = self
                                 .variables
                                 .get::<types::Value>(bind)
                                 .map(|x| VariableType::Str(x));
-                            self.set_variable(&bind, VariableType::Str(value.join(" ").into()));
+                            self.set(&bind, value.join(" ").to_string());
                         }
                     }
 
@@ -680,9 +679,9 @@ impl FlowLogic for Shell {
                     if let Some(ref bind) = case.binding {
                         if let Some(value) = previous_bind {
                             match value {
-                                str_ @ VariableType::Str(_) => { self.set_variable(bind, str_); }
-                                array @ VariableType::Array(_) => { self.variables.set_variable(bind, array); }
-                                map @ VariableType::HashMap(_) => { self.variables.set_variable(bind, map); }
+                                str_ @ VariableType::Str(_) => { self.set(bind, str_); }
+                                array @ VariableType::Array(_) => { self.variables.set(bind, array); }
+                                map @ VariableType::HashMap(_) => { self.variables.set(bind, map); }
                                 _ => (),
                             }
                         }
@@ -698,13 +697,13 @@ impl FlowLogic for Shell {
                                 .variables
                                 .get::<types::Array>(bind)
                                 .map(|x| VariableType::Array(x));
-                            self.variables.set_variable(&bind, VariableType::Array(value.clone()));
+                            self.variables.set(&bind, value.clone());
                         } else {
                             previous_bind = self
                                 .variables
                                 .get::<types::Value>(bind)
                                 .map(|x| VariableType::Str(x));
-                            self.set_variable(&bind, VariableType::Str(value.join(" ").into()));
+                            self.set(&bind, value.join(" ").to_string());
                         }
                     }
 
@@ -720,9 +719,9 @@ impl FlowLogic for Shell {
                     if let Some(ref bind) = case.binding {
                         if let Some(value) = previous_bind {
                             match value {
-                                str_ @ VariableType::Str(_) => { self.set_variable(bind, str_); }
-                                array @ VariableType::Array(_) => { self.set_variable(bind, array); }
-                                map @ VariableType::HashMap(_) => { self.set_variable(bind, map); }
+                                str_ @ VariableType::Str(_) => { self.set(bind, str_); }
+                                array @ VariableType::Array(_) => { self.set(bind, array); }
+                                map @ VariableType::HashMap(_) => { self.set(bind, map); }
                                 _ => (),
                             }
                         }
@@ -845,11 +844,11 @@ impl FlowLogic for Shell {
                         Statement::Error(number) => shell.previous_status = number,
                         Statement::Let(action) => {
                             shell.previous_status = shell.local(action);
-                            shell.variables.set_variable("?", VariableType::Str(shell.previous_status.to_string()));
+                            shell.variables.set("?", shell.previous_status.to_string());
                         }
                         Statement::Export(action) => {
                             shell.previous_status = shell.export(action);
-                            shell.variables.set_variable("?", VariableType::Str(shell.previous_status.to_string()));
+                            shell.variables.set("?", shell.previous_status.to_string());
                         }
                         Statement::While {
                             expression,
@@ -876,9 +875,9 @@ impl FlowLogic for Shell {
                             statements,
                             description,
                         } => {
-                            shell.variables.set_variable(
+                            shell.variables.set(
                                 &name,
-                                VariableType::Function(Function::new(description, name.clone(), args, statements)),
+                                Function::new(description, name.clone(), args, statements),
                             );
                         }
                         Statement::If {
@@ -931,7 +930,7 @@ impl FlowLogic for Shell {
                             }
                             shell
                                 .variables
-                                .set_variable("?", VariableType::Str(shell.previous_status.to_string()));
+                                .set("?", shell.previous_status.to_string());
                         }
                         _ => (),
                     }
diff --git a/src/lib/shell/fork.rs b/src/lib/shell/fork.rs
index df7a513edc9d87ea606d349ad8adc2976f5720dc..82670a33085537c65d58157b327d1f9aaa53de01 100644
--- a/src/lib/shell/fork.rs
+++ b/src/lib/shell/fork.rs
@@ -1,4 +1,4 @@
-use super::{variables::VariableType, IonError, Shell};
+use super::{IonError, Shell};
 use std::{
     fs::File,
     io,
@@ -130,7 +130,7 @@ impl<'a> Fork<'a> {
 
                 // Obtain ownership of the child's copy of the shell, and then configure it.
                 let mut shell: Shell = unsafe { (self.shell as *const Shell).read() };
-                shell.set_variable("PID", VariableType::Str(sys::getpid().unwrap_or(0).to_string()));
+                shell.set("PID", sys::getpid().unwrap_or(0).to_string());
                 let _ = shell.context.take();
 
                 // Execute the given closure within the child's shell.
diff --git a/src/lib/shell/mod.rs b/src/lib/shell/mod.rs
index 03b5dc9dc5b77cb638cc7cde05da94347c4703de..43ff0389bf4090a08db483d9b7a218733368b880 100644
--- a/src/lib/shell/mod.rs
+++ b/src/lib/shell/mod.rs
@@ -236,8 +236,8 @@ impl Shell {
     }
 
     /// Sets a variable of `name` with the given `value` in the shell's variable map.
-    pub fn set_variable(&mut self, name: &str, value: VariableType) {
-        self.variables.set_variable(name, value);
+    pub fn set<T: Into<VariableType>>(&mut self, name: &str, value: T) {
+        self.variables.set(name, value);
     }
 
     /// Executes a pipeline and returns the final exit status of the pipeline.
@@ -337,7 +337,7 @@ impl Shell {
 
         // Retrieve the exit_status and set the $? variable and history.previous_status
         if let Some(code) = exit_status {
-            self.set_variable("?", VariableType::Str(code.to_string()));
+            self.set("?", code.to_string());
             self.previous_status = code;
         }
 
diff --git a/src/lib/shell/variables/mod.rs b/src/lib/shell/variables/mod.rs
index 34548dd22549259a9ef8deca4ef738c771ff3f60..f71a32141bcdc16c32655eb19b32d346b05250f9 100644
--- a/src/lib/shell/variables/mod.rs
+++ b/src/lib/shell/variables/mod.rs
@@ -82,6 +82,36 @@ impl From<VariableType> for Function {
     }
 }
 
+impl From<String> for VariableType {
+    fn from(string: String) -> Self {
+        VariableType::Str(string)
+    }
+}
+
+impl From<Alias> for VariableType {
+    fn from(alias: Alias) -> Self {
+        VariableType::Alias(alias)
+    }
+}
+
+impl From<Array> for VariableType {
+    fn from(array: Array) -> Self {
+        VariableType::Array(array)
+    }
+}
+
+impl From<HashMap> for VariableType {
+    fn from(hash_map: HashMap) -> Self {
+        VariableType::HashMap(hash_map)
+    }
+}
+
+impl From<Function> for VariableType {
+    fn from(function: Function) -> Self {
+         VariableType::Function(function)
+    }
+}
+
 impl fmt::Display for VariableType {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
@@ -488,7 +518,8 @@ impl Variables {
         }
     }
 
-    pub fn set_variable(&mut self, name: &str, var: VariableType) {
+    pub fn set<T: Into<VariableType>>(&mut self, name: &str, var: T) {
+        let var = var.into();
         match self.lookup_any_mut(&name) {
             Some(VariableType::Str(ref mut str_)) => {
                 if !name.is_empty() {
@@ -658,7 +689,7 @@ impl Variables {
             for arg in args.into_iter().skip(1) {
                 match con.read_line(format!("{}=", arg.as_ref().trim()), None, &mut |_| {}) {
                     Ok(buffer) => {
-                        self.set_variable(arg.as_ref(), VariableType::Str(buffer.trim().into()));
+                        self.set(arg.as_ref(), buffer.trim().to_string());
                     }
                     Err(_) => return FAILURE,
                 }
@@ -669,7 +700,7 @@ impl Variables {
             let mut lines = handle.lines();
             for arg in args.into_iter().skip(1) {
                 if let Some(Ok(line)) = lines.next() {
-                    self.set_variable(arg.as_ref(), VariableType::Str(line.trim().into()));
+                    self.set(arg.as_ref(), line.trim().to_string());
                 }
             }
         }
@@ -706,7 +737,7 @@ mod tests {
     #[test]
     fn set_var_and_expand_a_variable() {
         let mut variables = Variables::default();
-        variables.set_variable("FOO", VariableType::Str("BAR".into()));
+        variables.set("FOO", "BAR".to_string());
         let expanded = expand_string("$FOO", &VariableExpander(variables), false).join("");
         assert_eq!("BAR", &expanded);
     }
diff --git a/src/main.rs b/src/main.rs
index 32e45f72dd2ad4a8311420690e3ca1b4690f7ef0..27314b929b10451fa18b6852f229ede7063cb07c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,7 +2,7 @@ extern crate ion_shell;
 extern crate ion_sys as sys;
 extern crate smallvec;
 
-use ion_shell::{flags::NO_EXEC, shell::variables::VariableType, Binary, JobControl, ShellBuilder, MAN_ION};
+use ion_shell::{flags::NO_EXEC, Binary, JobControl, ShellBuilder, MAN_ION};
 use smallvec::SmallVec;
 use std::{
     env, error::Error, io::{stdout, stdin, Write, BufRead, BufReader}, iter::FromIterator,
@@ -45,7 +45,7 @@ fn main() {
                 for arg in args {
                     array.push(arg.into());
                 }
-                shell.variables.set_variable("args", VariableType::Array(array));
+                shell.variables.set("args", array);
                 if let Err(err) = shell.execute_script(&path) {
                     eprintln!("ion: {}", err);
                 }