newLISP development release v.10.1.11
newLISP development release v.10.1.11
* new functions and additions to older functions
The 10.2 newLISP release notes and the "Deprecated functions" chapter in the users manual show how to make new code compatible with previous versions of newLISP.
files and CHANGES and release notes: http://www.newlisp.org/downloads/development/
The 10.2 newLISP release notes and the "Deprecated functions" chapter in the users manual show how to make new code compatible with previous versions of newLISP.
files and CHANGES and release notes: http://www.newlisp.org/downloads/development/
Re: newLISP development release v.10.1.11
Where did my makefile_darwin_universal_utf8_compat go? It's no longer with the source distribution. This is a rather important makefile, as with it I am able to safely bundle newlisp scripts with the newlisp binary.
Get your Objective newLISP groove on.
Re: newLISP development release v.10.1.11
Also, looks like caller isn't working as I'd hoped:
Apparently I have to call (foo) from within a function for caller to be useful, and not even any function but specifically a *user-defined* function. To me this makes caller almost completely useless; I can't define for-query-with-db or any other interesting functions with it. :-(
Can you introduce a function, or modify caller so that it returns the context that the function was called from?
Code: Select all
> (context 'foo)
foo
foo> (define (foo:foo) (caller))
(lambda () (caller))
foo> (context MAIN)
MAIN
> (foo)
nil
Can you introduce a function, or modify caller so that it returns the context that the function was called from?
Get your Objective newLISP groove on.
Re: newLISP development release v.10.1.11
The universal darwin makefile will be added back.
Regarding 'caller': It returns the calling function, not the context of the function called. See here for valid examples:
http://www.newlisp.org/downloads/develo ... tml#caller
Your example seems to imply, that you want to know the called function's context. You can have that by just returning '(context)' from the called function (not the caller). The reference for 'caller has an example how to get the context of the caller of a function.
Regarding 'caller': It returns the calling function, not the context of the function called. See here for valid examples:
http://www.newlisp.org/downloads/develo ... tml#caller
Your example seems to imply, that you want to know the called function's context. You can have that by just returning '(context)' from the called function (not the caller). The reference for 'caller has an example how to get the context of the caller of a function.
Re: newLISP development release v.10.1.11
Thanks!Lutz wrote:The universal darwin makefile will be added back.
Sorry, I edited my post because I saw that as well, please see the post again.Lutz wrote:Regarding 'caller': It returns the calling function, not the context of the function called. See here for valid examples:
No, you seem to have completely misread what I've said here, and in the other thread. context returns the context that the function is in. I need the context from which the function was called.Your example seems to imply, that you want to know the called function's context. You can have that by just returning '(context)' from the called function.
Here, again, is the function I'm trying to define, please read it:
Code: Select all
(define-smacro (for-query-with-db db query)
(letn (db (eval db) sql (db:prepare-sql (eval query)) keys '())
(dotimes (i (sql:col-count))
;(push (sym (upper-case (sql:col-name i)) (prefix (caller))) keys -1)
(push (sym (upper-case (sql:col-name i)) Dragonfly) keys -1)
)
(push-autorelease-pool) ; in case we have blobs
(while (list? (setf values (sql:next-row)))
(eval (expand (cons 'begin $args) (unify keys values)))
)
(pop-autorelease-pool)
(deallocate sql)
)
)
I don't know why it doesn't work, but I get nothing but nils. I have to manually write Dragonfly in (see the uncommented line above, just below the comment-out one), even though that results in an identical function call with the same exact parameters.
I'll repost here how this function is used:
Code: Select all
(for-query-with-db db "SELECT name,age FROM people"
(println NAME " " AGE)
)
Last edited by itistoday on Tue Feb 16, 2010 3:00 am, edited 1 time in total.
Get your Objective newLISP groove on.
Re: newLISP development release v.10.1.11
Here's more bizarro weirdness:
When I run that, the call to println prints: "Route.Static vs Dragonfly"
That doesn't make any sense.
The way for-query-with-db is called is as follows:
A function in a context Route.Static calls a function in the Dragonfly context that reads in a file using read-file, this file contains a mix of HTML and inlined newlisp code. This string is converted into a string containing nothing but executable newLISP code. It his then eval'd using the function eval-string in the Dragonfly context. Somewhere in that evaluated code is a call to for-query-with-db, which itself is a macro that is defined within its own context to protect against variable capture (using the define-smacro we discussed in a thread a while ago).
Code: Select all
(define-smacro (for-query-with-db db query)
(letn (db (eval db) sql (db:prepare-sql (eval query)) keys '() ctx (prefix (caller)))
(println ctx " vs " (prefix (caller))) ; <-------- WTF?
(dotimes (i (sql:col-count))
;(push (sym (upper-case (sql:col-name i)) (prefix (caller))) keys -1)
;(push (sym (upper-case (sql:col-name i)) ctx) keys -1)
(push (sym (upper-case (sql:col-name i)) Dragonfly) keys -1)
)
(push-autorelease-pool) ; in case we have blobs
(while (list? (setf values (sql:next-row)))
(eval (expand (cons 'begin $args) (unify keys values)))
)
(pop-autorelease-pool)
(deallocate sql)
)
)
That doesn't make any sense.
The way for-query-with-db is called is as follows:
A function in a context Route.Static calls a function in the Dragonfly context that reads in a file using read-file, this file contains a mix of HTML and inlined newlisp code. This string is converted into a string containing nothing but executable newLISP code. It his then eval'd using the function eval-string in the Dragonfly context. Somewhere in that evaluated code is a call to for-query-with-db, which itself is a macro that is defined within its own context to protect against variable capture (using the define-smacro we discussed in a thread a while ago).
Last edited by itistoday on Tue Feb 16, 2010 2:59 am, edited 2 times in total.
Get your Objective newLISP groove on.
Re: newLISP development release v.10.1.11
isn't 'Dragonfly' (as a context) what you want to have returned from the caller of '(for-query-with-db db query)' ? Isn't the function which calls '(for-query-with-db db query)' in the 'Dragonfly' context?When I run that, the call to println prints: "Route.Static vs Dragonfly"
In your edit of the post I am still not seeing the difference and I am not sure you understand how 'caller' works ;-?. Did you read the reference for 'caller' in the link I posted? You need a caller for the function called. So there are two functions involved: the caller and the callee who wants to know about the caller's symbol and context.
Also, please post a complete example, boiled down to an absolutely minimum. I am not going through other's code trying to find out what 'define-smacro' does etc..
What I mean is, a completely minimized example with only the necessary to reproduce the effect you want to show, nothing else.
PS: One other (important *) thing when using '(caller)' it makes a difference if the function is called by symbol or by lambda expression. This is an important distinction when using 'map' or 'apply' with a funtion:
Code: Select all
(define (foo) (bar))
(define (bar) (caller))
(foo) => foo
(apply foo) => nil ; calling lambda
(apply 'foo) => foo ; note the quote
Re: newLISP development release v.10.1.11
Yes, it is. Do you not see something weird about caller returning Route.Static, and then Dragonfly in the same function?Lutz wrote:isn't 'Dragonfly' (as a context) what you want to have returned from the caller of '(for-query-with-db db query)' ? Isn't the function which calls '(for-query-with-db db query)' in the 'Dragonfly' context?
I read it, and in my post above I demonstrated my understanding of how caller works by stating:In your edit of the post I am still not seeing the difference and I am not sure you understand how 'caller' works ;-?. Did you read the reference for 'caller' in the link I posted? You need a caller for the function called. So there are two functions involved: the caller and the callee who wants to know about the caller's symbol and context.
itistoday wrote:Apparently I have to call (foo) from within a function for caller to be useful, and not even any function but specifically a *user-defined* function. To me this makes caller almost completely useless; I can't define for-query-with-db or any other interesting functions with it. :-(
Unfortunately I don't have time right now to do that (I have a *lot* of stuff I need to finish right now). I think I've done a pretty good job of explaining exactly what the code does and how it's called, and I've certainly demonstrated that caller is broken.Lutz wrote:Also, please post a complete example, boiled down to an absolutely minimum. I am not going through other's code trying to find out what 'define-smacro' does etc..
Further, it is not required that I post any condensed version of code (you could do that yourself, I've shown caller is buggy, and I've explained how I use it), because when I originally explained the desire for a function like caller, I described in detail exactly how it should behave, yet this is not what it does. To reiterate:
If you can't add that, fine. I'll either have to scrap for-query-with-db (and a bunch of other functions that could benefit from a useful caller function) or rewrite it in some manner.itistoday wrote:No, you seem to have completely misread what I've said here, and in the other thread. context returns the context that the function is in. I need the context from which the function was called.
Get your Objective newLISP groove on.
Re: newLISP development release v.10.1.11
Given that it seems the situation is unlikely to change, I've changed the way the function works to be like so:
This is the function that will be in the next release of Dragonfly, and if caller is updated in the future to return the calling context, I'll add for-query-with-db as well.
Here is how fn-query-with-db would be used in a template file (slightly more verbose and possibly less efficient, but still, I think, a convenient function):
Code: Select all
(define (fn-query-with-db db query func)
(let (sql (db:prepare-sql query) keys '())
(setf keys (map sql:col-name (sequence 0 (-- (sql:col-count)))))
(push-autorelease-pool) ; in case we have blobs
(while (list? (setf values (sql:next-row)))
(func (transpose (list keys values)))
)
(pop-autorelease-pool)
(deallocate sql)
)
)
(global 'fn-query-with-db)
Here is how fn-query-with-db would be used in a template file (slightly more verbose and possibly less efficient, but still, I think, a convenient function):
Code: Select all
<table>
<tr class="header"><td>ID</td><td>Name</td><td>Age</td></tr>
<% (fn-query-with-db db "SELECT rowid,name,age FROM people" (fn (row) %>
<tr>
<td><%=(lookup "rowid" row)%></td>
<td><%=(lookup "name" row)%></td>
<td><%=(lookup "age" row)%></td>
</tr>
<% )) %>
</table>
Last edited by itistoday on Tue Feb 16, 2010 2:59 am, edited 1 time in total.
Get your Objective newLISP groove on.
Re: newLISP development release v.10.1.11
The 'caller' function introduced in development version 10.1.11, will be eliminated and not be present in v10.1.12.
-
- Posts: 394
- Joined: Wed Apr 26, 2006 3:37 am
- Location: Oregon, USA
- Contact:
Re: newLISP development release v.10.1.11
Goodbye, caller. We had so little time to get to know you. Call again sometime!
m i c h a e l
P.S. When you first announced this release, I wrote but neglected to post the following comment:
m i c h a e l
P.S. When you first announced this release, I wrote but neglected to post the following comment:
Now I'm glad I didn't ;-)I'm very curious to discover caller's possible role in FOOP. I know this issue came up for me once while working on something (error reporting, I think).
Re: newLISP development release v.10.1.11
Wow, I just realized something that makes me feel a little silly, I actually didn't need caller at all to do this. :-p
As long as I'm given at least one parameter to the macro which *is* a symbol (literals like strings won't work) then I can get the calling context. In this case the parameter db serves the purpose, and I can use the new prefix function to get the calling context:
fn-query-with-db will still be there as well, because it has one advantage over for-query-with-db, and that is that because its "body" is stored in a function (and not in the $args list), it can take an optional list of parameters at the end:
So now the next update to Dragonfly is going to have a lot of very useful and convenient functions for querying databases (there are currently 5 such functions in the new db/database_utils.lsp plugin).
If you're using the latest bleeding edge from mercurial, you'll find these functions are already available to you.
For comparison, here's how you'd use these two functions:
As long as I'm given at least one parameter to the macro which *is* a symbol (literals like strings won't work) then I can get the calling context. In this case the parameter db serves the purpose, and I can use the new prefix function to get the calling context:
Code: Select all
(define-smacro (for-query-with-db db query)
(letn (ctx (prefix db) db (eval db) sql (db:prepare-sql (eval query)) keys '() values)
(dotimes (i (sql:col-count))
(push (sym (upper-case (sql:col-name i)) ctx) keys -1)
)
(push-autorelease-pool) ; in case we have blobs
(while (list? (setf values (sql:next-row)))
(eval (expand (cons 'begin $args) (unify keys values)))
)
(pop-autorelease-pool)
(deallocate sql)
)
)
Code: Select all
(define (fn-query-with-db db query func params , sql keys values)
(when (setf sql (db:prepare-sql query))
(when (or (not params) (sql:bind-params params))
(setf keys (map sql:col-name (sequence 0 (-- (sql:col-count)))))
(push-autorelease-pool) ; in case we have blobs
(while (list? (setf values (sql:next-row)))
(func (transpose (list keys values))))
(pop-autorelease-pool)
)
(deallocate sql)
)
)
(global 'fn-query-with-db)
If you're using the latest bleeding edge from mercurial, you'll find these functions are already available to you.
For comparison, here's how you'd use these two functions:
Code: Select all
<table>
<tr class="header"><td>ID</td><td>Name</td><td>Age</td></tr>
<% (fn-query-with-db db "SELECT rowid,name,age FROM people WHERE age < ?" (fn (row) %>
<tr>
<td><%=(<- "rowid" row)%></td>
<td><%=(<- "name" row)%></td>
<td><%=(<- "age" row)%></td>
</tr>
<% ) (list max-age)) %>
</table>
<table>
<tr class="header"><td>ID</td><td>Name</td><td>Age</td></tr>
<% (for-query-with-db db "SELECT rowid,name,age FROM people" %>
<tr>
<td><%=ROWID%></td>
<td><%=NAME%></td>
<td><%=AGE%></td>
</tr>
<% ) %>
</table>
Get your Objective newLISP groove on.