Re: Classpath problem(?) with NetLogo-Ersatz integration
Not really. I've checked-in an updated version that works when ersatz/pil is invoked. Samuel Dennis R. Borlongan On Fri, Jun 27, 2014 at 1:28 PM, Christophe Gragnic christophegrag...@gmail.com wrote: Hi Samuel (and others reading!), On Fri, Jun 27, 2014 at 2:16 AM, Samuel Dennis Borlongan srborlon...@gmail.com wrote: You woud need to (load @java/java+.l) to load all the java interoperability functions. Thanks. Question to the audience: should I then add said function to the ersatz launch script as part of the changes? How do I add it to pil? Another question to the audience: I could replace my jar with the mainline jar, then advice users to mkJar so that they get a jar file containing my changes. Is it advisable? Launch script loading the lib: This could be nice for the user. Replace the .jar: Why not. Or provide both with some instructions. On Fri, Jun 27, 2014 at 4:11 AM, Samuel Dennis Borlongan srborlon...@gmail.com wrote: I have now added the ersatz enhancements library to ersatz/pil, and replaced the jar in my branch with mainline (users will now have to mkJar to have a version that has the enhancements). Great ! There is a problem with the path though. BTW, is there a good reason for the `java` dir not to be in the `ersatz` dir? /opt/srborlongan-picolisp $ ersatz/pil @java/java+.l -- Read open error /opt/srborlongan-picolisp $ mv java ersatz /opt/srborlongan-picolisp $ ersatz/pil : javaVersion - ((Print?) (javaVersion Print?)) : (bye) chri -- http://profgra.org/lycee/ (site pro) http://delicious.com/profgraorg (liens, favoris) https://twitter.com/profgraorg -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: Classpath problem(?) with NetLogo-Ersatz integration
How about now? (I blame Windows [path handling weirdness that allows syntax that doesn't work in non-Windows environments]) Samuel Dennis R. Borlongan On Fri, Jun 27, 2014 at 4:03 PM, Christophe Gragnic christophegrag...@gmail.com wrote: On Fri, Jun 27, 2014 at 9:10 AM, Samuel Dennis Borlongan srborlon...@gmail.com wrote: Not really. I've checked-in an updated version that works when ersatz/pil is invoked. Thanks but still no luck: $ ersatz/pil [ersatz/java/java+.l:1] !? (load @ersatz/java/init) @ersatz/java/init -- Read open error ? chri -- http://profgra.org/lycee/ (site pro) http://delicious.com/profgraorg (liens, favoris) https://twitter.com/profgraorg -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: Classpath problem(?) with NetLogo-Ersatz integration
Fixed. Now both ersatz/pil -javaVersion -bye and cd ersatz ; ./pil -javaVersion -bye ; cd .. work. Samuel Dennis R. Borlongan On Fri, Jun 27, 2014 at 8:26 PM, Christophe Gragnic christophegrag...@gmail.com wrote: On Fri, Jun 27, 2014 at 11:29 AM, Samuel Dennis Borlongan srborlon...@gmail.com wrote: How about now? Sorry, `ersatz/pil` is OK, but `cd ersatz` then `./pil` is not (ersatz/java/init -- Read open error). (I blame Windows [path handling weirdness that allows syntax that doesn't work in non-Windows environments]) Time to leave Windows ! (kidding) Well, I'm not sure about Windows vs others OSes differences playing a role here. You mean slashes vs backslashes or case insensitivity would affect Picolisp? Or something else that I miss? chri -- http://profgra.org/lycee/ (site pro) http://delicious.com/profgraorg (liens, favoris) https://twitter.com/profgraorg -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subjectUnsubscribe
Re: Classpath problem(?) with NetLogo-Ersatz integration
Fixed, and merged with v3.1.6.17. Samuel Dennis R. Borlongan On Sat, Jun 28, 2014 at 1:52 AM, Christophe Gragnic christophegrag...@gmail.com wrote: On Fri, Jun 27, 2014 at 4:11 PM, Samuel Dennis Borlongan srborlon...@gmail.com wrote: Fixed. Now both ersatz/pil -javaVersion -bye and cd ersatz ; ./pil -javaVersion -bye ; cd .. work. Almost. There is still a path separator issue. In ./pil, it's -cp .:tmp:... instead of -cp .;tmp:... Thanks for considering all the previous requests ! chri -- http://profgra.org/lycee/ (site pro) http://delicious.com/profgraorg (liens, favoris) https://twitter.com/profgraorg -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subjectUnsubscribe
Re: Classpath problem(?) with NetLogo-Ersatz integration
Try replacing the picolisp.jar file with the mainline jar. What I usually do is to call mkJar with the original jar, which then builds my version. The problem with my version of the jar is that I've been running Java 8 since the beta existed 6 months ago, so every time I cal mkJarWin, the resulting jar only works in Java 8. Apologies. Samuel Dennis R. Borlongan On Thu, Jun 26, 2014 at 9:55 PM, Christophe Gragnic christophegrag...@gmail.com wrote: Thanks. I'm making progress, but I can't figure out how the interop files in the java dir are loaded in Samuel's version. What I do for now is to manually append the files to the `pil` call. I'd like to understand and use the proper way ! -- http://profgra.org/lycee/ (site pro) http://delicious.com/profgraorg (liens, favoris) https://twitter.com/profgraorg -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: Classpath problem(?) with NetLogo-Ersatz integration
You woud need to (load @java/java+.l) to load all the java interoperability functions. Question to the audience: should I then add said function to the ersatz launch script as part of the changes? How do I add it to pil? Another question to the audience: I could replace my jar with the mainline jar, then advice users to mkJar so that they get a jar file containing my changes. Is it advisable? (As you may notice, I may be at least five years younger than you.) Samuel Dennis R. Borlongan On Fri, Jun 27, 2014 at 3:19 AM, Christophe Gragnic christophegrag...@gmail.com wrote: On Thu, Jun 26, 2014 at 5:54 PM, Samuel Dennis Borlongan srborlon...@gmail.com wrote: Try replacing the picolisp.jar file with the mainline jar. What I usually do is to call mkJar with the original jar, which then builds my version. The problem with my version of the jar is that I've been running Java 8 since the beta existed 6 months ago, so every time I cal mkJarWin, the resulting jar only works in Java 8. Thanks Samuel. I managed to build the .jar using a C/ASM Picolisp (irony!) but my problem is that I don't understand how to use your interop lib: how to load the files in your java dir? When I call ersatz/pil, javaImport is still NIL. I guess I'm missing something obvious. chri -- http://profgra.org/lycee/ (site pro) http://delicious.com/profgraorg (liens, favoris) https://twitter.com/profgraorg -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: Classpath problem(?) with NetLogo-Ersatz integration
I have now added the ersatz enhancements library to ersatz/pil, and replaced the jar in my branch with mainline (users will now have to mkJar to have a version that has the enhancements). Samuel Dennis R. Borlongan On Fri, Jun 27, 2014 at 8:16 AM, Samuel Dennis Borlongan srborlon...@gmail.com wrote: You woud need to (load @java/java+.l) to load all the java interoperability functions. Question to the audience: should I then add said function to the ersatz launch script as part of the changes? How do I add it to pil? Another question to the audience: I could replace my jar with the mainline jar, then advice users to mkJar so that they get a jar file containing my changes. Is it advisable? (As you may notice, I may be at least five years younger than you.) Samuel Dennis R. Borlongan On Fri, Jun 27, 2014 at 3:19 AM, Christophe Gragnic christophegrag...@gmail.com wrote: On Thu, Jun 26, 2014 at 5:54 PM, Samuel Dennis Borlongan srborlon...@gmail.com wrote: Try replacing the picolisp.jar file with the mainline jar. What I usually do is to call mkJar with the original jar, which then builds my version. The problem with my version of the jar is that I've been running Java 8 since the beta existed 6 months ago, so every time I cal mkJarWin, the resulting jar only works in Java 8. Thanks Samuel. I managed to build the .jar using a C/ASM Picolisp (irony!) but my problem is that I don't understand how to use your interop lib: how to load the files in your java dir? When I call ersatz/pil, javaImport is still NIL. I guess I'm missing something obvious. chri -- http://profgra.org/lycee/ (site pro) http://delicious.com/profgraorg (liens, favoris) https://twitter.com/profgraorg -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Java 7 Method Handles in Ersatz PicoLisp
http://picolisp.com/5000/!wiki?Invokedynamic http://code.google.com/r/srborlongan-picolisp/ Java 7 introduced the concept of method handles in the language, which are somewhat like function pointers in C++, except more type-safe (like Java) and with a more wordy API (also like Java). The current version of srborlongan-picolisp (essentially mainline PicoLisp with changes located in the ersatz/ and java/) now uses method handles on Java imports if Ersatz in run in a Java 7+ VM (Java 6 uses still use the old (last week) import code). Now, when a user invokes, say, String.format, instead of calling (java java.lang.String format %s%s (list 1 2) ), where the list must not contain primitives, users may now use (String.format %d%d%d 1 2 3), wherein the varargs property of the original method (String::format(String, Object...) is maintained by the corresponding method handle, which is then used internally by all imported Java functions. Thus, we now have the ability to call Java functions that previously dependended on all-Object arguments fluently: (java java.util.Arrays asList (1 2 3) ) # does not work (java+ java.util.Arrays asList (1 2 3) ) # still does not work (java java.util.Arrays asList (listAsArray (1 2 3) ) ) # uses method handles, works, but without varargs functionality of the original (Arrays.asList 1 2 3) $ works! This feature was inspired by the implementation of the cache method. In particular, the idea of binding a symbol in the function itself that may serves as an effectively private static variable (in Java-speak) if said symbol is transient is rather, well, beautiful. Samuel Dennis R. Borlongan
Ersatz Proposal: Interface implementations should return standard
Currently, if the resulting object from an 'interface' invocation is supposed to implement a method that returns values (like Supplier in Java 8): (setq String (interface java.util.function.Supplier get '(() (java java.lang.String T java.lang.String) ) ) ) Then, if the implemented method is invoked on the object: (java String get) The returned value is of the type PicoLisp$Symbol, since the curent implementation of interface returns the PicoLisp$Any result from evaluating the PicoLisp function bound to that method. Unfortunately, this means that there would be no way to retrieve the values returned from that interface implementation's method unless you implement heavy field-based recursion on the Any object. Fortunately, I've made a modification to interface that allows PicoLisp users to not only return Java values from interface implementation methods, but also all 5 possible value types from PicoLisp (T, NIL, Number, Symbol, and Cell): What I've done is to replace the return a; statement in interface to return toObject(a);, which is defined as: final static Object toObject(Any a) { if (a == T) { return true; } else if (a == Nil) { return null; } else if (a instanceof Number) { Number n = (Number) a; return n.Big instanceof BigInteger ? n.Big : n.Cnt; } else if (a instanceof Symbol) { Symbol s = (Symbol) a; return s.Obj instanceof Object ? s.Obj : s.Name; } else if (a instanceof Cell) { return toCollection((Cell) a); } return a; } In turn, the toCollection method is defined as (based on Cell::toString): final static Collection? toCollection(Cell c) { Any x, y; ListObject l; l = new ArrayListObject(); if (c.Car == Quotec != c.Cdr) { l.add(toObject(c.Car)); l.add(toObject(c.Cdr)); return l; } x = c; if ((y = circ(x)) == null) { for (;;) { l.add(toObject(x.Car)); if ((x = x.Cdr) == Nil) break; if (!(x instanceof Cell)) { l.add(toObject(x)); break; } } } else if (y == x) { do { l.add(toObject(x.Car)); } while (y != (x = x.Cdr)); } else { do { l.add(toObject(x.Car)); } while (y != (x = x.Cdr)); do { l.add(toObject(x.Car)); } while (y != (x = x.Cdr)); } return l; } Thus, using the previous example, the value returned would be of type String. With another example, if the Supplier implementation's get method was made to return a PicoLisp function: # Using srborlongan-picolisp's java interop functions (javaImport java.util.function.Supplier) (setq Supplier (Supplier.new () Supplier.new) ) # Supplier.new = (Body (interface java.util.function.Supplier get (cond ((and (= 1 (length Body)) (fun? (eval (car Body (eval (car Body))) ((fun? Body) Body) (T (append '(NIL) Body) (.get Supplier) # returns the value [Body, [interface, java.util.function.Supplier, get, [cond, [[and, [=, 1, [length, Body]], [fun?, [eval, [car, Body, [eval, [car, Body]]], [[fun?, Body], Body], [true, [append, [quote, [null]], Body] Please note that toCollection currently implements infinite lists or lists that end in atoms as normal lists. I might plan to implement infinite lists by adding the list itself at the end of the list, to make it easier to check if the list is looping. I do not know how to implement the other problematic type, however. Thanks! Samuel Dennis R. Borlongan
Re: Bouncing on trampolines (so cool...)
Re: side-note (bench (length (ack4 3 8000))) (32-bit Cygwin) 0.070 sec (bench (length (trampoline ack/t 3 8000))) (32-bit Cygwin) 2.010 sec (bench (length (trampoline ack/t 3 8000))) (64-bit Ersatz on Java 8, before =0 and length invocation removal) 9.625 sec (bench (length (trampoline ack/t 3 8000))) (64-bit Ersatz on Java 8, after =0 invocation removal) 4.981 sec (bench (length (trampoline ack/t 3 8000))) (64-bit Ersatz on Java 8, after =0 and length invocation removal) 0.123 sec I therefore conclude that ack/t was programmed badly. My fault. Also, efficient programming in Ersatz apparently _relies_ on things that might speed up a little. Trampolines are still fun, though. New version: (de ack/t (M N R S) (default R '()) (if R (unless S (setq M (pop 'R) ) ) (push 'R M) ) (cond ((not R) (done N) ) ((= M 0) (continue ack/t M (+ N 1) R) ) ((= M 1) (continue ack/t M (+ N 2) R) ) ((= M 2) (continue ack/t M (+ (* N 2) 3) R) ) ((= N 0) (continue ack/t (- M 1) 1 R T) ) (T (push 'R (- M 1) ) (continue ack/t M (- N 1) R T) ) ) ) Thanks for the comments! P.S. For the sake of context and gratuitous post-scripts, most of my work is done using Ersatz PicoLisp with LispIDE / Notepad++ on Windows workstations that run pre-release Java 8 and 108-tab Firefox. Again, thanks! Samuel Dennis R. Borlongan On Thu, May 16, 2013 at 7:33 PM, Alexander Burger a...@software-lab.dewrote: Hi all, I didn't bother with trampolines so far, but add some comments to On Thu, May 16, 2013 at 12:00:20AM +0800, Samuel Dennis Borlongan wrote: ... http://stackoverflow.com/questions/12186672/how-can-i-prevent-my-ackerman-function-from-overflowing-the-stack ... The bad thing with overflowing your stack is ... well, overflowing your stack. But you may as well overflow your heap, so nothing is gained. As it is recommended for PicoLisp anyway to set 'ulimit -s unlimited', the stack will use as much memory as is physically available, like the heap. The recursive version is usually faster than the one using an explicit stack, but uses perhaps a little bit more memory because each recursion level takes several stack lokations. Let's take the standard Ackermann function (de ack (M N) (cond ((=0 M) (inc N)) ((=0 N) (ack (dec M) 1)) (T (ack (dec M) (ack M (dec N ) ) Eliminating tail-recursion gives (de ack2 (M N) (loop (T (=0 M) (inc N)) (NIL (=0 N) (ack (dec M) (ack M (dec N (dec 'M) (one N) ) ) Both functions show roughly the same speed, : (bench (ack 4 1)) 249.465 sec - 65533 : (bench (ack2 4 1)) 252.487 sec - 65533 though the less-recursive function is slightly slower (as expected). If we go - as usually recommended - for the iterative version with an explict stack, (de ack3 (M N) (for (Stack (cons M) Stack) (if (=0 (setq M (pop 'Stack))) (inc 'N) (push 'Stack (dec M)) (if (=0 N) (one N) (push 'Stack M) (dec 'N) ) ) ) ) things get significantly slower: : (bench (ack3 4 1)) 312.028 sec - 65533 The fastest is - as expected and described - the cheating version: (de ack4 (M N) (for (Stack (cons M) Stack) (cond ((=0 (setq M (pop 'Stack))) (inc 'N)) ((= 1 M) (inc 'N 2)) ((= 2 M) (setq N (+ 3 (* 2 N (T (push 'Stack (dec M)) (if (=0 N) (one N) (push 'Stack M) (dec 'N) ) ) ) ) ) With that we get : (bench (ack4 4 1)) 0.000 sec - 65533 : (bench (length (ack4 4 2))) 0.981 sec - 19729 (de ack/t (M N R S) (default R '()) (if ( (length R) 0) (unless S (setq M (pop 'R) ) ) (push 'R M) ) (cond ((=0 (length R) ) (done N) ) ((= M 0) (continue ack/t M (+ N 1) R) ) ((= M 1) (continue ack/t M (+ N 2) R) ) ((= M 2) (continue ack/t M (+ (* N 2) 3) R) ) ((= N 0) (continue ack/t (- M 1) 1 R T) ) (T (push 'R (- M 1) ) (continue ack/t M (- N 1) R T) ) ) ) Honestly, I hate my Ackermann implementation, not because its performance is bad ( (trampoline ack/t 3 8000) takes 1.970 sec and 10.287 sec in 32-bit and ersatz, respectively) Are you sure? Here I get : (bench (length (ack4 3 8000))) 0.018 sec - 2410 and even on my humble Netbook with a slow Atom CPU (pil32): : (bench (length (ack4 3 8000))) 0.213 sec - 2410 ♪♫ Alex Side note (though this doesn't really matter for the speed): It is never wise to use 'length' to detect short lists. Better replace (if (=0 (length R)) ..)with (if R ..) or (if (= (length R) 3) ..) with (if (cddr R
Bouncing on trampolines (so cool...)
I'm currently playing a modified version of Hlavaty's trampoline function which accepts functions with multiple parameters ( http://code.google.com/r/srborlongan-picolisp/source/browse/java/trampoline.l) : (de trampoline (F . @) (let A (rest) (use R (loop (NIL (car (setq R (apply F A) ) ) (cdr R) ) (setq F (car R) A (cdr R) ) ) ) ) ) So far, I've successfully created test functions for mutual recursion, factorial, fibonacci, and ackermann. Comments that precede function definition are to be regarded as inspiration for said function. (de even/t (N) (if (=0 N) (done T) (continue odd/t (- N 1) ) ) ) (de odd/t (N) (if (=0 N) (done) (continue even/t (- N 1) ) ) ) (de fact/t (N R) (default R 1) (if ( N 2) (done R) (continue fact/t (- N 1) (* R N) ) ) ) # http://www.solutionsiq.com/resources/agileiq-blog/bid/72880/Programming-with-Groovy-Trampoline-and-Memoize (de fib/t (N R S) (default R 1 S 1) (if ( N 2) (done R) (continue fib/t (- N 1) S (+ R S) ) ) ) # http://stackoverflow.com/questions/12186672/how-can-i-prevent-my-ackerman-function-from-overflowing-the-stack (de ack/t (M N R S) (default R '()) (if ( (length R) 0) (unless S (setq M (pop 'R) ) ) (push 'R M) ) (cond ((=0 (length R) ) (done N) ) ((= M 0) (continue ack/t M (+ N 1) R) ) ((= M 1) (continue ack/t M (+ N 2) R) ) ((= M 2) (continue ack/t M (+ (* N 2) 3) R) ) ((= N 0) (continue ack/t (- M 1) 1 R T) ) (T (push 'R (- M 1) ) (continue ack/t M (- N 1) R T) ) ) ) Honestly, I hate my Ackermann implementation, not because its performance is bad ( (trampoline ack/t 3 8000) takes 1.970 sec and 10.287 sec in 32-bit and ersatz, respectively), but because I have had a nagging suspicion that there must something better than using a stack rather than a plain atom for storing intermediate values. One problem for me is that the other solution that has been presented involves making the continue function return functions instead of lists, which would mean I would have to rewrite the trampoline function. That's the thing: Hlavaty's trampoline function is too gosh darn _elegant_ for me to rewrite. I mean, seriously, the way it manages to use basic list manipulation to replace what would have been continuous function unwrapping in other languages. Thus, should I really complain that ack/t uses a stack if it means that the underlying bouncing principles are still maintained. Unless, of course, if using stacks in this context is stupid in the first place. P. S. I apologize for the length and relative lack of quality of this post. I'm actually feeling quite sleepy (GMT +8). The sleepier I get, the more hyperactive I get. Thus, long post. P.P.S. DaanSystem's LispIDE is cool. Samuel Dennis R. Borlongan
Ersatz updates (srborlongan branch): interface
http://code.google.com/r/srborlongan-picolisp/source/detail?r=cf63aa6f28cfead28c5a02ee3de4c322b5a3c9d7 I've changed the InvocationHandler in interface to return the correct Java object when used with interface with returning values. Example Java classes: @FunctionalInterface public interface FieldFIELD extends Enum?, VALUE { public VALUE field(FIELD field); } @FunctionalInterface public interface User extends FieldUser.Fields, String { public enum Fields { firstName, lastName } public default String firstName() { return field(Fields.firstName); } public default String lastName() { return field(Fields.lastName); } } Example Ersatz PicoLisp code: (javaImport User) (de user (@FirstName @LastName) (User.new # (interface User field (curry (@FirstName @LastName) (Field) (cond ((= Field User.Fields.firstName) @FirstName) ((= Field User.Fields.lastName) @LastName) ) ) ) ) # Before (.field (user Albert Wily) User.Fields.firstName) # = $PicoLisp$Symbol (might not be useful for Java interoperability) # After (.field (user Albert Wily) User.Fields.firstName) # = $String (might be useful for Java interoperability) (.field (user (.field (user Albert Wily) User.Fields.firstName) Einstein) User.Fields.firstName) # = $String (still useful) As always, the srborlongan-picolisp repository is always in sync with mainline. Have fun! P.S. Next plan is to refactor the heck out of my old Java code into Java 8 code, which would then make it easy to translate them to Ersatz PicoLisp, which may eventually result in Plan Super-Omega Plus: rewrite Ersatz PicoLisp in Java 8, then rewrite resulting Java 8 code into (Java-6 compatible) Ersatz PicoLisp; Ersatz in Ersatz, for radical (slow-as-fossilized-carbonite-mollases) self-hosting capabilities. P.P.S. I have no idea how to call Java 8 default methods from objects created using Ersatz PicoLisp's interface method. Any suggestions? Samuel Dennis R. Borlongan
Re: Ersatz Picolisp misc interop libraries update
Implemented Java 8 Lambda-style interface instantiation (version-agnostic, can run on Java 6). javaDefStatic can now check if the class it's defining is a functional interface. Java 8: Runnable println = () - System.out.println(Lambda); Ersatz: (let Println (Runnable.new () (println quote) ) ) --or-- (let Println (Runnable.new (println quote) ) ) Java 8: ConsumerString println = s - System.out.println(s); Ersatz: (let Println (Consumer.new (S) (println S) ) ) Sources: https://dl.dropbox.com/u/21827264/lisp.tar.gz https://docs.google.com/file/d/0B5bgSneQe6lYMHF4cXY5YkZqNTg/edit?usp=sharing Samuel Dennis R. Borlongan On Sat, Mar 9, 2013 at 6:09 PM, Jakob Eriksson ja...@aurorasystems.euwrote: This is so awesome, getting access to all Java libraries etc from PicoLisp :) lisp.tar.gz Description: GNU Zip compressed data