From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Emil Newsgroups: gmane.emacs.help Subject: Re: Programmatically creating functions Date: Tue, 28 Oct 2008 13:29:50 -0700 (PDT) Organization: http://groups.google.com Message-ID: <1eb86a73-62e8-4f3c-89bc-6b109a5a54e4@c22g2000prc.googlegroups.com> References: <87r669lrvk.fsf@zeekat.nl> <1224615828.488025@arno.fh-trier.de> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: ger.gmane.org 1225255271 19872 80.91.229.12 (29 Oct 2008 04:41:11 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 29 Oct 2008 04:41:11 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Wed Oct 29 05:42:11 2008 connect(): Connection refused Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1Kv2si-0007QZ-Le for geh-help-gnu-emacs@m.gmane.org; Wed, 29 Oct 2008 05:42:08 +0100 Original-Received: from localhost ([127.0.0.1]:56640 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Kv2rc-0004qA-9G for geh-help-gnu-emacs@m.gmane.org; Wed, 29 Oct 2008 00:41:00 -0400 Original-Path: news.stanford.edu!headwall.stanford.edu!news.glorb.com!postnews.google.com!c22g2000prc.googlegroups.com!not-for-mail Original-Newsgroups: gnu.emacs.help Original-Lines: 136 Original-NNTP-Posting-Host: 70.79.63.110 Original-X-Trace: posting.google.com 1225225791 1747 127.0.0.1 (28 Oct 2008 20:29:51 GMT) Original-X-Complaints-To: groups-abuse@google.com Original-NNTP-Posting-Date: Tue, 28 Oct 2008 20:29:51 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: c22g2000prc.googlegroups.com; posting-host=70.79.63.110; posting-account=flt7vgoAAAB0ZmFFH4Ct9KMZ5PVyoetH User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3,gzip(gfe),gzip(gfe) Original-Xref: news.stanford.edu gnu.emacs.help:163884 X-Mailman-Approved-At: Wed, 29 Oct 2008 00:35:14 -0400 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:59226 Archived-At: On Oct 25, 11:28=A0am, Ian Eure wrote: > On Oct 21, 2008, at 11:57 AM, Andreas Politz wrote: > > > > > Joost Diepenmaat wrote: > >> Ian Eure writes: > >>> So, I have a list of symbols: > > >>> '(foo bar baz) > > >>> I want to iterate over the list and create a function from each =A0 > >>> which > >>> does something like this: > > >>> (defun call-foo () > >>> =A0(interactive) > >>> =A0(invoke-stuff 'foo) > > >>> How can I accomplish this? I can't figure out how to create the > >>> function. I've tried a number of approaches, but have not met with > >>> success. > > >>> - eval'ing the defun. Returns a function symbol, but I can't call > >>> it. Maybe it's only created within the scope of the (eval) and not > >>> callable from outside? > > >>> - Creating a symbol and using fset to assign a lambda to it's > >>> function cell. It sort of works, but I'm unclear on how to pass a > >>> variable function name to defun, nor am I clear on how I can make =A0 > >>> sure > >>> it calls invoke-stuff with the right symbol. > >> I'm not /quite/ sure where you've got problems, but in this case =A0 > >> elisp's > >> lack of closures hurts. IMHO the simplest way to get what you want =A0 > >> is to > >> use a macro: > >> (defmacro make-caller-macro (symbol) =A0 `(defun ,(intern (concat =A0 > >> "call-" (symbol-name symbol))) () =A0 =A0 =A0(,symbol))) > >> But that won't evaluate the argument, so you'd more or less have to = =A0 > >> use > >> eval as well: > >> (dolist (s '(foo bar)) (eval `(make-caller-macro ,s))) > > > Does this work ? (in general) > > Yes, with a little hacking, it works: > > (defvar sql-connection-alist > =A0 =A0'((poola > =A0 =A0 =A0 (sql-product 'mysql) > =A0 =A0 =A0 (sql-server "pool-a") > =A0 =A0 =A0 (sql-user "me") > =A0 =A0 =A0 (sql-password "mypass") > =A0 =A0 =A0 (sql-database "default") > =A0 =A0 =A0 (sql-port 3306)) > =A0 =A0 =A0(poolb > =A0 =A0 =A0 (sql-product 'mysql) > =A0 =A0 =A0 (sql-server "pool-b") > =A0 =A0 =A0 (sql-user "me") > =A0 =A0 =A0 (sql-password "mypass") > =A0 =A0 =A0 (sql-database "default") > =A0 =A0 =A0 (sql-port 3307))) > =A0 =A0"AList of preset connections for `sql-connect-preset'.") > > (defun sql-connect-preset (name) > =A0 =A0"Connect to a predefined SQL connection listed in `sql-connection- > alist'" > =A0 =A0(require 'sql) > =A0 =A0(let ((conn (cdr (assoc name sql-connection-alist))) > =A0 =A0 =A0 =A0 =A0(sql-name (symbol-name name))) > =A0 =A0 =A0(eval `(let ,conn > =A0 =A0 =A0 =A0 =A0 =A0 =A0 (flet ((sql-get-login (&rest what))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (sql-product-interactive sql-product)))))= ) > > (defun sql-convenience () > =A0 =A0(interactive) > =A0 =A0(mapcar (lambda (conn) > =A0 =A0 =A0 =A0 =A0 =A0 =A0(let ((name (car conn))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(fset (intern (format "sql-%s" name)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0`(lambda nil > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ,(format "Connect to %s S= QL preset." name) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (interactive) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (sql-connect-preset ',nam= e))))) > =A0 =A0 =A0 =A0 =A0 =A0sql-connection-alist)) > > So now I can define preset connections and get sql-* methods to invoke = =A0 > them directly. Here is another attempt I wrote recently : (setq sql-connection-alist '((local (sql-product 'mysql) (sql-server "") (sql-user "") (sql-password "") (sql-database "") (sql-port 3306)) (qa (sql-product 'mysql) (sql-server "") (sql-user "") (sql-password "") (sql-database "") (sql-port 3306)))) (defun sql-connect-preset (name) "Connect to a predefined SQL connection listed in `sql-connection- alist'" (eval `(let ,(cdr (assoc name sql-connection-alist)) (flet ((sql-get-login (&rest what))) (sql-product-interactive sql-product))))) ;; iterate over the alist and create functions (mapcar '(lambda(x) (let ((ds-name (symbol-name x))) (eval (car (read-from-string (format "(defun sql-%s() (interactive) (sql-connect-preset '%s))" ds-name ds-name)))))) (mapcar 'car sql-connection-alist)) (provide 'mysql-utils) Require mysql-utils and it i becomes available as M-x sql-local, or M- x sql-qa. emil