diff --git a/source/simple/support/carcdr.hpp b/source/simple/support/carcdr.hpp
index eff41f8b5e6f9c6359594710a20acdc323d253c8..875dc25fe88d3b9a308a7ee764714cdc55c2be84 100644
--- a/source/simple/support/carcdr.hpp
+++ b/source/simple/support/carcdr.hpp
@@ -1,11 +1,12 @@
 #ifndef SIMPLE_SUPPORT_CARCDR_HPP
 #define SIMPLE_SUPPORT_CARCDR_HPP
 
-#include <tuple>
+#include <cstdint>
 #include <utility>
 
 namespace simple::support
 {
+	using std::size_t;
 
 	template <typename Int, Int... Values>
 	using lisp_list = std::integer_sequence<Int, Values...>;
@@ -23,67 +24,38 @@ namespace simple::support
 	template <typename IntSeq>
 	using cdr = typename carcdr<IntSeq>::cdr;
 
-	template <typename IntSeq>
-	constexpr typename IntSeq::value_type car() noexcept
-	{
-		static_assert( IntSeq::size() > 0 );
-		return carcdr<IntSeq>::car;
-	}
+	template <typename List, size_t = 0, auto ... Rest>
+	std::nullptr_t car;
 
-	template <typename IntSeq>
-	constexpr typename IntSeq::value_type car(typename IntSeq::value_type value) noexcept
+	template <typename List, size_t N,
+		typename List::value_type nil>
+	constexpr typename List::value_type
+	car<List, N, nil> = []()
 	{
-		if constexpr ( IntSeq::size() > 0 )
-			return (void)value, carcdr<IntSeq>::car;
+		if constexpr ( N >= List::size() )
+			return nil;
 		else
-			return value;
-	}
+			return car<List, N>;
+	}();
 
-	template <typename IntSeq, size_t N>
-	constexpr typename IntSeq::value_type car() noexcept
+	template <typename List, size_t N>
+	constexpr typename List::value_type
+	car<List, N> = []()
 	{
-		static_assert( N < IntSeq::size() );
+		static_assert( N < List::size() );
 		if constexpr (N == 0)
-			return car<IntSeq>();
-		else
-			return car<cdr<IntSeq>, N - 1>();
-	}
-
-	template <typename IntSeq, size_t N>
-	constexpr typename IntSeq::value_type car(typename IntSeq::value_type value) noexcept
-	{
-		if constexpr ( N >= IntSeq::size() )
-			return value;
-		else if constexpr (N == 0)
-			return car<IntSeq>(value);
+			return car<List>;
 		else
-			return car<cdr<IntSeq>, N - 1>(value);
-	}
-
-	template <typename... Rest, size_t... indices>
-	constexpr auto subtuple(const std::tuple<Rest...>& tuple, std::integer_sequence<size_t, indices...>)
-	{
-		return std::make_tuple(std::get<indices>(tuple)...);
-	}
-
-	template <typename First, typename... Rest>
-	constexpr auto tuple_car(const std::tuple<First, Rest...>& tuple)
-	{
-		return std::get<0>(tuple);
-	}
-
-	constexpr std::nullptr_t tuple_car(const std::tuple<>&)
-	{
-		return nullptr;
-	}
+			return car<cdr<List>, N - 1>;
+	}();
 
-	template <typename First, typename... Rest>
-	constexpr auto tuple_cdr(const std::tuple<First, Rest...>& tuple)
+	template <typename List>
+	constexpr typename List::value_type
+	car<List, 0> = []()
 	{
-		using indices = std::make_index_sequence<
-			std::tuple_size_v<std::decay_t<decltype(tuple)>>>;
-		return subtuple(tuple, cdr<indices>{});
-	}
+		static_assert( List::size() > 0 );
+		return carcdr<List>::car;
+	}();
 
 } // namespace simple::support
 
