Menu

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 - rrq

#31
Nice! Though they should probably review the "Case expressions" section.
#32
newLISP in the real world / Re: nL cron script
October 26, 2019, 03:54:55 PM
* * * * * joe /home/joe/winny/winny.lsp A line like the above would be fine in /etc/crontab or in /etc/cron.d/something-or-other, but for a user's crontab line (crontab -e), you'd skip the "user" field:
* * * * * /home/joe/winny/winny.lsp It's of course all nicely documented in
$ man cron
hth
#33
newLISP in the real world / Re: translating big numbers
October 12, 2019, 07:28:25 PM
There is the interesting issue of "precision" in this, i.e. how precises the decimal representation is realative to the actual numberical value held. For example, you might define the following functions:
(define (digits n)
    (let (x 0 m 1)
        (while (!= n (add n m)) (inc x) (setf m (div m 10)))
        x))

(define (P n) (format (string "%0." (digits n) "f") n))

The first function , digits, determines how many fractional digits are representable, in terms of at which fractional position adding 1 at that position doesn't affect the represented number.



One might take that to be how many fractional digits to present, which is what the second function, P, implements. That function returns the number translated to a string (using the "f" format specifier) with a precision of that many fractional digits.



Anything more is kind of senseless, even though the normal "f" translation would happily offer some 76 non-zero fractional digits (which presumably arises due to the mechanics of mapping the number to a decimal representation). But if you want to look at zeroes, you could do
(format "%0.1000f" -2.000000000000049e-07)
:)
#34
newLISP in the real world / Re: Timing function problem
September 19, 2019, 01:06:03 AM
Most likely it's the define in define, which probably ends up growing the symbol table for each new define in some way. You could compare with making it a heap based temporary function instead:
(define (merge lstA lstB op)
  (let ((ciclo (fn (out lstA lstB)
                 (cond ((null? lstA) (extend (reverse out) lstB))
                       ((null? lstB) (extend (reverse out) lstA))
                       ((op (first lstB) (first lstA))
                        (ciclo (cons (first lstB) out) lstA (rest lstB)))
                       (true
                        (ciclo (cons (first lstA) out) (rest lstA) lstB))))
               ))
    (ciclo '() lstA lstB)
    ))

That should give the same result, except that the inner function is merely a heap element, and it does not add to the symbol table.



Of course I'm not sure exactly why the symbol table would grow, since the define clause, except for the first one, supposedly would merely redefine the ciclo, but maybe the reclaim of the discarded definitions has some kind of fault.



btw. what's wrong with:
(define (merge lstA lstB op) (sort (append lstA lstB) op))
#35
newLISP in the real world / Re: Twin primes
August 31, 2019, 06:35:39 PM
You will gain a bit in speed for handling larger numbers by checking if the modulus of a prime product include any of the product primes. The code could be something like the following:
(define (pairs-i1 a b)
  (let ((out (list)) (x nil) (FX (* 2 3 5 7 11 13)) (M 0))
    (for (y (if (odd? a) a (inc a)) b 2)
      (if (if (< y FX) (1 (factor y))
             (or (= (setf M (% y FX))) (if (factor M) (<= ($it 0) 13)) (1 (factor y))))
        (setf y nil)
        x (push (list x y) out -1))
      (setf x y))
    out))

That example uses the prime product (* 2 3 5 7 11 13). For numbers greater than that, it checks if the modulus is a product of any of those primes, in which case the number as whole is divisible by that prime (and therefore not a prime itself). Notably, the factorization of the modulus is typically faster, and the end result is a faster filtering out of these. The speed up for handling large numbers is significant (~30%).
#36
newLISP in the real world / Re: Twin primes
August 30, 2019, 12:11:24 AM
Something like this, perhaps:
(define (pairs-i a b)
  (let ((out (list)) (x nil))
    (for (y (if (odd? a) a (inc a)) b 2)
      (if (1 (factor y)) (setf y nil) x (push (list x y) out -1))
      (setf x y))
    out))
#37
newLISP in the real world / Re: Create polynomials
August 25, 2019, 08:57:12 PM
I'm not sure about "better/more elegant", but it's always fun and interesting to explore alternative newlisp articulations. I rendered this one, as an iterative though rather functional in style, "hiding" the iteration in a map primitive:
(define (make-poly coeff)
  (let ((rank (length coeff))
        (polyterm (fn (k) (case (dec rank)
                                (0 k)
                                (1 (list 'mul 'x k))
                                (true (list 'mul (list 'pow 'x rank) k))))))
    (push (cons 'add (reverse (map polyterm coeff))) (copy '(fn (x))) -1)))
#38
newLISP in the real world / Re: Web app server
August 06, 2019, 05:56:01 AM
As I remember, ranwar.tgz is an attempt to implement a front-end in newlisp to allow concurrent request handling, and "emulate" persistence for newlisp app scripts by means of the shared memory facility. It starts a sub process for every request, and is designed for a notion "app instance" by means of shared memory.



Then it also includes a good support framework for using newlisp to make templated HTML, which probably is the stronger aspect in that "mess" :)



In short, the "ranwar" infrastructure supports app instance data persitence, but not process persistance; pretty much the same as django through gunicorn off an nginx server, but with a nicer scripting language. If you have a keen interest in using newlisp, then it shouldn't be too hard to make good use of the infrastructure. That also gives you full control of all the facets in the HTTP handling pipeline, although at the expense of performance.



In fact, I have a real-life example still running, as an internal, back-office server with a mixture of complex computations, and remote host interactions, a flexible web app utility for a handful of users.



Ralph.
#39
newLISP in the real world / Re: Web app server
August 06, 2019, 04:21:03 AM
QuoteCan newLISP be used to create a standalone http web app server?

The answer to that one is of course "yes"; newlisp, with -http, provides a basic HTTP server for a small range of file types, including ".cgi" which it handles in a similar way to apache2. I.e., the ".cgi" file is an executable, and possibly a script in whatever scripting language.



There are however a number of caveats in having newlisp as the web service front-end. Especially that it's single threaded, and will handle one request at a time to completion. Also, the front-end process is a separate process from any ".cgi" processes, and the front-end doesn't provide any session management or "web app instance persistance".



The HTTP processing is built-in, and without hooks in the front-end processing apart from the usual command-event. So all in all it's easy to use for developing an app, and perhaps some personal, "odd" HTTP responders, while you'd move to a more capable front-end (e.g. nginx) for any more serious service.



On the other hand, newlisp is quite handy for response scripting as .cgi files, especially for services that don't need instance persistence.



That's 2c from me :)
#40
Well, as always, the first thing to exclude is "operator error". I don't know what the prevalent mistakes might be for Windows, but at least you should confirm that the program runs without being packed into a single executable. I.e., if the program is in the scripts A.lsp, B.lsp and C.lsp, with A.lsp being the main script, you would obviously test that by running newlisp A.lsp

Following that, you'll need to offer some more information. E.g. does it fail to build or does it fail to run a built .exe?
#41
If that printing happens from a CGI script for newlisp in -html operation, then it'd be explained as an API misunderstanding. newlisp in -html mode is quite forgiving about the CGI response, but it treats anything before the first empty line as the HTTP headers part, and that following the first empty line to be the HTTP payload part. That division holds regardless of whether the HTTP headers part is syntactically correct or not, where it silently discards anything non-header-ish. I remember it all as nicely documented but I can't bother looking it up right now.



Thus, if that's the reason, you would revise the template printing to add an initial newline
(println "n" template)  to serve the template text in full as HTTP payload.
#42
The use of  single symbol is not a documented http://www.newlisp.org/downloads/newlisp_manual.html#let">syntax form, and generally, that second element of the let term is not evaluated but processed as is (and only evaluated in parts). So that syntax form is a DIY opportunity :)



For a once-off need, I'd wrap it into a letex, as in the following.
(letex (l l) (let l (+ a b))) and for a more regular need, I'd define me a macro like the following:
(define-macro (lett)
    (if (list? (args 0)) (apply let (args))
        (apply let (cons (eval (pop (args))) (args))) ))

The latter would be a new function lett that kind of extends the function of let, but also lets me have a symbol as second element, in which case that symbol is evaluated so as to obtain an actual second argument for the let term. Thus, for your example, you would use (lett l (+ a b))

However, the resulting syntax is a case of non-local variable references (since the lett body includes a and b as out of context references), and that is something I would generally try to avoid, as I find it rather lacking in clarity, More specifically, the passing in of a variable assignment list into a let form conflates meta level and object level logic for no obvious reason, since the passed in list has to include the particular assignments that the body of the let form expects/requires anyhow, to be of any use. So if this would be used in a program, then that program would be slightly harder to read and understand than the equivalent program without using this feature.
#43
If you read first argument to format very carefully a few times, you will eventually discover the missing back-quote. :)
#44
Yes, I kind of thought that jsondata was the whole thing. Since you have
(set 'jsondata (lookup "products" (lookup "result" alie))) it'll already have gone into the "products" value part, and therefore my suggested ref of a ("product" ?) pair in jsondata isn't much good. As you noticed :)



If jsondata holds that value part of "products", then you'd get the simpler map term of: (map raisins jsondata) . And, completed with a println it might look like: (println (join (map raisins jsondata) "n"))
The key in my suggestion is that the term form, with different x and y:(if (ref '(x ?) y match true) ($it 1) '()) picks and returns the value part, i.e. the second element, of the first sub list of y starting with x at any depth in a depth-first traversal. It's a quick way to find stuff especially in a json structure, where one often will want to ignore the actual nesting of sub lists and just focus on the details of interest; the raisins in the cake :)



To be clear, the embedding into an if term: (if R ($it 1) '()) serves the purpose of avoiding a bad error if the ref term (i.e. the R above) doesn't find anything, and returns nil. In that way the code avoids the attempt of getting the value part of a list that isn't there (although it would be there had the ref succeeded). That embedding also utilizes the $it feature of newlisp, which simply holds the value of the condition term (it's available in if and and terms).
#45
You may want to build around using ref and ref-all, to "pick raisins";  something like this perhaps:
(define (raisins jsonitem)
    (format "<a href="%s">%s</a>n"<img src="%s">nn"
          (string (if (ref '("productUrl" ?) jsonitem match true) ($it 1)))
          (string (if (ref '("imageTitle" ?) jsonitem match true) ($it 1)))
          (string (if (ref '("imageUrl" ?) jsonitem match true) ($it 1))) ))

(map raisins (if (ref '("producs" ?) jsondata match true) ($it 1) '())


hth