3

How can I get the first N elements of a list?

I know I can use subseq:

(subseq '("one" "two" "three" "four" "five") 0 2)

Yet when I use subseq, it produces one of the following results:

  • on the first call, the message "function 'subseq' from cl package called at runtime" or,
  • an error that "progn: Symbol’s function definition is void: subseq" when using vanilla emacs -Q.

I could overcome these by using (require 'cl-extras) or cl-subseq. But given these hiccups, I expect there is a more direct way to get the first N elements.

Looking through documentation didn't turn up anything and the implementation of cl-subseq is non-trivial. If a builtin doesn't exist, I imagine to implement from scratch would require something like "Get the car of each cdr". Yet, this makes me think of loop... which is also a cl extension.

Thoughts?

2
  • 2
    "My ultimate goal is to read the first N lines of a file" is such a different use-case to the question that I strongly recommend you remove that text from this question, and ask a new separate question which is "Read the first N lines of a file".
    – phils
    Commented Mar 12, 2020 at 21:26
  • 1
    i.e. The best solution to your actual question will almost certainly be to move over N newlines and then you're done (more or less). No one is likely to recommend reading the entire file into a list as a starting point.
    – phils
    Commented Mar 12, 2020 at 21:40

3 Answers 3

4

Use butlast. The following code snippet returns the first 3 elements, you can vary the number 3 in the snippet.

(let ((list '("one" "two" "three" "four" "five")))
  (butlast list (- (length list) 3)))
1
  • Or nbutlast to do the same thing destructively.
    – phils
    Commented Mar 13, 2020 at 22:48
1

I think the sensible options are:

  • (require 'cl-lib) and use cl-subseq
  • (require 'seq) and use seq-subseq

The latter actually uses the former, but you might prefer using the seq library functions generally.

You could roll your own, but I would just use one of the above.

1
  • 4
    Worth mention seq-take does more directly what the questioner asks.
    – ideasman42
    Commented Mar 13, 2020 at 3:28
1

(Elevating ideasman42 comment to an answer)

Worth mention seq-take does more directly what the questioner asks.

(setq l1 '("one" "two" "three" "four" "five"))
(seq-take l1 3)
("one" "two" "three")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.