Giter Club home page Giter Club logo

x10d's Introduction

GitHub Workflow Status GitHub Issues Coverage NuGet Downloads Stable Version Nightly Version MIT License

About

X10D (pronounced extend), is a .NET package that provides extension methods for numerous types. The purpose of this library is to simplify a codebase by reducing the need for repeated code when performing common operations. Simplify your codebase. Take advantage of .NET. Use extension methods.

(I'm also dogfooding this library, so there's that.)

What are extension methods?

Extension methods are a clever .NET feature that augment existing types with new functionality. They are defined as static methods in a static class, and are called as if they were instance methods on the type they are extending. Take, for example, the following code:

public static class Program
{
    public static void Main()
    {
        string str = "Hello, world!";
        Console.WriteLine(str.Reverse());
    }
}

public static class StringExtensions
{
    public static string Reverse(this string str)
    {
        char[] chars = str.ToCharArray();
        Array.Reverse(chars);
        return new string(chars);
    }
}

This will print !dlrow ,olleH to the console. The Reverse method is defined in the StringExtensions class, yet is called as if it were an instance method on the str variable, even though it's not.

Why use extension methods?

Extension methods were introduced when LINQ was added to .NET. LINQ is a set of extension methods that provide a way to query, filter, and transform data. If you were to access LINQ's methods statically, you would have to write code like this:

public static class Program
{
    public static void Main()
    {
        int[] numbers = { 1, 2, 3, 4, 5 };
        IEnumerable<int> evenNumbers = Enumerable.Where(numbers, x => x % 2 == 0);
        IEnumerable<int> doubledNumbers = Enumerable.Select(evenNumbers, x => x * 2);
        int sum = Enumerable.Sum(doubledNumbers);
        Console.WriteLine(sum);
    }
}

And if you wanted to one-line this, you'd have to write this:

public static class Program
{
    public static void Main()
    {
        int[] numbers = { 1, 2, 3, 4, 5 };
        Console.WriteLine(Enumerable.Sum(Enumerable.Select(Enumerable.Where(numbers, x => x % 2 == 0), x => x * 2)));
    }
}

This is a lot of code to write, and it's not very readable. The nested method calls make it incredibly difficult to follow. However, because LINQ is implemented as extension methods, you can write the following code instead:

public static class Program
{
    public static void Main()
    {
        int[] numbers = { 1, 2, 3, 4, 5 };
        Console.WriteLine(numbers.Where(x => x % 2 == 0).Select(x => x * 2).Sum());
    }
}

Because the methods are called as if they were instance methods on IEnumerable<T>, they can be chained together, making the code much more readable.

X10D aims to provide these same benefits as LINQ, but for dozens of other types and for countless other use cases. See the documentation for a complete breakdown of what's available.

Installation

NuGet installation

Install-Package X10D -Version 4.0.0

Manual installation

Download the latest release from this repository and adding a direct assembly reference for your chosen platform.

Documentation

Documentation and the API reference is available at https://oliverbooth.github.io/X10D/index.html. I'm sorry this took so long to get up and running. DocFX will be the death of me.

Contributing

Contributions are welcome. See CONTRIBUTING.md.

License

X10D is released under the MIT License. See here for more details.

x10d's People

Contributors

oliverbooth avatar realityprogrammer avatar redageddon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

x10d's Issues

Vector2/3/4.With*

Types

System.Numerics.Vector2
System.Numerics.Vector3
System.Numerics.Vector4
UnityEngine.Vector2
UnityEngine.Vector3
UnityEngine.Vector4

Extension method signatures

Vector2 WithX(float);
Vector2 WithY(float);

Vector3 WithX(float);
Vector3 WithY(float);
Vector3 WithZ(float);

Vector4 WithX(float);
Vector4 WithY(float);
Vector4 WithZ(float);
Vector4 WithW(float);

Parameters

Parameter Type Description
x / y / z / w float The new component value.

Description
Returns a vector whose components are the same as a given vector, but with one component specified as a new value.

Benefits
Provides an easy way to transform a Vector2/3/4 without constructing a new one.

Drawbacks
This is already easily achievable using a with expression, since Vector2/3/4 are mutable.

