Before starting

Started by kib2, November 07, 2008, 12:19:42 PM

Previous topic - Next topic

kib2

Hi,



I'm new to newLisp, but before I really start playing with it, I need your lights on several points :



- can we make an executable file from a lsp one ? I know that asking such a question on a Lisp forum would result in "you don't have to, just run your script from the REPL". But I really do care about this: users are not programmers, and they need to be able to launch an app without having to spend their time fighting with EMacs/Slime or whatever.



- the only book I've got on Functionnal programming is Peter Seibel's "Practical Common Lisp". The first time he handles a macro, he shows something like this :



 
(defmacro backwards (expr) (reverse expr))

CL-USER> (backwards ("hello, world" t format))
hello, world
NIL


I've tried doing the same 'reverse' macro with newLisp, but I don't know where I'm going wrong :



> (define-macro (backwards expr) (reverse expr))
(lambda-macro (expr) (reverse expr))
> (backwards ("something" println))
(println "something")


The result is not interpreted and I must miss something, but what ?



Thanks for your answsers,



Kib².

unixtechie

#1
please, read the "Cookbook" ("Code Patterns") and/or "introduction" from the newlisp documentation.

It's chock full of practical examples.

You can reimplement shell scripts, perl scripts and so on to practically useful little programs -- completely avoiding (or rather postponing) the more academic books on the subject, which are mostly interested in "factorial" and then reimplementing very low-level stuff as an exercise in pedantry.



That is the unfortunate tradition in teaching Lisp.

You can avoid it by starting immediately to use high-level perl-like functionality of newlisp if you start from its own documentation.



Experimenting with building unobvious abstractions will be the next step after you've remembered and used the main operators of newlisp (which is like a nice cross between a scheme and common lisp) and got the hang of it.



See "Documentation" here:

http://www.newlisp.org/index.cgi?page=Features">http://www.newlisp.org/index.cgi?page=Features





TO ANSWER YOUR FIRST QUESTION, yes one can make a pseudo-standalone executable from a newlisp script: please READ THROUGH THE MANUAL at least once.

Basically, the idea is that you include some command file and run one command, and it will bundle your script with the newlisp executable together.

For the user it'll look like a standalone exec of 230k+(size of your script), very roughly.

For the machine it's a self-extracting script that will be then interpreted in a usual way by the small and fast newlisp language binary.

kib2

#2
Hi unixtechie,



You're right I've not read the entire docs (but if you want to test a new language, you often read between the lines...and the manual is just 329 pages long!).



I've no interest in building shell scripts-like, I'm using Python, Perl or Ruby for such everyday tasks. Nor do I want to write another factorial :)



But in following your suggestion, I just realized that I missed the nice vids from Michael Michaes : they are very well done.



Thanks for answering my first answer, I'll try to read the manual carefully.

What about the second one ?



I like playing with text and regexps, so I've tried to download the wiki engine, but the link seems dead.



Another question : when does the v10.0.0 comes out ?



Thanks.

cormullion

#3
Hi Kib2!



I'm not a Lisp expert, and so I'm puzzled by your CL example, but I would assume you want this in newLISP:


(define-macro (backwards expr) (eval (reverse expr)))

where the eval will actually evaluate the (reverse expr) expression, rather than just reverse it and return...

kib2

#4
Hi cormullion,



I've taken the sample from chapter 3 of PCL : http://gigamonkeys.com/book/practical-a-simple-database.html">http://gigamonkeys.com/book/practical-a ... abase.html">http://gigamonkeys.com/book/practical-a-simple-database.html (about 3/4 of the page, or search for the word 'macro', it's quicker). PCL is not like other academic books, it has been a pleasure to read.



Yes, once I saw the result in my newLisp code, I though I had to 'eval' the result, and sure it works. Now my question is rather "why should I eval the result ?" and "why is it different from Common Lisp internals ?".



See you.

cormullion

#5
It's an interesting challenge - learning one language from a book written about another. You're almost learning two languages at once...  And why not! :)



There are sufficient differences between CL and newLISP that would make that approach a bit frustrating for some people, though. Lutz' advice in the FAQ is to not refer to a Common Lisp or Scheme tutorial:


QuoteDon't read books about LISP to learn newLISP. Most books deal with Common LISP or Scheme, two different, older standards of LISP. These books teach you concepts that you don't need to know to learn newLISP. newLISP does things much differently from the older standards, in ways that are more applicable to today's programming tasks.



