I am using vim-sexp and vim-sexp-mappings-for-regular-people plugins for editing Clojure files. I don't quite understand what slurp and barf commands do exactly.
I tried playing with them, and it seems that they insert/remove forms at the beginning/end of an adjacent form. Is that correct? If not, what is the proper definition for slurp and barf?
slurping and barfing are the essential operations/concepts to use one of the modern structural code editors. after getting used to them I'm completely incapable of editing code without these. Of the ~20 people that sit with me writing clojure all day all of them use these all the time. so saying that they are "helpful for lisp coders" is a very tactful and polite understatement.
slurp: (verb)
"to include the item to one side of the expression surrounding the point into the expression"
barf: (verb)
"to exclude either the left most or right most item in the expression surrounding the point from the expression"
and some examples.
1 2 (3 4) 5 6
slurp right:
1 2 (3 4 5) 6
barf right:
1 2 (3 4) 5 6
slurp left:
1 (2 3 4) 5 6
barf left:
1 2 (3 4) 5 6
and we're back where we started.
When I give talks/presentations introducing paredit I generally leave students/attendees with just these two concepts because I feel they are enough to start getting the benefit of structural editing without being overwhelming. Once you are comfortable with these then move on to structual navigation by learning to move forward/backward and up/down by expression rather than by character.
even though it list emacs keybindings I still highly recommend the animated guide to paredit that Peter Rincker mentions in his answer.
it may seem gross, but i visualise barf-ing like vomiting (they are synonyms after all), where you are expelling something out.
slurping, i visualise having a drink through a straw and drawing in the drink.
The pipe symbol is the cursor in these illustrations.
so barf-ing to the right (pushing out the 4 )
1 2 (3 |4) 5 6 -> 1 2 (3|) 4 5 6
and slurping to the right gets you back the 4 (gross as it may be to re-ingest what you previously threw up)
1 2 (3|) 4 5 6 -> 1 2 (3 4) 5 6
The backward version do the same things but with items before the current s-exp.
I find I use the forward/right versions much more than the left, as I'm usually adding something in front, like a let binding, so a session might be:
(some-fn1 (count some-map))
(some-fn2 (count some-map))
aha, a let could come in here to refactor the (count some-map):
(let [c (count some-map)]|)
(some-fn1 c)
(some-fn2 c)
But the let isn't wrapping the 2 calls, so we want to pull in (slurp) the next 2 forms inside the let s-exp, so now at the cursor position, slurp twice which will give after first:
(let [c (count some-map)]|
(some-fn1 c))
(some-fn2 c)
and then on second:
(let [c (count some-map)]|
(some-fn1 c)
(some-fn2 c))
and any decent editor with paredit/structural editing will also do the indentation at the same time for you.
It's also important to note that the barf/slurp will happen within the current set of brackets (i.e. slurping (let [a (count x)]) will do different things depending on where the cursor is, as there are 3 sets of brackets), hence why I was careful where to put the cursor in the let binding above, else you're push in/out the wrong bracket (which is another way of thinking of barf/slurping - manipulating the position of the bracket rather than pull/pushing items into/out of the s-exp).
I am not an expert on: lisps, emacs, paredit, vim-sexp, or vim-sexp-mappings-for-regular-people. (Why am I posting right?!)
However I know that slurp and barf come form Emac's paredit mode. This Emacs mode is supposedly very helpful for lisp coders. I am sure you can find a nice helpful article on these subjects if you search for paredit. As a matter a fact I found a nice article for you: The Animated Guide to Paredit. From what I can tell you are right in your guesses about slurp and barf.
Related
In Vim, you can go 30i=<esc> to type 30 = signs. (This is handy for taking notes, becaus I like to put a bunch of equals signs under different section headers.)
Is there a way to do this in Kakoune? A numerical prefix on an insert session only types the content once.
There's some discussion of this topic here, where the most relevant comment seems to be:
Since #4041, we can create overlapping selections with the + command and Alt + + to merge them.
Example – Insert 80 asterisks:
80+i*<esc><a-+>
I can't quite get this to work myself (it does create a line of 80 * characters, but I'm not able to exit whatever mode I've gotten myself into at that point), but I haven't used kak before, so perhaps it will be more obvious to you.
I am wondering when I should use tabs and when I should use spaces?
Especially in guards, I'm working through he learn you a Haskell book and it said I should always use spaces.
The book itself seems to use 4 spaces in definition with guards though.
For example this function:
replicate' :: (Num i, Ord i) => i -> a -> [a]
replicate' n x
| n <= 0 = []
| otherwise = x:replicate' (n-1) x
When I replace the 4 spaces/tabs with a single space I get an indentation / missed brackets error in the otherwise case.
However, if I use a tab or 4 spaces this works.
Did I misunderstand something about using spaces over tabs? Should it be 4 spaces each time?
Because often 1 space does work, just with guards ghci is almost always (infuriatingly not always) complaining here.
I'm using sublime btw, in case there is an issue there.
Thanks a lot in advance.
For example:
maximum' [] = error "maximum of empty list"
maximum' [x] = x
maximum' (x:xs)
| x > maxTail = x
| otherwise = maxTail
where maxTail = maximum' xs
throws an indentation error
It sounds like the OP's actual problem was a weird state in a particular file, but I thought I'd provide an answer to the general question here.
Most parts of Haskell syntax are completely insensitive to indentation (most of the common practices about laying out Haskell code are stylistic, rather than necessary). For example, all of these ways of writing the last equation in the OP's example work just fine:
-- guards indented more than where
maximum' (x:xs)
| x > maxTail = x
| otherwise = maxTail
where maxTail = maximum' xs
-- where indented more than guards
maximum' (x:xs)
| x > maxTail = x
| otherwise = maxTail
where maxTail = maximum' xs
-- all on one line, no indentation at all!
maximum' (x:xs) | x > maxTail = x | otherwise = maxTail where maxTail = maximum' xs
Even something horrifying like this works:
-- please, no
maximum' (x:xs) |
x
> maxTail = x
| otherwise
= maxTail where
maxTail
= maximum' xs
There are exactly 2 things you can to do mess up indentation in the code shown:
Use more than one line to define the equation, with any of the continuation lines not starting with at least one whitespace character
Use more than one line to define the where clause, with any of the continuation lines starting at a character position less than that of the first character after the where keywords (i.e. the m in maxTail)
Otherwise, the whitespace in this example does not matter at all (apart from separating identifiers and keywords).
There is basically only one general way in which indentation matters in Haskell. And it's actually not indentation as such, but alignment that matters. That happens in the context of "blocks" containing a variable number of entries:
a let <decls> in <expr> expression contains 1 or more declarations in the <decls> part
a where clause introduces 1 or more declarations
an instance definition's where part has zero or more method definitions
a do block has 1 or more statements
a case expression has 1 or more cases (zero or more with the EmptyCase extension)
etc, etc
The variable number of entries in these blocks are the only places where alignment matters. There is always a keyword introducing the block, and the character position of the first entry in the block sets the alignment; after that every line that starts exactly at this character position is taken as the beginning of the next entry in the block, every line that starts past this position is taken as a continuation line of the previous entry, and the first line that starts before alignment position is taken as ending the block (and the contents of this line are not part of the block). Sometimes there is also a keyword that will indicate the end of the block, regardless of any indentation (e.g. the in part of let <decls> in <expr> is indicated by the in keyword even if it's on the same line as part or all of the <decls>).
As an aside, you may at this point be wondering why it's possible to get an error with code like this:
bar x y
= x + y
I haven't used any where, let, etc blocks above, but it's possible to get an alignment error here by continuing the bar definition onto a new line without indentation? Didn't I promise indentation only matters in blocks? Well, actually the entire global scope of a module is an aligned block! We just usually don't notice it because it's conventional to use alignment position 0 for this block. But technically, that's what's going on (thus you can't have a continuation line for one of the declarations in the global block that starts at alignment 0).
This layout based on alignment rather than indentation is why tabs are often considered difficult to use to layout Haskell code. As an example, consider this:
foo x y z = xy + yz
where xy = x * y
yz = y * z
Here I have used 4 spaces to indent the where part, and this is one of those places where the whitespace is completely irrelevant, so I could have used anything I like. Therefore, if I'm accustomed to using tabs as indentation in other programming languages, I might have been tempted to use a tab rather than 4 spaces.
Where things get nasty is that the correct indentation of the yx = y * z line is not "2 indent levels in", but rather "lining up exactly with the xy = x * y definition". So if I had used a tab to indent the where, the only correct way to indent the following line is to use a tab followed by 6 spaces. In my experience this is something that even smart formatting code editors never get right (let alone humans doing it manually); it is far more likely that if my view settings have a tab take up less space than the where keyword (such as the common 4 spaces) that I will get at least 2 leading tabs, followed by enough spaces to make the yz = y * z line appear to line up with the definition above.
Haskell compilers, by the spec, treat tab stops as eight spaces apart. So the situation I described above (where the first definition in the where is at 1 tab plus 6 normal characters and the second is at 2 tabs plus 2 normal characters) results in an invisible error. The compiler thinks these definitions are at positions 14 and 18, but to me they look the same. This sort problem is not fun. Hence the upvoted comment "When to use tabs? Never! That was an easy one."
Technically you can set your editor to show tabs stops at 8 spaces, and then it doesn't matter whether a given amount of indentation is all spaces or any mix of tabs and spaces that looks the same. However, most people don't like to have their editor set to show tabs as 8 spaces, and fixing any particular number defeats the entire point of indenting using tabs (having the visual appearance of "indent levels" be something that each user can configure independently in their editor).
It is also possible to adopt a code style that avoids the problem. Basically: always end the line immediately after a keyword introducing a block, so that the block starts on a new line (which you bump up the next indent level). You would then write (for the OP's example):
maximum' (x:xs)
| x > maxTail = x
| otherwise = maxTail
where
maxTail = maximum' xs
If you do that then your alignment positions will always be an exact number of tabs and zero normal characters, so you will not end up forced to use leading space that is a mix of tabs and spaces. In fact Haskell's alignment rules become extremely similar to Python's indentation rules if you code like this (the major reason they are different is that Haskell allows you to start an aligned block on the same line as preceding code, whereas Python's blocks are always preceded by a line ending in a colon).
But by far the most common approach to using tabs in Haskell is: simply don't do it. Configure your editor to insert spaces up to the next "tab-stop" when you press the tab key, if you like. But make sure the physical source code file is saved with spaces.
Gratuitous soapbox time!
For me personally, the reasoning above is why I don't like to use tabs in any language. Because sooner or later someone always ends up wanting to make something on one line visually align with something on another line, and this often needs indentation that is a mix of tabs and spaces. The tab and space mix is almost never correctly handled by the editor (to do so in general requires the editor to be able to tell when a line is a continuation line or the start of a new syntactic construct, before the coder has finished typing it, which is at best language-dependent and at-worst just impossible). So they write code that is simply incorrectly formatted as soon as someone uses a different tab-width preference than they used.
An example would be this fairly common layout (in no particular language):
class Foo {
public int foo(int x, char y, long listOfParameters,
bool z, double ooopsRanOutOfLetters) {
codeStartsHere();
If indent levels are tabs, then the correct indentation for the continuation of the parameter list is 1 tab and 15 spaces, but someone is just as likely to get 4 tabs and 3 spaces, which throws off the alignment completely at any other tab-width setting. Basically, if indent levels are to be configured for each coder's preference (by setting the tab-width), then there is a fundamental difference between inserting an indent level and inserting a visually-equivalent number of spaces, requiring you to think about which you intend every time you hit the tab key. Even if the formatting is purely a visual aid to human readers and causes no change in how the compiler/interpreter will read the code, aiding human readers is arguably more important than merely writing something that the machine will accept.
And again, this problem can be addressed by rigidly adhering to a style guide that is carefully constructed to avoid layouts like the above ever happening. But I just don't want to have to think about that when I'm designing or evaluating a style guide, nor when I'm writing code. "Always indent with spaces" is an incredibly simple rule to put in a style guide, and then it's never an issue regardless of the other rules you adopt (and regardless of whether those other rules are strictly followed or there are exceptions).
Only use spaces, because Haskell is indentation-sensitive and implicit layout blocks must start on a column greater than their layout keywords, so it's important to keep track of columns exactly.
Furthermore, tab stops are 8 columns apart according to Haskell2010, which is huge by today's indentation standards which are usually at most 4 spaces.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
In this Script,
approximation :: Int -> (String, Int)
approximation x
| (x<20000) && (19000<=x) && (numDigits<x) = (text1, x-numDigits)
| (x<20000) && (19000<=x) && (numDigits>x) = (text1, numDigits-x)
| (x<19800) && (x>=19700) && (numDigits<x) = (text2, x-numDigits)
| (x<19800) && (x>=19700) && (numDigits>x) = (text2, numDigits-x)
| otherwise = ("far from no. of Digits", 0)
where
text1 = "at 1000th place of no. of reallyBig, abosolute error="
text2 = "at 100th place of no. of reallyBig, nearly Exact, absolute error"
I inputted 2 definitions: text1, text2 for the Function approximation. However, the compiler GHCI said there is a Parse error on input '=' in text2. I was confused by the problem.
You have mixed tabs and spaces for your indentation. This is a bad plan, because your editor and ghc can think about tabs quite differently. I think your editor is displaying tabs as (up to) 4 characters, whereas ghc thinks of tabs as (up to) 8 spaces. I'll write <--> for a tab and . for a space in your last two lines:
<-->....text1 = "at 1000th place of no. of reallyBig, abosolute error="
<--><-->text2 = "at 100th place of no. of reallyBig, nearly Exact, absolute error"
Which is how your editor displays it. If I put ghc's 8 space tabs in, you get
<-------->....text1 = "at 1000th place of no. of reallyBig, abosolute error="
<--------><-------->text2 = "at 100th place of no. of reallyBig, nearly Exact, absolute error"
and you get the parse error.
It's easiest if you stick to spaces. Change your editor's settings.
If you use just spaces, you can't get this problem, because your editor has to show it the way the compiler thinks about it.
My editor lets me specify that when I press tab, it should insert the number of spaces that a tab would show as, so I use that, which is safe for a tabstop of 4. If your editor can do that, use that option. (If not, consider getting a cleverer editor for when you're programming.
My editor also has auto indent and outdent, where the next line copies the whitespace indentation of the previous line - this avoids the problem. Turn this on if your editor supports it, because it saves you effort and you're less likely to get the parse error. (When I then press backspace, my editor deletes back to the previous level of indentation, which is nice.)
Almost all editors can change how they display tabs. If you can't get it to use spaces for tabs, you should change the tabstop to be 8, because that matches ghc, and you're much less likely to get this error, but you're still better off using spaces.
This question already has answers here:
Quickest way to change a pair of parenthesis to brackets in vim
(6 answers)
Closed 8 years ago.
I am looking for a VIM key combo for changing something like
blahblah["hello"]
to
blahblah("hello")
My best effort so far is
0f[yi[%c%()^["0P^[
but anything better would be much appreciated.
BTW, my combo works by doing:
find the first instance of [ (you get my point),
yank the insides (which of course means to register 0 by default, and it leaves the cursor on the first "),
move the cursor back onto the first instance of [ with %,
delete the whole [...] bit and go into insert mode,
write () and <Esc> out of insert mode,
paste the contents of register 0 in between the ().
I was hoping to have a muscle-memorable key combination that I could use for things like this where you want to 'keep the contents but change the surroundings'.
My proposal, if you reduce it to the minimum (and use ca[ rather than %c% -- credit to this SO for the a motion that I had not really known about) is not too bad because it is the sort of thing you can invent again once you know it is possible:
yi[ca[()<Esc>"0P
However, it occurred to me that a search-and-replace is going to be just the right kind of solution when you need to do a few of these in a file. Here is my best effort:
select the area in visual mode (I tend to use VISUAL LINE mode as a default),
then :s/\[\(.\{-}\)\]/(\1)/g<Enter> and you're done.
That itself looks a bit mad, but it is just a simple example of so-called backreferencing so I was quite happy to have had to get that clear in my mind too.
I'm beginning to learn VIM (I've downloaded an emulator plugin for my IDE) and unsurprisingly it's making me irritated and extremely slow. That is all fine and I realize it's a phaze everyone goes through.
However this one feature is quite frustrating - being unable to jump to the next line via l, previous with h or search more than one line with f.
Is there a valid, typing speed enhancing reason for this?
You can make h and l wrap lines by adding h and l to the whichwrap option (:he whichwrap), although for the sake of compatibility with scripts and macros that don't expect h and l to wrap, you might want to avoid adding them, and add the < and > options instead (which allow the left and right arrow keys to wrap).
As for f (and F and t and T), they're just really not meant to do that, but you can use / and ? as movements -- d/foo<Enter> to delete everything between here and a following "foo" (whether it's on this line or a later one).