From: Leandro Rios on
slash dot <tyntyfax(a)gmail.com> writes:

>
> Well, you are an alert reader. "Unless your code does (read)..."
> My code doesn't (read), it gets the lambdas from an array and
> picks them by index as needed. Some of the lambdas need an argument,
> some don't. The caller inspects the lambda by one way or the other
> and passes an argument if needed. The alternative is to make all
> lambdas uniform in that all of them accept an argument, but some
> simply ignore it. However, there is a problem: the caller traverses
> a sequence and leaves maintaining the iterator to other parts of
> the system. If the caller fetches a value, passes it to the lambda,
> and the lambda does not need it, the system gets out of sync. The
> caller
> does something like
>
> (funcall my-lambda (next-item))

>
> where (next-byte) advances the iterator. If the called lambda
> does not consume the passed value, it is supposed to be process
> by a subsequent call to a (potentially other) lambda.


Do you have control about how lambdas are generated? If so, it would
be easy to do:

(funcall my-lambda #'next-item)

where all lambdas would take a parameter and would behave like this:

Lambdas not using next-item:

#'(lambda (item-fn)
(declare (ignore item-fn))
... stuff ...)

Lambdas using next-item:

#'(lambda (item-fn)
(let ((item (funcall item-fn)))
... stuff with item ...))

Would that be a viable solution? It's just ANSI CL :)

Leandro




>
> I hope you are still with me at this point. This route of a
> lambda-array saves a lot of code, because this representation
> of my data requires no parsing. Instead of deciphering some other
> representation and dispatching accordingly, the caller simply
> calls the unearthed lambda. For this to work, however, the caller
> must know whether the lambda will need the "next" item or not.
>
> What I can exploit here is the lucky coincidence that lambdas
> that need that particular data item expect it as an argument,
> and that this fact is reflected in the argument list. By inspecting
> the argument list, the caller can infer whether it is supposed
> to advance the iterator or not. Isn't that the lisp way?
From: slash dot on
On Feb 1, 8:11 pm, p...(a)informatimago.com (Pascal J. Bourguignon)
wrote:
> slash dot <tynty...(a)gmail.com> writes:
> > On Feb 1, 2:02 am, Paul Donnelly <paul-donne...(a)sbcglobal.net> wrote:
> >> slash dot <tynty...(a)gmail.com> writes:
> >> > lisp is famous for is reflection capabilities, and,
> >> > indeed, a function like '10+' is reported to be
>
> >> >     #<FUNCTION 10+ (NUMBER) (DECLARE (SYSTEM::IN-DEFUN 10+))
> >> >     (BLOCK 10+ (+ 10 NUMBER))>
>
> >> > in clisp.
>
> >> > (Disturbingly, this only works if I bind #'10+ to a variable and
> >> > evaluate
> >> > the variable, but that's a clisp implementation detail, right? RIGHT?)
>
> >> > So my question is: how can I inspect functions to find out how
> >> > many arguments it has, for example?
>
> >> Isn't that the sort of thing you should already know?
>
> > My code needs a largish number of very similar lambdas.
> > Right now the code does what you suggest. It maintains
> > the information on its arguments in an extra data structure.
> > The argument information is put into the data structure
> > when the lambda is declared. This DOES work, but I was
> > curious about automating this.
>
> If your code already does it, then it is already automated.  
> What more automation do you want?
>
> Unless your code does (read) and you have to type manually the
> argument list of each function when your code needs it...
>
> --
> __Pascal Bourguignon__

[ The other, similar, post is botched. Here is the improved edit. ]

Well, you are an alert reader. "Unless your code does (read)..."
My code doesn't (read), it gets the lambdas from an array and
picks them by index as needed. I do this, because these lambdas
represent data, not code. I typed all those lambdas in by hand,
automation (abstraction) is possible, but this would make it
harder for other programmers to verify the correctness of my
data. This route of a lambda-array saves a lot of code, because
this representation of my data requires no parsing. Instead of
deciphering some other representation and dispatching accordingly,
the caller simply calls the unearthed lambda. For this to work,
however, the caller must know whether the lambda will need
the "next" item or not.

The caller does this with a lambda retrieved by index:

(funcall my-lambda (next-item)) ; note the call to 'next-item'
; this is the argument we are
; talking about

However, there is a problem: the caller traverses
a sequence, calling lambdas for processing data items in packs that
are of various length. The caller leaves maintaining the iterator to
other parts of the system. If the caller fetches a value, passes it
to the lambda, and the lambda does not need it, the system gets
out of sync. If the called lambda does not consume the passed value,
it is supposed to be process by a subsequent call to a (potentially
other) lambda.

What I can exploit here is the lucky coincidence that lambdas
that need that particular data item expect it as an argument,
and this fact is reflected in the argument list. By inspecting
the argument list, the caller can infer whether it is supposed
to advance the iterator or not. Isn't that the lisp way?
From: slash dot on
On Feb 1, 11:43 pm, Leandro Rios <leandroprograma...(a)gmail.com> wrote:
> slash dot <tynty...(a)gmail.com> writes:
>
> > Well, you are an alert reader. "Unless your code does (read)..."
> > My code doesn't (read), it gets the lambdas from an array and
> > picks them by index as needed. Some of the lambdas need an argument,
> > some don't. The caller inspects the lambda by one way or the other
> > and passes an argument if needed. The alternative is to make all
> > lambdas uniform in that all of them accept an argument, but some
> > simply ignore it. However, there is a problem: the caller traverses
> > a sequence and leaves maintaining the iterator to other parts of
> > the system. If the caller fetches a value, passes it to the lambda,
> > and the lambda does not need it, the system gets out of sync. The
> > caller
> > does something like
>
> >     (funcall my-lambda (next-item))
>
> > where (next-byte) advances the iterator. If the called lambda
> > does not consume the passed value, it is supposed to be process
> > by a subsequent call to a (potentially other) lambda.
>
> Do you have control about how lambdas are generated? If so, it would
> be easy to do:
>
> (funcall my-lambda #'next-item)
>
> where all lambdas would take a parameter and would behave like this:
>
> Lambdas not using next-item:
>
> #'(lambda (item-fn)
>     (declare (ignore item-fn))
>     ... stuff ...)
>
> Lambdas using next-item:
>
> #'(lambda (item-fn)
>     (let ((item (funcall item-fn)))
>       ... stuff with item ...))
>
> Would that be a viable solution? It's just ANSI CL :)

