diff --git a/debug.lsp b/debug.lsp index 309735a..ab62f3e 100644 --- a/debug.lsp +++ b/debug.lsp @@ -1,30 +1,6 @@ +(write-file "/tmp/f.txt" "line 1\nline 2\nline3") +(read-file-lines "/tmp/f.txt" (lambda (ln) (print ln))) -;https://github.com/anthay/Lisp90/blob/master/lisp90.cpp -;http://howtowriteaprogram.blogspot.com/2010/11/lisp-interpreter-in-90-lines-of-c.html - -; https://stackoverflow.com/questions/526082/in-scheme-whats-the-point-of-set -;; (define x 3) -;; (defun foo() (do (define x 4) x)) -;; (defun bar() (do (set! x 4) x)) - -;; (foo) ; returns 4 -;; x ; still 3 -;; (bar) ; returns 4 -;; x ; is now 4 - - -;; (defun mini-uuid (uuid_len) (do -;; (define a_list '("_" "-" "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z")) -;; (reduce (lambda (acc y) (+ acc y)) "" (map (lambda (e) (index a_list (random 0 (- (len a_list) 1)))) (range 0 uuid_len))) -;; )) - -;; (benchmark "uuid 1000x :" (define i 0) (while (< i 1000) (do (mini-uuid 5) (define i (+ i 1))))) - - -;; (define first_tid (thread-create (while 1 (do (thread-under-lock "ilock" (print 1)) (thread-sleep 50))))) -;; (define second_tid (thread-create (while 1 (do (thread-under-lock "ilock" (print 2)) (thread-sleep 75))))) -;; (print "first thread id:" first_tid) -;; (print "second thread id:" second_tid) -;; (threads-join) -;; (print "ok") - +(define counter (lambda (ln) (do (set! ii (+ ii 1)) t ii)))) +(define ii 0) +(print (read-file-lines "/tmp/f.txt" counter)) diff --git a/doc/Doc.md b/doc/Doc.md index 9cc3d69..9f18fb5 100644 --- a/doc/Doc.md +++ b/doc/Doc.md @@ -56,12 +56,13 @@ |`(random low high)`|Get a random number between two numbers inclusively|| |`(include file)`|Read a file and execute its code|| |`(read-file filename)`|Get the contents of a file|| -|`(write-file filename)`|Write a string to a file|| +|`(read-file-lines filename lambda)`|Reads file and for each line call lambda with passing the line as a parameter|`(read-file-lines "/tmp/f.txt" (lambda (ln) (print ln))`| +|`(write-file filename content-str)`|Write a string to a file|| |`(read-url url [headers])`|Reads URL|Returns list (status-code content)| |`(system-cmd command_str)`|Execute system command|| -|`(ls-dir ..)`|List a dir|List of directory entries| -|`(is-file? ..)`|Returns true if passed filename is a file|| -|`(is-dir? ..)`|Returns true if passed filename is a directory|| +|`(ls-dir dir)`|List a dir|List of directory entries| +|`(is-file? filename)`|Returns true if passed filename is a file|| +|`(is-dir? filename)`|Returns true if passed filename is a directory|| |`(parse-csv string)`|Parse CSV string|| |`(parse-json json_string)`|Parse JSON string|| |`(save-csv ..)`||| diff --git a/ml.cpp b/ml.cpp index a38a1d3..a89eb13 100644 --- a/ml.cpp +++ b/ml.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -1126,6 +1127,30 @@ namespace builtin { return MlValue::string(read_file_contents(args[0].as_string())); } + // Reads file line by line and call passed lambda + MlValue read_file_lines(std::vector args, MlEnvironment &env) { + eval_args(args, env); + + if (args.size() != 2) + throw MlError(MlValue("read-file-lines", read_file_lines), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS); + // TODO check args[1].is_lambda + + long lines_nr = 0; + std::vector lambda_par{MlValue::nil()}; + std::ifstream file(args[0].as_string()); + if (file.is_open()) { + std::string line; + while (std::getline(file, line)) { + lines_nr++; + lambda_par[0] = MlValue::string(line); + args[1].apply(lambda_par, env); + } + file.close(); + } + + return MlValue{lines_nr}; + } + // Write a string to a file MlValue write_file(std::vector args, MlEnvironment &env) { eval_args(args, env); @@ -1978,6 +2003,7 @@ MlValue MlEnvironment::get(const std::string &name) const { if (name == "random") return MlValue("random", builtin::random); if (name == "include") return MlValue("include", builtin::include); if (name == "read-file") return MlValue("read-file", builtin::read_file); + if (name == "read-file-lines") return MlValue("read-file-lines", builtin::read_file_lines); if (name == "write-file") return MlValue("write-file", builtin::write_file); if (name == "read-url") return MlValue("read-url", builtin::read_url); if (name == "system-cmd") return MlValue("system-cmd", builtin::system_cmd); diff --git a/tests/test.lsp b/tests/test.lsp index bec07a5..921584f 100644 --- a/tests/test.lsp +++ b/tests/test.lsp @@ -14,6 +14,11 @@ (+ n (scitej (- n 1))) )) +(write-file "/tmp/f.txt" "line 1\nline 2\nline3") +(define counter (lambda (ln) (do (set! ii (+ ii 1)) ))) +(define ii 0) + + (define json_list (parse-json "{\"k1\":\"v1\", \"k2\":42, \"k3\":[\"a\",123,true,false,null]}")) @@ -108,6 +113,7 @@ (ut::define-test "result of (start-of-year)" '(ut::assert-equal 1609459200 (start-of-year (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")))) (ut::define-test "result of (end-of-year)" '(ut::assert-equal 1640995199 (end-of-year (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")))) +(ut::define-test "(read-file-lines \"/tmp/f.txt\" counter)" '(ut::assert-equal 3 (read-file-lines "/tmp/f.txt" counter))) ;(ut::define-test "result of " '(ut::assert-true ) (ut::run-tests)