Datamancer
Datamancer copied to clipboard
Datamancer works not with nimscript
I tried to run the example code from Datamancer's documentation:
import datamancer
let s1: seq[int] = @[22, 54, 34]
let s2: seq[float] = @[1.87, 1.75, 1.78]
let s3: seq[string] = @["Mike", "Laura", "Sue"]
let dfAutoNamed = toDf(s1, s2, s3)
echo dfAutoNamed
As a compiled binary works great. Out of curiosity I tried to run it as a Nimscript but I get the following output:
command: nim datamancer_intro.nims
output:
Hint: used config file '/opt/homebrew/Cellar/nim/2.0.8/nim/config/nim.cfg' [Conf]
Hint: used config file '/opt/homebrew/Cellar/nim/2.0.8/nim/config/config.nims' [Conf]
/Users/nox/.nimble/pkgs2/nimblas-0.3.0-d5033749759fc7a2a316acf623635dcb6d69d32a/nimblas/private/common.nim(52, 7) Hint: Using BLAS library with name: libblas.dylib [User]
/Users/nox/.nimble/pkgs2/arraymancer-0.7.32-e1fa31ad09f0199e93c1bf9959e1f3af5bdacc08/arraymancer/tensor/init_cpu.nim(245, 18) template/generic instantiation of `randomTensorCpu` from here
/Users/nox/.nimble/pkgs2/arraymancer-0.7.32-e1fa31ad09f0199e93c1bf9959e1f3af5bdacc08/arraymancer/tensor/init_cpu.nim(218, 18) template/generic instantiation of `allocCpuStorage` from here
/Users/nox/.nimble/pkgs2/arraymancer-0.7.32-e1fa31ad09f0199e93c1bf9959e1f3af5bdacc08/arraymancer/laser/tensor/datatypes.nim(110, 29) template/generic instantiation of `finalizer` from here
/Users/nox/.nimble/pkgs2/arraymancer-0.7.32-e1fa31ad09f0199e93c1bf9959e1f3af5bdacc08/arraymancer/laser/tensor/datatypes.nim(77, 23) Error: attempting to call undeclared routine: 'deallocShared'
Is there a solution or workaround?
It would be nice for Datamancer to work in scripts so when REPL is available for Nim, a tool similar to R/Jupyter Notebooks could be built.
So there's two things to mention:
- We can make (most of) Datamancer work with NimScript by making it pick the recently added JS backend (see #62). It more or less works, I've tried it locally (Note that it still throws some errors when using
nim secretdue tostd/random). - With Nim secret there is a REPL already that uses NimScript. If we ever get a good real REPL, it'll end up compiling the code anyway and Datamancer will work as expected using the "default" backend.
For 1), here is the patch I used. Apply it to a local Datamancer version of yours and your nimscript code should run. Maybe I'll merge it one of these days, but at the moment I don't think it's extremely useful.
diff --git a/src/datamancer/column.nim b/src/datamancer/column.nim
index bf71741..34f9e2f 100644
--- a/src/datamancer/column.nim
+++ b/src/datamancer/column.nim
@@ -1,7 +1,7 @@
-when not defined(js):
- import arraymancer/tensor
-else:
+when defined(js) or defined(NimScript):
import seq_tensor
+else:
+ import arraymancer/tensor
import std / [sugar, strformat, tables, macros, strutils]
import value
diff --git a/src/datamancer/dataframe.nim b/src/datamancer/dataframe.nim
index cdd8025..4a5dc5e 100644
--- a/src/datamancer/dataframe.nim
+++ b/src/datamancer/dataframe.nim
@@ -1,12 +1,12 @@
import std / [macros, tables, strutils, options, sets, hashes, math,
sequtils, stats, strformat, algorithm, typetraits]
-when not defined(js):
- import arraymancer/tensor
- export tensor
-else:
+when defined(js) or defined(NimScript):
import seq_tensor
export seq_tensor
+else:
+ import arraymancer/tensor
+ export tensor
import value
export value
diff --git a/src/datamancer/formulaExp.nim b/src/datamancer/formulaExp.nim
index 8f12ecb..8c1640a 100644
--- a/src/datamancer/formulaExp.nim
+++ b/src/datamancer/formulaExp.nim
@@ -709,7 +709,7 @@ proc convertLoop(p: Preface, dtype, fctColResType, loop: NimNode,
fnKind: FormulaKind,
generateLoop: bool): NimNode =
let memCopyable = ["float", "int", "bool"]
- when defined(js):
+ when defined(js) or defined(NimScript):
let isMemcopyable = false
else:
let isMemCopyable = dtype.strVal in memCopyable and
diff --git a/src/datamancer/io.nim b/src/datamancer/io.nim
index 8bc6eb9..f0f9611 100644
--- a/src/datamancer/io.nim
+++ b/src/datamancer/io.nim
@@ -1,7 +1,7 @@
import dataframe, value, column
import std / [streams, strutils, tables, parsecsv, sequtils, strformat, os]
-when not defined(js):
+when not (defined(js) or defined(NimScript)):
import memfiles
# for reading CSV files from URLs (former) and `showBrowsers` (latter)
import httpclient, browsers
@@ -79,8 +79,7 @@ proc readCsv*(s: Stream,
result[colHeaders[i]].add parser.rowEntry(col)
parser.close()
-
-when defined(js):
+when defined(js) or defined(NimScript):
type
MemoryView[T] = seq[T]
@@ -109,7 +108,7 @@ template copyBuf(data: MemoryView[char], buf: var string,
let nIdx = idx - colStart
if nIdx > 0:
buf.setLen(nIdx) # will auto reallocate if `len` is larger than capacity!
- when defined(js):
+ when defined(js) or defined(NimScript):
for i in 0 ..< nIdx:
buf[i] = data[colStart + i]
else:
@@ -667,7 +666,7 @@ proc parseCsvString*(csvData: string,
skipInitialSpace, quote, maxGuesses, lineBreak, eat,
allowLineBreaks = allowLineBreaks)
-when not defined(js):
+when not (defined(js) or defined(NimScript)):
proc readCsvFromUrl(url: string,
sep: char = ',',
header: string = "",
@@ -749,7 +748,7 @@ when not defined(js):
## parser using `std/parsecsv` is available under the name `readCsvAlt`. However,
## it does not return a full `DataFrame`. You need to call `toDf` on the result.
if fname.startsWith("http://") or fname.startsWith("https://"):
- when not defined(js):
+ when not (defined(js) or defined(NimScript)):
return readCsvFromUrl(fname, sep=sep, header=header, skipLines=skipLines,
toSkip=toSkip, colNames=colNames)
else:
@@ -757,7 +756,7 @@ when not defined(js):
let fname = fname.expandTilde()
result = newDataFrame()
try:
- when not defined(js):
+ when not (defined(js) or defined(NimScript)):
var ff = memfiles.open(fname)
var lineCnt = 0
for slice in memSlices(ff, delim = lineBreak, eat = eat):
@@ -891,7 +890,7 @@ proc toHtml*[C: ColumnLike](df: DataTable[C], tmpl = ""): string =
body.add "</tbody>"
result = tmpl % (header & body)
-when not defined(js):
+when not (defined(js) or defined(NimScript)):
proc showBrowser*[C: ColumnLike](
df: DataTable[C], fname = "df.html", path = getTempDir(), toRemove = false,
htmlTmpl = "", title = "") =