help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: (goto-char ...) error


From: Tim X
Subject: Re: (goto-char ...) error
Date: Wed, 23 Feb 2011 09:50:06 +1100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (gnu/linux)

ken <gebser@mousecar.com> writes:

> On 02/22/2011 01:45 PM Deniz Dogan wrote:
>> 2011/2/22 ken <gebser@mousecar.com>:
>>> On 02/22/2011 12:31 PM Deniz Dogan wrote:
>>>> 2011/2/22 ken <gebser@mousecar.com>:
>>>>> ....
>>>>
>>> My understanding is that the 4th arg to re-search-forward is to repeat
>>> the search, so I set that to nil.
>>>
>>> I get the same error whether the 3rd arg is t or nil (!?):
>>>
>>> (setq ptname (re-search-forward "REGEXP" endpt t nil))
>>>      (if ptname
>>>          ((goto-char (- ptname 1))
>>>           ....
>>>
>>> The error line in *Messages* says:
>>>
>>> if: Invalid function: (goto-char (- begin-name-value 1))
>>>
>>>
>> 
>> You have one pair of parentheses too many.
>> 
>> Change:
>> 
>> ((goto-char (- ptname 1))
>> 
>> to:
>> 
>> (goto-char (- ptname 1))
>> 
>> The error is telling you that "(goto-char (- ptname 1))" is an invalid
>> function, which could potentially be confusing, but it really makes
>> sense.  You call a function named `foo' like (foo ...), but if you do
>> "((foo ...))" you're trying to call a function named "(foo ...)" which
>> is not a valid function.
>> 
>> From the documentation of `if':
>> 
>> (if COND THEN ELSE...)
>> If COND yields non-nil, do THEN, else do ELSE...
>> 
>> This means that your THEN clause must be a single expression.
>> Everything starting with the third argument to `if' is considered part
>> of the ELSE clause.
>> 
>> If you want to multiple expressions in the THEN clause, use `progn' as
>> such:
>> 
>> (if (= x y)
>>     (progn
>>       (message "They're equal")
>>       (message "Hooray!"))
>>   (message "They're not equal.")
>>   (message "Too bad, bro."))
>> 
>> I hope that helps!
>
> Yeah, I think it should.  Thanks.
>
> Just to be clear about one more thing I'll be addressing subsequently,
> i.e., another "if" nested inside the first:
>
> (if (= x y)
>    (progn
>      (message "They're equal")
>      (message "Hooray!")
>      (if (= x z)
>           (progn
>             (message "The next one's equal too.")
>             (message "Hooray++!")))) ; enuf )s to match up to 1st progn
>  (message "They're not equal.")
>  (message "Too bad, bro."))
>
>
> elisp is weird.

When you need to use progn in your if statement, it is a sign you are
using the wrong construct or you need to reverse things. Although things
may seem weird, once you know the alternatives, you will likely find it
much clearer. 

1. if statements allow multiple forms in the else part, so reversing
your test means you can get rid of the progn statements. 

(if (not (= x y))
       (message "They're not equal. Too bad, bro.")
    (message "They're equal Horay!")
    (if (not (= x z))
         (message "The next one is not equal though")
      (message "The next one is equal as well. Hooray!")))

However, sometimes, this is not a good solution because it inverts the
way you think about the test and causes another layer of indirection. In
that case, one of the following may be more appropriate -

2. If you don't really need 'else' clauses, then the when or unless
statement is a better choice as it allows multiple forms i.e.

(when (= x y)
      (message "They match")
      (if (= x z)
          (message "The next ones match too")))

(unless (= x y)
        (message "They don't match")
        (do-some-stuff)
        ....)

3. If you need conditional branches, then cond is a good choice

(cond ((= x y)
       (message "y matches")
       (do-some-things)
       (do-some-more-things)
       (if (= x z)
           (message "z matches")))
     ((= x b)
      (message "b matches")
      (do-some-stuff)
      ...)
    (t (message "No match)))

Use the construct which makes your intention clear. Lots of nested if's
or progn's indicate there is probably a better form to express what you
mean. Of course, these are just rules of thumb - sometimes it makes
sense to use nested ifs and sometimes it makes sense to use progn (just
like sometimes code is clearer with a goto). Often, cluttered/unclear
code is really an indicaiton of a cluttered/unclear solution - this is
normal as you really only get to understand the problem when you try to
solve it. This is why refactoring is so important - as your
understanding of the probolem increases, your ability to express the
solution in a clear and concise form will also increase. If you can't
make the code clear, then you probably don't understand the problem yet.

Tim
-- 
tcross (at) rapttech dot com dot au


reply via email to

[Prev in Thread] Current Thread [Next in Thread]