diff --git a/source/simple/support/tuple_utils.hpp b/source/simple/support/tuple_utils.hpp
index 4561716acd5d8f79454ccbc83209426add4ffb27..36ee8fbe27ab3fb11222474c0cf1f326fd3fae07 100644
--- a/source/simple/support/tuple_utils.hpp
+++ b/source/simple/support/tuple_utils.hpp
@@ -1,50 +1,3 @@
-#ifndef SIMPLE_SUPPORT_TUPLE_UTILS_HPP
-#define SIMPLE_SUPPORT_TUPLE_UTILS_HPP
-#include <tuple>
-#include <functional>
-#include "range.hpp"
-
-namespace simple::support
-{
-
-	// wow this is a mess... you think it'll be optimized? O_o
-	//TODO: return a variant??
-	template<typename F, typename First, size_t I = std::tuple_size_v<std::remove_reference_t<First>> - 1, typename... Rest>
-	[[nodiscard]] constexpr
-	decltype(auto) apply_for(size_t index, F&& f, First&& first, Rest&&... rest)
-	{
-		using std::remove_reference_t;
-		using First_t = remove_reference_t<First>;
-		using std::apply;
-		using std::get;
-		using std::tuple_element_t;
-		using std::forward;
-		static_assert(I >= 0 && I < std::tuple_size_v<First_t>);
-		if(I == index)
-			// std::invoke is not constexpr -_-
-			return apply(forward<F>(f), std::forward_as_tuple(
-					forward<tuple_element_t<I, First_t>>(get<I>(first)),
-					forward<tuple_element_t<I, remove_reference_t<Rest>>>(get<I>(rest))...
-			));
-		if constexpr (I > 0)
-			return apply_for<F, decltype(forward<First_t>(first)), I - 1>(index, forward<F>(f),
-					forward<First_t>(first), forward<remove_reference_t<Rest>>(rest)...);
-
-		throw std::logic_error("simple::support::apply_for - this should never happen");
-	}
-
-	template<typename F, typename First, size_t I = std::tuple_size_v<std::remove_reference_t<First>> - 1, typename... Rest>
-	constexpr
-	void apply_for(range<size_t> index_range, F&& f, First&& first, Rest&&... rest)
-	{
-		for(size_t i = index_range.lower(); i < index_range.upper(); ++i)
-		{
-			apply_for(i, std::forward<F>(f),
-				std::forward<std::remove_reference_t<First>>(first),
-				std::forward<std::remove_reference_t<Rest>>(rest)...);
-		}
-	}
-
-} // namespace simple::support
-
-#endif /* end of include guard */
+#include "tuple_utils/apply_for.hpp"
+#include "tuple_utils/carcdr.hpp"
+#include "tuple_utils/subtuple.hpp"
diff --git a/source/simple/support/tuple_utils/apply_for.hpp b/source/simple/support/tuple_utils/apply_for.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..504ac61e7db01ab8ff277a0b815b2c09f8255d69
--- /dev/null
+++ b/source/simple/support/tuple_utils/apply_for.hpp
@@ -0,0 +1,51 @@
+#ifndef SIMPLE_SUPPORT_TUPLE_UTILS_APPLY_FOR_HPP
+#define SIMPLE_SUPPORT_TUPLE_UTILS_APPLY_FOR_HPP
+
+#include <tuple>
+#include <functional>
+#include "../range.hpp"
+
+namespace simple::support
+{
+
+	// wow this is a mess... you think it'll be optimized? O_o
+	//TODO: return a variant??
+	template<typename F, typename First, size_t I = std::tuple_size_v<std::remove_reference_t<First>> - 1, typename... Rest>
+	[[nodiscard]] constexpr
+	decltype(auto) apply_for(size_t index, F&& f, First&& first, Rest&&... rest)
+	{
+		using std::remove_reference_t;
+		using First_t = remove_reference_t<First>;
+		using std::apply;
+		using std::get;
+		using std::tuple_element_t;
+		using std::forward;
+		static_assert(I >= 0 && I < std::tuple_size_v<First_t>);
+		if(I == index)
+			// std::invoke is not constexpr -_-
+			return apply(forward<F>(f), std::forward_as_tuple(
+					forward<tuple_element_t<I, First_t>>(get<I>(first)),
+					forward<tuple_element_t<I, remove_reference_t<Rest>>>(get<I>(rest))...
+			));
+		if constexpr (I > 0)
+			return apply_for<F, decltype(forward<First_t>(first)), I - 1>(index, forward<F>(f),
+					forward<First_t>(first), forward<remove_reference_t<Rest>>(rest)...);
+
+		throw std::logic_error("simple::support::apply_for - this should never happen");
+	}
+
+	template<typename F, typename First, size_t I = std::tuple_size_v<std::remove_reference_t<First>> - 1, typename... Rest>
+	constexpr
+	void apply_for(range<size_t> index_range, F&& f, First&& first, Rest&&... rest)
+	{
+		for(size_t i = index_range.lower(); i < index_range.upper(); ++i)
+		{
+			apply_for(i, std::forward<F>(f),
+				std::forward<std::remove_reference_t<First>>(first),
+				std::forward<std::remove_reference_t<Rest>>(rest)...);
+		}
+	}
+
+} // namespace simple::support
+
+#endif /* end of include guard */
diff --git a/source/simple/support/tuple_utils/carcdr.hpp b/source/simple/support/tuple_utils/carcdr.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..6b3ae64605a538fa01e4ade3a9eabad80406de39
--- /dev/null
+++ b/source/simple/support/tuple_utils/carcdr.hpp
@@ -0,0 +1,46 @@
+#ifndef SIMPLE_SUPPORT_TUPLE_UTILS_CARCDR_HPP
+#define SIMPLE_SUPPORT_TUPLE_UTILS_CARCDR_HPP
+
+#include "subtuple.hpp"
+#include "../carcdr.hpp"
+
+namespace simple::support
+{
+
+	template <typename Tuple>
+	constexpr decltype(auto) tuple_car(Tuple&& tuple)
+	noexcept(noexcept(std::get<0>(std::forward<Tuple>(tuple))))
+	{
+		return std::get<0>(std::forward<Tuple>(tuple));
+	}
+
+	constexpr std::nullptr_t tuple_car(const std::tuple<>&)
+	{
+		return nullptr;
+	}
+
+	template <typename First, typename... Rest>
+	constexpr auto tuple_cdr(const std::tuple<First, Rest...>& tuple)
+	{
+		using indices = std::make_index_sequence<
+			std::tuple_size_v<std::decay_t<decltype(tuple)>>>;
+		return subtuple(tuple, cdr<indices>{});
+	}
+
+	template <typename First, typename... Rest>
+	constexpr auto tuple_tie_cdr(const std::tuple<First, Rest...>& tuple)
+	{
+		using indices = tuple_indecies<decltype(tuple)>;
+		return tie_subtuple(tuple, cdr<indices>{});
+	}
+
+	template <typename First, typename... Rest>
+	constexpr auto tuple_tie_cdr(std::tuple<First, Rest...>& tuple)
+	{
+		using indices = tuple_indecies<decltype(tuple)>;
+		return tie_subtuple(tuple, cdr<indices>{});
+	}
+
+} // namespace simple::support
+
+#endif /* end of include guard */
diff --git a/source/simple/support/tuple_utils/subtuple.hpp b/source/simple/support/tuple_utils/subtuple.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f9086d8ced3c5a9fb78f32e20c2b4a81f2659115
--- /dev/null
+++ b/source/simple/support/tuple_utils/subtuple.hpp
@@ -0,0 +1,34 @@
+#ifndef SIMPLE_SUPPORT_TUPLE_UTILS_SUBTUPLE_HPP
+#define SIMPLE_SUPPORT_TUPLE_UTILS_SUBTUPLE_HPP
+#include <utility>
+#include <tuple>
+
+namespace simple::support
+{
+
+	template <typename... Rest, size_t... indices>
+	constexpr auto subtuple(const std::tuple<Rest...>& tuple, std::integer_sequence<size_t, indices...>)
+	{
+		return std::make_tuple(std::get<indices>(tuple)...);
+	}
+
+	template <typename... Rest, size_t... indices>
+	constexpr auto tie_subtuple(const std::tuple<Rest...>& tuple, std::integer_sequence<size_t, indices...>)
+	{
+		return std::tie(std::get<indices>(tuple)...);
+	}
+
+	template <typename... Rest, size_t... indices>
+	constexpr auto tie_subtuple(std::tuple<Rest...>& tuple, std::integer_sequence<size_t, indices...>)
+	{
+		return std::tie(std::get<indices>(tuple)...);
+	}
+
+	template <typename T>
+	using tuple_indecies = std::make_index_sequence<
+		std::tuple_size_v<std::decay_t<T>>
+	>;
+
+} // namespace simple::support
+
+#endif /* end of include guard */
diff --git a/unit_tests/carcdr.cpp b/unit_tests/carcdr.cpp
index 28b3f26898cc9103a7c80ccd9f3949b7e82e78e6..e31fe9d19f293db938e82ad44055caa4c0bb0992 100644
--- a/unit_tests/carcdr.cpp
+++ b/unit_tests/carcdr.cpp
@@ -5,15 +5,12 @@ using namespace simple::support;
 int main()
 {
 	using ints = lisp_list<int, -1, 10, 13, 999>;
-	static_assert(car<ints>() == -1);
+	static_assert(car<ints> == -1);
 	static_assert(std::is_same_v< cdr<ints>, lisp_list<int, 10, 13, 999> >);
-	static_assert(car< cdr<cdr<ints>> >() == 13);
-	static_assert(car<ints, 3>() == 999);
-	static_assert(car<lisp_list<int>>(321) == 321);
-	static_assert(car<ints, 10>(9517) == 9517); // *shrug*
+	static_assert(car< cdr<cdr<ints>> > == 13);
+	static_assert(car<ints, 3> == 999);
+	static_assert(car<lisp_list<int>, 0, 321> == 321);
+	static_assert(car<ints, 10, -9517> == -9517); // *shrug*
 
-	constexpr auto t = std::make_tuple(true, 1.5, 5);
-	static_assert(tuple_car(t));
-	static_assert(1.5 == tuple_car(tuple_cdr(t)));
 	return 0;
 }
