diff --git a/README.md b/README.md
index edaad25dbe128aa0e0a75338471991814e679806..a431d0b1cb853ddf30baa5776414626504791a14 100644
--- a/README.md
+++ b/README.md
@@ -38,6 +38,14 @@ Series are immutable, but non-hashable.
 Read the source code of the [base class](firanka/series/series.py#L11) to get
 to know more about series operations.
 
+
+### Applying and joining
+
+Applying requires a callable(index: float, value: current value) -> value.
+Joining requires a callable(index: float, valueSelf, valueOther: values from self and other table) -> value.
+
+
+
 ### DiscreteSeries
 
 To use a _DiscreteSeries_ you must give it a set of data to work with. These
@@ -116,6 +124,20 @@ any other discrete series would be.
 Sometimes you just need to update a DiscreteSeries, or to blang a brand new one. This little fella
 will help you out.
 
+You can pass a DiscreteSeries to build on or start from stratch:
+```python
+kb = DiscreteSeriesBuilder(series)
+kb = DiscreteSeriesBuilder()
+
+kb.put(1,2)
+
+series = kb.as_series()
+isinstance(series, DiscreteSeries)
+```
+
+By calling `as_series()` you get a new DiscreteSeries instance returned.
+
+
 ## Ranges
 
 Can be imported from _sai.ranges_.
diff --git a/firanka/series/base.py b/firanka/series/base.py
index 2855e208337b741c37aaca02b9bb6e2325a111c1..b31c3ad802f20e7b24953c4a2624db7bf0f3b45a 100644
--- a/firanka/series/base.py
+++ b/firanka/series/base.py
@@ -2,12 +2,17 @@
 from __future__ import print_function, absolute_import, division
 
 import six
+import inspect
 
 from firanka.exceptions import NotInDomainError
 from firanka.ranges import Range, EMPTY_SET
 from sortedcontainers import SortedList
 
 
+def has_arguments(fun, n):
+    return len(inspect.getargspec(fun).args) == n
+
+
 class Series(object):
     """
     Abstract, base class for series.
@@ -60,6 +65,8 @@ class Series(object):
         :param fun: callable(index: float, value: any) => 1
         :return: Series instance
         """
+        assert has_arguments(fun, 2), 'Callable to apply needs 2 arguments'
+
         return AlteredSeries(self, applyfun=fun)
 
     def discretize(self, points, domain=None):
@@ -87,6 +94,8 @@ class Series(object):
         :param fun: callable(t: float, v1: any, v2: any) => value
         :return: new Series instance
         """
+        assert has_arguments(fun, 3), 'Callable to join needs 3 arguments'
+
         return JoinedSeries(self, series, fun)
 
     def translate(self, x):
@@ -241,6 +250,8 @@ class JoinedSeries(Series):
 
     def __init__(self, ser1, ser2, op, *args, **kwargs):
         """:type op: callable(time: float, v1, v2: any) -> v"""
+        assert has_arguments(op, 3), 'op must have 3 arguments'
+
         super(JoinedSeries, self).__init__(ser1.domain.intersection(ser2.domain), *args, **kwargs)
         self.ser1 = ser1
         self.ser2 = ser2
diff --git a/tests/test_series.py b/tests/test_series.py
index 627ecfa531528f98020ac510be8981bcc231cadf..8c4301b8d8bb233593cffb0b62c5274309dc0a78 100644
--- a/tests/test_series.py
+++ b/tests/test_series.py
@@ -207,7 +207,7 @@ class TestModuloSeries(unittest.TestCase):
         ser1 = ModuloSeries(FunctionSeries(lambda x: x ** 2, '<0;3)'))
         ser2 = FunctionSeries(NOOP, '<0;3)')
 
-        ser3 = ser1.join(ser2, lambda x, y: x * y)
+        ser3 = ser1.join(ser2, lambda i, x, y: x * y)
 
 
 class TestLinearInterpolation(unittest.TestCase):