help with map(), please!

21 views
Skip to first unread message

Charles Campbell

unread,
Nov 27, 2020, 7:06:04 PM11/27/20
to vim...@googlegroups.com
I'm having a bit of a problem with map(). I've had problems with map() before, and consequently I really really hate to use it.
Here goes:

1: construct a comment:
"   Testing: one two | three four | five | six |
"            seven | eight |;
2. grab characters:
fo<ctrl-v>j$"ay

3. convert to list:
let list= split(@a,'\s*|\s*;\=',' ')
4. Now, try to use map():
call map(list,"substitute(v:val,'<&>','','ge')")

Intent: to put <...> around every argument. Now, this isn't really my final intent for this, but if I could get that substitute to work, it'd be a nice start. Please note, the request is on how to get a substitute() to work with map(), not to put angle brackets around every list element, for which :help map() already has an example.
5. Bonus request: my construction above carefully gets a newline into the list. Using :echo string(list):
['one two', 'three four', 'five', 'six', '
seven', 'eight', '                    ']
    I cannot seem to get rid of the newline, but its probably due to my lack of success with substitute().

I've spent about three hours on this so far, with multiple attempts, all unsuccessful. Perhaps an extra example in help map() illustrating how to do this would be of use?

Thank you,
Chip Campbell

Salman Halim

unread,
Nov 27, 2020, 7:23:29 PM11/27/20
to Vim Users
Dr. Chip,

I may be trivializing what's happening, but have you considered using \_s instead of just \s?

Or passing it to another map that calls trim before?

Something like split -> mapWithTrim -> yourOriginalMap

I'm sure I'm missing something obvious because someone with your experience wouldn't ask a question if it were this simple. Also, I'm using my mobile phone right now so I can't actually type the full syntax.

I would've used a join instead of the last map and just wrap the result in a <> pair. 

--

Salman

--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/vim_use/91e26ba3-9e1b-19ad-3c43-ff7b42a0de3c%40drchip.org.

Charles Campbell

unread,
Nov 27, 2020, 8:19:46 PM11/27/20
to vim...@googlegroups.com, Salman Halim
Salman Halim wrote:
> Dr. Chip,
>
> I may be trivializing what's happening, but have you considered using
> \_s instead of just \s?
>
> Or passing it to another map that calls trim before?
>
> Something like split -> mapWithTrim -> yourOriginalMap
>
> I'm sure I'm missing something obvious because someone with your
> experience wouldn't ask a question if it were this simple. Also, I'm
> using my mobile phone right now so I can't actually type the full syntax.
>
> I would've used a join instead of the last map and just wrap the
> result in a <> pair.
Actually, a join is in use .. but it needed several processing steps.
Thank you! I don't think I've ever used (or noticed) trim() before.
Still plenty to learn, and trim did the trick. Still, I think an example
using substitute with map would be a Good Idea. I did finally get it to
work, but then your note about trim() appeared, and I switched to using
that.

Regards,
Chip Campbell

Andy Wokula

unread,
Dec 1, 2020, 12:12:29 PM12/1/20
to vim...@googlegroups.com
Am 28.11.2020 um 01:05 schrieb Charles Campbell:
> I'm having a bit of a problem with map(). I've had problems with map()
> before, and consequently I really really hate to use it.
> Here goes:
>
> 1: construct a comment:
>
> " Testing: one two | three four | five | six |
> " seven | eight |;
>
> 2. grab characters:
>
> fo<ctrl-v>j$"ay
>
> 3. convert to list:
>
> let list= split(@a,'\s*|\s*;\=',' ')

" convert newlines, then split ...
let list1 = split(tr(@a, "\n", " "), '\s*|\s*;\=')

> 4. Now, try to use map():
>
> call map(list,"substitute(v:val,'<&>','','ge')")

" (using copy() below is for easier debugging ...)

" you somehow did not check the substitute() arguments ...
let list2a = map(copy(list1), "substitute(v:val, '.*', '<&>', 'g')")

" the same, but avoiding inner quotes with lambda:
let list2b = map(copy(list1), {_, s -> substitute(s, '.*', '<&>', 'g')})
" ^
" |
" Note: do not forget THIS goiter argument

" Or what I actually do: define convenience functions, like this one:

" Msubstitute({lod}, {pat}, {repl}, {flags}[, ...])
"
" "map substitute": call substitute(Item, {pat}, {repl}, {flags}) for each
" {lod} Item.
"
" {lod} (list or dict)
" [...] values `a:1', `a:2', ... accessible in a {repl} expression
"

func! Msubstitute(_lod_, pat, repl, flags, ...)
return map(a:_lod_, 'substitute(v:val, a:pat, a:repl, a:flags)')
endfunc

" then you can use:
let list2c = Msubstitute(copy(list1), '.*', '<&>', 'g')

> Intent: to put <...> around every argument. Now, this isn't really
> my final intent for this, but if I could get that substitute to
> work, it'd be a nice start. Please note, the request is on how to
> get a substitute() to work with map(), not to put angle brackets
> around every list element, for which :help map() already has an
> example.
>
> 5. Bonus request: my construction above carefully gets a newline into
> the list. Using :echo string(list):
>
> ['one two', 'three four', 'five', 'six', '
> seven', 'eight', ' ']
>
> I cannot seem to get rid of the newline, but its probably due to my
> lack of success with substitute().
>
> I've spent about three hours on this so far, with multiple attempts,
> all unsuccessful. Perhaps an extra example in help map() illustrating
> how to do this would be of use?
>
> Thank you,
> Chip Campbell

--
Andy
Reply all
Reply to author
Forward
0 new messages