Hi,
Frequently I encounter calculations where I fill a vector (or array)
using a function (maybe mapping from another, but not in the example
below). Most of the time the return type is one for which it makes sense
to use an array with a specific element type, say double-float, but not
always. I can specify the resulting element type manually, but it would
be neater if the function could communicate it somehow. For example,
consider
(defun vector-fill (n function &optional
(return-type (return-type function)))
(declare (function function)
(fixnum n))
(let ((result (make-array n :element-type return-type)))
(dotimes (i n)
(setf (aref result i) (funcall function)))
result))
Then return-type and functions that can report it could look like this:
(defun return-type (function)
(funcall function 'return-type))
(defun my-function (&optional report-return-type-p)
(if report-return-type-p
'double-float
(random 10d0)))
The problem is efficiency:
(vector-fill 10000000 #'my-function)
is about 40% slower (SBCL, (optimize (speed 3))) than
(defun my-function2 ()
(random 10d0))
(vector-fill 10000000 #'my-function2 'double-float)
Is there some other way for a (possibly unnamed) function to communicate
its return type? Or should I just specify it manually all the time if I
want speed?
Thanks,
Tamas
In article <··············@mid.individual.net>,
Tamas K Papp <······@gmail.com> wrote:
> Hi,
>
> Frequently I encounter calculations where I fill a vector (or array)
> using a function (maybe mapping from another, but not in the example
> below). Most of the time the return type is one for which it makes sense
> to use an array with a specific element type, say double-float, but not
> always. I can specify the resulting element type manually, but it would
> be neater if the function could communicate it somehow. For example,
> consider
>
> (defun vector-fill (n function &optional
> (return-type (return-type function)))
> (declare (function function)
> (fixnum n))
> (let ((result (make-array n :element-type return-type)))
> (dotimes (i n)
> (setf (aref result i) (funcall function)))
> result))
>
> Then return-type and functions that can report it could look like this:
>
> (defun return-type (function)
> (funcall function 'return-type))
>
> (defun my-function (&optional report-return-type-p)
> (if report-return-type-p
> 'double-float
> (random 10d0)))
>
> The problem is efficiency:
>
> (vector-fill 10000000 #'my-function)
>
> is about 40% slower (SBCL, (optimize (speed 3))) than
>
> (defun my-function2 ()
> (random 10d0))
>
> (vector-fill 10000000 #'my-function2 'double-float)
>
> Is there some other way for a (possibly unnamed) function to communicate
> its return type? Or should I just specify it manually all the time if I
> want speed?
There's no standard mechanism for this. Common Lisp's introspection
mechanisms don't include type declarations. At one point during the
standardization there was a proposal for environment inquiry functions,
but we never got them quite right and it wasn't included in the final
standard.
If you only need this for certain applications in your function, you
could maintain a hash table, and provide your own defining macros that
add the functions to the hash table.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
On Sat, 01 Nov 2008 12:25:20 -0400, Barry Margolin wrote:
> In article <··············@mid.individual.net>,
> Tamas K Papp <······@gmail.com> wrote:
>
>> Hi,
>>
>> Frequently I encounter calculations where I fill a vector (or array)
>> using a function (maybe mapping from another, but not in the example
>> below). Most of the time the return type is one for which it makes
>> sense to use an array with a specific element type, say double-float,
>> but not always. I can specify the resulting element type manually, but
>> it would be neater if the function could communicate it somehow. For
>> example, consider
>>
>> (defun vector-fill (n function &optional
>> (return-type (return-type function)))
>> (declare (function function)
>> (fixnum n))
>> (let ((result (make-array n :element-type return-type)))
>> (dotimes (i n)
>> (setf (aref result i) (funcall function)))
>> result))
>>
>> Then return-type and functions that can report it could look like this:
>>
>> (defun return-type (function)
>> (funcall function 'return-type))
>>
>> (defun my-function (&optional report-return-type-p)
>> (if report-return-type-p
>> 'double-float
>> (random 10d0)))
>>
>> The problem is efficiency:
>>
>> (vector-fill 10000000 #'my-function)
>>
>> is about 40% slower (SBCL, (optimize (speed 3))) than
>>
>> (defun my-function2 ()
>> (random 10d0))
>>
>> (vector-fill 10000000 #'my-function2 'double-float)
>>
>> Is there some other way for a (possibly unnamed) function to
>> communicate its return type? Or should I just specify it manually all
>> the time if I want speed?
>
> There's no standard mechanism for this. Common Lisp's introspection
> mechanisms don't include type declarations. At one point during the
> standardization there was a proposal for environment inquiry functions,
> but we never got them quite right and it wasn't included in the final
> standard.
>
> If you only need this for certain applications in your function, you
> could maintain a hash table, and provide your own defining macros that
> add the functions to the hash table.
Thanks for the suggestion.
I have been thinking about something that would implement a strongly
typed layer on CL where needed, eg I could write functions using S-
expressions, then they would be specialized to the appropriate type,
generate Lisp code with all the fancy declarations and then compile
that. Possibly something like a subset of what Qi does.
But I know very little about the theory behind these things, so I guess a
lot of reading would be beneficial before I try. If anyone could help
with suggestions/pointers, I would appreciate that.
Thanks,
Tamas
* Tamas K Papp <··············@mid.individual.net> :
Wrote on 1 Nov 2008 19:38:30 GMT:
| I have been thinking about something that would implement a strongly
| typed layer on CL where needed, eg I could write functions using S-
| expressions, then they would be specialized to the appropriate type,
| generate Lisp code with all the fancy declarations and then compile
| that. Possibly something like a subset of what Qi does.
|
| But I know very little about the theory behind these things, so I guess a
| lot of reading would be beneficial before I try. If anyone could help
| with suggestions/pointers, I would appreciate that.
Also consider Drew McDermott's NISP's approach
,---- <URL:http://www.cs.yale.edu/homes/dvm/> ----
| * Nisp (version 2.93.22, 2006-12-01) is a strongly typed dialect of
| Lisp, implemented as a collection of macros. Older versions of Nisp
| (see below) were based on a tool set called "NILS," but recent
| versions are based on YTools. (Hence it is referred to in some
| places as YNisp.) The tar file contains a single directory called
| ydecl which contains all the type-checking stuff.
`----
From that page: <URL:http://www.cs.yale.edu/homes/dvm/papers/nispman.pdf>
Also, types and the return type have to be specified when defining
foreign function interfaces, and each lisp system has ways of
representing them and syntax for specifying them. (CFFI's choice
doesn't match my personal taste)
--
Madhu