Arc Forumnew | comments | leaders | submitlogin
Help with a function
2 points by wfarr 6071 days ago | 5 comments
The following function is designed to return the first three paragraphs of a string.

    (def shortify (i str)
      "Shortens a given chunk of text to i paragraphs."
      (unless (> i 3)
        (iflet var (posmatch "\n\n" str)
               (unless (is var "")
                 (string (cut str 0 (- (+ var 2) (len str)))
                         (shortify (+ i 1) (cut str (+ var 2))))))))
The following:

    (shortify 1 "foo\n\nbar\n\nbaz\n\nbing!")
Would return:

    "foo\n\nbar\n\nbaz\n\n"
The only problem is, it falls on its face with an index out of range error for the string if there are less than three instances of "\n\n" in a string.

Any ideas? Also, general cleanup and improvement of the function itself is welcome! The function is super-ugly right now, since I'm focusing on well, getting it to work before I clean up the semantics of it.



2 points by almkglor 6071 days ago | link

Here's an alternative using Anarki scanners (or if you prefer, you can always use coerce which is cheaper on the memory; however scanners are lazier and, if you need to process less than maybe 1/4 the original string, is cheaper in memory too)

  (def shortify (i s)
    (let shorten nil
      (= shorten
         (fn (i ss)
           (if (is i 0)
               nil
               (when ss
                 (pr:car ss)
                 (if (and (caris ss #\newline) (is (cadr ss) #\newline))
                     (let ss (cdr ss)
                       (while (caris ss #\newline)
                         (prn)
                         (zap cdr ss))
                       (shorten (- i 1) ss))
                     (shorten i (cdr ss)))))))
      ; replace with (coerce s 'cons) to taste
      (tostring:shorten i (scanner-string s))))
Untested of course, and you better make sure the parens match, I don't have access to vi right now ~.~ ^^.

Edit: s/l/ss/, because l (small letter L) looks like 1 (number one)

Edit2: err. Actually I thought i would be number of paras. Oh well. At least now you have more generic code ^^:

  (shortify 3 "foo\n\nbar\n\nnitz\n\nkoo\n\n")
  => "foo\n\nbar\n\nnitz\n\n"
As an aside, if you want you can study also the paragraph scanner in Arki, the wiki in Anarki.

-----

1 point by wfarr 6071 days ago | link

I'll definitely give this one a shot, because I have a tendency to get a bit long-winded. =D

-----

2 points by offby1 6071 days ago | link

This might make life worth living again:

  diff --git a/strings.arc b/strings.arc
  index a28b2fe..1d3b010 100644
  --- a/strings.arc
  +++ b/strings.arc
  @@ -83,7 +83,7 @@
       (if (isa pat 'fn)
           (for i start (- (len seq) 1)
             (when (pat (seq i)) (throw i)))
  -        (for i start (- (len seq) (- (len pat) 2))
  +        (for i start (- (len seq) (len pat) 1)
             (when (headmatch pat seq i) (throw i))))
       nil))

-----

1 point by wfarr 6071 days ago | link

Works for me as well.

-----

1 point by wfarr 6071 days ago | link

It seems the error I get is caused by (posmatch):

  > (posmatch "a" "foo")
    Error: "string-ref: index 3 out of range [0, 2] for string: \"foo\""
=(

-----