If you study other LISPs before trying to understand newLISP, you won't learn to solve problems the newLISP way. But if you want a deeper understanding of newLISP, read the Users Manual section of the newLISP manual, with less theory and more examples. There is also Code Patterns with more tips and code pieces.

 

Part of the specific answer to your question is that technically (and I'm not confident that I know what I'm talking about here) newLISP doesn't have macros, but http://en.wikipedia.org/wiki/Fexpr">fexprs. These are frowned upon in the CL world for (possibly) perfectly valid reasons, but these reasons may not be significant for your application or purpose.



As for version 10, only Lutz knows, but if I were to guess a release date, I'd say early December... :)

Kazimir Majorinc

#6
Why CL needs macros, on the first place?



Because there are some things that cannot be done with functions. For example, you cannot write function ifnt that behaves like inverse if ((ifnt a b c) = (if a c b)) in Common Lisp .
(ifnt (> i 1) (setf i 10) (setf i 100))

because both (setf i 10) and (setf i 100) are evaluated before ifnt is called. And ifnt, just like if wants that only one of these two is evaluated. One might think that expressions can be quoted
(ifnt '(> i 1) '(setf i 10) '(setf i 100))

But neither it works in Common Lisp - because function ifnt doesn't understand what is the value of i (except if i is global variable). Common Lisp need something much different than function.



In Newlisp this second works - because Newlisp has dynamic scoping and unrestricted eval. CL has static scoping and restricted eval. Newlisp functions see that i from caller environment, you do not need to pass it as a separate argument. So, Newlisp essentially doesn't need macros at all - functions can do all that. And macros are functions with tiny bit of syntactic sugar - one doesn't need to use quotes like in '(> i 1) in caller environment.



CL macros are more complicated. They are evaluated during compile time, and they generate expression that is evaluated during runtime. Newlisp macros are just like functions. That's why texts on CL macros are not very useful for Newlisp macros.



This really isn't simple issue.
http://kazimirmajorinc.com/\">WWW site; http://kazimirmajorinc.blogspot.com\">blog.

m i c h a e l

#7
Quote from: "kib2"... I just realized that I missed the nice vids from Michael Michaes : they are very well done.


Thank you for your kind words, kib2. Actually, I've just finished the first episode of a new video series (although work on the second episode is presently holding up completion of the first ;-) This latest offering will be released with a companion slideshow, too!



m i c h a e l

kib2

#8
-->cormullion : "You're almost learning two languages at once...

    And why not! :)"

   

You're right, maybe that's not the good approach. Thanks for telling me about

the CL fexprs : I wasn't aware of them.



    -->Kazimir :

   

Thanks for your nice sample. Maybe I'm wrong, but the simple 'if' cannot be a function too : right ?

   

    -->michael :

   

Cool : the slideshow is a good idea too.

newBert

#9
Quote from: "cormullion"It's an interesting challenge - learning one language from a book written about another. You're almost learning two languages at once...  And why not! :)


I learnt NewLISP (and Scheme, that I left on one side now to concentrate on newLISP) using a french Python tutorial, that I annotated with newLISP codes.



It's interesting to learn two or more languages at once ...so long as they are not too nearby like newLISP and Common Lisp or newLISP and Scheme for instance. Because, in a way one interfere too much with the other, in any case as for me. I prefer to use different languages, which enrich each other instead...



I quite like using, almost at the same time, http://www.newlisp.org/">newLISP, http://www.rebol.com/">Rebol, http://www.fbsl.net/pmwiki/index.php">FBSL and http://www.elica.net/site/about/about.html">ELICA ...



... moreover http://www.gigamonkeys.com/book/">Practical Common Lisp is an excellent and easy tutorial which gave me help too



:-)
<r><I>>Bertrand<e></e></I> − <COLOR color=\"#808080\">><B>newLISP<e></e></B> v.10.7.6 64-bit <B>>on Linux<e></e></B> (<I>>Linux Mint 20.1<e></e></I>)<e></e></COLOR></r>

Kazimir Majorinc

#10
Quote from: "kib2"  

simple 'if' cannot be a function too : right ?


True, if cannot be the function in CL, with or without extra quotes. However, if can be function in Newlisp with extra quotes.


