From: Zaka on
Hello!!

Thanks to all (specifically to Pascal Bourguignon) for the answers.
That helps me a lot.

I'm trying to subdivide a string in an arbitrary length (provided as
arguments)
substrings.

It would look like this.

(various-parts-st "0123456789" 1 3 3 3)
=> ("1" "123" "456" "789")

But I only could got this:

(various-parts-st "0123456789" '(1 3 3 3))
=> ("1" "123" "456" "789")

The thing is that I have an &optional argument around, and it must be
the last argument,
so if I don't want to use it, it just has his default value. But,
being not possible to have
a &rest argument before an &optional one (that's what I understood,
maybe I'm mistaken)
I couldn't realize how to solve it the way I want.

I hope you understand my ugly English, if not I could try to explain
it other way.

Here I let my code:

(defun various-parts-st (string parts &optional (string-length (length
string)))
(cond
((null parts (list string))
((<= string-length (car parts (list string))
(t
(cons (subseq string 0 (car parts))
(various-parts-st (subseq string (car parts string-length) (cdr
parts (- string-length (car parts)))))))

Thanks for your help.

Zaka.
From: D Herring on
Zaka wrote:

> I'm trying to subdivide a string in an arbitrary length (provided as
> arguments)
> substrings.
>
> It would look like this.
>
> (various-parts-st "0123456789" 1 3 3 3)
> => ("1" "123" "456" "789")
>
> But I only could got this:
>
> (various-parts-st "0123456789" '(1 3 3 3))
> => ("1" "123" "456" "789")
>
> The thing is that I have an &optional argument around, and it must be
> the last argument,
> so if I don't want to use it, it just has his default value. But,
> being not possible to have
> a &rest argument before an &optional one (that's what I understood,
> maybe I'm mistaken)
> I couldn't realize how to solve it the way I want.

With &rest, you can do arbitrary parsing or defaults... Try something
like
(defun various-parts-st (string &rest parts)
(unless parts
(setf parts (list (length string))))
...)


- Daniel
From: Barry Margolin on
In article
<9412a711-150a-4150-b4c5-89a4efc355c2(a)z34g2000vbl.googlegroups.com>,
Zaka <shanatorio(a)gmail.com> wrote:

> Hello!!
>
> Thanks to all (specifically to Pascal Bourguignon) for the answers.
> That helps me a lot.
>
> I'm trying to subdivide a string in an arbitrary length (provided as
> arguments)
> substrings.
>
> It would look like this.
>
> (various-parts-st "0123456789" 1 3 3 3)
> => ("1" "123" "456" "789")
>
> But I only could got this:
>
> (various-parts-st "0123456789" '(1 3 3 3))
> => ("1" "123" "456" "789")
>
> The thing is that I have an &optional argument around, and it must be
> the last argument,
> so if I don't want to use it, it just has his default value. But,
> being not possible to have
> a &rest argument before an &optional one (that's what I understood,
> maybe I'm mistaken)

Your understanding is correct. How is it supposed to tell whether the
last argument is the last element of the &rest list or the argument that
goes with &optional? E.g. in

(various-parts-st "0123456789" 1 2 3 4)

should it be

PARTS = (1 2 3)
STRING-LENGTH = 4

or

PARTS = (1 2 3 4)
STRING-LENGTH = default

You may have a preference, but how is CL supposed to figure it out? You
need to come up with an unambiguous way to call your function. What's
so bad about using a list instead of &rest?

> I couldn't realize how to solve it the way I want.
>
> I hope you understand my ugly English, if not I could try to explain
> it other way.
>
> Here I let my code:
>
> (defun various-parts-st (string parts &optional (string-length (length
> string)))
> (cond
> ((null parts (list string))
> ((<= string-length (car parts (list string))
> (t
> (cons (subseq string 0 (car parts))
> (various-parts-st (subseq string (car parts string-length) (cdr
> parts (- string-length (car parts)))))))
>
> Thanks for your help.
>
> Zaka.

--
Barry Margolin, barmar(a)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 ***
From: Kaz Kylheku on
On 2009-09-23, Zaka <shanatorio(a)gmail.com> wrote:
> the last argument, so if I don't want to use it, it just has his default
> value. But, being not possible to have a &rest argument before an &optional
> one (that's what I understood, maybe I'm mistaken) I couldn't realize how to
> solve it the way I want.

You can can begin the rest list after the last required argument, and process
it with another lambda list inside your function, using destructuring-bind:

(defun fun (required &rest rest)
(destructuring-bind (&optional (optional 'default-val) &rest ignored) rest
(declare (ignore ignored))
...))

So now you have access to all arguments after REQUIRED in the rest
variable, and also you have the OPTIONAL variable parsed out, which
gets the first element of REST, or else the default value if REST
is empty.

Also, look into keywords. The built-in Lisp feature which gives you a rest list
in parallel with a structured parse of some of its elements is the keyword
feature, in particular when used with &allow-other-keys.

(defun fun (required &rest rest &key a (b 42) c &allow-other-keys) ...)

You get all the rest arguments in REST, and those of them which match
the keys are also parsed out into their respective keyword arguments.

Keys are effectively optional arguments in the sense that a keyword
argument is never mandatory, and defaulting of values is supported.
Only, the syntax is different.

From: Zaka on
Thanks all for your answers!

Finally I put off the optional argument without which is easy to
solve the problem the manner I wanted.

Daniel Herring:

Your solution can't be applied cause I wanted to use the optional
argument and the list at the same time.

Barry Margolin:

Thanks for your explanation. Is nothing bad about the usage of lists
as arguments (I'm using Lisp), but, firstly, is kind of a challenge
while I'm learning the ins and outs of the language, and, secondly and
more important, is that the problem is proposed that way so the
solution must be that way.

Kaz Kylheku:

I've learned a lot reading about the subjects you recommended me, but
I hadn't be able to realize a way to solve my problem with those
tools.

Here a let the code, which is less efficient because it has to
compute the length of the string every execution of the function.

(defun various-parts-st (string &rest parts)
(let ((string-length (length string)))
(cond
((null (car parts)) (list string))
((<= string-length (car parts)) (list string))
(t
(cons (subseq string 0 (car parts))
(apply 'various-parts-st
(cons (subseq string (car parts) string-length)
(cdr parts))))))))

Zaka.