PicoLisp win x86-64 app/main edit workaround, other musings on [2016-08-19 Fri 03:14]

I've been working on a windows x64 port of picolisp

Two issues were resolved or worked around

  1. edit buttons and new buttons would crash in the demo app. It turns out that (sync) would cause the process to crash. For now, I've just redef'd sync to be NIL. This is likely due to locking which will be commented on below

  2. debug mode in the repl works but is fairly clunky. First, to invoke debug mode one must use the equivalent of

    bin\ntctty.exe -e bin\ptycon --sysroot %cd% -e bin\picolisp.exe lib.l ext.l lib/debug.l +

    However, it's not that easy since Dbg sets all sorts of other things in various files. I had to run through different files and change the bottom to be NIL instead of `Dbg. I think the main issue is with the integrated editor (led.l), but for now if you want to use debug mode you can, but you need to hack files to exclude things. I will attempt to document this more later

Other things worked on:

Locking. midipix does not currently have FSETL, and FSETLKW implemented. Instead, I skip it. midipix said he'd work on implementing this weekend and asked for a test case. I created the following test case and learned a lot about locking in the interim.

Other things learned or remembered:

   (setq SomeData (mapcar chop '("abc" "name" "color")))
   (de example () 
      (for V SomeData
         (if (= V '`(chop "abc")) (msg "found abc")) ) )

The chop gets evaluated once at read. Proof:

    -> (NIL (for V SomeData (if (= V '("a" "b" "c")) (msg "found abc"))))

Given a JSON file of data which is fairly large, how would you extract all the customer numbers

    (setq Data (chop "{\"CustomerNumber\": \"1234\", \"Name\":\"Test\"},{\"CustomerNumber\": \"4444\", \"Name\": \"Test2\"}"))

My first attempt

     car (maplist
        (if (pre? "CustomerNumber" X)
           (car (split
             (head 30 (nth X 18))
             " ")))))

-> ("\"1234\"," "\"4444\",")

My first attempt ran OK on small data, but was exponentially slow on the real data. I killed it after a minute

My second attempt ran in 3 seconds

    (setq D (maplist '((X) (head 30 X)) P)) T
    (setq R (filter '((X) (pre? "CustomerNumber" X)) D)) T
    (setq Nums (mapcar '((X) (pack (nth t(cadr (split X " ")) 2))) R)) T

Here's the evolution of the later attempts

    # 0.053 seconds... seemed to make sense at the time to use indexes to read ahead
    # but, since lists aren't indexed in constant time, this could get slow
    (de parseCustomer (Data)
     (let Split (split Data " " "\"")
          (for (I . V) Split
           (if (= V '`(chop "CustomerNumber"))
             (link (pack (car (nth Split (+ I 3))))))))))

    # 0.0153 seconds ... by using the 3rd type of for, we can use nth on a shorter list
    (de parseCustomer2 (Data)
     (let Split (split Data " " "\"")
          (for ((I . V) Split V (cdr V))
           (if (= (car V) '`(chop "CustomerNumber"))
             (link (pack (car (nth V 4) ))))))))

    # 0.0143 seconds .. I thought this would be faster since we eliminate the cdr
    (de parseCustomer3 (Data)
          (for (V (split Data " " "\"") V)
           (when (= (pop 'V) '`(chop "CustomerNumber"))
             (link (pack (car (nth V 3) )))))))

    # 0.0147 seconds still, had a hunch that caddr would be faster then (car (nth...)
    # more readable though
    (de parseCustomer4 (Data)
          (for (V (split Data " " "\"") V)
           (when (= (pop 'V) '`(chop "CustomerNumber"))
             (link (pack (caddr V )))))))

Testing method.. (for I (range 0 100) (bench (parseCustomer4 Data)))

The performance only matters because I'll have 100 forked processes executing this code 3 times per minute. The tests were already CPU constrained from the test client. I personally like parseCustomer4 as it meets the performance objective and is the most concise.

  Next: MicroJ - explicit dyad support added