diff --git a/unit_tests/tuple_utils.cpp b/unit_tests/tuple_utils.cpp
index 7d3fa704bec72e314390aaf934556b7a10f33717..ac7e8a23764f0540e9571b2955fe30ae1f9763e9 100644
--- a/unit_tests/tuple_utils.cpp
+++ b/unit_tests/tuple_utils.cpp
@@ -3,9 +3,10 @@
 #include <iostream>
 #include "simple/support/tuple_utils.hpp"
 
-int main()
+using namespace simple::support;
+
+void ApplyFor()
 {
-	using simple::support::apply_for;
 	auto t = std::tuple(0," one ",2," three");
 	std::stringstream ss;
 
@@ -47,5 +48,52 @@ int main()
 	assert( 4 == apply_for(2, [](auto&& x)
 			{ return x + 2; }, t3) );
 
+}
+
+template <typename... T>
+constexpr auto tuple_tie(std::tuple<T...>& t)
+{
+	return std::apply(std::tie<T...>, t);
+}
+
+void CarCdr()
+{
+
+	{ auto t = std::tuple(true, 1.5, 5);
+		assert(tuple_car(t));
+		assert(1.5 == tuple_car(tuple_cdr(t)));
+	}
+
+	{ auto t = std::tuple(1, 2, 3);
+		auto tref = tuple_tie(t);
+
+		assert(t == tref);
+
+		tuple_car(tref) = -4;
+
+		assert(tuple_car(t) == -4);
+		assert(t == tref);
+
+		auto tref_cdr = tuple_tie_cdr(tref);
+
+		tuple_car(tref_cdr) = 13;
+
+		assert(std::get<1>(t) == 13);
+		assert(tref_cdr == std::tuple(13,3));
+
+		auto tref_cdr2 = tuple_tie_cdr(t);
+		tuple_car(tref_cdr2) = 12;
+
+		assert(std::get<1>(t) == 12);
+		assert(tref_cdr2 == tref_cdr);
+		assert(tref_cdr2 == std::tuple(12,3));
+		assert(tref_cdr == std::tuple(12,3));
+	}
+}
+
+int main()
+{
+	ApplyFor();
+	CarCdr();
 	return 0;
 }