(Optional) Implementation example
n/a

IReadOnlyDictionary<T1, T2>.ToGetParameters(string) - Add option to specify joiner string for array values in source dictionary

Type

System.Collections.Generic.Dictionary
System.Collections.Generic.IReadOnlyDictionary

Extension method signature

string ToGetParameters<T1, T2>(string arrayJoiner)

Parameters

Parameter Type Description
arrayJoiner string The value with which to concatenate array values.

Description
Converts an IReadOnlyDictionary<T1,T2> to a HTTP GET parameter string.

Benefits
This overload would introduce the option to specify a string with which to join array values in the source dictionary, such that multiple dictionary values which are arrays do not need to explicitly call string.Join by the caller.

Drawbacks

  1. Such a feature involves reflection, and may not be the most optimal solution.
  2. A major limitation is that arrayJoiner would apply to every value which is an array, which eliminates the possibility of joining disparate arrays differently.

(Optional) Implementation example

string Stringify(T2 value)
{
    var type = value.GetType();
    var isEnumerable = typeof(IEnumerable<>).IsAssignableFrom(type);
    return isEnumerable ? string.Join(arrayJoiner, value) : value.ToString();
}

string Sanitize(KeyValuePair<T1, T2> kvp)
{
    var key = HttpUtility.UrlEncode(kvp.Key.ToString());
    var value = HttpUtility.UrlEncode(Stringify(kvp.Value));
    return $"{key}={value}";
}

return string.Join("&", dictionary.Select(Sanitize));

Update READMEs through repository

Repo root

  • Delegate explanations to wiki (?) or external documentation site
  • Update badges
  • Add Unity installation instructions

Children

  • Remove

Random.NextInt64

Type

System.Random

Extension method signature

long NextInt64([long[, long]]);

Parameters
Document each of the parameters here, with their name and description - i.e. this would be equivalent to the entry in the XMLDoc. Use a table layout like in the following example:

Parameter Type Description
minValue long The inclusive lower bound of the random number returned.
maxValue long The exclusive upper bound of the random number returned.

Description
Returns a random 64-bit integer that is within a specified range.

Benefits
System.Random does not offer a method to produce a random long, unlike Java's java.util.Random which does.

Drawbacks
It will involve instantiating a temporary Random instance to produce a second sample without breaking the sequence of the provided instance.

(Optional) Implementation example

{
    var sample = random.Next();
    var sampledRandom = new Random(sample);
    return (long)sample << 32 | sampledRandom.Next();
}

Relocate extension methods to child namespaces

The rationale:

The consumer can decide which types to extend by only importing the necessary namespace. This will avoid conflicts with other libraries where the euser must resolve name collision by fully qualifying a static invocation.

Random.NextDouble and Random.NextSingle clusivity, + bonus typo

Random.NextDouble and Random.NextSingle describe their maxValue parameters as being inclusive, but in fact System.Random.NextDouble() returns a value that is less than 1.0 - meaning the implementation used here has an exclusive upper bound not an inclusive one.

RandomExtensions.cs lines 64 and 156 should be changed to read "exclusive" instead of "inclusive"

Bonus typo: NextSingle also describes maxValue as a "lower bound" when it should read "upper bound"

Use ArgumentNullException.ThrowIfNull instead of is null check

.NET 6 introduced a new way to throw ArgumentNullException in the event of a null argument.
The following snippet:

void Foo(string arg)
{
    if (arg is null)
    {
        throw new ArgumentNullException(arg);
    }
}

Can now be written in the form:

void Foo(string arg)
{
    ArgumentNullException.ThrowIfNull(arg);
}

This reduces indentation and number of lines necessary to throw.

Random.NextSingle with optional range parameters

Type

System.Random

Extension method signature

float NextSingle([float, float]);

Parameters

Parameter Type Description
minValue float The inclusive lower bound of the random number returned.
maxValue float The inclusive upper bound of the random number returned.

Description
Returns a random single-precision floating point number that is within a specified range.

