<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def send(self):
 """ Sends all the key-value pairs to the graphics card. These uniform variables will be available in the currently-bound shader. """


        for name, array in iteritems(self):

            shader_id = c_int(0)
            gl.glGetIntegerv(gl.GL_CURRENT_PROGRAM, byref(shader_id))
            if shader_id.value == 0:
                raise UnboundLocalError("""Shader not bound to OpenGL context--uniform cannot be sent.
                ------------ Tip -------------
                with ratcave.default_shader:
                    mesh.draw()
                ------------------------------
                """)

            # Attach a shader location value to the array, for quick memory lookup. (gl calls are expensive, for some reason)
            try:
                loc, shader_id_for_array = array.loc
                if shader_id.value != shader_id_for_array:
                    raise Exception('Uniform location bound to a different shader')
            except (AttributeError, Exception) as e:
                array.loc = (gl.glGetUniformLocation(shader_id.value, name.encode('ascii')), shader_id.value)

            if array.ndim == 2:  # Assuming a 4x4 float32 matrix (common for graphics operations)
                try:
                    pointer = array.pointer
                except AttributeError:
                    array.pointer = array.ctypes.data_as(POINTER(c_float * 16)).contents
                    pointer = array.pointer
                gl.glUniformMatrix4fv(array.loc[0], 1, True, pointer)

            else:
                sendfun = self._sendfuns[array.dtype.kind][len(array) - 1]  # Find correct glUniform function
                sendfun(array.loc[0], *array)