Git Product home page Git Product logo

mouse's Introduction

Mouse Continuous Integration Maven Central Cats friendly

Mouse is a small companion to the Cats functional programming library and the Scala standard library.

The library arose from this Cats issue and is a Typelevel member.

Mouse is published for Scala 2.12, 2.13 and 3.0. For Scala.jvm:

"org.typelevel" %% "mouse" % version

For scala.js 1.x:

"org.typelevel" %%% "mouse" % version

Learn more about Mouse at https://typelevel.org/mouse/.

Content

Mouse includes enrichments for:

Example:

scala> import mouse.all._
import mouse.all._

scala> true.option("Its true!")
res0: Option[String] = Some(Its true!)

scala> def makeEven(i: Int) = (i % 2 == 1).applyIf(i)(_ - 1)
def makeEven(i: Int): Int

scala> val e1: Either[String, Int] = Left("failed")
e1: Either[String,Int] = Left(failed)

scala> true.whenA(e1)
res0: Either[String,Unit] = Left(failed)

scala> false.whenA(e1)
res1: Either[String,Unit] = Right(())

scala> res0.cata(msg => s"Message received: ${msg}", "No message")
res1: String = Message received: Its true!

scala> "1.0".parseFloat
res0: Either[NumberFormatException, Float] = Right(1.0F)

scala> "foo".parseIntValidated
res1: cats.data.Validated[NumberFormatException,Int] = Invalid(java.lang.NumberFormatException: For input string: "foo")