Benefits
Simply acts as an automatic conversion method for Random.NextDouble() (as described in #33)

Drawbacks
Largely redundant as it would simply cast the result of NextDouble to float.

IComparable<T> Max and Min

Type

System.IComparable<T>

Extension method signature

T Max<T>(T);
T Min<T>(T);

Parameters

Parameter Type Description
other T The value to compare against.

Description
Returns the maximum/minimum of two values.

Benefits
Math.Min() and Math.Max only support primitives and do not support generic comparable types.

Drawbacks
None considered (at this time)

(Optional) Implementation example

{
    return value.GreaterThan(other) ? value : other;
    // or
    return value.LessThan(other) ? value : other;
}

IComparable<T> "operators"

Type

System.IComparable<T>

Extension method signature

T GreaterThan<T>(T);
T GreaterThanOrEqualTo<T>(T);
T LessThan<T>(T);
T LessThanOrEqualTo<T>(T);

Parameters

Parameter Type Description
other T The value to compare against.

Description
Determines if the current value is greater/less than (or equal to) another value.

Benefits
The IComparable<T> interface offers CompareTo(T) method, but naturally does not offer operators such as > < >= and <=. These methods would essentially implement that functionality.

Drawbacks
None considered (at this current time)

(Optional) Implementation example

{
    return value.CompareTo(other) < 0;
    // or
    return value.CompareTo(other) <= 0;
    // or
    return value.CompareTo(other) > 0;
    // or
    return value.CompareTo(other) >= 0;
}

Stream extensions to mimick BinaryWriter

Type

System.IO.Stream

Extension method signatures

int Write(short, [Endianness]);
int Write(int, [Endianness]);
int Write(long, [Endianness]);
int Write(ushort, [Endianness]);
int Write(uint, [Endianness]);
int Write(ulong, [Endianness]);

Parameters

Parameter Type Description
value T The valu to write.
endianness Endianness The endian encoding to use. Defaults to the system endianness.

Description
Writes an n-byte parameter type to the current stream and advances the stream position by n bytes, and returns the number of bytes written.

Benefits
This would save needing to allocate a BinaryWriter for quickly and fire-and-forgetly writing primitive types.

Drawbacks
None considered at this time

(Optional) Implementation example
Implementation example is for int (System.Int32), adjust for sister types.

{
    byte[] buffer = BitConverter.GetBytes(value);

    var swapNeeded = BitConverter.IsLittleEndian == (endianness == Endianness.BigEndian);
    if (swapNeeded)
        Array.Reverse(buffer);

    var positionBefore = stream.Position;
    stream.Write(buffer, 0, buffer.Length);
    return stream.Position - positionBefore;
}

(short/int/long).To(Host/Network)Order

Types

System.Int16
System.Int32
System.Int64

Extension method signatures

short ToHostOrder();
int ToHostOrder();
long ToHostOrder();

short ToNetworkOrder();
int ToNetworkOrder();
long ToNetworkOrder();

Parameters
n/a

Description
Converts a short/integer/long value from host byte order to network byte order.
- or -
Converts a short/integer/long value from network byte order to host byte order.

Benefits
Accessing IPAddress.NetworkToHostOrder() and IPAddress.HostToNetworkOrder() can start to get unwieldy, and also requires an import of System.Net.

Drawbacks
n/a

(Optional) Implementation example

{
    return IPAddress.HostToNetworkOrder(value);
    // - or -
    return IPAddress.NetworkToHostOrder(value);
}

Ranged Random.NextDouble

Type

System.Random

Extension method signature

double NextDouble(double, double);

Parameters

Parameter Type Description
minValue double The inclusive lower bound of the random number returned.
maxValue double The inclusive upper bound of the random number returned.

Description
Returns a random double-precision floating point number that is within a specified range.

Benefits
System.Random does not support ranges for floating point values, Random.NextDouble() simply returns a value between 0-1. This extension method would offer this missing functionaality.

Drawbacks
n/a

(Optional) Implementation example

{
    return random.NextDouble() * (maxValue - minValue) + minValue;
}

IReadOnlyDictionary.ToGetParameters joins with incorrect character

Describe the bug
It would appear that in migrating the extension method to a child namespace as of 9db0249, line 85 has a call to string.Join passing in ;

To Reproduce
n/a

Expected behavior
This method should join by & not ;, as this is the character used to delimit GET query parameters.

Additional context
This is presumably due to my confusion with ToConnectionString, I likely copied and pasted it. :notlikethis:

IEnumerable.For and IEnumerable.ForEach

Type

System.IEnumerable<T>

Extension method signature

void For<T>(System.Action<int, T>);
// and
void ForEach<T>(System.Action<T>);

Parameters
For

Parameter Type Description
action System.Action<int, T> The Action<int, T> delegate to perform on each element of the IEnumerable<T>. The int argument passed to this delegate represents the index.

ForEach

Parameter Type Description
action System.Action<T> The Action<T> delegate to perform on each element of the `IEnumerable.

Description
Performs the specified action on each element of the IEnumerable<T>.

Benefits
Similar functionality exists built-in for List<T>, see https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.foreach?view=net-6.0 - this functionality is not provided for IEnumerable<T>

Drawbacks
Potential naming collisions when attempting to call on a List<T>

(Optional) Implementation example

{
    foreach (T item in source)
    {
        action(item);
    }
}

2.6.0 heading in CHANGELOG does not link to tag

Describe the bug
2.6.0 heading in CHANGELOG does not link to tag, as it does with other headings

To Reproduce
n/a

Expected behavior
2.6.0 should link to the tag of the same name

Additional context
n/a

Stream extensions to mimick BinaryReader

Type

System.IO.Stream

Extension method signatures

short ReadInt16([Endianness]);
int ReadInt32([Endianness]);
long ReadInt64([Endianness]);
ushort ReadUInt16([Endianness]);
uint ReadUInt32([Endianness]);
ulong ReadUInt64([Endianness]);

Parameters

Parameter Type Description
endianness Endianness The endian encoding to use. Defaults to the system endianness.

Description
Reads an n-byte return type from the current stream and advances the current position of the stream by n bytes using a specified endian encoding.

Benefits
This would save needing to allocate a BinaryReader for quickly and fire-and-forgetly reading primitive types.

Drawbacks
Reading a string would require several parameters, such as the byte count to read and the System.Text.Encoding object to use for decoding.

(Optional) Implementation example
Implementation example is for int (System.Int32), adjust for sister types.

{
    byte[] buffer = new byte[4];
    stream.Read(buffer, 0, buffer.Length);

    var swapNeeded = BitConverter.IsLittleEndian == (endianness == Endianness.BigEndian);
    if (swapNeeded)
        Array.Reverse(buffer);

    return BitConverter.ToInt32(buffer, 0);
}

Implement Unity-esque Random extensions

I've written a blog post with regards to UnityEngine.Random and how it fails to encapsulate state, and recommending the use of System.Random instead.

The drawback to using System.Random is that Unity's RNG does offer some useful values that are related to game dev such as generating a random point in a circle, or on the surface of - or inside of - a sphere, or a random rotation. These are incredibly useful values that take a bit of implementation to create, and so on the post I explained how such methods could be implemented.

These methods will be brought into both X10D and X10D.Unity, with the core X10D module accepting and working with types defined in System.Numerics, whereas X10D.Unity would offer overloads which accept and work with types defined in UnityEngine (making the need for manual conversion redundant)

The following methods will be included:

  • NextUnitVector2
  • NextUnitVector3
  • NextRotation (NextQuaternion perhaps?)
  • NextRotationUniform (NextQuaternionUniform?)
  • NextColor

Type.Inherits() and Type.Implements()

Type

System.Type

Extension method signature

bool Implements<T>();
bool Implements(Type);
bool Inherits<T>();
bool Inherits(Type);

Parameters

Parameter Type Description
T T The type.
type System.Type The type.

Description
Returns a value indicating whether the current type implements a specified interface.
-or-
Returns a value indicating whether the current type inherits a specified type.

Benefits
Simplifies the call to typeof(T).IsSubclassOf(Type) and/or type.IsInterface && typeof(T).IsAssignableFrom(type)

Drawbacks
None considered (at this time).

(Optional) Implementation example
n/a

Color.Inverted

Types

System.Drawing.Color
UnityEngine.Color
UnityEngine.Color32

Extension method signatures

Color Inverted();
Color32 Inverted();

Parameters
n/a

Description
Returns a new Color with the red, green, and blue components inverted. Alpha is not affected.

Benefits
No such method exists in any of these APIs.

Drawbacks
n/a

(Optional) Implementation example

{
    // System.Drawing.Color:
    return Color.FromArgb(color.A, 255 - color.R, 255 - color.G, 255 - color.B);

    // UnityEngine.Color:
    return new Color(1f - color.r, 1f - color.g, 1f - color.b, color.a);

    // UnityEngine.Color32:
    return new Color32((byte)(255 - color.r), (byte)(255 - color.g), (byte)(255 - color.b), color.a);
}

IComparable<T>.Clamp

Type

System.IComparable<T>

Extension method signature

T Clamp<T>(T, T);

Parameters

Parameter Type Description
lower T The lower bound of the result.
upper T The upper bound of the result.

Description
Returns the current value clamped to the inclusive range of lower and upper.

Benefits
Math.Clamp only supports primitives and does not support generic types.

Drawbacks
None considered (at this time)

(Optional) Implementation example

{
    return value.Max(lower).Min(upper);
}

Show some Unity methods

In the README file, it only shows methods from X10D's namespace, not X10D.Unity, which is kind of a bummer as it does not fully show what X10D itself has to offer. I think it would be a good idea to also show some Unity extension methods.

Color.With*

Types

System.Drawing.Color
UnityEngine.Color
UnityEngine.Color32

Extension method signatures

Color WithR(byte/int/float);
Color WithG(byte/int/float);
Color WithB(byte/int/float);
Color WithA(byte/int/float);

Color32 WithR(byte/int/float);
Color32 WithG(byte/int/float);
Color32 WithB(byte/int/float);
Color32 WithA(byte/int/float);

Parameters

Parameter Type Description
r / g / b / a byte / int / float The new component value.

Description
Returns a color whose components are the same as a given color, but with one component specified as a new value.

Benefits
Provides an easy way to transform a Color without constructing a new one with .NET's FromArgb.

Drawbacks
In Unity, this is already easily achievable using a with expression, since Unity's Color/Color32 structs are mutable.

(Optional) Implementation example
n/a

Explicitly implement inline functionality instead of casting

Currently, implementations of methods which are available for more than 1 type, invoke the functionality already defined for a larger type, as an example, refer to DegreesToRadians defined for both double and float:

public static double DegreesToRadians(this double value)
{
    return Math.PI * value / 180.0;
}

public static float DegreesToRadians(this float value)
{
    return (float)((double)value).DegreesToRadians();
}

The float version of this method casts the input to a double so that the implementation is not duplicated. However the drawback with this is that it has a minor performance hit having to allocate more space and perform a conversion, only to have it convert back again after the result is evaluated.

A more optimal solution would be to directly use float constants without the need for casting, like so:

public static float DegreesToRadians(this float value)
{
    return MathF.PI * value / 180.0f;
}

However, again, a drawback remains that MathF is not defined for .NET Standard 2.0 which this library must continue to support until Unity upgrades to a newer version of the CLR.

As such, DegreesToRadians should be implemented like so:

public static float DegreesToRadians(this float value)
{
    return (float)Math.PI * value / 180.0f;
}

This float-cast of a constant double results in 0 performance drop, as the compiler is able to inline the result.

Single/Double.Lerp

Type

System.Single
System.Double

Extension method signature

float Lerp(float, float);
double Lerp(double, double);

Parameters

Parameter Type Description
target float / double The target of the interpolation.
alpha float / double The interpolation alpha.

Description
Linearly interpolates from the current value to a specified target with a specified alpha.

Benefits
Could be implemented using "precise" method as outlined on Wikipedia.

Drawbacks
Deciding a reasonable order of parameters is a task in its own right. i.e. should the format be value.Lerp(target, alpha) or alpha.Lerp(value, target)?

(Optional) Implementation example

{
    return (1 - alpha) * value + alpha * target;
}

string.IsPalindrome

Type

System.String

Extension method signature

bool IsPalindrome()

Parameters
n/a

Description
Determines whether the current string is considered palindromic; that is, the letters within the string are the same when reversed.

Benefits
Useful.

Drawbacks
Niche

(Optional) Implementation example

{
    if (value is null)
    {
        throw new ArgumentNullException(nameof(value));
    }

    if (value.Length == 0)
    {
        // empty string is not palindromic
        return false;
    }

    for (int index = 0, endIndex = value.Length - 1; index < value.Length; index++, endIndex--)
    {
        Rune startRune = new Rune(value[index]);
        Rune endRune = new Rune(value[endIndex]);

        if (!Rune.IsLetter(startRune) && !Rune.IsNumber(startRune))
        {
            endIndex++;
            continue;
        }

        if (!Rune.IsLetter(endRune) && !Rune.IsNumber(endRune))
        {
            index--;
            continue;
        }

        if (Rune.ToUpperInvariant(startRune) != Rune.ToUpperInvariant(endRune))
        {
            return false;
        }
    }

    return true;
}

Add argument validation

Extension methods should perform argument validation for all necessary arguments.

Example, extension methods for nullable types should throw ArgumentNullException on null this parameter, rather than letting the CLR throw NullReferenceException.

  • BooleanExtensions
  • ByteExtensions (n/a)
  • CharExtensions
  • ComparableExtensions
  • DateTimeExtensions (n/a)
  • DictionaryExtensions
  • DoubleExtensions
  • EndPointExtensions
  • EnumerableExtensions
  • EnumExtensions
  • Int16Extensions
  • Int32Extensions
  • Int64Extensions
  • ListExtensions
  • RandomExtensions
  • ReflectionExtensions
  • SingleExtensions
  • StringExtensions
  • WaitHandleExtensions

AsArray/AsEnumerable

Type

T

Extension method signature
Provide the full method signature here, without parameter names, but do not include the leading this T x parameter. Example:

T[] AsArray<T>(this T value)
// and
IEnumerable<T> AsEnumerable<T>(this T value)

Parameters

Parameter Type Description
value T The value to encapsulate.

Description
Encapsulates the value into an array of length 1 containing the value.
or
Yields the value into an IEnumerable<T> with one element.

Benefits
To save having to encapsulate as new Foo[] { myFoo } when object is known singleton where array is expected, myFoo.AsArray() or myFoo.AsEnumerable() allows for contiguous method chaining.

Drawbacks
AsEnumerable could conflict with LINQ's AsEnumerable, this may be something to consider.

(Optional) Implementation example

{
    return new[] {value};
    // or
    yield return value;
}

IDictionary<K, V>.ToConnectionString() does not safely sanitize types with ToString() that includes a space

Describe the bug
Local function SanitizeValue in IDictionary<K, V>.ToConnectionString() accepts generic T.
Pattern matching to string does not account for non-string T where T.ToString() returns a string with a space

To Reproduce

class Foo
{
    /// <inheritdoc />
    public override string ToString() => "Foo Bar";
}

var dictionary = new Dictionary<string, object>
{
    { "foo", new Foo() }
};

const string expected = "foo=\"Foo Bar\"";
var result = dictionary.ToConnectionString();

Assert.AreEqual(expected, result); // Assertion fails

Expected behavior
SanitizeValue local function should accept string not T, and sanitize spaces regardless.

Additional context
n/a

Trigonometric functions

Type

System.Single
System.Double

Extension method signature

float Acos();
double Acos();
// and
float Acosh();
double Acosh();
// and
float Asin();
double Asin();
// and
float Asinh();
double Asinh();
// and
float Atan();
double Atan();
// and
float Atanh();
double Atanh();
// and
float Atan2();
double Atan2();
// and
float Cos();
double Cos();
// and
float Cosh();
double Cosh();
// and
float Sin();
double Sin();
// and
float Sinh();
double Sinh();
// and
float Tan();
double Tan();
// and
float Tanh();
double Tanh();

Parameters
n/a

Description
Returns the [hyperbolic] (co)sine/tangent of the specified angle.

Benefits
n/a

Drawbacks
Input must be assumed to be radians so as to be consistent with System.Math and System.MathF

(Optional) Implementation example

{
    return Math.[Equivalent](value); // MathF for float
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.