Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - hartrock

newLISP newS / mem leak in v10.7.1
March 17, 2016, 05:08:14 AM

sr@freen:~/newLISP_Core/mirror$ ./newlisp
newLISP v.10.7.1 64-bit on Linux IPv4/6 UTF-8 libffi, options: newlisp -h

> (set 'v nil 'r (string "foo")) (sys-info 0)
> (set 'v nil 'r (string "foo")) (sys-info 0)
;; no mem leak:
(set 'r (string "foo")) (sys-info 0)


Same applies to v10.7.0 .
newLISP Graphics & Sound / Inspector v.0.4.2
February 20, 2016, 08:58:15 AM

[*] symbols view: more detailed info about dynsyms">Remote Inspector: dynamic symbols (dynsyms)
  • [*] permanently show PID of remote and remote's status

  • [*] better interrupt handling: now it works for remote startup code given by startup arguments, too.
  • [/list]

    Project page:">

  • [*] Inspector's webserver for serving RI's GUI runs as a newLISP process, to be started by the user (it's a standalone webserver not needing more software);

  • [*] RI's GUI is running inside a browser window with Javascript;

  • [*] RI's remote is a newLISP process to be visualized and controlled by RI's GUI.
  • [/list]
    A screenshot says more than many words:">Remote Inspector: debugging session.

  • [*] interaction with,

  • [*] introspection of, and

  • [*] control of this remote.
  • [/list]

    [*] Interaction: remote console mimicking a newLISP interpreter shell inside a terminal;
  • [*] introspection: remote's symbols will be shown in symbols view and updated after each evaluation;

  • [*] control:

    [*] start: with startup CLI arguments,

  • [*] termination: SIGTERM, SIGKILL, and

  • [*] interruption: SIGINT.
  • [/list]


    For more details see:">

    Project page:">

    Feedback is appreciated.
    Title of">// is

    newLISP v.1.7.0 Release Notes...

    At bottom there is

    - development version 1.64

    - guiserver.jar version 1.65 (probably wrong, too),


    Besides this: Thanks for the ongoing work!

    sr@freen:~$ newlisp
    newLISP v.10.6.5 64-bit on Linux IPv4/6 UTF-8 libffi, options: newlisp -h

    > (set 's (sym "Foo bar" MAIN))
    Foo bar
    > (context s)

    ERR: invalid parameter in function context : "Foo bar"
    > (context s)
    Segmentation fault
    [Update with full example]

    Unfortunately I have to put some water into the wine...

    newLISP v.10.6.5 64-bit on Linux IPv4/6 UTF-8 libffi, options: newlisp -h

    (set 'sy nil)
    (set 'foo MAIN)
    (define (f) (foo:println 'sy:bar))
    (delete 'sy)

    (lambda () (foo:println 'sy:bar))
    (lambda () (nil 'nil))

    Fix is nil'ing too much...
    Thanks, Lutz!

    By your fix a 'Bus error' related to this problem has disappeared, too (in a more complex scenario: had just given a minimal version to trigger the problem).
    I had to add to NEWLISP_DIR/modules/crypto.lsp :

    "/usr/lib/x86_64-linux-gnu/" ; Debian jessie

    There is an already existing path, if libssl-dev has been installed, but not without (which I noticed after a fresh OS install).
    While looking deeper into the semantics of dynamic symbols, there has been this unexpected behavior:

    sr@freen:~/newLISP$ newlisp
    newLISP v.10.6.5 64-bit on Linux IPv4/6 UTF-8 libffi, options: newlisp -h

    (set 'sy nil)
    (define (f) (println 'sy:bar))
    (delete 'sy)

    (lambda () (println 'sy:bar))
    Quote from: "abaddon1234"that let and letex are the exception of a general left to right evaluation for setting symbols? Or is it more complicated?">เล่นจีคลับผ่านเว็บ

    let and letex are using the outer binding of given symbols for initialization; e.g.]
    sr@free:~$ newlisp
    newLISP v.10.6.4 64-bit on Linux IPv4/6 UTF-8 libffi, options: newlisp -h

    > (letex (x 1 y 2 z 3) '(x y z))
    (1 2 3)
    > ; but:
    > (letex (x 1 y (+ x 1) z (+ y 1)) '(x y z))

    ERR: value expected in function + : nil
    > ; but:
    > (set 'x 10 'y 11)
    > (letex (x 1 y (+ x 1) z (+ y 1)) '(x y z))
    (1 11 12)
    My point regarding set - denoted as a special form in other Lisps - has been, that it should stated somewhere in the manual, that it follows the general rule of left-to-right evaluation using formerly set bindings at the same level (there is no new level of bindings):

    sr@free:~$ newlisp
    newLISP v.10.6.4 64-bit on Linux IPv4/6 UTF-8 libffi, options: newlisp -h

    > (set 'x 1 'y (+ x 1) 'z (+ y 1)) (list x y z)
    (1 2 3)
    That there are no new bindings introduced is clear, but set - as well as let - guaranteed to follow the general left-to-right evaluation rule has not been self-evident to me. Think of parallelization opportunities, if this would not been the case; on the other side parallelization could be dangerous in case of side-effects.

    Possibly some thoughts along 'pure functional programming is good for parallelization, because it has no side effects' has made my thinking more complicated than needed here.

    It is probably correct to say for newLISP, that the general rule of left-to-right evaluation:

    [*] also applies for expressions like set, let - even if denoted as special forms in other Lisps -;
  • [*] does not apply only, if explicitely stated so.
  • [/list]

    Taking the definition of special forms from the newLISP manual (different from other Lisps):
    Quote from: "manual"
    Lisp functions that do not evaluate all or some of their arguments are called special forms.
    ; denoting something as special form there only implies, that the general rule of left-to-right evaluation does not apply to all arguments.

    Quote from: "Lutz"
    Evaluation order in general is always depth first from left to right.


    [*] arguments are evaluated - like for function calls and also for expressions like let -, and
  • [*] nothing is said about a special evaluation order,
  • [/list]
    left-to-right evaluation applies.

    Note: It is possible, of course, to write some macro for changing evaluation order by rearranging to be evaluated macro arguments.
    Quote from: "xytroxon"A potential problem exists in handling UTF-8 string values in UTF-8 enabled versions of newLISP. In UTF-8 versions, the length function would return the number of bytes and not the number of UTF-8 characters in the string. Hence, your function would not return the correct number of characters from your string!

    Thanks for the pointer!

    This is indeed a problem for usecase triggering this thread: there is a transfer of newlisp interpreter stdin/stdout/stderr via websocket protocol, whose text will be transfered in chunks for having intermediate results in case of longer running computations. Separating these chunks is byte string orientated, but transfer goes by transferring these chunks as - encoded - JSON strings. But JSON encoding could fail, if an UTF-8 char will be cutted at the border between two chunks; with fragments becoming part of different chunks.

    So there is something to do; trying to provoke problem triggers error (to be eval'ed code and results of evalutions transferred via websocket as UTF-8 text):

    > (set 's "我能吞下玻璃而不伤身体。")(dup s 500) ; dup leading to chunked transfer
    > (set 's "我能吞下玻璃而不伤身体。")(dup s 500) ; dup leading to chunked transfer
    -> this run has failed for transfer of second (chunk borders are varying) dup result (first succeeded one shown truncated).
    Quote from: "ralph.ronnquist"Not really simpler, but the negative index case would be slightly shorter with the following.
    ((length 0 pos str) str)
    Thanks for the suggestion!

    Corrected it is:

    ((length (0 pos str)) str)
    ; which is shorter and easier to understand than:

    ((- (min (- pos) (length str))) str)

    The longer variant avoids copying str for computing valid negative index, though.

    Asymmetry triggering this thread is:

    > (set 'str "foobar")
    > (11 str)
    > (-11 str)

    ERR: invalid string index
    (same for (slice pos str)); but there may be reasons for this semantics: e.g. negative indices near to tail of a list are inefficient compared to positive ones near to its head; which could be a reason for making use of negative ones more uncomfortable.
    There is the following function leave-string for leaving left (positive pos) or right (negative pos) part of a string, which works for pos out of range, too:

    (define (leave-string str pos)
      (if (>= pos 0)
          (0 pos str)
          ((- (min (- pos) (length str))) str)))
    (set 'str "foobar")
    (leave-string str 3) ; first 3
    (leave-string str -3) ; last 3
    (leave-string str 7) ; first 7 (all with pos one out of range)
    (leave-string str -7) ; last 7 (all with pos one out of range)

    (lambda (str pos)
     (if (>= pos 0)
      (0 pos str)
      ((- (min (- pos) (length str))) str)))
    Any idea for simplifying the negative pos case?

    Or is there any other possibility to get this truncating string functionality, I don't have on the radar?
    This reminds me on Smalltalk's #messageNotUnderstood selectors.

    Here is something similar for newLISP FOOPs; due to not having messages, but function calls, there is the renaming to callNotUnderstood.

    After loading cnu.lsp:

    (new Class 'Foo)
    (context Foo)
    (define (fun)
      (string "FOOP: " (self) ", call: " 'fun ", arguments: " (args)))
    (define (callNotUnderstood symbol arguments)
      (string "FOOP: " (self) ", call: " symbol " *** not understood ***,"
              " arguments: " arguments))
    (context MAIN)
    (define (call-sym-foop Symbol foop)
      (if (not (symbol? Symbol))
          (throw-error "1. argument: symbol expected."))
      (letn ((ctx (and (list? foop) foop (foop 0)))
             (symbol (if (context? ctx) (sym Symbol ctx))))
        (if (not (context? ctx))
            (throw-error "2. argument: FOOP expected."))
        (if (lambda? (eval symbol))
            (eval (append (expand '(: Symbol foop)) (args)))
            (:callNotUnderstood foop symbol (args)))))
    ; there may be following session:

    > ; create an instance of Foo:
    > (set 'foo (Foo "I'm a foo."))
    (Foo "I'm a foo.")
    > ; calling Foo:fun for instance foo by:
    > (:fun foo 1 2 3)
    "FOOP: (Foo "I'm a foo."), call: fun, arguments: (1 2 3)"
    > ;;
    > ; call existing Foo:fun indirectly:
    > (call-sym-foop 'fun foo 1 2 3)
    "FOOP: (Foo "I'm a foo."), call: fun, arguments: (1 2 3)"
    > ; try to call non-existing Foo:funNotThere :
    > (call-sym-foop 'funNotThere foo 1 2 3)
    "FOOP: (Foo "I'm a foo."), call: funNotThere *** not understood ***, arguments: (1 2 3)"

    Foo:callNotUnderstood is the place for handling the case of not having some func in Foo context; under the precondition, that func will be called (more) indirectly by using call-sym-foop: taking func symbol, FOOP instance and optional more as arguments.

    This would also work for other FOOPs; e.g. Bar:callNotUnderstood would be called for an instance of Class Bar, if some Bar func is missing.

    Note: There may be more elegant ways to reach this kind of behavior.
    Quote from: "ssqq"I think first lambda expression should is 'lambda:

    > (first (lambda (x y) (+ x y)))
    > (first (fn (x y) (+ x y)))
    > 'lambda
    > 'fn
    > (cons 'fn '((x y) (+ x y)))
    (fn (x y) (+ x y))

    Why newLISP use args as first elements of lambda expression?

    Why could not quote *lambda* and *fn*?

    lambda is a property of a list, and not a symbol at its beginning; an example:

    > (set 'li (cons '(x y) (cons '(+ x y) '())))
    ((x y) (+ x y))
    > (first li)
    (x y)
    > (set 'la (cons '(x y) (cons '(+ x y) '(lambda))))
    (lambda (x y) (+ x y))
    > (first la)
    (x y)
    -> both list and lambda list having (x y) as first element.

    But only the lambda list works as function:

    > (li 3 4)

    ERR: invalid list index
    > (la 3 4)

    From the manual">//
    ... The fn or lambda word does not exist on its own as a symbol, but indicates a special list type: the lambda list. ...