com-lihaoyi / ammonite Goto Github PK
View Code? Open in Web Editor NEWScala Scripting
Home Page: http://ammonite.io
License: MIT License
Scala Scripting
Home Page: http://ammonite.io
License: MIT License
@lihaoyi tks for the awesome ammonite-repl! I am very excited to use it
There is one feature that I do miss. In the regular scala repl, i can hit after a complete method name to see a method signature(s)
for example
scala> foo.replace<TAB>
def replace(Char, Char): String def replace(CharSequence, CharSequence): String
it would be sweet to get the same kind of behavior in ammonite-repl
Apparently code directly inside an object Foo{ ... }
block doesn't get JITed, and the commands that you enter into Ammonite all are run that way. This seems to result in a 10x slowdown in the rare-ish case you're doing intensive work directly in that block.
@ (() => {val start = System.currentTimeMillis(); var i = 1L; while(i < 1000000000L) i += (i % 2) + 1; System.currentTimeMillis() - start})()
res13: Long = 1065L
@ {val start = System.currentTimeMillis(); var i = 1L; while(i < 1000000000L) i += (i % 2) + 1; System.currentTimeMillis() - start}
res14: Long = 11464L
A solution would be to lift all var
/val
/lazy val
/<expr>
statements automatically into (() => ...)()
in the Preprocessor
.
Eventually this makes the process die with a too-many-open-files error
Opening lots of files seems to cause IOException: Too many open files
. We're probably not closing things properly.
Example: https://github.com/seratch/AWScala#amazon-elastic-compute-cloud-amazon-ec2
Loading Ammonite Repl...
@ load.ivy("com.github.seratch" %% "awscala" % "0.3.+")
:: loading settings :: url = jar:file:/Users/haoyi/.ivy2/cache/org.apache.ivy/ivy/jars/ivy-2.4.0.jar!/org/apache/ivy/core/settings/ivysettings.xml
:: resolving dependencies :: com.github.seratch#awscala_2.11-caller;working
confs: [default]
found com.github.seratch#awscala_2.11;0.3.2 in central
[0.3.2] com.github.seratch#awscala_2.11;0.3.+
found org.scala-lang#scala-library;2.11.2 in central
[2.11.2] org.scala-lang#scala-library;2.11.2
found com.amazonaws#aws-java-sdk;1.8.11 in central
found com.amazonaws#aws-java-sdk-core;1.8.11 in central
found commons-logging#commons-logging;1.1.1 in central
found org.apache.httpcomponents#httpclient;4.2 in central
found org.apache.httpcomponents#httpcore;4.2 in central
found commons-codec#commons-codec;1.6 in central
found com.fasterxml.jackson.core#jackson-core;2.1.1 in central
found com.fasterxml.jackson.core#jackson-databind;2.1.1 in central
found com.fasterxml.jackson.core#jackson-annotations;2.1.1 in central
found joda-time#joda-time;2.5 in central
found org.joda#joda-convert;1.7 in central
found com.decodified#scala-ssh_2.11;0.7.0 in central
found net.schmizz#sshj;0.10.0 in central
found org.slf4j#slf4j-api;1.7.7 in central
found org.bouncycastle#bcpkix-jdk15on;1.50 in central
found org.bouncycastle#bcprov-jdk15on;1.50 in central
found org.bouncycastle#bcprov-jdk16;1.46 in central
found com.jcraft#jzlib;1.1.3 in central
res0: Unit = ()
@ awscala.Region
res1: awscala.Region.type = awscala.Region$@4d662a90
@ awscala.Region
Compilation Failed
Main.scala:25: inferred type arguments [awscala.Region.type] do not conform to method shellPPrint's type parameter bounds [T]
def $main() = {Iterator(ReplBridge.shell.shellPPrint(res2, "res2")) ++ Iterator(" = ") ++ ammonite.pprint.PPrint(res2)}
^
Main.scala:25: type mismatch;
found : awscala.Region.type
required: T
def $main() = {Iterator(ReplBridge.shell.shellPPrint(res2, "res2")) ++ Iterator(" = ") ++ ammonite.pprint.PPrint(res2)}
^
Main.scala:25: inferred type arguments [awscala.Region.type] do not conform to method apply's type parameter bounds [T]
def $main() = {Iterator(ReplBridge.shell.shellPPrint(res2, "res2")) ++ Iterator(" = ") ++ ammonite.pprint.PPrint(res2)}
^
Main.scala:25: type mismatch;
found : awscala.Region.type
required: T
def $main() = {Iterator(ReplBridge.shell.shellPPrint(res2, "res2")) ++ Iterator(" = ") ++ ammonite.pprint.PPrint(res2)}
^
@
A typical completion presentation. The docs say "you get the same autocomplete-anywhere support that you get in a modern IDE." I haven't checked lately but I bet the modern IDE alphabetizes.
## asInstanceOf isInstanceOf toString hashCode equals
!= == size isEmpty elemAt foreach
getClass foreachSlice viewOps mapIndices foreachIntIndex foreachIndex
containsIndex lastNth lastIndex lastIntIndex nths indices
isPositive isZero intSize longSize byShow byRef
byEquals partition span splitAt join directlySlice
linearlySlice build force withFilter takeWhile takeRight
take map flatMap dropWhile dropRight drop
collect ++ :| |: xs toEach
foldFrom fold foldr foldl foldWithIndex groupBy
clusterBy dropIndex takeToFirst ofClass zipView zipIndex
zip withSize tail sliceWhile slice mapZip
mapWithIndex mapApply labelOp init grep gatherClass
gather filterNot filter sortBy sortDistinct sorted
min max zfoldr zfoldl zfirst toRefs
tabular nonEmpty mk_s mkString last indicesWhere
indexWhere head forallTrue forall first find
exists count foreachReverse foreachWithIndex synchronized ne
eq wait notifyAll notify any_s try_s
matchOr requiring optionally same fix id_##
id_== |> sideEffect isOr doto reflect
isNull toRef castTo isClass shortPackage shortClass
x __shown_rep
"It is much more featureful than the default REPL ... Ammonite-REPL supports many more features than the default REPL"
I propose that delivering feature parity - and working at all - should take place before making grandiose claims of this kind. I might be unusually conservative in that regard. Here's some completion from the scala repl:
scala> List(1)
res0: List[Int] = List(1)
scala> res0.map<tab>
map mapConserve
scala> res0.map<tab> // it elaborates
def map[B, That](f: A => B)(implicit bf: generic.CanBuildFrom[List[A],B,That]): That
scala> java.lang.String.valueOf<tab>
def valueOf(Boolean): String def valueOf(Int): String
def valueOf(Any): String def valueOf(Char): String def valueOf(Long): String
def valueOf(Array[Char]): String def valueOf(Double): String
def valueOf(Array[Char], Int, Int): String def valueOf(Float): String
Ammonite offers the method name, that's it.
The signature the repl gives for map is wrong (it's a List[Int] so the A should have been substituted to Int) so there's an opportunity for you to actually improve on it. You only hurt your credibility with the glib claims, and frankly there's plenty of room for humility when you only got imports sort of working a few hours ago.
Even your chosen example output has issues. It suggests "scala.concurrent.Future$class" and then acts like it has never heard of it.
@ scala.concurrent.Future<tab>
Future FutureTaskRunner
@ val f: Int -> String = 5 -> ""
f: psp.std.->[psp.std.Int,psp.std.String] = 5 ->
@
Scala choose a pathologically awful way to print the type Int -> String
. That issue goes back forever. You could print them sensibly, with the operator infix.
It will be convenient for me to import a bunch of stuff in the ammonite REPL, but "initialCommand in console" is ignored inside the ammonite REPL. It would help to have this work or some replacement.
These cases do the wrong thing
@ new St<tab>
@ import java.<tab>Display all 660 possibilities? (y or n)
Would be nice if they worked
@ Array(1,2,3)
res6: scala.Array[Int] = Array(1, 2, 3)
@ res6.
!= ## == apply asInstanceOf clone
eq equals getClass hashCode isInstanceOf length
ne notify notifyAll synchronized toString update
wait
We should get .reduce
and all the other extension-methods as well
I definitely wanted to try Ammonite REPL
out, it looks really promising. I wanted to play a little bit with Scalaz
as well:
@ load.ivy("org.scalaz" %% "scalaz-core" % "7.1.1")
@ import scalaz._
@ import Scalaz._
After that, whatever expression I write, throws a bunch of errors:
java.lang.StackOverflowError
scala.tools.nsc.typechecker.Contexts$Context.collect$1(Contexts.scala:818)
scala.tools.nsc.typechecker.Contexts$Context.collect$1(Contexts.scala:824)
scala.tools.nsc.typechecker.Contexts$Context.collect$1(Contexts.scala:824)
...
Something unexpected went wrong =(
Otherwise we pollute the String#
and Symbol#
namespace with all sorts of things we don't want in general, which interferes with pollution provided by others (e.g. uTest also provides a String#-
operator).
This will mean you'll have to write relative paths as rel/'path/'segments
rather than 'path/'segments
, but that's maybe OK
This would be much nicer than doing (p2 - p1).ups > 0
, which is what you have to do now
I was trying to get this to work, but it seems there is an ammonite jar in maven, but no ammonite-core, and depending on the ammonite jar doesn't seem to work,
This is with deafdc7, commit of 45 minutes ago.
@ import psp._, std._, api._, StdShow._, StdEq._
@
As opposed to
@ import psp._
import psp._
@
Good news is this works in initial test:
@ implicit def someShow[A](implicit z: Show[A]) = ammonite.pprint.PPrinter[A]((t, c) => Iterator(z show c))
defined function someShow
@ Direct(1, 2, 3)
res6: psp.api.Direct[Int] = [ 1, 2, 3 ]
@
@ val x = 9
x: Int = 9
@
class A {
val xxxx = 0
def foo = xxxx
}
defined class A
@ //Now hitting up twice
class A {
val xxxx = 0
def foo = xxxx
} val x = 9
Power REPL mode is very handy for compiler writers (small number of folks) but also for macro writers that want to poke around.
We would need some equivalent or preferably direct port of :power
command.
Would give us hashcode/equality for free, and other nice things
Seems to pop up the first time you download things from the internet. We're probably doing something wrong but I don't know what
Loading Ammonite Repl...
@ load.ivy("com.github.seratch" %% "awscala" % "0.5.2")
:: loading settings :: url = jar:file:/Users/haoyi/.ivy2/cache/org.apache.ivy/ivy/jars/ivy-2.4.0.jar!/org/apache/ivy/core/settings/ivysettings.xml
:: resolving dependencies :: com.github.seratch#awscala_2.11-caller;working
confs: [default]
found com.github.seratch#awscala_2.11;0.5.2 in central
found org.scala-lang#scala-library;2.11.6 in central
[2.11.6] org.scala-lang#scala-library;2.11.6
found com.amazonaws#aws-java-sdk-iam;1.9.31 in central
found com.amazonaws#aws-java-sdk-core;1.9.31 in central
found commons-logging#commons-logging;1.1.3 in central
found org.apache.httpcomponents#httpclient;4.3.4 in central
found org.apache.httpcomponents#httpcore;4.3.2 in central
found commons-codec#commons-codec;1.6 in central
found com.fasterxml.jackson.core#jackson-databind;2.3.2 in central
found com.fasterxml.jackson.core#jackson-annotations;2.3.0 in central
found com.fasterxml.jackson.core#jackson-core;2.3.2 in central
found com.amazonaws#aws-java-sdk-sts;1.9.31 in central
found com.amazonaws#aws-java-sdk-ec2;1.9.31 in central
found com.amazonaws#aws-java-sdk-s3;1.9.31 in central
found com.amazonaws#aws-java-sdk-kms;1.9.31 in central
found com.amazonaws#aws-java-sdk-sqs;1.9.31 in central
found com.amazonaws#aws-java-sdk-emr;1.9.31 in central
found com.amazonaws#aws-java-sdk-redshift;1.9.31 in central
found com.amazonaws#aws-java-sdk-dynamodb;1.9.31 in central
found com.amazonaws#aws-java-sdk-simpledb;1.9.31 in central
found joda-time#joda-time;2.7 in central
found org.joda#joda-convert;1.7 in central
found com.decodified#scala-ssh_2.11;0.7.0 in central
found net.schmizz#sshj;0.10.0 in central
found org.slf4j#slf4j-api;1.7.7 in central
found org.bouncycastle#bcpkix-jdk15on;1.50 in central
found org.bouncycastle#bcprov-jdk15on;1.50 in central
found org.bouncycastle#bcprov-jdk16;1.46 in central
found com.jcraft#jzlib;1.1.3 in central
downloading http://repo1.maven.org/maven2/com/github/seratch/awscala_2.11/0.5.2/awscala_2.11-0.5.2.jar ...
[SUCCESSFUL ] com.github.seratch#awscala_2.11;0.5.2!awscala_2.11.jar (579ms)
downloading http://repo1.maven.org/maven2/com/github/seratch/awscala_2.11/0.5.2/awscala_2.11-0.5.2-sources.jar ...
[SUCCESSFUL ] com.github.seratch#awscala_2.11;0.5.2!awscala_2.11.jar(source) (103ms)
downloading http://repo1.maven.org/maven2/com/github/seratch/awscala_2.11/0.5.2/awscala_2.11-0.5.2-javadoc.jar ...
[SUCCESSFUL ] com.github.seratch#awscala_2.11;0.5.2!awscala_2.11.jar(javadoc) (525ms)
downloading http://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-iam/1.9.31/aws-java-sdk-iam-1.9.31.jar ...
[SUCCESSFUL ] com.amazonaws#aws-java-sdk-iam;1.9.31!aws-java-sdk-iam.jar (267ms)
downloading http://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-sts/1.9.31/aws-java-sdk-sts-1.9.31.jar ...
[SUCCESSFUL ] com.amazonaws#aws-java-sdk-sts;1.9.31!aws-java-sdk-sts.jar (35ms)
downloading http://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-ec2/1.9.31/aws-java-sdk-ec2-1.9.31.jar ...
[SUCCESSFUL ] com.amazonaws#aws-java-sdk-ec2;1.9.31!aws-java-sdk-ec2.jar (509ms)
downloading http://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-s3/1.9.31/aws-java-sdk-s3-1.9.31.jar ...
[SUCCESSFUL ] com.amazonaws#aws-java-sdk-s3;1.9.31!aws-java-sdk-s3.jar (205ms)
downloading http://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-sqs/1.9.31/aws-java-sdk-sqs-1.9.31.jar ...
[SUCCESSFUL ] com.amazonaws#aws-java-sdk-sqs;1.9.31!aws-java-sdk-sqs.jar (367ms)
downloading http://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-emr/1.9.31/aws-java-sdk-emr-1.9.31.jar ...
[SUCCESSFUL ] com.amazonaws#aws-java-sdk-emr;1.9.31!aws-java-sdk-emr.jar (359ms)
downloading http://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-redshift/1.9.31/aws-java-sdk-redshift-1.9.31.jar ...
[SUCCESSFUL ] com.amazonaws#aws-java-sdk-redshift;1.9.31!aws-java-sdk-redshift.jar (426ms)
downloading http://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-dynamodb/1.9.31/aws-java-sdk-dynamodb-1.9.31.jar ...
[SUCCESSFUL ] com.amazonaws#aws-java-sdk-dynamodb;1.9.31!aws-java-sdk-dynamodb.jar (328ms)
downloading http://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-simpledb/1.9.31/aws-java-sdk-simpledb-1.9.31.jar ...
[SUCCESSFUL ] com.amazonaws#aws-java-sdk-simpledb;1.9.31!aws-java-sdk-simpledb.jar (52ms)
downloading http://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-core/1.9.31/aws-java-sdk-core-1.9.31.jar ...
[SUCCESSFUL ] com.amazonaws#aws-java-sdk-core;1.9.31!aws-java-sdk-core.jar (140ms)
downloading http://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-kms/1.9.31/aws-java-sdk-kms-1.9.31.jar ...
[SUCCESSFUL ] com.amazonaws#aws-java-sdk-kms;1.9.31!aws-java-sdk-kms.jar (75ms)
:: problems summary ::
:::: ERRORS
unknown resolver sbt-chain
unknown resolver null
unknown resolver sbt-chain
unknown resolver null
unknown resolver sbt-chain
unknown resolver null
unknown resolver sbt-chain
unknown resolver null
unknown resolver sbt-chain
unknown resolver null
unknown resolver sbt-chain
unknown resolver null
unknown resolver sbt-chain
unknown resolver null
unknown resolver sbt-chain
unknown resolver null
:: USE VERBOSE OR DEBUG MESSAGE LEVEL FOR MORE DETAILS
res0: Unit = ()
@
// build.sbt
name := "test-repl"
version := "1.0"
scalaVersion := "2.11.5"
libraryDependencies += "com.lihaoyi" %% "ammonite" % "0.1.6"
libraryDependencies += "com.lihaoyi" %% "ammonite-repl" % "0.1.6"
initialCommands in console := "ammonite.repl.Repl.main(null)"
#Command Line
jon$ sbt console
[info] Loading project definition from /Users/jon/code/test-repl/project
[info] Set current project to test-repl (in build file:/Users/jon/code/test-repl/)
[info] Starting scala interpreter...
[info]
java.lang.AbstractMethodError
at scala.tools.nsc.backend.JavaPlatform$class.$init$(JavaPlatform.scala:22)
at ammonite.repl.interp.Compiler$$anon$1$$anon$6.<init>(Compiler.scala:70)
at ammonite.repl.interp.Compiler$$anon$1.platform$lzycompute(Compiler.scala:70)
at ammonite.repl.interp.Compiler$$anon$1.platform(Compiler.scala:70)
at scala.tools.nsc.interactive.Global$$anon$8.<init>(Global.scala:401)
at scala.tools.nsc.interactive.Global.loaders$lzycompute(Global.scala:399)
at scala.tools.nsc.interactive.Global.loaders(Global.scala:399)
at scala.tools.nsc.Global$GlobalMirror.rootLoader(Global.scala:65)
at scala.reflect.internal.Mirrors$Roots$RootClass.<init>(Mirrors.scala:307)
at scala.reflect.internal.Mirrors$Roots.RootClass$lzycompute(Mirrors.scala:321)
at scala.reflect.internal.Mirrors$Roots.RootClass(Mirrors.scala:321)
at scala.reflect.internal.Mirrors$Roots$EmptyPackageClass.<init>(Mirrors.scala:330)
at scala.reflect.internal.Mirrors$Roots.EmptyPackageClass$lzycompute(Mirrors.scala:336)
at scala.reflect.internal.Mirrors$Roots.EmptyPackageClass(Mirrors.scala:336)
at scala.reflect.internal.Mirrors$Roots.EmptyPackageClass(Mirrors.scala:276)
at scala.reflect.internal.Mirrors$RootsBase.init(Mirrors.scala:250)
at scala.tools.nsc.Global.rootMirror$lzycompute(Global.scala:74)
at scala.tools.nsc.Global.rootMirror(Global.scala:72)
at scala.tools.nsc.Global.rootMirror(Global.scala:40)
at scala.reflect.internal.Definitions$DefinitionsClass.ObjectClass$lzycompute(Definitions.scala:257)
at scala.reflect.internal.Definitions$DefinitionsClass.ObjectClass(Definitions.scala:257)
at scala.reflect.internal.Definitions$DefinitionsClass.init(Definitions.scala:1391)
at scala.tools.nsc.Global$Run.<init>(Global.scala:1216)
at scala.tools.nsc.interactive.Global$TyperRun.<init>(Global.scala:1208)
at scala.tools.nsc.interactive.Global.newTyperRun(Global.scala:1231)
at scala.tools.nsc.interactive.Global.<init>(Global.scala:297)
at ammonite.repl.interp.Compiler$$anon$1.<init>(Compiler.scala:68)
at ammonite.repl.interp.Compiler.<init>(Compiler.scala:68)
at ammonite.repl.interp.Interpreter.init(Interpreter.scala:23)
at ammonite.repl.interp.Interpreter.<init>(Interpreter.scala:55)
at ammonite.repl.Repl.<init>(Repl.scala:11)
at ammonite.repl.Repl$.main(Repl.scala:73)
... 39 elided
Welcome to Scala version 2.11.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala>
Hi,
I try to use Ammonite with conscript cs command tool (https://github.com/n8han/conscript) to run scala script as SBT manual say ( http://www.scala-sbt.org/0.13/docs/Combined+Pages.html )
#!/usr/bin/env scalas
/***
scalaVersion := "2.11.5"
resolvers += Resolver.url("Sonatype OSS Snapshots",url("https://oss.sonatype.org/content/repositories/snapshots"))(Resolver.ivyStylePatterns)
libraryDependencies += "com.lihaoyi" %% "ammonite" % "0.1.4"
*/
import ammonite.all._
val wd = processWorkingDir
ls! wd
I have this error :
[info] Loading global plugins from /home/srey/.sbt/0.13/plugins
[info] Set current project to root-68794879dd0af3f5dec3 (in build file:/home/srey/.conscript/boot/68794879dd0af3f5dec3/)
[error] (run-main-0) java.lang.NoSuchMethodError: java.nio.file.Files.list(Ljava/nio/file/Path;)Ljava/util/stream/Stream;
java.lang.NoSuchMethodError: java.nio.file.Files.list(Ljava/nio/file/Path;)Ljava/util/stream/Stream;
at ammonite.ops.ls$.apply(Ops.scala:173)
at ammonite.ops.ls$.apply(Ops.scala:170)
at ammonite.ops.Op1$class.$bang(Ops.scala:79)
at ammonite.ops.ls$.$bang(Ops.scala:170)
at convert_svg$$anon$1.<init>(convert_svg.scala:15)
at convert_svg$.main(convert_svg.scala:2)
at convert_svg.main(convert_svg.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
[trace] Stack trace suppressed: run last compile:run for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last compile:run for the full output.
[error] (compile:run) Nonzero exit code: 1
@ class A {def t: Int = {println("getter"); -282}; def t_=(p: Int) { println("setter") }; def m(v: String) = new A}
defined class A
@ val a = new A
a: cmd19.A = cmd19$A@4641e3dd
@ a m "txt" t = 18; println("x")
java.util.NoSuchElementException: Either.left.value on Right
scala.util.Either$LeftProjection.get(Either.scala:289)
ammonite.repl.interp.Preprocessor$$anon$2.apply(Preprocessor.scala:91)
ammonite.repl.interp.Interpreter$$anonfun$processLine$2.apply(Interpreter.scala:36)
ammonite.repl.interp.Interpreter$$anonfun$processLine$2.apply(Interpreter.scala:32)
ammonite.repl.Catching.flatMap(Util.scala:73)
ammonite.repl.interp.Interpreter.processLine(Interpreter.scala:32)
ammonite.repl.Repl$$anonfun$action$1$$anonfun$apply$4.apply(Repl.scala:44)
ammonite.repl.Repl$$anonfun$action$1$$anonfun$apply$4.apply(Repl.scala:43)
ammonite.repl.frontend.Scoped$$anonfun$flatMap$1.apply(Signaller.scala:43)
ammonite.repl.frontend.Signaller.apply(Signaller.scala:28)
ammonite.repl.frontend.Scoped$class.flatMap(Signaller.scala:43)
ammonite.repl.frontend.Signaller.flatMap(Signaller.scala:10)
ammonite.repl.Repl$$anonfun$action$1.apply(Repl.scala:43)
ammonite.repl.Repl$$anonfun$action$1.apply(Repl.scala:42)
ammonite.repl.Res$Success.flatMap(Util.scala:22)
ammonite.repl.Repl.action(Repl.scala:42)
ammonite.repl.Repl.loop$1(Repl.scala:53)
ammonite.repl.Repl.run(Repl.scala:56)
ammonite.repl.Repl$.main(Repl.scala:80)
$line1.$read$$iw$$iw$.<init>(<console>:8)
$line1.$read$$iw$$iw$.<clinit>(<console>)
$line1.$eval$.$print$lzycompute(<console>:7)
$line1.$eval$.$print(<console>:6)
$line1.$eval.$print(<console>)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:483)
scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:755)
scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:1002)
scala.tools.nsc.interpreter.IMain$WrappedRequest$$anonfun$loadAndRunReq$1.apply(IMain.scala:609)
scala.tools.nsc.interpreter.IMain$WrappedRequest$$anonfun$loadAndRunReq$1.apply(IMain.scala:608)
scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
scala.reflect.internal.util.AbstractFileClassLoader.asContext(AbstractFileClassLoader.scala:19)
scala.tools.nsc.interpreter.IMain$WrappedRequest.loadAndRunReq(IMain.scala:608)
scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:540)
scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:536)
xsbt.ConsoleInterface$$anon$2.createInterpreter(ConsoleInterface.scala:54)
scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:852)
scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:850)
scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:850)
scala.reflect.internal.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:97)
scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:850)
scala.tools.nsc.interpreter.ILoop.main(ILoop.scala:872)
xsbt.ConsoleInterface.run(ConsoleInterface.scala:62)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:483)
sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:101)
sbt.compiler.AnalyzingCompiler.console(AnalyzingCompiler.scala:76)
sbt.Console.sbt$Console$$console0$1(Console.scala:22)
sbt.Console$$anonfun$apply$2$$anonfun$apply$1.apply$mcV$sp(Console.scala:23)
sbt.Console$$anonfun$apply$2$$anonfun$apply$1.apply(Console.scala:23)
sbt.Console$$anonfun$apply$2$$anonfun$apply$1.apply(Console.scala:23)
sbt.Logger$$anon$4.apply(Logger.scala:85)
sbt.TrapExit$App.run(TrapExit.scala:248)
java.lang.Thread.run(Thread.java:745)
Something unexpected went wrong =(
When I run Ammonite on Windows, I got this exception:
Caused by: java.lang.IllegalArgumentException: requirement failed: Absolute Paths must start with /
at scala.Predef$.require(Predef.scala:219)
at ammonite.ops.Path$.apply(Path.scala:202)
at ammonite.Bundle$class.$init$(Bundles.scala:37)
at ammonite.all$.<init>(Bundles.scala:11)
at ammonite.all$.<clinit>(Bundles.scala)
Mainly because of this
val home = Path(System.getProperty("user.home"))
System.getProperty("user.home")
returns something like c:\Users\pocorall
in Windows.
Here's what the scala repl does if you start it with -Yno-imports:
scala -Yno-imports
Welcome to Scala version 2.11.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_40).
Type in expressions to have them evaluated.
Type :help for more information.
scala> <console>:6: error: not found: type Any
def set(x: Any) = value = x.asInstanceOf[scala.tools.nsc.interpreter.IMain]
^
It flounders even harder in sbt. There's no way to fix it without hacking the repl.
This leaves me with hundreds and hundreds of identifiers in scope in the psp-std repl which I don't want.
If you can get me to a repl where I only have my own identifiers I would undoubtedly abandon the scala repl. It would be a start to expose Settings somehow, as right now I see no way at it. If you're advertising "null" as the argument to main clearly you're not getting a lot of mileage out of the arguments. How about
ammonite.repl.Repl.main(Array("-Yno-predef", "-Yno-imports"))
Speaking of too many identifiers,
Loading Ammonite Repl...
@ <tab> Display all 678 possibilities? (y or n)
Does that really seem like an improvement to you? There's a reason the scala repl doesn't blast every identifier it has ever seen at you in response to a tab. But it's especially bad for me, because in my source base none of those 678 offerings should be in scope except the tiny subset which I have aliased into one of my packages.
Try Stream.iterate(1)(_+1)
. The repl tries to fully realize the stream leading to infinite output. Not sure what's better, Scala REPL's no-info or ammonite's non-termination. Preview of just a few values would be nice.
REPL session with Ammonite 0.2.7:
@ object ODef { case class Foo(i: Int, s: String) }
defined object ODef
@ ODef.Foo(2, "ba") // Nested in object, succeeds
res1: cmd0.ODef.Foo = Foo(2, "ba")
@ class CDef { case class Foo(i: Int, s: String) }
defined class CDef
@ object CDef extends CDef
defined object CDef
@ CDef.Foo(2, "ba") // Nested in class implemented by object, fails
Compilation Failed
Main.scala:26: could not find implicit value for evidence parameter of type ammonite.pprint.PPrint[cmd3.CDef.Foo]
def $main() = {Iterator(ReplBridge.shell.shellPPrint(res4, "res4")) ++ Iterator(" = ") ++ ammonite.pprint.PPrint(res4)}
^
This can be reproduced out of the Ammonite REPL, see https://gist.github.com/alexarchambault/90f79a160eca9a9e6932.
Note that contrary to Ammonite macros, shapeless Generic
succeeds in these two cases (in the gist too).
We need an easier way to search through a big list of things fuzzily, e.g. using their toString or Repr, in cases where you don't really know what you want or what shape the data-structure is. Something like
implicit object GreppableString extends Greppable[String]
implicit object GreppableRegex extends Greppable[String]
def grep[T: Repr, V: Greppable](pat: V)(thing: T) = if (implicitly[Greppable[V]].grep(pat.PPrint(thing))) Some(thing) else None
It seems like a bug in RangePositions slicing them at the wrong spots. Probably not going to bother fixing.
@ <dependency>
<groupId>com.lihaoyi</groupId>
<artifactId>scalatags_2.11</artifactId>
<version>0.4.5</version>
</dependency>
Compilation Failed
Main.scala:10: in XML literal: name expected, but char '/' cannot start a name
</dependency>)
^
Main.scala:10: in XML literal: '=' expected instead of '>'
</dependency>)
^
Main.scala:10: in XML literal: ' or " delimited attribute value or '{' scala-expr '}' expected
</dependency>)
^
Main.scala:11: in XML literal: '=' expected instead of '$'
def $main() = {Iterator(ReplBridge.shell.shellPPrint(`res1`, "res1")) ++ Iterator(" = ") ++ ammonite.pprint.PPrint(`res1`)}
^
Main.scala:11: in XML literal: ' or " delimited attribute value or '{' scala-expr '}' expected
def $main() = {Iterator(ReplBridge.shell.shellPPrint(`res1`, "res1")) ++ Iterator(" = ") ++ ammonite.pprint.PPrint(`res1`)}
^
Main.scala:11: in XML literal: whitespace expected
def $main() = {Iterator(ReplBridge.shell.shellPPrint(`res1`, "res1")) ++ Iterator(" = ") ++ ammonite.pprint.PPrint(`res1`)}
^
Main.scala:11: in XML literal: '=' expected instead of '('
def $main() = {Iterator(ReplBridge.shell.shellPPrint(`res1`, "res1")) ++ Iterator(" = ") ++ ammonite.pprint.PPrint(`res1`)}
^
Main.scala:11: in XML literal: ' or " delimited attribute value or '{' scala-expr '}' expected
def $main() = {Iterator(ReplBridge.shell.shellPPrint(`res1`, "res1")) ++ Iterator(" = ") ++ ammonite.pprint.PPrint(`res1`)}
^
Main.scala:11: in XML literal: '>' expected instead of '='
def $main() = {Iterator(ReplBridge.shell.shellPPrint(`res1`, "res1")) ++ Iterator(" = ") ++ ammonite.pprint.PPrint(`res1`)}
^
Main.scala:12: in XML literal: in XML content, please use '}}' to express '}'
}
^
Main.scala:13: ')' expected but eof found.
^
Basically what ~
is for bash. It's probably going to be convenient for people doing system housekeeping
e.g.
In standard scala repl
scala> val s = Stream.from(1)
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
In ammonite
@ val s = Stream.from(1)
s: scala.collection.immutable.Stream[Int] = Stream(
1,
2,
3,
4,
...
It collides with rel
from Scalatags.
It will be convenient for me to import a bunch of stuff in the ammonite REPL, but "initialCommand in console" is ignored inside the ammonite REPL
@ import ammonite.all._
import ammonite.all._
@
@ // Get the current working directory
@ val wd = processWorkingDir
wd: ammonite.ops.Path = root/'Users/'chris/'bin/"ammonite-scala-repl"
@
@ // Make a folder named "folder1"
@ mkdir! wd/'folder1
res2: Unit = ()
@
@ // List the current directory
@ ls! wd
@
Here is my build.sbt
libraryDependencies += "com.lihaoyi" %% "ammonite-repl" % "0.2.0" % "test"
initialCommands in console := "ammonite.repl.Repl.main(null)"
name := "Ammonite Repl"
scalaVersion := "2.11.4"
Hi,
I search in the doc, but i doesn't find a way to run extern command like this :
val results = (ls! wd |? (_.ext == "svg"))
(0 until results).map{ r => inkscape -z -D --file=$r --export-pdf=$r --export-latex}
Best regards
Sr.
Similar to #51, but in this case it should fail, just more gracefully than it ends up failing
@ type x = {def t: Int = 1}
java.util.NoSuchElementException: Either.left.value on Right
scala.util.Either$LeftProjection.get(Either.scala:289)
ammonite.repl.interp.Preprocessor$$anon$2.apply(Preprocessor.scala:91)
ammonite.repl.interp.Interpreter$$anonfun$processLine$2.apply(Interpreter.scala:36)
ammonite.repl.interp.Interpreter$$anonfun$processLine$2.apply(Interpreter.scala:32)
ammonite.repl.Catching.flatMap(Util.scala:73)
ammonite.repl.interp.Interpreter.processLine(Interpreter.scala:32)
ammonite.repl.Repl$$anonfun$action$1$$anonfun$apply$4.apply(Repl.scala:44)
ammonite.repl.Repl$$anonfun$action$1$$anonfun$apply$4.apply(Repl.scala:43)
ammonite.repl.frontend.Scoped$$anonfun$flatMap$1.apply(Signaller.scala:43)
ammonite.repl.frontend.Signaller.apply(Signaller.scala:28)
ammonite.repl.frontend.Scoped$class.flatMap(Signaller.scala:43)
ammonite.repl.frontend.Signaller.flatMap(Signaller.scala:10)
ammonite.repl.Repl$$anonfun$action$1.apply(Repl.scala:43)
ammonite.repl.Repl$$anonfun$action$1.apply(Repl.scala:42)
ammonite.repl.Res$Success.flatMap(Util.scala:22)
ammonite.repl.Repl.action(Repl.scala:42)
ammonite.repl.Repl.loop$1(Repl.scala:53)
ammonite.repl.Repl.run(Repl.scala:56)
ammonite.repl.Repl$.main(Repl.scala:80)
ammonite.repl.Repl.main(Repl.scala)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:483)
sbt.Run.invokeMain(Run.scala:67)
sbt.Run.run0(Run.scala:61)
sbt.Run.sbt$Run$$execute$1(Run.scala:51)
sbt.Run$$anonfun$run$1.apply$mcV$sp(Run.scala:55)
sbt.Run$$anonfun$run$1.apply(Run.scala:55)
sbt.Run$$anonfun$run$1.apply(Run.scala:55)
sbt.Logger$$anon$4.apply(Logger.scala:85)
sbt.TrapExit$App.run(TrapExit.scala:248)
java.lang.Thread.run(Thread.java:745)
Something unexpected went wrong =(
Why do I get to know the type of val f but not of def f?
@ def f: Int -> String = 5 -> ""
defined function f
@ val f: Int -> String = 5 -> ""
f: psp.std.->[psp.std.Int,psp.std.String] = 5 ->
@
It seems you're not printing any methods types. This seems a significant omission.
Attempting to build with 2.10.4 (for use with Spark projects):
[info] Compiling 11 Scala sources to /Users/deanwampler/projects/scala/Ammonite/core/target/scala-2.10/classes...
[error] /Users/deanwampler/projects/scala/Ammonite/core/src/main/scala/ammonite/pprint/PPrint.scala:219: object blackbox is not a member of package scala.reflect.macros
[error] def FinalRepr[T: c.WeakTypeTag](c: scala.reflect.macros.blackbox.Context) = c.Expr[PPrint[T]] {
[error] ^
[error] /Users/deanwampler/projects/scala/Ammonite/core/src/main/scala/ammonite/ops/Tools.scala:19: value quote is not a member of object scala.util.matching.Regex
[error] Regex.apply(scala.util.matching.Regex.quote(t).r, s)
[error] ^
[error] two errors found
Once fixed, would it be possible to publish 2.10 artifacts?
@ Range(0, 5) map {_ * 2}
Compilation Failed
Main.scala:6: Missing closing brace `}' assumed here
def $main() = {ReplBridge.shell.shellPPrint(`res3`, "res3") + " = " + ammonite.pprint.PPrint(`res3`)}
^
@ Direct(1).<tab>
## asInstanceOf isInstanceOf toString hashCode equals != ==
size isEmpty elemAt foreach getClass any_s try_s matchOr
requiring optionally same fix id_## id_== |> sideEffect
isOr doto reflect isNull toRef castTo isClass shortPackage
shortClass x __shown_rep
// Same thing
@ Seq(Direct(1)).map(_.<tab>
## asInstanceOf isInstanceOf toString hashCode equals != ==
size isEmpty elemAt foreach getClass any_s try_s matchOr
requiring optionally same fix id_## id_== |> sideEffect
isOr doto reflect isNull toRef castTo isClass shortPackage
shortClass x __shown_rep
That's missing a ton of completions, which can be seen (possibly only in part) with a slightly different formulation:
@ Direct(Direct(1)).map(_.<tab> Display all 136 possibilities? (y or n)
## asInstanceOf isInstanceOf toString hashCode equals
!= == size isEmpty elemAt foreach
getClass foreachSlice viewOps mapIndices foreachIntIndex foreachIndex
containsIndex lastNth lastIndex lastIntIndex nths indices
isPositive isZero intSize longSize byShow byRef
byEquals partition span splitAt join directlySlice
linearlySlice build force withFilter takeWhile takeRight
take map flatMap dropWhile dropRight drop
collect ++ :| |: xs toEach
foldFrom fold foldr foldl foldWithIndex groupBy
clusterBy dropIndex takeToFirst ofClass zipView zipIndex
zip withSize tail sliceWhile slice mapZip
mapWithIndex mapApply labelOp init grep gatherClass
gather filterNot filter sortBy sortDistinct sorted
min max zfoldr zfoldl zfirst toRefs
tabular nonEmpty mk_s mkString last indicesWhere
indexWhere head forallTrue forall first find
exists count foreachReverse foreachWithIndex synchronized ne
eq wait notifyAll notify any_s try_s
matchOr requiring optionally same fix id_##
id_== |> sideEffect isOr doto reflect
isNull toRef castTo isClass shortPackage shortClass
x __shown_rep
In case you doubt:
@ Direct(1).nonEmpty
res7: psp.std.Boolean = true
@
Hi Haoyi,
it would be great to be able to use Ammonite-REPL in ALL the projects :)
Could you package it as a plugin that can be added to the global SBT plugins?
If you don't have time, I can try to make a PR although it might take some time as I haven't built an SBT plugin yet.
Best
Martin
Having to import them separately is annoying
Are the tests supposed to pass right now?
See their output here for example.
Can you please provide a hook for how to print repl results? Pretty-printing is by default defined for most standard library types, as well as case classes and case objects. For other types not supported, it falls back to using toString says the doc. That's all undesirable for me.
I've gone to great lengths not to let toString infect everything in my library. It's essentially impossible to get out in front of scala's call to scala.runtime.ScalaRunTime.replStringOf because sbt is proguarded and bundled with a stripped down version. But Ammonite doesn't have to be as hostile to decent printing. I have a method like
object psp { def show[A: Show](x: A): String = implicitly[Show[A]] show x }
If there were some way to get the ammonite repl to use it on all results it would be hugely helpful.
I think you should start a list somewhere of open tickets fixed in Ammonite. Random example from early in the search results is REPL can't handle (A*) => A.
scala> val f: (Int*) => Int = _.size
<console>:5: error: type mismatch;
found : Int* => Int
required: Seq[Int] => Int
lazy val $result = f
^
vs.
@ val f: (Int*) => Int = _.size
f: Seq[psp.std.Int] => psp.std.Int = <function1>
@
Ammonite-Ops will likely always need Java 7's NIO stuff to work without heavy refactoring, but Ammonite-REPL doesn't need to. We should split off the two to cut this dependency and perhaps have a fifth project e.g. "Ammonite-Shell" which aggregates them and provides the all-in-one functionality should people want it.
Currently, when something gets echoed in the console, it gets printed no matter how much output it produces, so for example this input:
@ Seq.fill(100)(100)
Leaves your terminal looking like this
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100
)
@
After it's done. It's even worse with data-structures like infinite streams (described in #27) which will keep printing indefinitely.
We should control the output, such that after a certain amount of lines or characters has been printed, the rest is represented as ...
:
@ Seq.fill(100)(100)
res0: Seq[Int] = List(
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
...
@
That prevents your console from being taken over by accidentally echoing large data structures to stdout. Similarly, commands which result in lots of lines, but only after wrapping, should have their output truncated to fit within some number of rows. e.g.
@ Seq.fill(1000)(100).toString
currently leaves your terminal looking like
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100)"
@
But we really want to make it look like
@ Seq.fill(1000)(100).toString
res2: String = "List(100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
...
@
We'll also need some way for the user to tell Ammonite to print the whole thing, on demand. e.g. something like
@ pprint(...)
Would print out the entire, console-flooding version of the command.
This feature would essentially fix #27
Using the current master branch, I get
Loading Ammonite Repl...
@ load.ivy("com.chuusai" %% "shapeless" % "2.1.0")
:: resolving dependencies :: com.chuusai#shapeless_2.11-caller;working
...
res0: Unit = ()
@ import shapeless._
import shapeless._
@ () // Nothing compiles starting from here, whatever the line we enter
Compilation Failed
Main.scala:1136: '}' expected but identifier found.
~?>$,
^
@
(re-formatted/stripped for readability).
The wrapper fails to compile once one imported shapeless._
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.