public static CTObject Map(CTObject[] args)
        {
            AssertParameterCountAtLeast(MapFunctionName, 2, args);
            CTProcedure proc = args[0] as CTProcedure;

            if (proc == null)
            {
                throw new TypeError(MapFunctionName, CTProcedure.TypeName, args[0].DisplayType());
            }
            for (int i = 1; i < args.Length; ++i)
            {
                if (args[i].GetType() != typeof(CTPair))
                {
                    throw new TypeError(MapFunctionName, CTPair.TypeName, args[i].DisplayType());
                }
            }

            List <CTObject> results = new List <CTObject>();

            CTObject[] applyArgs      = new CTObject[args.Length - 1];
            bool       firstListEnded = false;

            while (!firstListEnded)
            {
                for (int i = 1; i < args.Length; ++i)
                {
                    if (args[i].GetType() == typeof(CTEmptyList))
                    {
                        firstListEnded = true;
                        break;
                    }
                    else if (args[i].GetType() == typeof(CTPair))
                    {
                        CTPair arg = (CTPair)args[i];
                        applyArgs[i - 1] = arg.car;
                        args[i]          = arg.cdr;
                    }
                    else
                    {
                        throw new TypeError(MapFunctionName, CTPair.TypeName, args[i].DisplayType());
                    }
                }

                if (!firstListEnded)
                {
                    results.Add(Apply(proc, applyArgs));
                }
            }

            return(List(results));
        }
        private static CTObject Apply(CTProcedure proc, CTObject[] args)
        {
            switch (args.Length)
            {
            case 0: return(proc.apply0());

            case 1: return(proc.apply1(args[0]));

            case 2: return(proc.apply2(args[0], args[1]));

            case 3: return(proc.apply3(args[0], args[1], args[2]));

            case 4: return(proc.apply4(args[0], args[1], args[2], args[3]));

            case 5: return(proc.apply5(args[0], args[1], args[2], args[3], args[4]));

            default: return(proc.applyN(args));
            }
        }