(set 'iff (lambda(a b c)(if (eval a) (eval b) (eval c)))

(iff '(= (+ 2 2) 4)'(println "yes")'(println "no"))


The function iff uses macro-like primitive if, but it can be avoided.


(set 'ifily (lambda(a b c)
             (eval (nth (find (eval a) '(true nil))
                        (list b c)))))

(ifily '(= (+ 2 2) 5) '(println "yap!") '(println "nope!"))


Note that CL has not fexprs=Newlisp macros. Older, pre-CL Lisps had fexprs. It would be hard to implement fexprs in CL; on the other hand, it is easy to implement CL macros in Newlisp.
http://kazimirmajorinc.com/\">WWW site; http://kazimirmajorinc.blogspot.com\">blog.

kib2

#11
QuoteNote that CL has not fexprs=Newlisp macros. Older, pre-CL Lisps had fexprs. It would be hard to implement fexprs in CL; on the other hand, it is easy to implement CL macros in Newlisp.


ok, that suggest me some more questions :



- if fexprs were so good, why do they disappear from CL ?



- P.Seibel said :
QuoteAnd, in a compiled Lisp program, that new language is just as efficient as normal Lisp because all the macro code--the code that generates the new expression--runs at compile time. In other words, the compiler will generate exactly the same code whether you write
. Is this statement true for newLisp too ?

cormullion

#12
newLISP doesn't compile, so you just write elegant and efficient code to begin with. :)



As for the fexpr stuff, that wikipedia article told me more than I wanted to know... :) They pose problems for compilers, was my understanding... (" the compiler cannot tell whether a subexpression can be safely optimized, since the subexpression might be treated as unevaluated data at run-time".

Kazimir Majorinc

#13
Quote from: "kib2"if fexprs were so good, why do they disappear from CL ?


In my opinion it is bad design. It is justified by fact that fexprs are hard to understand by programmers, and trouble for compiler writers. For example, one of the arguments is that if you have fexprs, compiler cannot optimize (f (+ 1 1)) because it doesn't know whether f is fexpr of function. Function doesn't care, but fexpr does. Kent Pitman wrote historically important article http://www.nhplace.com/kent/Papers/Special-Forms.html">Special forms in Lisp about that. It took me long time to understand it, but I think it is all more-less wrong.


Quote- P.Seibel said :
QuoteAnd, in a compiled Lisp program, that new language is just as efficient as normal Lisp because all the macro code--the code that generates the new expression--runs at compile time. In other words, the compiler will generate exactly the same code whether you write
. Is this statement true for newLisp too ?


If Newlisp has optimizing compiler, it could be the truth. With "ordinary" compiler, compiled code would be bit slower. Only a bit, however. But, as Cormullion said, there is no compiler for Newlisp at all, it is interpreter, so every function and macro you write is necessarily slower than primitives.



However, that macroexpansion phase that Siebel described enthusiastically is not really good thing in every situation. Look at following CLisp code:


[1]> (defun pump-l(n x)(setf L ())(dotimes(i n)(push x L)))
[2]> (defun eval-whole-L()(dolist (f L)(eval f)))

[3]> (pump-l 100000 '(progn (setq A ())(push 0 A)))
[4]> (time (eval-whole-l))

Real time: 3.046875 sec.
Run time: 3.046875 sec.
Space: 91965272 Bytes
GC: 144, GC time: 0.375 sec.


This is relatively slow - because it contains macro push. Now, look what happens if I avoid macro (push 0 A), replacing it with its expansion (setq A (cons 0 A)) manually:


[5]> (pump-l 100000 '(progn (setq A ())(setq A (cons 0 A))))
[6]> (time (eval-whole-l))

Real time: 0.1875 sec.
Run time: 0.1875 sec.
Space: 800008 Bytes
GC: 1, GC time: 0.015625 sec.


You see, 15 times faster code and 100 times less memory use. Why? In this example, code is generated - and then evaluated during runtime. Hence, because code contained push macro, macroexpansion happened during runtime - there was no choice. And that macroexpansion took some 95% of total processing time. So, CL macros are not really suitable for code generated and evaluated during runtime.
http://kazimirmajorinc.com/\">WWW site; http://kazimirmajorinc.blogspot.com\">blog.

newdep

#14
I love how intresting topics popup here...

...and with even nicer explanations ;-)





PS: Kazimir, you got some psychedelic webpage there ;-)
-- (define? (Cornflakes))