Git Product home page Git Product logo

rserve-ruby-client's Introduction

rserve-client

Build Status

DESCRIPTION:

Ruby client for Rserve, a Binary R server (http://www.rforge.net/Rserve/).

Follows closely the new Java client API, but maintains all Ruby conventions when possible.

FEATURES / LIMITATIONS

  • 100% ruby
  • Uses TCP/IP sockets to interchange data and commands
  • Requires Rserve installed on the server machine. On debian / ubuntu, you should use sudo apt-get install r-cran-rserve Pros:
  • Work with Ruby 1.9.3, 2.0.0, 2.1.1, 2.3.1 (tested on Travis) and and JRuby 1.5.
  • Retrieve and assign various R's datatypes: integer, doubles, chars, logical vectors, lists and raw data.
  • Session allows to process data asynchronously. You start a command, detach the process and retrieve result later. You can marshall the session, store on file or database and use it when you need it.
  • Ruby API follows closely the Java API, so any change on the server API could be adopted without much problem
  • Fast: 5-10 times faster than RinRuby.
  • Easy management of differences between R and Ruby, or "You can have your cake and eat it, too!"
    • From R side: The evaluation of expression retrieves REXP object, with a lot of information from original variables on R. You can construct your REXP objects and assign them to variables on R fast using binary TCP/IP port or send complex expression without lost of time using void_eval
    • Between R and Ruby: Every REXP object implements methods to convert to specific Ruby type: as_integers, as_doubles, as_strings
    • From Ruby side: Every REXP objects has a to_ruby method, which automagicly converts every R type on equivalent Ruby type. So, a vector of size 1 is converted to an integer or double, a vector of size>1 returns an array, a named list returns a hash and so on. If you need to create a complex expression, you could always use method eval without problem Cons:
  • Requires Rserve
  • Limited features on Windows, caused by limitations on Rserve on this platform: single concurrent connection allowed, server crash on parse errors and can't spawn sessions.

RELATED LIBRARIES (Ruby / R)

  • Rinruby [http://rinruby.ddahl.org/]
    • 100% ruby
    • Uses pipes to send commands and evals
    • Uses TCP/IP Sockets to send and retrieve data
    • Pros:
      • Doesn't requires anything but R
      • Works flawlessly on Windows
      • Work with Ruby 1.8, 1.9 and JRuby 1.5
      • All API tested
    • Cons:
      • VERY SLOW on assignation
      • Very limited datatypes: Only vector and Matrix
  • RSRuby
    • C Extension for Ruby, linked to R's shared library
    • Pros:
      • Blazing speed! 5-10 times faster than Rserve and 100-1000 than RinRuby.
      • Seamless integration with ruby. Every method and object is treated like a Ruby one
    • Cons:
      • Transformation between R and Ruby types aren't trivial
      • Dependent on operating system, Ruby implementation and R version
      • Ocassionaly crash
      • Not available for alternative implementations of Ruby (JRuby, IronRuby and Rubinius)

TODO

Implements

  • Original test

Spec

  • Test suite on Rserve Java new API
  • First tutorial on R

SYNOPSIS:

require 'rserve'
con=Rserve::Connection.new

# Evaluation retrieves a <tt>Rserve::REXP</tt> object

x=con.eval('x<-rnorm(1)')
=> #<Rserve::REXP::Double:0x000000010a81f0 @payload=[(4807469545488851/9007199254740992)], @attr=nil>

# You could use specific methods to retrieve ruby objects
x.as_doubles => [0.533736337958596]
x.as_strings => ["0.533736337958596"]

# Every Rserve::REXP could be converted to Ruby objects using
# method <tt>to_ruby</tt>
x.to_ruby => (4807469545488851/9007199254740992)

# The API could manage complex recursive list

x=con.eval('list(l1=list(c(2,3)),l2=c(1,2,3))').to_ruby
=> #<Array:19590368 [#<Array:19590116 [[(2/1), (3/1)]] names:nil>, [(1/1), (2/1), (3/1)]] names:["l1", "l2"]>


# You could assign a REXP to R variables

con.assign("x", Rserve::REXP::Double.new([1.5,2.3,5]))
=> #<Rserve::Packet:0x0000000136b068 @cmd=65537, @cont=nil>
con.eval("x")
=> #<Rserve::REXP::Double:0x0000000134e770 @payload=[(3/2), (2589569785738035/1125899906842624), (5/1)], @attr=nil>

# Rserve::REXP::Wrapper.wrap allows you to transform Ruby object to 
# REXP, could be assigned to R variables

Rserve::REXP::Wrapper.wrap(["a","b",["c","d"]])

=> #<Rserve::REXP::GenericVector:0x000000010c81d0 @attr=nil, @payload=#<Rserve::Rlist:0x000000010c8278 @names=nil, @data=[#<Rserve::REXP::String:0x000000010c86d8 @payload=["a"], @attr=nil>, #<Rserve::REXP::String:0x000000010c85c0 @payload=["b"], @attr=nil>, #<Rserve::REXP::String:0x000000010c82e8 @payload=["c", "d"], @attr=nil>]>>

REQUIREMENTS:

  • R
  • Rserve

INSTALL:

sudo gem install rserve-client

LICENSE:

REngine - Java interface to R Copyright (C) 2004,5,6,7 Simon Urbanek Copyrigth (C) 2010-2017 Claudio Bustos (Ruby version)

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

rserve-ruby-client's People

Contributors

545ch4 avatar bgipsy avatar clbustos avatar frisoft avatar jergason avatar jtprince avatar michaelkirk avatar mvdamme avatar nessche avatar ryanmt avatar smartperson 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

rserve-ruby-client's Issues

how to retrieve the connection number?

Each connection makes a subfolder into which files are placed. For instance, I create a plot and it ends up in "/tmp/Rserv/conn154/". The /tmp/Rserv is the working directory, but the "conn154"? How do I retrieve the connection number (the 154) during a session? [I fiddled around for a while and couldn't figure it out]

Thanks again!

void_eval <<- EOF marca error en Ruby 2.3

Hola Claudio
Tengo una aplicación que desarrollé usando Ruby, Sinatra y R. En Debian Jessie funciona bien, pero en Debian Stretch la instrucción void_eval <<-EOF marca el siguiente error

voidEval failed: Packet[cmd=2130771970,len=, con='', status=error:'Unknown variable/method'(127)]

Imagino que es debido a que Debian Jessie viene con Ruby 1.9 y Debian Stretch trae Ruby 2.3, hay alguna forma de solucionar el error?
Saludos y gracias de antemano

Different behavior betw Linux & Mac (Linux not handling Matrices from R correctly?)

I'm using rserve_client with Rserve to collect forecasted data (generated by R) that is, in turn, delivered to a ruby front-end. It looks like a matrix generated by R, and handed back from Rserve to rserve_client, is not being properly parsed into a ruby object on Linux, whereas it does seem to work correctly on Mac OSX. Feel free to contact me directly if more debugging info is needed: [email protected].

[ common steps ]

values = records.collect{|x| x[:value]}
=> [25.8043299534119, 23.186241697132, 23.5713558113477, 22.2457726908765, 22.3256031419488, 21.3815211663446, 19.7979797979798, 19.0964225395363, 21.0004912395612, 20.4561187600954, 20.6901748040989, 21.016081871345, 20.557236773453, 19.8786867357746, 19.3829564175528, 19.1470133807539, 19.7171551547448, 19.3986337782605, 18.7582137588843, 15.9112717859454, 51.0074791025077, 38.112141758635, 27.6637861308586, 21.4773742144395, 19.1068979031942, 16.4286107266949, 15.0076170083768, 13.3114969321866, 12.7488286691149]
r.assign("values", Rserve::REXP::Double.new(values))
=> #<Rserve::Packet:0x2b9d01cb3080 @cmd=65537, @ConT=nil>
r.eval("valuesy <- ts(values, frequency = 4)")
=> #<Rserve::REXP::Double:0x2b9d01cab740 @payload=[25.8043299534119, 23.186241697132, 23.5713558113477, 22.2457726908765, 22.3256031419488, 21.3815211663446, 19.7979797979798, 19.0964225395363, 21.0004912395612, 20.4561187600954, 20.6901748040989, 21.016081871345, 20.557236773453, 19.8786867357746, 19.3829564175528, 19.1470133807539, 19.7171551547448, 19.3986337782605, 18.7582137588843, 15.9112717859454, 51.0074791025077, 38.112141758635, 27.6637861308586, 21.4773742144395, 19.1068979031942, 16.4286107266949, 15.0076170083768, 13.3114969321866, 12.7488286691149], @attr=#<Rserve::REXP::List:0x2b9d01cac190 @payload=#<Rserve::Rlist:23976669962480 [tsp=#Rserve::REXP::Double:0x2b9d01cac0f0, class=#Rserve::REXP::String:0x2b9d01cab880][2]>, @attr=nil>>
r.eval("xholt<-HoltWinters(valuesy)")
=> #<Rserve::REXP::GenericVector:0x2b9d01c8d948 @payload=#<Rserve::Rlist:23976669899960 [fitted=#Rserve::REXP::Double:0x2b9d01ca09d0, x=#Rserve::REXP::Double:0x2b9d01c941a8, alpha=#Rserve::REXP::Double:0x2b9d01c90670, beta=#Rserve::REXP::Double:0x2b9d01c8ff90, gamma=#Rserve::REXP::Double:0x2b9d01c8f8b0, coefficients=#Rserve::REXP::Double:0x2b9d01c8ef78, seasonal=#Rserve::REXP::String:0x2b9d01c8e230, SSE=#Rserve::REXP::Double:0x2b9d01c8e118, call=#Rserve::REXP::Language:0x2b9d01c8dd30named][9]>, @attr=#<Rserve::REXP::List:0x2b9d01ca2848 @payload=#<Rserve::Rlist:23976669942860 [names=#Rserve::REXP::String:0x2b9d01ca2348, class=#Rserve::REXP::String:0x2b9d01ca20f0][2]>, @attr=nil>>
r.eval("valuesb <- predict(xholt, 12, TRUE, level = 0.95)")
=> #<Rserve::REXP::Double:0x2b9d0230d610 @payload=[12.2338688095476, 11.4640333644427, 10.0622448280341, 10.1027010134071, 9.28732347467274, 8.51748802956789, 7.11569949315929, 7.15615567853229, 6.34077813979789, 5.57094269469304, 4.16915415828444, 4.20961034365744, 27.3081281680487, 29.5883403246365, 30.7926020455859, 33.1462449671325, 34.4321465109807, 35.6010500757098, 36.0081992238366, 37.7508243034277, 38.5477797985542, 39.3133220332505, 39.3800242271577, 40.8301316204914, -2.8403905489535, -6.66027359575106, -10.6681123895176, -12.9408429403182, -15.8574995616353, -18.566074016574, -21.776800237518, -23.4385129463632, -25.8662235189585, -28.1714366438644, -31.0417159105889, -32.4109109331765], @attr=#<Rserve::REXP::List:0x2b9d0230e998 @payload=#<Rserve::Rlist:23976673309940 [dim=#Rserve::REXP::Integer:0x2b9d0230e8f8, dimnames=#Rserve::REXP::GenericVector:0x2b9d0230e1c8, tsp=#Rserve::REXP::Double:0x2b9d0230dfe8, class=#Rserve::REXP::String:0x2b9d0230d750][4]>, @attr=nil>>

[ on Mac - Snow Leopard 10.6.3, R 2.11.1, Rserve 0.6-2, rserve_client 0.2.5 ] This seems correct.

r.eval("valuesb").to_ruby
=> Matrix[[12.2338688095477, 27.3081281680488, -2.84039054895338], [11.4640333644428, 29.5883403246361, -6.66027359575041], [10.0622448280342, 30.7926020455851, -10.6681123895166], [10.1027010134073, 33.1462449671313, -12.9408429403168], [9.28732347467285, 34.4321465109793, -15.8574995616336], [8.51748802956799, 35.6010500757081, -18.5660740165721], [7.11569949315939, 36.0081992238347, -21.7768002375159], [7.1561556785324, 37.7508243034256, -23.4385129463608], [6.340778139798, 38.5477797985519, -25.8662235189559], [5.57094269469314, 39.3133220332479, -28.1714366438616], [4.16915415828454, 39.380024227155, -31.041715910586], [4.20961034365754, 40.8301316204886, -32.4109109331735]]

[ on Linux - Centos 2.6.18-194.11.1.el5, R 2.11.1, Rserve 0.6-2, rserve_client 0.2.5 ]

r.eval("valuesb").to_ruby
LocalJumpError: no block given
from /usr/lib64/ruby/gems/1.8/gems/rserve-client-0.2.5/lib/rserve/rexp.rb:357:in times' from /usr/lib64/ruby/gems/1.8/gems/rserve-client-0.2.5/lib/rserve/rexp.rb:357:insplit_array'
from /usr/lib64/ruby/gems/1.8/gems/rserve-client-0.2.5/lib/rserve/rexp.rb:326:in as_nested_array' from /usr/lib64/ruby/gems/1.8/gems/rserve-client-0.2.5/lib/rserve/rexp.rb:304:inas_double_matrix'
from /usr/lib64/ruby/gems/1.8/gems/rserve-client-0.2.5/lib/rserve/rexp.rb:316:in as_matrix' from /usr/lib64/ruby/gems/1.8/gems/rserve-client-0.2.5/lib/rserve/rexp/double.rb:64:into_ruby_internal'
from /usr/lib64/ruby/gems/1.8/gems/rserve-client-0.2.5/lib/rserve/rexp.rb:394:in `to_ruby'
from (irb):17
from :0
r.eval("valuesb").as_doubles
=> [12.2338688095476, 11.4640333644427, 10.0622448280341, 10.1027010134071, 9.28732347467274, 8.51748802956789, 7.11569949315929, 7.15615567853229, 6.34077813979789, 5.57094269469304, 4.16915415828444, 4.20961034365744, 27.3081281680487, 29.5883403246365, 30.7926020455859, 33.1462449671325, 34.4321465109807, 35.6010500757098, 36.0081992238366, 37.7508243034277, 38.5477797985542, 39.3133220332505, 39.3800242271577, 40.8301316204914, -2.8403905489535, -6.66027359575106, -10.6681123895176, -12.9408429403182, -15.8574995616353, -18.566074016574, -21.776800237518, -23.4385129463632, -25.8662235189585, -28.1714366438644, -31.0417159105889, -32.4109109331765]

Fatal error: you must specify '--save', '--no-save' or '--vanilla'

Hi,

I'm running my deploying my rails app with Heroku using the R buildpack.
Whenever my app creates a connection using Rserve-client it crashes giving the following message:

2014-01-09T12:58:28.290655+00:00 app[web.1]: WARNING: ignoring environment value of R_HOME
2014-01-09T12:58:28.309165+00:00 app[web.1]: Fatal error: you must specify '--save', '--no-save' or '--vanilla'

Do you have any idea how to fix it?

Thanks,
Luis

Error handling NA values on integer matrix

Took me a while to chase this down and come up with a succint reproduction but here it is:

r = Rserve::Connection.new
=> #<Rserve::Connection:0x000000064afa78 @auth_req=false, @transfer_charset="UTF-8", @auth_type=0, @hostname="127.0.0.1", @port_number=6311, @max_tries=5, @cmd_init="R CMD Rserve", @proc_rserve_ok=#<Proc:0x000000064af910@/var/lib/gems/2.1.0/gems/rserve-client-0.3.1/lib/rserve/connection.rb:58 (lambda)>, @session=nil, @tries=0, @connected=true, @s=#<TCPSocket:fd 16>, @rt=#<Rserve::Talk:0x000000064af8c0 @io=#<TCPSocket:fd 16>>, @rsrv_version=103, @protocol="QAP1", @last_error="OK">

r.eval('m<-matrix(as.integer(c(1, NA, NA, 4)), ncol=2)')
=> #<Rserve::REXP::Integer:0x0000000649c298 @payload=[1, -2147483648, -2147483648, 4], @attr=#<Rserve::REXP::List:0x0000000649c9a0 @payload=#<Rserve::Rlist:52750520 [dim=#<Rserve::REXP::Integer:0x0000000649cba8>][1]>, @attr=nil>>

r.eval('m').to_ruby
=> Matrix[[1.0, -2147483648.0], [-2147483648.0, 4.0]]

Fixnum is deprecated

Using Ruby 2.5:

/var/lib/gems/2.5.0/gems/rserve-client-0.3.5/lib/rserve/rexp/wrapper.rb:26: warning: constant ::Fixnum is deprecated
/var/lib/gems/2.5.0/gems/rserve-client-0.3.5/lib/rserve/rexp/wrapper.rb:56: warning: constant ::Fixnum is deprecated

Hi Claudio

I'm working on the code,
hope to have improved it.
~eike

what's new?

  • refactored eval, void_eval etc
  • the eval methods now take a args:hash as an optional argument
  • those args are assigned before executing the cmd
  • add geterrmessage() to the exception message
  • add ".r" method (experimental) (inspired by the py client)

I'm not yet really satisfied with that.
I'd like to call R like a rpc.

~eike

Using ggplot

I try to use rserve-ruby-client but I got a probleme with ggplot that don't display.

I first try this:
r.eval("ggplot(df, aes(x=size,y=mem)))")
and then that:
r.eval("print(ggplot2::qplot(df, aes(x=size,y=mem)))")
that give me the error
Error in unit(at, "native") : 'x' and 'units' must have length > 0

Return error messages from R?

Is it possible to get the "real" error message from R? No matter what kind of error that occurs, I get the same exception from Rserve. Here is an example:

con.eval('summary(some_undefined_object)')
#=> Rserve::Connection::EvalError: eval failed: Packet[cmd=2130771970,len=<nil>, con='<nil>', status=error:'Unknown variable/method'(127)]

Where the actual error message when evaluated in R is:

> summary(some_unknown_var)
Error in summary(some_unknown_var) : object 'some_unknown_var' not found

Rserve::Connection::EvalError: eval failed

Hello,
Recently i discovered that my application had an error when doing an evaluation and i succeed to reproduce it easily with:
irb
irb(main):001:0> require 'rserve'
=> true
irb(main):002:0> con=Rserve::Connection.new
=> #<Rserve::Connection:0x0000560de8c59b20 @auth_req=false, @transfer_charset="UTF-8", @auth_type=0, @hostname="127.0.0.1", @port_number=6311, @max_tries=5, @cmd_init="R CMD Rserve", @proc_rserve_ok=#<Proc:0x0000560de8c599e0@/usr/local/share/gems/gems/rserve-client-0.3.5/lib/rserve/connection.rb:61 (lambda)>, @username=nil, @password=nil, @session=nil, @tries=0, @connected=true, @s=#<TCPSocket:fd 9>, @rt=#<Rserve::Talk:0x0000560de8c59968 @io=#<TCPSocket:fd 9>>, @rsrv_version=103, @protocol="QAP1", @last_error="OK">
irb(main):003:0> x=con.eval('x<-rnorm(1)')
Rserve::Connection::EvalError: eval failed:
from /usr/local/share/gems/gems/rserve-client-0.3.5/lib/rserve/connection.rb:212:in eval' from (irb):3 from /usr/bin/irb:11:in

'

I am using rserve-client 0.3.5, ruby 2.4.4 and R 3.5.0 on fedora 27.
I don't know precisely when this problem appeared but only recently (less than 2 weeks) as i test my application frequently.
Have an idea of what happens?

more options on Rserve startup

First, the Rserve ruby client is outstanding. Thanks for all the work you put into this gem.

  1. I would like to be able to start Rserve in a quiet mode (something like: " 2>&1 >/dev/null"), but the commands to start Rserve ("R CMD Rserve") and kill Rserve ("killall -s 0 Rserve") during initialization are fixed and unaccessible in the initialize method. A :quiet option would probably be cleanest, but access to the actual commands would work too. Something like: :rserve_cmd => "R CMD Rserve", :killall_rserve => "killall -s 0 Rserve".
  2. I would like to be able to change the working directory to my current working directory (or another directory of my choosing). This could be an option or, if the Rserve startup command was accessible, a person could set it with something like: "R CMD Rserve --RS-workdir #{Dir.pwd}".

Thanks Claudio

How do you use a config file to preload packages?

I'm trying to use a json package in R and I've tried googling for loading the package from Rserve. The best thing I can figure out is that I can preload it with a config file for Rserve. Unfortunately I can't find any examples. Do you know how I might set that up? Thx!

Using mlogit library

Thanks for a great gem. I'm trying use the mlogit package from my rails application and I was hoping you could point me to some documentation or examples that might help me use the mlogit package.

Rserve: Socket locked?

Hi @clbustos, first thanks for this ruby gem!

Now I'm facing a weird problem, I'm newbie in Rserve, but sometimes (randomly) I get processes locked and the logs show me this:

app_folder/shared/bundle/ruby/2.1.0/gems/rserve-client-0.3.1/lib/rserve/talk.rb:91:in recv'
app_folder/shared/bundle/ruby/2.1.0/gems/rserve-client-0.3.1/lib/rserve/talk.rb:91:in request' app_folder/shared/bundle/ruby/2.1.0/gems/rserve-client-0.3.1/lib/rserve/connection.rb:199:in eval'`

other times show me this:

app_folder/shared/bundle/ruby/2.1.0/gems/rserve-client-0.3.1/lib/rserve/talk.rb:72:in recv'
app_folder/shared/bundle/ruby/2.1.0/gems/rserve-client-0.3.1/lib/rserve/talk.rb:72:in request' app_folder/shared/bundle/ruby/2.1.0/gems/rserve-client-0.3.1/lib/rserve/connection.rb:199:in eval'`

Both in the recv call of the socket. Have you faced this problem before? maybe you could give some useful information. What about implementing a socket timeout?

Thanks

Using Rserve::Connection.new(:hostname => "HOST") fails

Using a hostname of anything other than "localhost", the Rserve::Connection.new fails to connect to Rserve, as shown here:

require 'rserve'

c = Rserve::Connection.new(:hostname => "myhostname")
Rserve::Connection::IncorrectServerError: Handshake failed: Rsrv signature expected, but received []
from /path/path/gem/gems/rserve-client-0.3.0/lib/rserve/connection.rb:110:in connect' from /path/path/gem/gems/rserve-client-0.3.0/lib/rserve/connection.rb:68:ininitialize'

It works if you do:

c = Rserve::Connection.new(:hostname => "localhost")

Note that localhost === the same host as myhostname, and it does not matter if you use the fully qualified dns host name or not.

tcp connections are not being closed on server side

I use conn.close() for closing the connection between ruby and Rserve, but if I check the processes runing in my Rserve instance, the processes are not being closed and when multiple users open connections to load some charts with R, the instance get many processes and it crashes.
iamge

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.