scala> val t1 = scala.util.Try(new java.net.URL("https://www.github.com"))
t1: scala.util.Try[java.net.URL] = Success(https://www.github.com)

scala> t1.cata(msg => s"URL is valid!", error => s"URL is invalid: ${error.getMessage}")
res1: String = URL is valid!

scala> t1.toEither
res2: Either[Throwable,java.net.URL] = Right(https://www.github.com)

scala> val t2 = scala.util.Try(new java.net.URL("https//www.github.com"))
t2: scala.util.Try[java.net.URL] = Failure(java.net.MalformedURLException: no protocol: https//www.github.com)

scala> t2.cata(msg => s"URL is valid!", error => s"URL is invalid: ${error.getMessage}")
res3: String = URL is invalid: no protocol: https//www.github.com

scala> t2.toEither
res4: Either[Throwable,java.net.URL] = Left(java.net.MalformedURLException: no protocol: https//www.github.com)

scala> val intToBytes = 123456789.toByteArray
intToBytes: Array[Byte] = Array(7, 91, -51, 21)

scala> val longToBase64 = 123456789L.toBase64
longToBase64: String = AAAAAAdbzRU

scala> 5.squared
res0: Int = 25

scala> 1.5 |> (_.toInt) |> (_.toString)
res0: String = 1

//lift a partial function into a total function to an Either, when you want to treat unhandled input cases as an error
scala> liftEither[Option[Int]]({case Some(n) => n}, a => s"Unexpected: $a")(Some(6))
res0: Either[String,Int] = Right(6)

scala> val mapped = Map(1 -> 2, 3 -> 4).mapKeys(_ * 2)
mapped: Map[Int,Int] = Map(2 -> 2, 6 -> 4)

scala> val foption = List(Option(1), Option(2), Option(4)).mapIn(_ * 2)
foption: List[Option[Int]] = List(Some(2), Some(4), Some(8))

scala> val feither = List(Either.cond(true, 1, "0")).mapIn(_ * 2)
foption: List[Either[String, Int]] = List(Right(2))

scala> val listOption = List(Option(1), Option(2)).mapNested2(_ * 2)
listOption: List[Option[Int]] = List(Some(2), Some(4))

scala> val listOptionList = List(Option(List(1)), Option(List(2))).mapNested3(_ * 2)
listOptionList: List[Option[List[Int]]] = List(Some(List(2)), Some(List(4)))

scala> val tupleHead = (1, 2, 4, 8).head
tupleHead: Int = 1

scala> val tupleLast = (1, 2, 4, 8).last
tupleHead: Int = 8

scala> Set(0).tailOrEmpty
val res3: Set[Int] = Set()

scala> Nil.tailOrEmpty
val res1: List[Nothing] = List()

scala> Set(0).tailOption
val res4: Option[cats.data.NonEmptySet[Int]] = None

scala> List(0,1,2).tailOption
val res5: Option[cats.data.NonEmptyList[Int]] = Some(NonEmptyList(1, 2))

Scope of Library

  • Provide enrichments to classes from the Scala standard library that convert to Cats datatypes, or otherwise improve the functional programming experience.

Contributing

Mouse is maintained by @benhutchison and @danicheg.

Issues and pull requests are welcome. Code contributions should be aligned with the above scope to be included, and include unit tests. See contributing guide for more details.

This project supports the Scala code of conduct and aims that its channels (mailing list, Gitter, github, etc.) to be welcoming environments for everyone.

mouse's People

Contributors

armanbilge avatar benhutchison avatar danicheg avatar dwijnand avatar falconepl avatar frosforever avatar geirolz avatar gerferra avatar jhnsmth avatar kailuowang avatar kubukoz avatar larsrh avatar lukestephenson avatar majk-p avatar matwojcik avatar mberndt123 avatar nebtrx avatar ronancamargo avatar sakulk avatar scala-steward avatar sethtisue avatar sh0hei avatar ssanj avatar stephen-lazaro avatar timomeijer avatar tmccarthy avatar tobiasroland avatar tpolecat avatar typelevel-steward[bot] avatar xuwei-k 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

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

mouse's Issues

Adding mapValuesF to MapOps

Do you think it would be useful to have mapValuesF in MapOps? I recently had to get from Map[A, B] to F[Map[A, C]] (instead of Map[A, F[C]]) when mapping values with B => F[C] function. After some time I've realized that it can be done with parUnorderedTraverse, but it wasn't too obvious - my first thought was to check if there's mapValuesF in Mouse.

When it comes to mapValuesF definition for MapOps, it could look like this:

import cats.syntax.parallel._

def mapValuesF[F[_], C](f: B => F[C])(implicit F: CommutativeApplicative[F], P: Parallel.Aux[F, F]): F[Map[A, C]] =
  map.parUnorderedTraverse(f)

What do you think? There's is a quite popular thread on StackOverflow related to this topic so maybe it would be useful to have mapValuesF here

Microsite for `mouse`

As have we discussed with @benhutchison in #243 mouse documentation is needed enhancements. I propose to create a microsite for it, where we can nicely organize more detailed docs. What do you folks think about it?

Add whenA/unlessA extension methods for Boolean

final class BooleanOps(private val b: Boolean) extends AnyVal {
  @inline def whenA[F[_], A](fa: F[A])(implicit F: Applicative[F]): F[Unit] = F.whenA(b)(fa)
  @inline def unlessA[F[_], A](fa: F[A])(implicit F: Applicative[F]): F[Unit] = F.unlessA(b)(fa)
}

Motivation: Having to put the branch condition after the action it guards hurts readability. Consider:

getCondition.flatMap(
  // We won't know that this is conditional until two lines later
  doSomething
    .productR(doSomethingElse)
    .whenA(_)
)
// versus
getCondition.flatMap {
  // The condition is front and center
  _.whenA( 
    doSomething
      .productR(doSomethingElse)
  )
}

It gets even more annoying if you have something else to do after the conditional branch - the two blocks of logic are not visually separated:

doSomething
  .productR(doSomethingElse)
  .whenA(condition)
  .productR(alwaysDoThis)
// versus
condition.whenA(
  doSomething
    .productR(doSomethingElse)
).productR(alwaysDoThis)

Both whenA and unlessA are present in Scalaz as whenM and unlessM.

consider merging into cats

I think this repo should be moved into a cats submodule.

Keep the artifact name.

This would simplify PRs to cats (recently we have seen several PRs that we say would be better as mouse PRs) and it would reduce the maintenance load since all the build updates and publishing could be done in one go.

Adding `toRightIn` and `toOptionIn`

What do you think about adding toRightIn for IO[Option[_]] and toOptionIn for IO[Either[_, _]]? Having those two allows us to switch between Either and Option without the need to wrap toRight/toOption in map (namely, it's the same case as with mapIn or flatMapIn).

Here's some example:

val eitherIO: IO[Either[String, Int]] = ...
val res1: IO[Option[Int]] = eitherIO.toOptionIn
// ...instead of: eitherIO.map(_.toOption)

val optionIO: IO[Option[BigInt]] = ...
val res2: IO[Either[String, BigInt]] = optionIO.toRightIn(left = "whoops")
// ...instead of: optionIO.map(_.toRight(left = "whoops"))

For those two, the implementation might be the following:

final class FOptionOps[F[_], A](private val foa: F[Option[A]]) extends AnyVal {

  // (...)

  def toRightIn[L](left: => L)(implicit F: Functor[F]): F[Either[L, A]] =
    F.map(foa) {
      case None    => Left(left)
      case Some(a) => Right(a)
    }

}

and:

final class FEitherOps[F[_], L, R](private val felr: F[Either[L, R]]) extends AnyVal {

  // (...)

  def toOptionIn(implicit F: Functor[F]): F[Option[R]] =
    F.map(felr)(_.toOption)

}

I'm not 100% sure about the naming, so if there's anything that more accurately matches Mouse conventions then just treat toRightIn/toOptionIn only as a suggestion πŸ™‚

Proposal: Enhance navigation in the root `mouse` package

There are a bunch of different syntaxes in the mouse - for boxed primitive-like data types (Int, Long, Boolean, etc), for collections (Map, Set, List, etc), for nested things (F[Either[A, B]], F[Option[A]], etc). And as you probably already guessed, we can combine some of those in groups - mouse.collections, mouse.nested, etc. It'd be a bit nicer from a design perspective, as well as from navigation. But this would require us to do a new major release since that change isn't binary compatible. What do you think about it?

whenA and unlessA do not have lazy functions

Is there a reason the Boolean functions whenA and unlessA are not by-name (lazy) functions like option, xor, fold etc?
Now when using false.whenA(f) function f is evaluated even when the boolean is false. Similar for unlessA.
Is this a bug or a feature?

Functions like Option.when and Option.unless are also by-name, so I would have expected these Boolean function to also be by-name.

Scala 3 migration

Dotty-compatibility mode provides a way to use mouse now in Scala 3 projects, eg
("org.typelevel" %% "mouse" % "0.25").withDottyCompat(dottyVersion)

However, Scala 3 migration is also a good time for any major refactors of the lib. Im thinking about a Scala 3 only version which would allow a clean break.

  • Top level values and extension methods
  • Dropping any obsolete methods that are now in core
  • Move to munit for testing (just for the simplicity)

If you have any ideas/requests for a Scala 3 rewrite, please add them to this issue

Adding `mapInF`

What do you think about adding mapInF to both FOptionOps and FEitherOps?

// FOptionOps:
def mapInF[B](f: A => F[B])(implicit F: Monad[F]): F[Option[B]] = ???

// FEitherOps:
def mapInF[A](f: R => F[A])(implicit F: Monad[F]): F[Either[L, A]] = ???

Suggestion: Add `parFlatMapN`

Motivation

I really like flatMap.

I also really like parMapN on tuples.

I therefore suspect I'd really love a parFlatMapN

currently:

val helloF: F[String] = (someF, someOtherF).parMapN((a,b) => "hello")
val worldFF: F[F[String]] = (someF, someOtherF).parMapN((a,b) => "world".pure[F])
val worldF: F[String] = stringFF.flatten

what I'd love to have:

val helloF: F[String] = (someF, someOtherF).parMapN((a,b) =>"hello")
val worldF: F[String] = (someF, someOtherF).parFlatMapN((a,b) => "world".pure[F])

Is there another way to accomplish this than parFlatMapN

Yep, but I think it'd be quite nifty to have it.
The argument against is I suspect that you can just do .parMapN(..).flatten - it's not that much more code to look at - but wouldn't the same argument apply to most flatMap operations (you could just do .map(...).flatten)?

It came up in a $DAYJOB example that looked not-really-but-kind-of-sort-of like this (using cats-effects IO here for the sake of the example)

def ioEnrichOrAbsent(thing: Thing): IO[Option[Enriched]] = ???

val enriched: IO[List[Enriched]] = (ioAPICall, ioSomeOtherAPICall).parMapN {
   (a,b) => {
      val listOfThings: List[Thing] = getListToTraverse(a,b)
      listOfThings
         .parTraverse(ioEnrichOrAbsent)
         .map(_.flatten)
   }
}.flatten

... which, yes, in this simplified could be refactored this to be more legible in a myriad ways. But, I still think parFlatMapN would have made it more obvious than a flatten (especially because I'm already using .flatten for the List[Option[A]]` inside the parMapN, so there's a bit of mental gymnastics people have to do to realize which thing is being flattened and why)

mapKeys method isn't pure

Hey there,

The mapKeys is not pure because you can pass a function that will map two different input keys to the same output key. The result in such cases depends on the iteration order of the Map and is hence not deterministic. I don't think this is appropriate for a pure FP library, so I propose to deprecate this method.

binary compatibility post 1.0

If we lock binary compatibility post 1.0, I think the main implication is that we can't add methods existing traits, however we can still add new traits.
If someone want to add a new extension to Option, he just need to create a new trait say OptionSyntax2 and let the
mouse.all extends and mouse.option extend this new trait.
Here is an example of this solution I am trying to suggest in a cats PR
typelevel/cats#2138 (comment)
In the case of implicit extension namespace collusion, I don't know a good solution, I imagine when user encounter this they just need to stop using the all-inclusive import and use specific imports to avoid the ones that causing conflicts.

Possibility of moving mouse to typelevel org?

mouse being a separate module of cats, is it possible to move to the typelevel org? Having it under a different org just seems not as "official" as other separate modules of cats like cats-mtl and cats-effects( I am raising the same issue in alleycats ), and thus hurts its popularity, which is a shame.

Offer of code, int/long to le/be endian array and string to zero terminated array support

Hi.

It's unclear what the boundaries of this library are for submission. Most of the functionality integrates with cats, but there are a few utility functions that are stand-alone working with basic types (see Int in Readme.md). I'm able to offer the latter, but would like to hear whether my submission would be accepted before I do additional work to polish it / respond to scrutiny outside the scope of my personal project. These would end up in Int/Long and String.

object EndianUtils {
  def toBEInteger(a: Array[Byte], offset: Int, numBytes: Int, signExtend: Boolean = false): Int = {
    val fillBytes = 4 - numBytes

    val i = if (fillBytes > 0) {
      val fill = if (signExtend && (a(0 + offset) & 0x80) == 0x80) 0xFF else 0

      (0 until fillBytes).foldLeft(0)((acc, _) => acc << 8 | fill)
    } else 0

    (0 until numBytes).foldLeft(i)((acc, index) => acc << 8 | (a(index + offset) & 0xFF))
  }

  def toLEInteger(a: Array[Byte], offset: Int, numBytes: Int, signExtend: Boolean = false): Int = {
    val fillBytes = 4 - numBytes

    val i = if (fillBytes > 0) {
      val fill = if (signExtend && (a(numBytes - 1 + offset) & 0x80) == 0x80) 0xFF else 0

      (0 until fillBytes).foldLeft(0)((acc, _) => acc << 8 | fill)
    } else 0

    (numBytes-1 to 0 by -1).foldLeft(i)((acc, index) => acc << 8 | (a(index + offset) & 0xFF))
  }

  def toBELong(a: Array[Byte], offset: Int, numBytes: Int, signExtend: Boolean = false): Long = {
    val fillBytes = 8 - numBytes

    val i = if (fillBytes > 0) {
      val fill = if (signExtend && (a(0 + offset) & 0x80) == 0x80) 0xFFL else 0L

      (0 until fillBytes).foldLeft(0L)((acc, _) => acc << 8 | fill)
    } else 0L

    (0 until numBytes).foldLeft(i)((acc, index) => acc << 8 | (a(index + offset) & 0xFF))
  }

  def toLELong(a: Array[Byte], offset: Int, numBytes: Int, signExtend: Boolean = false): Long = {
    val fillBytes = 8 - numBytes

    val i = if (fillBytes > 0) {
      val fill = if (signExtend && (a(numBytes - 1 + offset) & 0x80) == 0x80) 0xFFL else 0L

      (0 until fillBytes).foldLeft(0L)((acc, _) => acc << 8 | fill)
    } else 0L

    (numBytes-1 to 0 by -1).foldLeft(i)((acc, index) => acc << 8 | (a(index + offset) & 0xFF))
  }

  // These only work with unsigned ints
  def intToBEArray(v: Int, a: Array[Byte], offset: Int, numBytes: Int): Unit =
    for (i <- 0 until numBytes)
      a(offset + i) = (v >>> ((numBytes - i - 1) << 3)).toByte

  def intToLEArray(v: Int, a: Array[Byte], offset: Int, numBytes: Int): Unit =
    for (i <- 0 until numBytes)
      a(offset + i) = (v >>> (i << 3)).toByte

  def longToBEArray(v: Long, a: Array[Byte], offset: Int, numBytes: Int): Unit =
    for (i <- 0 until numBytes)
      a(offset + i) = (v >>> ((numBytes - i - 1) << 3)).toByte

  def longToLEArray(v: Long, a: Array[Byte], offset: Int, numBytes: Int): Unit =
    for (i <- 0 until numBytes)
      a(offset + i) = (v >>> (i << 3)).toByte
}

import java.nio.charset.StandardCharsets

import scala.annotation.tailrec

object StringUtils {
  val charset = StandardCharsets.ISO_8859_1

  def zeroTerminatedStringFromArray(a: Array[Byte], offset: Int, maxLength: Int): String = {
    val maxLengthAndOffset = maxLength + offset

    @tailrec
    def findZeroTerminator(i: Int): Int =
      if (i == maxLengthAndOffset) i
      else if (a(i) == 0) i
      else findZeroTerminator(i+1)

    val end = findZeroTerminator(offset)

    new String(a, offset, end - offset, charset)
  }

  def stringToArray(str: String, a: Array[Byte], offset: Int, maxLength: Int): Unit = {
    val bytes = str.getBytes(charset)
    val strLengthToCopy = Math.min(maxLength, bytes.size)

    System.arraycopy(bytes, 0, a, offset, strLengthToCopy)
    if (strLengthToCopy < maxLength)
      a(offset + strLengthToCopy) = 0
  }
}

lazy params for boolean ops?

It may make sense for the option and xor methods on BooleanOps to take by-name parameters so that they don't evaluate arguments that they may not end up using. This would make them consistent with methods like Option.getOrElse.

bad option `-doc-external-doc` on Scala 3

This is stolen from typelevel/sbt-typelevel#166. Actually, kudos to @armanbilge for this finding.
https://github.com/typelevel/mouse/runs/5172959686?check_suite_focus=true#step:14:186
[warn] bad option '-doc-external-doc:/home/runner/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-core_3/2.7.0/cats-core_3-2.7.0.jar#http://typelevel.org/cats/api/,/home/runner/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.6/scala-library-2.13.6.jar#https://www.scala-lang.org/api/2.13.6/,/home/runner/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-kernel_3/2.7.0/cats-kernel_3-2.7.0.jar#http://typelevel.org/cats/api/' was ignored
Probably that's not the Mouse problem itself and the fix should be within SBT. But let's investigate this a bit.

RFE - partialFunction liftEither as extended method

Currently PartialFunctionLift comes in on AllSyntax but it's not possible to

import mouse.partialFunction._

Additionally the syntax is for a wrapper instead of an extended method. Would it be in mouse style to change this around?

my pf: PartialFunction[Int, String] = { case 1 => "one"; case 2 => "two" }
pf.liftEither(identity)(7) // Left(7)

Given that everything else uses this style there might be something going on I'm not aware of so I wanted to raise the issue before submitting a patch.

Cats 1.1.0

Can we please get a version of mouse that is build against cats 1.1.0? :)

Code Coverage

Consider code test coverage reports via https://codecov.io/ ?

It's currently being used in Cats. Just wondering if you want to keep the same standards/tools?

Proposal: Renaming this library

I often talk to colleagues who use cats-core, cats-effect, etc... but know nothing about mouse.
This is sad because I love mouse and all its features ( which prevents the usage of EitherT and OptionT for instance) , but I see the reasons why this can't be merged within cats-core.

However, I wonder if there is a way to improve the visibility of this project.
With the arrival of Scala 3 we can take the opportunity to rename/fork this library to a better and clearer name which includes cats- as prefix to let it be more part of an ecosystem. I see cats-core as the base, mouse as an advanced syntax of cats and cats-effect as the effects system.
At the moment, mouse seems an independent library and not a cats ecosystem add-on to me.

I don't want to blame the current name, I just wonder if a rebranding would improve the visibility of this library which, in my humble opinion, should be part of every cats-based project. Too many times I have seen boilerplate and operators that are already part of mouse rewritten within Utils classes.

Going deeper, the problem I see with the mouse name is that it doesn't really describe the purpose of the library, which aim to just enrich cats with a nice and useful syntax without adding new type classes or features.

Some ideas:

  • cats-pragmatics (polished, but I'm not sure if it is correct)
  • cats-mouse ( more conservative )
  • cats-suit / cats-dress ( fancy and funny but I don't know how explanatory it is )
  • cats-enrichments / cats-rich-syntax ( more serious but clear )

Something like this, for instance:

"org.typelevel" %% "cats-core" % "x.y.z",
"org.typelevel" %% "cats-rich-syntax" % "x.y.z",
"org.typelevel" %% "cats-effect" % "x.y.z",

Once done with the name, I'd also rethink the packages because it would be nice to try to keep the same pattern as cats-core in order to simplify the life of the users.
Since mouse adds syntax to cats core, maybe it is correct to put it under cats.syntax package, where mouse is a specialization of the basic cats syntax. This creates a kind of boundary.

Moreover, this is also useful to better organize imports with Scalafmt

rewrite.rules = [ SortImports ]

Example

// current 
import cats.syntax.all.* // imports all cats-core syntax
import mouse.all.* // import all mouse syntax

// new
import cats.syntax.all.* // imports all cats-core syntax
import cats.syntax.rich.all.* // import all cats rich syntax

We could also consider to no having a global import but split them by type as suggested in #362 which I like TBH


import cats.syntax.collections.* // import all cats boxed syntax
import cats.syntax.nested.* // import all cats nested syntax

//or 
import cats.syntax.rich.collections.* // import all cats boxed syntax
import cats.syntax.rich.nested.* // import all cats nested syntax

To rename or not, what name and how to do it is up to you, but I just wanted to sow a seed for a discussion.
Maybe I am the only one who sees this problem.

Let me know what you think :)

parseUrl for String on the JVM

The constructor for java.net.URL throws MalformedURLException if the String provided to the constructor is not a valid URL. I often find myself writing utility functions of the form String => Either[MalformedUrlException, URL] to handle this case in a typesafe way.

This seems like something that might be appropriate to add to a syntax for String in mouse. Something like a parseUrl extension method that returns Either[MalformedUrlException, URL]. Unfortunately it doesn't seem like the java.net.URL class exists in Scala.js.

I'm wondering if a PR would be welcome that adds a parseUrl syntax only for the JVM version of mouse? It may have some impact on how the package object is constructed, but I'm happy to try it out and submit a PR.

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.