If nothing else, this is a good idea. I see no
reason why this should not work, thanks. However,
I won't know before tomorrow, because there might
be a non-obvious spoiler...




>
> Leandro
>
>
>
> > I hope you are still with me at this point. This route of a
> > lambda-array saves a lot of code, because this representation
> > of my data requires no parsing. Instead of deciphering some other
> > representation and dispatching accordingly, the caller simply
> > calls the unearthed lambda. For this to work, however, the caller
> > must know whether the lambda will need the "next" item or not.
>
> > What I can exploit here is the lucky coincidence that lambdas
> > that need that particular data item expect it as an argument,
> > and that this fact is reflected in the argument list. By inspecting
> > the argument list, the caller can infer whether it is supposed
> > to advance the iterator or not. Isn't that the lisp way?
>
>

From: Thomas A. Russ on
slash dot <tyntyfax(a)gmail.com> writes:

> Well, you are an alert reader. "Unless your code does (read)..."
> My code doesn't (read), it gets the lambdas from an array and
> picks them by index as needed. Some of the lambdas need an argument,
> some don't. The caller inspects the lambda by one way or the other
> and passes an argument if needed. The alternative is to make all
> lambdas uniform in that all of them accept an argument, but some
> simply ignore it. However, there is a problem: the caller traverses
> a sequence and leaves maintaining the iterator to other parts of
> the system. If the caller fetches a value, passes it to the lambda,
> and the lambda does not need it, the system gets out of sync. The
> caller
> does something like
>
> (funcall my-lambda (next-item))
>
> where (next-byte) advances the iterator. If the called lambda
> does not consume the passed value, it is supposed to be process
> by a subsequent call to a (potentially other) lambda.

OK. What about making all of the functions uniform in not taking ANY
arguments and having those that need data just call (NEXT-ITEM) whenever
they need the information?

Do these functions have any independent use outside of this iteration
environment?

In any case, I think it would still be fairly simple to store the arity
of the function along with its code if that turns out to be what you
need to do.
>
> I hope you are still with me at this point. This route of a
> lambda-array saves a lot of code, because this representation
> of my data requires no parsing. Instead of deciphering some other
> representation and dispatching accordingly, the caller simply
> calls the unearthed lambda. For this to work, however, the caller
> must know whether the lambda will need the "next" item or not.

Well, assuming I understand your description properly, it seems that
what you have effectively done is to pre-compile the parsing of the the
data stream into a series of lambda expressions that are each invoked on
parts of the input in turn. It seems that these expressions must (at
least some of them) have side effects, or else calling them wouldn't
really have any effect.

Do you make any use of the return value of the expressions, or all they
called solely for their side effects?

> What I can exploit here is the lucky coincidence that lambdas
> that need that particular data item expect it as an argument,
> and that this fact is reflected in the argument list. By inspecting
> the argument list, the caller can infer whether it is supposed
> to advance the iterator or not. Isn't that the lisp way?

You could do that. On the other hand, you could restructure things as
noted above so that routines that need arguments will just fetch them
rather than making their caller do it for them. Certainly from the
point of view of a rather uninformed caller, that would be appealing
from a uniformity of interface point of view.

--
Thomas A. Russ, USC/Information Sciences Institute
From: Pascal J. Bourguignon on
slash dot <tyntyfax(a)gmail.com> writes:

> On Feb 1, 6:11�pm, Duane Rettig <du...(a)franz.com> wrote:
>> On Jan 31, 3:34�pm, slash dot <tynty...(a)gmail.com> wrote:
>>
>> > lisp is famous for is reflection capabilities, and,
>> > indeed, a function like '10+' is reported to be
>>
>> > � � #<FUNCTION 10+ (NUMBER) (DECLARE (SYSTEM::IN-DEFUN 10+))
>> > � � (BLOCK 10+ (+ 10 NUMBER))>
>> [1i] CL-USER(4): (inspect #'foo)
>
> I tried that. Totally works, thanks...

Notice that it the worst of the cases, you can do something like:

(with-input-from-string (in (with-output-to-string (*standard-output*) (describe (function 10+))))
(read-char in) (read-char in) (read in) (read in) (read in))
--> (NUMBER)

or something similar with INSPECT.

The only caveat being that again, the parsing of the output of these
function is implementation dependant.

--
__Pascal Bourguignon__
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13
Prev: Do as the Romans do
Next: managing large table of data