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

Topics - itistoday

#41
newLISP newS / bizarre string bug [nevermind]
January 10, 2009, 09:40:18 PM
never mind, my stupid mistake, see posts below.



Basically, newLISP claims that two strings, that are identical, are not.



Given this input file named "test.csv"]Date, Type, Net,
"11/22/2008","Web Accept Payment Received","15.00",
[/code]

Here is the output of the program:


'Web Accept Payment Received' vs 'Web Accept Payment Received'
data-type=Web Accept Payment Received, filter-type=Web Accept Payment Received
(!= date-type filter-type)=true
0 27


The string "Web Accept Payment Received" is stored in two variables, filter-type, and date-type.  It is defined in the script for filter-type, and it's read from the file and stored in data-type.



When printing the contents of those variables, they appear identical.  I even iterated over each character and verified they were the same ASCII value.  However, when asking for the length, newLISP claims data-type is 0 characters in length, and when checking equality (as shown above), it fails.



Here is the script so far (it's not complete), see the part where it says "BUG HERE":
#!/usr/bin/newlisp

; =============
; = configure =
; =============

(set 'csv-delimiter ",")
(set 'header-date "Date")
(set 'header-amount "Net")
(set 'header-type "Type")

; filters
(set 'filter-type "Web Accept Payment Received")
(set 'filter-min-amount 15)
(set 'filter-max-amount 20)

; ============
; = end conf =
; ============

; --------------
(context 'DataStore)

(context MAIN)
; --------------

(define (fail) (apply println (args)) (exit 1))
(define-macro (fail-on-nil) (doargs (arg) (if (nil? (eval arg)) (fail arg " is nil"))))
(define-macro (paras)
(join (map (lambda (x)
(string x "=" (eval x))
) (args)) ", ")
)

(set 'csv-input-file (main-args 2))

(if-not csv-input-file (fail "usage: ./" (main-args 1) " <paypal>"))
(if-not (file? csv-input-file) (fail "no such file: " csv-input-file))
(if-not (regex "(.*).csv" csv-input-file) (fail "not a csv file: " csv-input-file))

(set 'csv-output-file (append $1 "-out.csv"))

(set 'fin (open csv-input-file "r"))
(set 'fout (open csv-output-file "w"))

(set 'header-list (map trim (parse (read-line fin) csv-delimiter)))

; set the indexes
(set 'index-date (find header-date header-list))
(set 'index-amount (find header-amount header-list))
(set 'index-type (find header-type header-list))
(fail-on-nil index-type index-amount index-date)

; write the header
(write-line fout (append "Date" csv-delimiter " Copies Sold" csv-delimiter " "))

(while (read-line fin)
(set 'data-list (map (fn (x) (trim x """)) (parse (current-line) csv-delimiter)))
(set 'data-date (data-list index-date))
(set 'data-type (data-list index-type))
(set 'data-amount (float (data-list index-amount)))
(fail-on-nil data-date data-amount data-type)


;; BUG HERE
(println "'" data-type "' vs '" filter-type "'")
(println (paras data-type filter-type))
(println (paras (!= date-type filter-type)))
(println (length date-type) " " (length filter-type))

; (dostring (c data-type) (println c " - " (char c)))
; (println)
; (dostring (c filter-type) (println c " - " (char c)))

(exit)
;; END BUG

(if (and (= (length date-type) (length filter-type)) (>= data-amount filter-min-amount) (<= data-amount filter-max-amount))
(begin
(println data-date " " data-amount)
(DataStore data-date (+ (if $it $it 0) 1))
)
(println "skipping " data-date " $" data-amount)
)
)


(println "result: " (DataStore))

(close fin)
(close fout)
(exit)
#42
Whither newLISP? / Dynamic function creation
November 22, 2008, 04:12:59 PM
Let me know if you've seen this sort of thing in another language.  Let's say you have the following functions:


(define (foo a b c)
(string "error: " a b c)
)
(define (bar a b c)
(string "info: " a b c)
)


Wouldn't it be cool if you could eliminate the need for having multiple function definitions in certain situations? You could do something like this:


(define (log[var] a b c)
(string var ": " a b c)
)


Then you would call it like this:


(logerr "jazziffy" mylist)

And get the output:


Quoteerr: jazzify (1 2 3) nil


 You might even add some conditional syntactic sugar to it like so:


(define (log[-?var] a b c)
(string var ": " a b c)
)

; call it
(log-err "jazzify) ; => err: jazzify nil nil
(log-info "jazzify") ; => info: jazzify nil nil
(log- "jazzify") ; => nil: jazzify nil nil
(log "jazzify") ; => nil: jazzify nil nil


This is admittedly a very very stupid example, but I'm sure this could turn out to be really useful in some situations where otherwise you'd have multiple functions essentially doing the same thing, they could be called "newLISP function templates", or something. :-)
#43
I've just finished a massive endeavor.



I'm making a site that uses AJAX.  To know whether or not there was an error AJAX needs to get the right HTTP header, (e.g. "HTTP/1.0 200 OK", etc.)



The problem: newLISP does not do this properly, so testing the site via http mode in it did not work.



The solution: I spent a LONG time figuring out what was going on, and in the meantime learning about .cgi and HTTP.  I ended up compiling a custom version of newLISP to get things working because...



newLISP ignores .cgi Status: headers.  As far as I can tell from what I've read, the way things are supposed to work (and the way it works with Apache), a .cgi script does not write the first HTTP status header.  Instead it uses a custom Status: header that's pretty much identical, which the server is then supposed to translate to the corresponding HTTP status header.



newLISP does not do this.  It always responds with "HTTP/1.0 200 OK" as long as it managed to load the .cgi script and execute it.



So, what I'm doing right now for my testing purposes to get around this problem is I modified the newLISP binary to not print out the first header if it's running a .cgi script (and then my script prints it out for it, if it detects that newLISP is the server):



I modified the sendHTTPpage function in nl-web.c to take an extra parameter.


void sendHTTPpage(char * content, size_t size, char * media, int closeFlag, int headerFlag)
{
if ( headerFlag ) varPrintf(OUT_CONSOLE, "HTTP/1.0 200 OKrnServer: newLISP v.%d (%s)rn", version, ostype);


This is obviously a hack, the correct behavior should be that newLISP reads the headers that the cgi script provides and changes its response if it sees a Status header (e.g. "Status: 500 Internal Error").



(Oh, I'm going to be posting my template system for newLISP soon, as it's going to drive part of my site (see sig).)
#44
newLISP newS / Bus error in 9.9.2 - unless crapping out
September 20, 2008, 11:17:52 AM
I'm running newlisp like this:


newlisp -w . -d 8080 -http

Visiting localhost:8080 and getting this error on the command line:


sh: line 1:  8513 Bus error               ./index.cgi > /tmp/nl497f6f194365e8400d

line 1 contains:


#!/usr/bin/newlisp

I was able to find out what the problem was.  In upgrading my templating system to use 9.9.2 stuff, I had changed this code:


; file util.lsp (included several times)

(define (load-once:load-once)
(doargs (file)
(if-not (find file load-once:_loaded)
(begin
(push file load-once:_loaded)
(load file)
)
)
)
)

(context MAIN)


To this code:


; file util.lsp (included several times)

(define (load-once:load-once)
(doargs (file)
(unless (find file load-once:_loaded)
(push file load-once:_loaded)
(load file)
)
)
)

(context MAIN)
#45
newLISP newS / Making true and nil functions...
September 10, 2008, 10:12:20 AM
I don't know scheme very well, but I saw something in some scheme code the other day that I've wished before was in newlisp:


((> i n) (newline))

Wouldn't it be cool if you could do that?  So instead of doing:


(if (> 1 0) (println "it is!"))

You could just do:


((> 1 0) (println "it is!"))

You could even have the syntax allow an entire body of statements to be evaluated, e.g.:



function: (true <body>) => evaluates <body>

function: (nil <body>) => does NOT evaluate <body>



Or would this break too many things..?
#46
This is a somewhat significant bug as it makes web-development not possible using Firefox (I have to use Safari instead).



Safari picks up the error in its console:



"Resource interpreted as stylesheet but transferred with MIME type text/html."

For http://localhost:8080/css/style.css">http://localhost:8080/css/style.css



and



"Resource interpreted as script but transferred with MIME type text/html."

For http://localhost:8080/js/effects.js">http://localhost:8080/js/effects.js



Firefox won't load the CSS file (and probably ignores the javascript too) because of this...
#47
The basic idea is to allow a file to be loaded multiple times safely, same concept as with C header guards.  I'm having issues with my solution though which goes like this:


;; file class.lsp

(context MAIN)
(if-not Class (begin

(context 'Class)

(define (some-function) (println "hello!"))

))


This way "class.lsp" can be (load)'ed multiple times from multiple files.



However, it doesn't really work.  For some odd reason the defined functions go into the MAIN context and not the Class context.



Help?
#48
Hey, I wrote a program to count lines of code.. it'll go down an entire directory tree.  Move it to /usr/local/bin/numlines or wherever your preferred PATH is and run it like this:



$ cd path/to/project/dir

$ numlines



If you want to filter out someone else's code (say you have code from the Growl framework) you run it like this:



$ numlines Growl



If "Growl" is in the filename (case-sensitive) then it won't be counted as part of the total.


#!/usr/bin/newlisp

; numlines

(constant 'S_IFLNK 40960)
(constant 'SIGINT 2)
(constant 'extensions '(".h" ".cpp" ".c" ".cc" ".m" ".java" ".lsp" ".lisp" ".sh" ".py" ".rb"))

(set 'total 0)

(define (string-contains L str)
(!= '() (filter (fn (x) (find x str)) L))
)

(define (string-ends-with L str)
(!= '() (filter (fn (x) (ends-with str x)) L))
)

(define (ctrlC-handler)
(println "Total lines so far: " total)
(exit 1)
)

(define (num-lines-in-file file , (num 0) fd)
(if (string-ends-with extensions file)
(if (string-contains (2 (main-args)) file)
(if (> (length (2 (main-args))) 0)
(println "skipping file: " file)
)
(begin
(set 'fd (open file "r"))
(if fd
(begin
(while (read-line fd) (inc 'num))
(close fd)
(println num "ttlines in: " file)
)
(println "*** couldn't open: " file)
)
)
)
)
(inc 'total num)
)

(define (num-lines-in-dir dir)
(change-dir dir)
(dolist (e (directory))
(if (!= "." (e 0))
(if (directory? e)
(if (= 0 (& S_IFLNK (file-info e 1)))
(num-lines-in-dir e)
(println "skipping symbolic link: " e)
)
(num-lines-in-file e)
)
)
)
(change-dir "..")
)

; begin program

(signal SIGINT 'ctrlC-handler)
(num-lines-in-dir ".")
(println "Total: " total " lines")
(exit)
#49
Anything else we might add? / Calling newLISP from C
February 28, 2008, 08:46:22 PM
Note: If you're wondering why there's a space in between semi-colons and parenthesis it's because this forum cannot handle them.  It took me a while to figure this out.  Try posting this: 'exec(asdf)' (no quotes) followed immediately by a semi-colon.  Just try it.



Update: Woah.. and apparently it doesn't like the ".h" on the end of a header file either... Very very weird forum.




I wrote some convenience functions for dealing with newLISP in C.  I use the term "dealing with" as opposed to "using" because currently it doesn't seem like newLISP is really designed to be called from C/C++ applications.  It would be nice for example if C apps could have direct access to raw data types inside of the newLISP world instead of having to parse strings.



Here are some examples of using some of these functions:



nl_exec(const char *cmd, ...)
nl_exec("(append {/tmp/} (lower-case (slice (join (find-all {[a-zA-Z]+} {%s}) {-}) 0 10)) {.socket})", name) ;

int nl_copyresult(char *buff, int len, int options) ;
char buff[100];
nl_copyresult(buff, 100, NL_NO_QUOTE) ;


There we passed NL_NO_QUOTE because since, again, the only interface you have to newLISP is what's output on the read-eval loop, strings will have quotes around them, and you probably don't want those.



char *nl_result(void) ;
char *my_copy = strcpy(nl_result()) ;

Note: nl_result returns a pointer to newLISP's result buffer (with the n removed), so you probably want to copy it.



Here's the code:



Header file:


#define NL_NO_QUOTE (1<<0)

int nl_load(void) ;
bool nl_loaded(void) ;
int nl_exec(const char *cmd, ...) ;
int nl_error(void) ; // result of running nl_exec
char * nl_result(void) ;
int nl_copyresult(char *buff, int len, int options) ;


Implementation:


#include <stdarg>

static bool newlisp_loaded = false;
static char * (*newlispEvalStr)(char *) ;
static char * nl_buff = NULL; // pointer to newlisp's result buffer
static int nl_err = 0;

int load_newlisp()
{
// load newLISP.(dylib|so|dll) ...

newlisp_loaded = true;
nl_exec("(signal 2 true)") ; // default action for SIGINT, makes ^C work properly
return 0;
}

bool nl_loaded()
{
return newlisp_loaded;
}

#define CMD_BUFF_LEN 2048
int nl_exec(const char *cmd_fmt, ...)
{
va_list data;
static char cmd_buff[CMD_BUFF_LEN];

if ( ! newlisp_loaded ) {
log_err("nl_exec: newlisp not loaded") ;
return -1;
}

va_start(data, cmd_fmt) ;
vsnprintf(cmd_buff, CMD_BUFF_LEN-1, cmd_fmt, data) ;
va_end(data) ;

nl_buff = newlispEvalStr(cmd_buff) ;

if (strncmp(nl_buff, "nmissing", 8) != 0)
nl_err = 0;
else
nl_err = -1; // error occurred, most likely command too long

return nl_err;
}

char * nl_result()
{
if ( ! newlisp_loaded ) {
log_err("nl_result: newlisp not loaded") ;
return NULL;
}
else if (nl_buff == NULL) {
log_err("nl_result: nl_exec not called") ;
return NULL;
}

char *ptr = nl_buff;
while (*ptr != '') ++ptr;
*(--ptr) = ''; // get rid of n

return nl_buff;
}

int nl_copyresult(char *buff, int len, int options)
{
if ( ! newlisp_loaded ) {
log_err("nl_copyresult: newlisp not loaded") ;
return -1;
}
else if ( nl_buff == NULL ) {
log_err("nl_copyresult: nl_exec not called") ;
return -1;
}

char *ptr = nl_buff;
int copied = 0;

if ( (NL_NO_QUOTE & options) > 0 && *ptr == '"' )
++ptr;

while ( *ptr != '' && --len >= 0 ) {
*buff = *ptr;
++ptr; ++buff; ++copied;
}

if ( len > 0 )
{
if ( *(ptr-1) == 'n' ) {
*(--buff) = '';
--copied;
}
else *buff = '';

if ( (NL_NO_QUOTE & options) > 0 && *(buff-1) == '"' ) {
*(buff-1) = '';
--copied;
}
}

return copied;
}

int nl_error(void)
{
return nl_err;
}
#50
Anything else we might add? / Streams in newLISP
February 23, 2008, 03:51:06 PM
Note: This was originally http://www.alh.net/newlisp/phpbb/viewtopic.php?p=11844#11844">a response to Pavel in his thread, but I figure it deserves its own thread.


Quote from: "Elica"Now let me go back to newLisp. Does it support streams/sequences? (Not in the sense of I/O streams, but in the sense of infinite lists with delayed evaluation).


Thanks for asking this question.  I was planning on investigating this question myself a while ago but never got around to it.  Because of you I decided to spend the time finally. :-)



Short answer: Yes, but not elegantly like with Scheme.  I think this is mainly due to the newLISP's dynamic scope.  For example, trying to do memoization does not seem ... possible (actually it is, see several posts down).  You might be able to do something with contexts but I think it would turn out ugly...



Long answer](set 'the-empty-stream '())

(define-macro (cons-stream)
   (letex (x (args 0) y (args 1))
      (cons x (list (delay y)))
   )
)

(define-macro (delay)
   (letex (x (args 0)) (fn () x))
   ;(letex (x (args 0)) (memo-proc (fn () x)))
)

(define (memo-proc)
   (letex (func (args 0))
      (fn ()
         (if (not already-run?)
            (begin
               (set 'result (func))
               (set 'already-run true)
            )
         )
         result
      )
   )
)

(define (head s)
   (first s)
)

(define (tail p)
   (force (last p))
)

(define (force func)
   (func)
)

(define (nth-stream n s)
   (if (= n 0)
      (head s)
      (nth-stream (- n 1) (tail s))
   )
)

(define (empty-stream? s)
   (empty? s)
)

(define (print-stream s)
   (if (empty-stream? s)
      "done"
      (begin
         (print (head s) " ")
         (print-stream (tail s))
      )
   )
)

(define (enum-interval low high)
   (if (> low high)
      the-empty-stream
      (expand (cons-stream low (enum-interval (+ low 1) high)) 'low 'high)
   )
)

(define (integers-from n)
   (expand (cons-stream n (integers-from (+ n 1))) 'n)
)

(set 'integers (integers-from 1))
(println "nth 20: " (nth-stream 20 integers))

(while true
   (print "> ")
   (read-line)
   (if (= (current-line) "")
      (exit)
      (println (eval-string (current-line)))
   )
)
[/code]

I tried:


> (print-stream integers)

And it printed up to 678 and then crashed:


call stack overflow in function list : delay
called from user defined function integers-from
called from user defined function func
called from user defined function force
called from user defined function tail
called from user defined function print-stream
called from user defined function print-stream
called from user defined function print-stream
...




This is simply because newLISP doesn't have tail-call recursion.  You can change the stack size using the -s option when running newlisp.  Update]


(define (print-stream s)
(while (not (empty-stream? s))
(print (head s) " ")
(set 's (tail s))
)
"done"
)


You can have fun, here's an example using the above program's evaluator:


> (set 'ones (cons-stream 1 ones))
(1 (lambda () ones))
> (print-stream ones)
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 .... (it goes on.. and then crashes)
#51
Anything else we might add? / newLISP Cocoa Bridge
February 05, 2008, 01:51:28 PM
Is this possible?  Is there any interest in it / has there been any discussion about it?  I know that there's a http://programming.nu/">Nu language out there... but I like newLISP so much!
#52
I'm trying to create a tree class using http://www.alh.net/newlisp/phpbb/viewtopic.php?p=11096">the data-type macro Lutz introduced.  The class is created like so:


(data-type (tree data children))

data can be anything, and children is a list of other trees.  So say I want to define a function (or macro, don't know which) called tree:add-child that takes a tree node and a child node and adds the child to the parent node's children list.  How do I do this without copying data?  I just want to update the list inside the parent without having to duplicate and replace it.



If the data is an integer, then an example of a node containing 2 leaf nodes is this:


(tree 0 ((tree 1 ()) (tree 2 ())))

Also, I do not want this to be a solution involving creating a context for every object, because I want to be able to refer to these things anonymously and in general that's not a very elegant solution as it requires that you have a naming scheme for your context symbols (like tree1, tree2, etc...).



Any help is much appreciated!
#53
newLISP newS / (length my-list) - O(n) or O(1) ?
December 03, 2007, 07:00:06 PM
Does (length) calculate the size of a list by iterating through its elements or is there a value stored somewhere internally?
#54
Anything else we might add? / IRC channel
December 03, 2007, 05:31:33 PM
Is there an IRC channel for newLISP?  I think it would be really helpful to the entire community if there was...
#55
newLISP newS / Better array support?
December 02, 2007, 06:44:18 PM
Is this planned for the future?  It would be nice if more of the functions that operated on lists would also operate on arrays, for example (sort).  As a big fan of newLISP I would be glad to help implement this myself, it's just that school won't give me a minute's rest.  :